00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "mmstools/mmsthread.h"
00034 #include "mmstools/mmserror.h"
00035 #include "mmstools/tools.h"
00036 #include <map>
00037
00038 #ifdef __HAVE_DIRECTFB__
00039 extern "C" {
00040 #include <direct/debug.h>
00041 #include <direct/thread.h>
00042 #include <direct/trace.h>
00043 }
00044
00045 D_DEBUG_DOMAIN( MMS_Thread, "MMS/Thread", "MMS Thread" );
00046
00047 #endif
00048
00049
00050 typedef struct {
00051 void *udata;
00052 void (*handlerfunc)(void *);
00053 } CLEANUP_STRUCT;
00054
00055
00056 static std::map<pthread_t, CLEANUP_STRUCT *> cleanups;
00057
00058
00059 MMSThread::MMSThread(string identity, int priority, bool autodetach) {
00060 #ifdef __HAVE_DIRECTFB__
00061 D_DEBUG_AT( MMS_Thread, "MMSThread( %s )\n", identity.c_str() );
00062
00063 direct_trace_print_stack(NULL);
00064 #endif
00065
00066
00067 this->identity = identity;
00068 this->priority = priority;
00069
00070
00071 this->starting = false;
00072 this->running = false;
00073 this->detached = false;
00074 this->autodetach = autodetach;
00075 setStacksize();
00076 }
00077
00078
00079 MMSThread::~MMSThread() {
00080 }
00081
00082
00083 void *MMSThread::runThread(void *thiz) {
00084 static_cast<MMSThread *>(thiz)->run();
00085 return NULL;
00086 }
00087
00088
00089 void MMSThread::run() {
00090 try {
00091 #ifdef __HAVE_DIRECTFB__
00092 direct_thread_set_name( this->identity.c_str() );
00093 #endif
00094 if(this->autodetach) {
00095 this->detach();
00096 }
00097
00098
00099 this->running = true;
00100 this->starting = false;
00101
00102
00103 threadMain();
00104
00105
00106 this->running = false;
00107
00108 } catch(MMSError &error) {
00109 this->running = false;
00110 this->starting = false;
00111 DEBUGMSG(this->identity.c_str(), "Abort due to: " + error.getMessage());
00112 }
00113 }
00114
00115 bool MMSThread::start() {
00116
00117
00118 this->startlock.lock();
00119 if (isRunning()) {
00120 this->startlock.unlock();
00121 return false;
00122 }
00123 this->starting = true;
00124 this->startlock.unlock();
00125
00126
00127 pthread_attr_init(&this->tattr);
00128 pthread_attr_getschedparam(&this->tattr, &this->param);
00129 this->param.sched_priority = this->priority;
00130 pthread_attr_setschedparam(&this->tattr, &this->param);
00131 pthread_attr_setstacksize(&this->tattr, this->stacksize);
00132
00133
00134 int rc;
00135 for (int i = 0; i < 3; i++) {
00136
00137 rc = pthread_create(&this->id, &this->tattr, this->runThread, static_cast<void *>(this));
00138 if (!rc) {
00139
00140 break;
00141 }
00142 usleep(50000);
00143 }
00144
00145
00146 pthread_attr_destroy(&this->tattr);
00147
00148 if (rc) {
00149
00150 this->starting = false;
00151 return false;
00152 }
00153
00154
00155
00156 return true;
00157 }
00158
00159
00160 bool MMSThread::isRunning() {
00161
00162 if (this->starting) return true;
00163 return this->running;
00164 }
00165
00166
00167 void MMSThread::detach() {
00168 pthread_detach(this->id);
00169 this->detached = true;
00170 }
00171
00172
00173 bool MMSThread::cancel() {
00174 if (!isRunning()) {
00175
00176 return false;
00177 }
00178
00179
00180 int rc;
00181 for (int i = 0; i < 3; i++) {
00182
00183 rc = pthread_cancel(this->id);
00184 if (!rc) {
00185
00186 break;
00187 }
00188 }
00189
00190 if (rc) {
00191
00192 return false;
00193 }
00194
00195
00196 this->running = false;
00197 this->starting = false;
00198 return true;
00199 }
00200
00201
00202 void MMSThread::join() {
00203 if (!this->detached)
00204 pthread_join(this->id, NULL);
00205 }
00206
00207
00208 void MMSThread::setStacksize(size_t stacksize) {
00209 this->stacksize = stacksize;
00210 }
00211
00212
00213 void addGarbageHandler(void (*handlerfunc)(void *), void *data) {
00214 CLEANUP_STRUCT *item = new CLEANUP_STRUCT;
00215 std::map<pthread_t, CLEANUP_STRUCT *>::iterator it;
00216 pthread_t self = pthread_self();
00217
00218 item->handlerfunc=handlerfunc;
00219 item->udata=data;
00220
00221 it=cleanups.find(self);
00222 if(it!=cleanups.end()) {
00223 if(it->second)
00224 delete it->second;
00225 it->second = item;
00226 } else {
00227 cleanups.insert(std::make_pair(self,item));
00228 }
00229 }
00230
00231 void callGarbageHandler() {
00232 std::map<pthread_t, CLEANUP_STRUCT *>::iterator it;
00233 pthread_t self = pthread_self();
00234
00235 it = cleanups.find(self);
00236 if(it!=cleanups.end()) {
00237
00238 it->second->handlerfunc(it->second->udata);
00239
00240
00241 delete it->second;
00242 cleanups.erase(self);
00243 }
00244 }
00245
00246 void clearGarbageHandler() {
00247 std::map<pthread_t, CLEANUP_STRUCT *>::iterator it;
00248 pthread_t self = pthread_self();
00249
00250 it = cleanups.find(self);
00251 if(it!=cleanups.end()) {
00252
00253
00254 delete it->second;
00255 cleanups.erase(self);
00256 }
00257 }
00258