00001 #include <map>
00002 #include <vector>
00003 #include <string.h>
00004 #include <malloc.h>
00005 #include <stdio.h>
00006 #include <unistd.h>
00007 #include <stdlib.h>
00008 #include <pthread.h>
00009 #include "tools/assert.h"
00010 #include "tools/log.h"
00011
00012 #include "thread_obj.h"
00013
00014 pthread_mutex_t mgmt_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
00015
00016 std::map<pthread_t, ThreadObj*> thread_map;
00017
00018 ThreadObj::ThreadObj(std::string n) : lock(RECURSIVE_MUTEX),
00019 has_started(false), ask_stop(false), stopped(true), thread_running(false), id(0)
00020 {
00021 lock.Lock();
00022 name = n;
00023 lock.Unlock();
00024
00025 log(LogDebug, "Starting thread %p : %s", this, n.c_str());
00026 }
00027
00028 ThreadObj::~ThreadObj()
00029 {
00030
00031
00032
00033
00034
00035 }
00036
00037 void ThreadObj::Start()
00038 {
00039 lock.Lock();
00040 pthread_mutex_lock(&mgmt_lock);
00041 thread_running = true;
00042 int r = pthread_create(&id, NULL, StartThread, (void*)this);
00043 thread_map.insert(std::make_pair(id, this));
00044 if(r != 0)
00045 log(LogError, "Could not start thread: %s", strerror(r));
00046 pthread_mutex_unlock(&mgmt_lock);
00047 lock.Unlock();
00048 }
00049
00050 void *ThreadObj::StartThread(void* arg)
00051 {
00052 ThreadObj* thr = static_cast<ThreadObj*>(arg);
00053 thr->OnStart();
00054
00055 thr->lock.Lock();
00056 thr->stopped = false;
00057 thr->ask_stop = false;
00058 thr->has_started = true;
00059 thr->lock.Unlock();
00060
00061 thr->Main();
00062
00063 thr->lock.Lock();
00064 thr->stopped = true;
00065 thr->ask_stop = false;
00066 thr->OnStop();
00067 thr->lock.Unlock();
00068
00069 pthread_exit(NULL);
00070 return NULL;
00071 }
00072
00073 void ThreadObj::Kill()
00074 {
00075 lock.Lock();
00076 pthread_mutex_lock(&mgmt_lock);
00077 log(LogDebug, "Killing thread %p : %s", this, name.c_str());
00078 stopped = true;
00079 ask_stop = false;
00080
00081 std::map<pthread_t, ThreadObj*>::iterator it = thread_map.find(id);
00082 if(it != thread_map.end())
00083 thread_map.erase(it);
00084
00085 int r = pthread_cancel(id);
00086
00087 if(r != 0)
00088 log(LogError, "Unable to cancel thread %s", strerror(r));
00089 pthread_mutex_unlock(&mgmt_lock);
00090 lock.Unlock();
00091 }
00092
00093 ThreadObj* GetCurrentThread()
00094 {
00095 pthread_mutex_lock(&mgmt_lock);
00096 pthread_t current_id = pthread_self();
00097
00098 std::map<pthread_t, ThreadObj*>::iterator it = thread_map.find(current_id);
00099 if(it != thread_map.end())
00100 {
00101 ThreadObj* th = it->second;
00102 pthread_mutex_unlock(&mgmt_lock);
00103 return th;
00104 }
00105 pthread_mutex_unlock(&mgmt_lock);
00106 return NULL;
00107 }
00108
00109 bool ThreadObj::GetAskStop()
00110 {
00111 lock.Lock();
00112 bool ret = ask_stop;
00113 lock.Unlock();
00114 return ret;
00115 }
00116
00117 bool ThreadObj::GetStopped()
00118 {
00119 lock.Lock();
00120 bool ret = stopped && has_started;
00121 lock.Unlock();
00122 return ret;
00123 }
00124
00125 void ThreadObj::Stop()
00126 {
00127 lock.Lock();
00128 ask_stop = true;
00129 lock.Unlock();
00130
00131 while(!GetStopped())
00132 usleep(5000);
00133
00134
00135 pthread_mutex_lock(&mgmt_lock);
00136 if(!thread_running)
00137 {
00138 pthread_mutex_unlock(&mgmt_lock);
00139 return;
00140 }
00141
00142 thread_running = false;
00143 pthread_join(id, NULL);
00144
00145 std::map<pthread_t, ThreadObj*>::iterator it = thread_map.find(id);
00146 if(it != thread_map.end())
00147 thread_map.erase(it);
00148
00149 pthread_mutex_unlock(&mgmt_lock);
00150 }
00151