线程操作对象 有关线程的操作,可以查看Linux系统编程:线程
今天介绍三个对象:CThread,CMutex,CCond。分别负责创建线程,线程互斥以及线程同步
CThread CThread继承ThreadClass,ThreadClass是一个只包含纯虚函数run()接口基类,如下:
1 2 3 4 5 class ThreadClass { public : virtual void run () = 0 ; };
CThread有两种使用方式:
继承CThread,实现run()方法,根据C++的特性,派生类在重定义一个基类的函数时,基类的函数会被隐藏,所以在调用start()方法启动线程时,会执行派生类的run()方法
继承ThreadClass,实现run()方法,将派生类作为参数创建CThread,调用CThread的start()方法启动线程
线程数据设置:
pthread_key_create分配用于标识进程中线程特定数据的键。
pthread_getspecific根据键获取特定的数据
这里用来保存线程名称,函数原型如下:
1 2 3 int pthread_key_create (pthread_key_t *key, void (*destructor)(void *)) ;void *pthread_getspecific (pthread_key_t key) ;int pthread_setspecific (pthread_key_t key, const void *value) ;
具体实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 #include "cthread.h" #include <unistd.h> pthread_key_t key;bool is_key_create = false ;void *CThread::staticRun (void *ptr) { CThread *thread = static_cast <CThread *>(ptr); thread->preparationRun (); return thread; }void CThread::preparationRun () { int ret, pthread_cancel; ret = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &pthread_cancel); setCurrentThreadName ((char *)getThreadName ().c_str ()); mThreadStatus = C_THREAD_STATUS_RUNNING; run (); mThreadStatus = C_THREAD_STATUS_EXIT; pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &pthread_cancel); pthread_exit (nullptr ); }void CThread::run () { if (mThreadClass != nullptr ) { mThreadClass->run (); } } CThread::CThread () { mThreadId = 0 ; mThreadStatus = C_THREAD_STATUS_NEW; pthread_attr_init (&mThreadAttr); } CThread::CThread (ThreadClass *thread_class) { mThreadClass = thread_class; CThread (); } CThread::~CThread () { pthread_attr_destroy (&mThreadAttr); }bool CThread::start (std::string name) { int ret = pthread_create (&mThreadId, &mThreadAttr, staticRun, this ); if (ret != 0 ) { mThreadId = 0 ; return false ; } mThreadName = name; return true ; }int CThread::stop () { int ret = -1 ; if (mThreadId > 0 ) { ret = pthread_cancel (mThreadId); } return ret; }void CThread::join () { int ret, count; for (count = 0 ; count < 20 ; count++) { if (mThreadId > 0 ) { ret = pthread_tryjoin_np (mThreadId, nullptr ); if (ret == 0 ) { ret = pthread_join (mThreadId, nullptr ); return ; } } sleep (10 ); } }void CThread::join (unsigned long millis_time) { if (mThreadId > 0 ) { if (millis_time == 0 ) { join (); } else { while (mThreadStatus != C_THREAD_STATUS_EXIT && millis_time > 0 ) { sleep (1 ); millis_time--; } } } }void CThread::sleep (unsigned long millis_time) { usleep (millis_time * 1000 ); }void CThread::setThreadName (const char *name) { mThreadName = name; }void CThread::setThreadInfo (const char *name) { if (name != nullptr ) { setThreadName (name); setCurrentThreadName (name); } }void CThread::setCurrentThreadName (const char *name) { int ret = -1 ; if (!is_key_create) { ret = pthread_key_create (&key, nullptr ); if (ret == 0 ) { is_key_create = true ; } } if (is_key_create) { ret = pthread_setspecific (key, (void *)name); if (ret != 0 ) { } } }std::string CThread::getCurrentThreadName () { char *name = nullptr ; if (is_key_create) { name = (char *)pthread_getspecific (key); if (name != nullptr ) { return name; } } return "Unknown" ; }int CThread::getCurrentThreadId () { return pthread_self (); }
注:线程中可能会使用syslog或其他异步信号不安全的函数,所以当收到cancel信号可能会产生死锁,所以屏蔽cancel信号,设置PTHREAD_CANCEL_DISABLE标志位
CMutex CMutex是一个简单的互斥锁实现类,提供lock和unloke方法,实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <string.h> #include "cmutex.h" CMutex::CMutex () { memset (&mAttr, 0 , sizeof (mAttr)); pthread_mutexattr_init (&mAttr); pthread_mutex_init (&mMutex, nullptr ); } CMutex::CMutex (bool recursive) { memset (&mAttr, 0 , sizeof (mAttr)); pthread_mutexattr_init (&mAttr); if (recursive) { pthread_mutexattr_settype (&mAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init (&mMutex, &mAttr); } else { pthread_mutex_init (&mMutex, nullptr ); } } CMutex::~CMutex () { pthread_mutex_destroy (&mMutex); pthread_mutexattr_destroy (&mAttr); }int CMutex::lock () { return pthread_mutex_lock (&mMutex); }int CMutex::unlock () { return pthread_mutex_unlock (&mMutex); }pthread_mutex_t *CMutex::getMutex () { return &mMutex; }
CCond CCond是一个简单的线程同步实现类,主要提供了wait和signal方法,实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include "ccond.h" #include <ctime> #include <cerrno> CCond::CCond () { pthread_condattr_init (&mCondAttr); pthread_condattr_setclock (&mCondAttr, CLOCK_MONOTONIC); pthread_cond_init (&mCond, &mCondAttr); } CCond::~CCond () { pthread_condattr_destroy (&mCondAttr); pthread_cond_destroy (&mCond); }void CCond::wait (CMutex *mutex) { if (mutex != nullptr ) { pthread_cond_wait (&mCond, mutex->getMutex ()); } }int CCond::wait (CMutex *mutex, unsigned int millis_time) { int wait_value = ETIMEDOUT; timespec wait_time; clock_gettime (CLOCK_MONOTONIC, &wait_time); wait_time.tv_sec += millis_time / 1000 ; wait_time.tv_nsec += (millis_time % 1000 ) * 1000000 ; if (mutex != nullptr ) { wait_value = pthread_cond_timedwait (&mCond, mutex->getMutex (), &wait_time); if (wait_value == ETIMEDOUT) { return 0 ; } else { return 1 ; } } return -1 ; }void CCond::signal () { pthread_cond_signal (&mCond); }