You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

threading.cpp 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. // threading.cpp
  2. //
  3. // (C) 2006 - 2009 MicroNeil Research Corporation.
  4. //
  5. // This program is part of the MicroNeil Research Open Library Project. For
  6. // more information go to http://www.microneil.com/OpenLibrary/index.html
  7. //
  8. // This program is free software; you can redistribute it and/or modify it
  9. // under the terms of the GNU General Public License as published by the
  10. // Free Software Foundation; either version 2 of the License, or (at your
  11. // option) any later version.
  12. //
  13. // This program is distributed in the hope that it will be useful, but WITHOUT
  14. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  16. // more details.
  17. //
  18. // You should have received a copy of the GNU General Public License along with
  19. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  20. // Place, Suite 330, Boston, MA 02111-1307 USA
  21. // For details on the Threading module and development history see threading.hpp
  22. #include "threading.hpp"
  23. using namespace std; // Introduce std namespace.
  24. ThreadManager Threads; // Master thread manager.
  25. void ThreadManager::rememberThread(Thread* T) { // Threads register themselves.
  26. ScopeMutex ThereCanBeOnlyOne(MyMutex); // Protect the known pool.
  27. KnownThreads.insert(T); // Add the new thread pointer.
  28. }
  29. void ThreadManager::forgetThread(Thread* T) { // Threads remove themselves.
  30. ScopeMutex ThereCanBeOnlyOne(MyMutex); // Protect the known pool.
  31. KnownThreads.erase(T); // Add the new thread pointer.
  32. }
  33. ThreadStatusReport ThreadManager::StatusReport() { // Get a status report, All Threads.
  34. ScopeMutex ThereCanBeOnlyOne(MyMutex); // Protect our set -- a moment in time.
  35. ThreadStatusReport Answer; // Create our vector to hold the report.
  36. for( // Loop through all of the Threads.
  37. set<Thread*>::iterator iT = KnownThreads.begin();
  38. iT != KnownThreads.end(); iT++
  39. ) { // Grab each Threads' report.
  40. Thread& X = *(*iT); // Handy reference to the Thread.
  41. Answer.push_back(X.StatusReport()); // Push back each Thread's report.
  42. }
  43. return Answer; // Return the finished report.
  44. }
  45. bool ThreadManager::lockExistingThread(Thread* T) { // Locks ThreadManager if T exists.
  46. MyMutex.lock(); // Lock the mutex for everyone.
  47. if(KnownThreads.end() == KnownThreads.find(T)) { // If we do not find T in our set
  48. MyMutex.unlock(); // then unlock the mutex and return
  49. return false; // false.
  50. } // If we did find it then
  51. LockedThread = T; // set our locked thread and
  52. return true; // return true;
  53. }
  54. // We use assert() in the code below because if these conditions fail then there
  55. // is something seriously wrong and potentially dangerous with the calling code.
  56. void ThreadManager::unlockExistingThread(Thread* T) { // Unlocks ThreadManager if T locked.
  57. assert(0 != LockedThread); // We had better have a locked thread.
  58. assert(T == LockedThread); // The locked thread had better match.
  59. LockedThread = 0; // Clear the locked thread.
  60. MyMutex.unlock(); // Unlock the mutex.
  61. }
  62. //// Scope Thread Lock allows for a safe way to lock threads through the Threads
  63. //// object for delivering short messages. Just like a ScopeMutex, when the object
  64. //// goes away the lock is released.
  65. ScopeThreadLock::ScopeThreadLock(Thread* T) : // Construct a scope lock on a Thread.
  66. MyLockedThread(0) { // To star with we have no lock.
  67. if(Threads.lockExistingThread(T)) { // If we achieve a lock then we
  68. MyLockedThread = T; // remember it. Our destructor will
  69. } // unlock it if we were successful.
  70. }
  71. ScopeThreadLock::~ScopeThreadLock() { // Destruct a scope lock on a Thread.
  72. if(0 != MyLockedThread) { // If we were successfully constructed
  73. Threads.unlockExistingThread(MyLockedThread); // we can unlock the thread and
  74. MyLockedThread = 0; // forget about it before we go away.
  75. }
  76. }
  77. bool ScopeThreadLock::isGood() { // If we have successfully locked T
  78. return (0 != MyLockedThread) ? true:false; // it will NOT be 0, so return true.
  79. }
  80. bool ScopeThreadLock::isBad() { // If we did not successfully lock T
  81. return (0 == MyLockedThread) ? false:true; // it will be 0, so return false.
  82. }
  83. ////////////////////////////////////////////////////////////////////////////////
  84. // Thread
  85. const ThreadType Thread::Type("Generic Thread");
  86. const ThreadState Thread::ThreadInitialized("Thread Initialized");
  87. const ThreadState Thread::ThreadStarted("Thread Started");
  88. const ThreadState Thread::ThreadFailed("Thread Failed");
  89. const ThreadState Thread::ThreadStopped("Thread Stopped");
  90. const ThreadState Thread::ThreadDestroyed("Thread Destroyed");
  91. bool Thread::isRunning() { return RunningFlag; } // Return RunningFlag state.
  92. bool Thread::isBad() { return BadFlag; } // Return BadFlag state.
  93. const string Thread::MyFault() { return BadWhat; } // Return exception Bad fault if any.
  94. const string Thread::MyName() { return MyThreadName; } // Return the instance name if any.
  95. const ThreadType& Thread::MyType() { return MyThreadType; } // Return the instance Thread Type.
  96. const ThreadState& Thread::MyState() { return (*MyThreadState); } // Thread state for this instance.
  97. void Thread::CurrentThreadState(const ThreadState& TS) { // Set Current Thread State.
  98. MyThreadState = const_cast<ThreadState*>(&TS);
  99. }
  100. const ThreadState& Thread::CurrentThreadState() { return (*MyThreadState); } // Get Current Thread State.
  101. ThreadStatusRecord Thread::StatusReport() { // Get a status report from this thread.
  102. return
  103. ThreadStatusRecord( // Status record.
  104. this,
  105. const_cast<ThreadType&>(MyThreadType),
  106. *MyThreadState,
  107. RunningFlag,
  108. BadFlag,
  109. BadWhat,
  110. MyThreadName
  111. );
  112. }
  113. // launchTask() calls and monitors myTask for exceptions and set's the correct
  114. // states for the isBad and isRunning flags.
  115. void Thread::launchTask() { // Launch and watch myTask()
  116. try { // Do this safely.
  117. RunningFlag = true; // Now we are running.
  118. CurrentThreadState(ThreadStarted); // Set the running state.
  119. myTask(); // myTask() is called.
  120. } // myTask() should handle exceptions.
  121. catch(exception& e) { // Unhandled exceptions are informative:
  122. BadFlag = true; // They mean the thread went bad but
  123. BadWhat = e.what(); // we have an idea what went wrong.
  124. } // We shouldn't get other kinds of
  125. catch(...) { // exceptions because if things go
  126. BadFlag = true; // wrong and one gets through this
  127. BadWhat = "Unkown Exception(...)"; // is all we can say about it.
  128. }
  129. RunningFlag = false; // When we're done, we're done.
  130. if(BadFlag) CurrentThreadState(ThreadFailed); // If we're bad we failed.
  131. else CurrentThreadState(ThreadStopped); // If we're not bad we stopped.
  132. }
  133. // getMyThread() returns the local thread primative.
  134. thread_primative Thread::getMyThread() { return MyThread; } // Return my thread primative.
  135. // runThreadTask() is a helper function to start threads. It is the function
  136. // that is acutally launched as a new thread. It's whole job is to call the
  137. // myTask() method on the object passed to it as it is launched.
  138. // The run() method creates a new thread with ThreadRunner() as the main
  139. // function, having passed it's object.
  140. // WIN32 and POSIX have different versions of both the main thread function
  141. // and the way to launch it.
  142. #ifdef WIN32
  143. Thread::Thread() : // When constructing a WIN32 thread
  144. MyThreadType(Thread::Type), // Use generic Thread Type.
  145. MyThreadName("UnNamed Thread"), // Use a generic Thread Name.
  146. MyThread(NULL), // Null the thread handle.
  147. RunningFlag(false), // Couldn't be running yet.
  148. BadFlag(false) { // Couldn't be bad yet.
  149. Threads.rememberThread(this); // Remember this thread.
  150. CurrentThreadState(ThreadInitialized); // Set our initialized state.
  151. }
  152. Thread::Thread(const ThreadType& T, const string N) : // Construct with specific Type/Name
  153. MyThreadType(T), // Use generic Thread Type.
  154. MyThreadName(N), // Use a generic Thread Name.
  155. MyThread(NULL), // Null the thread handle.
  156. RunningFlag(false), // Couldn't be running yet.
  157. BadFlag(false) { // Couldn't be bad yet.
  158. Threads.rememberThread(this); // Remember this thread.
  159. CurrentThreadState(ThreadInitialized); // Set our initialized state.
  160. }
  161. Thread::~Thread() { // In WIN32 land when we destroy the
  162. if(NULL != MyThread) { // thread object check for a valid
  163. CloseHandle(MyThread); // thread handle and destroy it if
  164. } // it exists.
  165. RunningFlag = false; // The thread is not running.
  166. Threads.forgetThread(this); // Forget this thread.
  167. CurrentThreadState(ThreadDestroyed); // The Thread has left the building.
  168. }
  169. unsigned __stdcall runThreadTask(void* thread_object) { // The WIN32 version has this form.
  170. ((Thread*)thread_object)->launchTask(); // Run the task.
  171. _endthreadex(0); // Signal the thread is finished.
  172. return 0; // Satisfy the unsigned return.
  173. }
  174. void Thread::run() { // Run a WIN32 thread...
  175. unsigned tid; // Thread id to toss. Only need Handle.
  176. MyThread = (HANDLE) _beginthreadex(NULL,0,runThreadTask,this,0,&tid); // Create a thread calling ThreadRunner
  177. if(NULL == MyThread) BadFlag = true; // and test that the resutl was valid.
  178. }
  179. void Thread::join() { // To join in WIN32
  180. WaitForSingleObject(MyThread, INFINITE); // Wait for the thread by handle.
  181. }
  182. #else
  183. Thread::Thread() : // POSIX Thread constructor.
  184. MyThreadType(Thread::Type), // Use a generic Thread Type.
  185. MyThreadName("UnNamed Thread"), // Use a generic Thread Name.
  186. RunningFlag(false), // Can't be running yet.
  187. BadFlag(false) { // Can't be bad yet.
  188. Threads.rememberThread(this); // Remember this thread.
  189. CurrentThreadState(ThreadInitialized); // Set our initialized state.
  190. }
  191. Thread::Thread(const ThreadType& T, const string N) : // POSIX Specific Thread Constructor.
  192. MyThreadType(T), // Use a generic Thread Type.
  193. MyThreadName(N), // Use a generic Thread Name.
  194. RunningFlag(false), // Can't be running yet.
  195. BadFlag(false) { // Can't be bad yet.
  196. Threads.rememberThread(this); // Remember this thread.
  197. CurrentThreadState(ThreadInitialized); // Set our initialized state.
  198. }
  199. Thread::~Thread() { // POSIX destructor.
  200. RunningFlag = false; // Not running now for sure.
  201. Threads.forgetThread(this); // Forget this thread.
  202. CurrentThreadState(ThreadDestroyed); // The Thread has left the building.
  203. }
  204. void* runThreadTask(void* thread_object) { // The POSIX version has this form.
  205. ((Thread*)thread_object)->launchTask();
  206. }
  207. void Thread::run() { // Run a POSIX thread...
  208. int result = pthread_create(&MyThread, NULL, runThreadTask, this); // Create a thread calling ThreadRunner
  209. if(0 != result) BadFlag = true; // and test that there was no error.
  210. }
  211. void Thread::join() { // To join in POSIX
  212. pthread_join(MyThread, NULL); // call pthread_join with MyThread.
  213. }
  214. #endif
  215. // End Thread
  216. ////////////////////////////////////////////////////////////////////////////////
  217. ////////////////////////////////////////////////////////////////////////////////
  218. // Mutex
  219. #ifdef WIN32
  220. // WIN32 Mutex Implementation //////////////////////////////////////////////////
  221. // The original design of the WIN32 Mutex used critical sections. However after
  222. // additional research it was determined that the use of a Semaphore with an
  223. // initial count of 1 would work better overall on multiple Winx platforms -
  224. // especially SMP systems.
  225. Mutex::Mutex() : // Creating a WIN32 Mutex means
  226. IAmLocked(false) { // Setting IAmLocked to false and
  227. MyMutex = CreateSemaphore(NULL, 1, 1, NULL); // create a semaphore object with
  228. assert(NULL != MyMutex); // a count of 1.
  229. }
  230. Mutex::~Mutex() { // Destroying a WIN32 Mutex means
  231. assert(false == IAmLocked); // Make sure we're not in use and
  232. CloseHandle(MyMutex); // destroy the semaphore object.
  233. }
  234. bool Mutex::tryLock() { // Trying to lock WIN32 Mutex means
  235. bool DoIHaveIt = false; // Start with a pessimistic assumption
  236. if(
  237. false == IAmLocked && // If we have a shot at this and
  238. WAIT_OBJECT_0 == WaitForSingleObject(MyMutex, 0) // we actually get hold of the semaphore
  239. ) { // then we can set our flags...
  240. IAmLocked = true; // Set IAmLocked, because we are and
  241. DoIHaveIt = true; // set our result to true.
  242. }
  243. return DoIHaveIt; // Return true if we got it (see above).
  244. }
  245. void Mutex::lock() { // Locking the WIN32 Mutex means
  246. assert(WAIT_OBJECT_0 == WaitForSingleObject(MyMutex, INFINITE)); // Wait on the semaphore - only 1 will
  247. IAmLocked = true; // get through or we have a big problem.
  248. }
  249. void Mutex::unlock() { // Unlocking the WIN32 Mutex means
  250. assert(true == IAmLocked); // making sure we're really locked then
  251. IAmLocked = false; // reset the IAmLocked flag and
  252. ReleaseSemaphore(MyMutex, 1, NULL); // release the semaphore.
  253. }
  254. bool Mutex::isLocked() { return IAmLocked; } // Return the IAmLocked flag.
  255. #else
  256. // POSIX Mutex Implementation //////////////////////////////////////////////////
  257. Mutex::Mutex() : // Constructing a POSIX mutex means
  258. IAmLocked(false) { // setting the IAmLocked flag to false and
  259. assert(0 == pthread_mutex_init(&MyMutex,NULL)); // initializing the mutex_t object.
  260. }
  261. Mutex::~Mutex() { // Before we destroy our mutex we check
  262. assert(false == IAmLocked); // to see that it is not locked and
  263. assert(0 == pthread_mutex_destroy(&MyMutex)); // destroy the primative.
  264. }
  265. void Mutex::lock() { // Locking a POSIX mutex means
  266. assert(0 == pthread_mutex_lock(&MyMutex)); // asserting our lock was successful and
  267. IAmLocked = true; // setting the IAmLocked flag.
  268. }
  269. void Mutex::unlock() { // Unlocking a POSIX mutex means
  270. assert(true == IAmLocked); // asserting that we are locked,
  271. IAmLocked = false; // clearing the IAmLocked flag.
  272. assert(0 == pthread_mutex_unlock(&MyMutex)); // asserting our unlock was successful and
  273. }
  274. bool Mutex::tryLock() { // Trying to lock a POSIX mutex means
  275. bool DoIHaveIt = false; // starting off pessimistically.
  276. if(false == IAmLocked) { // If we are not locked yet then we
  277. if(0 == pthread_mutex_trylock(&MyMutex)) { // try to lock the mutex. If we succeed
  278. DoIHaveIt = IAmLocked = true; // we set our IAmLocked flag and our
  279. } // DoIHaveIt flag to true;
  280. }
  281. return DoIHaveIt; // In any case we return the result.
  282. }
  283. bool Mutex::isLocked() { return IAmLocked; } // Return the IAmLocked flag.
  284. #endif
  285. // End Mutex
  286. ////////////////////////////////////////////////////////////////////////////////
  287. ////////////////////////////////////////////////////////////////////////////////
  288. // ScopeMutex
  289. ScopeMutex::ScopeMutex(Mutex& M) : // When constructing a ScopeMutex,
  290. MyMutex(M) { // Initialize MyMutex with what we are given
  291. MyMutex.lock(); // and then immediately lock it.
  292. }
  293. ScopeMutex::~ScopeMutex() { // When a ScopeMutex is destroyed,
  294. MyMutex.unlock(); // it first unlocks it's mutex.
  295. }
  296. // End ScopeMutex
  297. ////////////////////////////////////////////////////////////////////////////////
  298. ////////////////////////////////////////////////////////////////////////////////
  299. // Production Gateway
  300. #ifdef WIN32
  301. // Win32 Implementation ////////////////////////////////////////////////////////
  302. ProductionGateway::ProductionGateway() { // Construct in Windows like this:
  303. const int HUGENUMBER = 0x7fffffL; // Work without any real limits.
  304. MySemaphore = CreateSemaphore(NULL, 0, HUGENUMBER, NULL); // Create a Semaphore for signalling.
  305. assert(NULL != MySemaphore); // That should always work.
  306. }
  307. ProductionGateway::~ProductionGateway() { // Be sure to close it when we're done.
  308. CloseHandle(MySemaphore);
  309. }
  310. void ProductionGateway::produce() { // To produce() in WIN32 we
  311. ReleaseSemaphore(MySemaphore, 1, NULL); // release 1 count into the semaphore.
  312. }
  313. void ProductionGateway::consume() { // To consume() in WIN32 we
  314. WaitForSingleObject(MySemaphore, INFINITE); // wait for a count in the semaphore.
  315. }
  316. #else
  317. // POSIX Implementation ////////////////////////////////////////////////////////
  318. ProductionGateway::ProductionGateway() : // Construct in POSIX like this:
  319. Product(0), // All of our counts start at zero.
  320. Waiting(0),
  321. Signaled(0) {
  322. assert(0 == pthread_mutex_init(&MyMutex, NULL)); // Initialize our mutex.
  323. assert(0 == pthread_cond_init(&MyConditionVariable, NULL)); // Initialize our condition variable.
  324. }
  325. ProductionGateway::~ProductionGateway() { // When we're done we must destroy
  326. assert(0 == pthread_mutex_destroy(&MyMutex)); // our local mutex and
  327. assert(0 == pthread_cond_destroy(&MyConditionVariable)); // our condition variable.
  328. }
  329. void ProductionGateway::produce() { // To produce in POSIX
  330. assert(0 == pthread_mutex_lock(&MyMutex)); // Lock our mutex.
  331. ++Product; // Add an item to our product count.
  332. if(Signaled < Waiting) { // If anybody is waiting that has not
  333. assert(0 == pthread_cond_signal(&MyConditionVariable)); // yet been signaled then signal them
  334. ++Signaled; // and keep track. They will count this
  335. } // down as they awaken.
  336. assert(0 == pthread_mutex_unlock(&MyMutex)); // At the end unlock our mutex so
  337. } // waiting threads can fly free :-)
  338. void ProductionGateway::consume() { // To consume in POSIX
  339. assert(0 == pthread_mutex_lock(&MyMutex)); // Lock our mutex.
  340. while(0 >= Product) { // Until we have something to consume,
  341. ++Waiting; // wait for a signal from
  342. assert(0 == pthread_cond_wait(&MyConditionVariable, &MyMutex)); // our producer. When we have a signal
  343. --Waiting; // we are done waiting and we have
  344. --Signaled; // been signaled. Of course, somebody
  345. } // may have beaten us to it so check.
  346. --Product; // If we have product then take it.
  347. assert(0 == pthread_mutex_unlock(&MyMutex)); // At the end unlock our mutex so
  348. }
  349. #endif
  350. // End Production Gateway
  351. ////////////////////////////////////////////////////////////////////////////////