C++11 provides thread, but it's too complex, and we prefer to write our own thread in the project.
The use of Posix thread is not mentioned here.
The point is this function:
#include <pthread.h>intconst pthread_attr_t *attr, void * (*start_ routine) (voidvoid *arg);
The third parameter is a callback function that must return a value of void*, and only one argument, and the type is also void*.
POSIX thread By default is joinable, you need to manually call the Pthread_join function to reclaim, you can also call Pthread_detach to detachable, thereis no need to manually recycle threads.
The wrapper for thread is described below.
We put the thread's statement here first:
#ifndef Thread_h_#defineThread_h_#include"NonCopyable.h"#include<pthread.h>classthread:noncopyable{ Public: Thread (); ~Thread (); voidstart (); voidjoin (); Virtual voidRun () =0; pthread_t GetThreadId ()Const { returnthreadid_;}Private:
The third parameter supplied to Pthread_create uses the staticvoid *runinthread (void *arg); pthread_t threadid_; // // process marked bool isrunning_;}; #endif // Thread_h_
Here's what you need to explain:
First, to get the cleanest semantics,thread should be non-replicable , so you need to inherit noncopyable.
Secondly, in order to invoke pthread_create to create a thread, we cannot register it with a member function because the member function contains an implicit argument that causes the function's pointer type to be not void * (*start_routine) (void *), so we The static function is used .
The static function cannot access the members of an object, so we use the this pointer as a parameter to the callback function when we call Pthread_create.
Here the relevant code is as follows:
// Static void *thread::runinthread (void *arg) { *pt = static_cast<thread*>(ARG); //pt->tid_ = Syscall (Sys_gettid); Pt->Run (); return NULL;}
The user registers their logic in run.
This thread does not provide the detach function, because we do the following in the destructor, if the thread object is being refactored and the threads are still running, you need to set the thread to the detach state .
thread::~Thread () { if(isrunning_) { Pthread_detach (threadid_);} }
Most of the logic is fixed, the user only needs to change the code inside the run, so we set the run to pure virtual function, let the user inherit the thread class .
The complete CPP implementation is as follows:
#include"Thread.h"#include<assert.h>#include<unistd.h>#include"MutexLock.h"thread::thread (): Threadid_ (0), Isrunning_ (false) {}thread::~Thread () {if(isrunning_) {Tiny_check (!Pthread_detach (threadid_)); }}//Staticvoid*thread::runinthread (void*Arg) {Thread*PT = static_cast<thread*>(ARG); //pt->tid_ = Syscall (Sys_gettid);Pt->run (); returnNULL;}voidThread::start () {Tiny_check (!pthread_create (&threadid_, NULL, Thread::runinthread, This)); Isrunning_=true;}voidThread::join () {assert (isrunning_); Tiny_check (!Pthread_join (threadid_, NULL)); Isrunning_=false;}
The test code is as follows: Use this class in an inherited way.
#include"Thread.h"#include<iostream>#include<unistd.h>using namespacestd;classMyThread: Publicthread{ Public: voidrun () {cout<<"Foo"<<Endl; }};intMainintargcChar Const*argv[]) {MyThread T; T.start (); T.join (); return 0;}
Linux component Encapsulation (iii) encapsulating thread with object-oriented programming