00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "global.hpp"
00016 #include "log.hpp"
00017 #include "thread.hpp"
00018
00019 #include <new>
00020 #include <iostream>
00021 #include <memory>
00022 #include <vector>
00023
00024 #define ERR_G LOG_STREAM(err, general)
00025
00026 static int run_async_operation(void* data)
00027 {
00028 threading::async_operation* const op = reinterpret_cast<threading::async_operation*>(data);
00029 op->run();
00030
00031 bool should_delete = false;
00032 {
00033 const threading::lock l(op->get_mutex());
00034 op->notify_finished();
00035 if(op->is_aborted()) {
00036 should_delete = true;
00037 }
00038 }
00039
00040 if(should_delete) {
00041 delete op;
00042 }
00043
00044
00045 return 0;
00046 }
00047
00048 namespace {
00049
00050 std::vector<SDL_Thread*> detached_threads;
00051
00052 }
00053
00054 namespace threading {
00055
00056 manager::~manager()
00057 {
00058 for(std::vector<SDL_Thread*>::iterator i = detached_threads.begin(); i != detached_threads.end(); ++i) {
00059 SDL_WaitThread(*i,NULL);
00060 }
00061 }
00062
00063 thread::thread(int (*f)(void*), void* data) : thread_(SDL_CreateThread(f,data))
00064 {}
00065
00066 thread::~thread()
00067 {
00068 join();
00069 }
00070
00071 void thread::kill()
00072 {
00073 if(thread_ != NULL) {
00074 SDL_KillThread(thread_);
00075 thread_ = NULL;
00076 }
00077 }
00078
00079 void thread::join()
00080 {
00081 if(thread_ != NULL) {
00082 SDL_WaitThread(thread_,NULL);
00083 thread_ = NULL;
00084 }
00085 }
00086
00087 void thread::detach()
00088 {
00089 detached_threads.push_back(thread_);
00090 thread_ = NULL;
00091 }
00092
00093 mutex::mutex() : m_(SDL_CreateMutex())
00094 {}
00095
00096 mutex::~mutex()
00097 {
00098 SDL_DestroyMutex(m_);
00099 }
00100
00101 lock::lock(mutex& m) : m_(m)
00102 {
00103 SDL_mutexP(m_.m_);
00104 }
00105
00106 lock::~lock()
00107 {
00108 SDL_mutexV(m_.m_);
00109 }
00110
00111 condition::condition() : cond_(SDL_CreateCond())
00112 {}
00113
00114 condition::~condition()
00115 {
00116 SDL_DestroyCond(cond_);
00117 }
00118
00119 bool condition::wait(const mutex& m)
00120 {
00121 return SDL_CondWait(cond_,m.m_) == 0;
00122 }
00123
00124 condition::WAIT_TIMEOUT_RESULT condition::wait_timeout(const mutex& m, unsigned int timeout)
00125 {
00126 const int res = SDL_CondWaitTimeout(cond_,m.m_,timeout);
00127 switch(res) {
00128 case 0: return WAIT_OK;
00129 case SDL_MUTEX_TIMEDOUT: return WAIT_TIMEOUT;
00130 default:
00131 ERR_G << "SDL_CondWaitTimeout: " << SDL_GetError() << "\n";
00132 return WAIT_ERROR;
00133 }
00134 }
00135
00136 bool condition::notify_one()
00137 {
00138 if(SDL_CondSignal(cond_) < 0) {
00139 ERR_G << "SDL_CondSignal: " << SDL_GetError() << "\n";
00140 return false;
00141 }
00142
00143 return true;
00144 }
00145
00146 bool condition::notify_all()
00147 {
00148 if(SDL_CondBroadcast(cond_) < 0) {
00149 ERR_G << "SDL_CondBroadcast: " << SDL_GetError() << "\n";
00150 return false;
00151 }
00152 return true;
00153 }
00154
00155 bool async_operation::notify_finished()
00156 {
00157 finishedVar_ = true;
00158 return finished_.notify_one();
00159 }
00160
00161 async_operation::RESULT async_operation::execute(waiter& wait)
00162 {
00163
00164
00165
00166
00167
00168
00169
00170 std::auto_ptr<thread> t(NULL);
00171 {
00172 const lock l(get_mutex());
00173 t = std::auto_ptr<thread>(new thread(run_async_operation,this));
00174
00175 bool completed = false;
00176 while(wait.process() == waiter::WAIT) {
00177 const condition::WAIT_TIMEOUT_RESULT res = finished_.wait_timeout(get_mutex(),20);
00178 if(res == condition::WAIT_OK || finishedVar_) {
00179 completed = true;
00180 break;
00181 }
00182 #ifndef __BEOS__
00183 else if(res == condition::WAIT_ERROR) {
00184 break;
00185 }
00186 #endif
00187 }
00188
00189 if(!completed) {
00190 aborted_ = true;
00191 t->detach();
00192 return ABORTED;
00193 }
00194 }
00195
00196 return COMPLETED;
00197 }
00198
00199
00200 }