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