PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcommon/llthread.h

https://bitbucket.org/lindenlab/viewer-beta/
C Header | 283 lines | 170 code | 58 blank | 55 comment | 16 complexity | 8e083e735df34af28bdc9e29341c1a10 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llthread.h
  3. * @brief Base classes for thread, mutex and condition handling.
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LL_LLTHREAD_H
  27. #define LL_LLTHREAD_H
  28. #include "llapp.h"
  29. #include "llapr.h"
  30. #include "apr_thread_cond.h"
  31. class LLThread;
  32. class LLMutex;
  33. class LLCondition;
  34. #if LL_WINDOWS
  35. #define ll_thread_local __declspec(thread)
  36. #else
  37. #define ll_thread_local __thread
  38. #endif
  39. class LL_COMMON_API LLThread
  40. {
  41. private:
  42. static U32 sIDIter;
  43. public:
  44. typedef enum e_thread_status
  45. {
  46. STOPPED = 0, // The thread is not running. Not started, or has exited its run function
  47. RUNNING = 1, // The thread is currently running
  48. QUITTING= 2 // Someone wants this thread to quit
  49. } EThreadStatus;
  50. LLThread(const std::string& name, apr_pool_t *poolp = NULL);
  51. virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
  52. virtual void shutdown(); // stops the thread
  53. bool isQuitting() const { return (QUITTING == mStatus); }
  54. bool isStopped() const { return (STOPPED == mStatus); }
  55. static U32 currentID(); // Return ID of current thread
  56. static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
  57. public:
  58. // PAUSE / RESUME functionality. See source code for important usage notes.
  59. // Called from MAIN THREAD.
  60. void pause();
  61. void unpause();
  62. bool isPaused() { return isStopped() || mPaused == TRUE; }
  63. // Cause the thread to wake up and check its condition
  64. void wake();
  65. // Same as above, but to be used when the condition is already locked.
  66. void wakeLocked();
  67. // Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
  68. void checkPause();
  69. // this kicks off the apr thread
  70. void start(void);
  71. apr_pool_t *getAPRPool() { return mAPRPoolp; }
  72. LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
  73. U32 getID() const { return mID; }
  74. private:
  75. BOOL mPaused;
  76. // static function passed to APR thread creation routine
  77. static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
  78. protected:
  79. std::string mName;
  80. LLCondition* mRunCondition;
  81. apr_thread_t *mAPRThreadp;
  82. apr_pool_t *mAPRPoolp;
  83. BOOL mIsLocalPool;
  84. EThreadStatus mStatus;
  85. U32 mID;
  86. //a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
  87. //Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
  88. // otherwise it will cause severe memory leaking!!! --bao
  89. LLVolatileAPRPool *mLocalAPRFilePoolp ;
  90. void setQuitting();
  91. // virtual function overridden by subclass -- this will be called when the thread runs
  92. virtual void run(void) = 0;
  93. // virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
  94. virtual bool runCondition(void);
  95. // Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
  96. inline void lockData();
  97. inline void unlockData();
  98. // This is the predicate that decides whether the thread should sleep.
  99. // It should only be called with mRunCondition locked, since the virtual runCondition() function may need to access
  100. // data structures that are thread-unsafe.
  101. bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
  102. // To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
  103. // mRunCondition->lock();
  104. // if(!shouldSleep())
  105. // mRunCondition->signal();
  106. // mRunCondition->unlock();
  107. };
  108. //============================================================================
  109. #define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
  110. class LL_COMMON_API LLMutex
  111. {
  112. public:
  113. typedef enum
  114. {
  115. NO_THREAD = 0xFFFFFFFF
  116. } e_locking_thread;
  117. LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
  118. virtual ~LLMutex();
  119. void lock(); // blocks
  120. void unlock();
  121. bool isLocked(); // non-blocking, but does do a lock/unlock so not free
  122. bool isSelfLocked(); //return true if locked in a same thread
  123. U32 lockingThread() const; //get ID of locking thread
  124. protected:
  125. apr_thread_mutex_t *mAPRMutexp;
  126. mutable U32 mCount;
  127. mutable U32 mLockingThread;
  128. apr_pool_t *mAPRPoolp;
  129. BOOL mIsLocalPool;
  130. #if MUTEX_DEBUG
  131. std::map<U32, BOOL> mIsLocked;
  132. #endif
  133. };
  134. // Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
  135. class LL_COMMON_API LLCondition : public LLMutex
  136. {
  137. public:
  138. LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
  139. ~LLCondition();
  140. void wait(); // blocks
  141. void signal();
  142. void broadcast();
  143. protected:
  144. apr_thread_cond_t *mAPRCondp;
  145. };
  146. class LLMutexLock
  147. {
  148. public:
  149. LLMutexLock(LLMutex* mutex)
  150. {
  151. mMutex = mutex;
  152. if(mMutex)
  153. mMutex->lock();
  154. }
  155. ~LLMutexLock()
  156. {
  157. if(mMutex)
  158. mMutex->unlock();
  159. }
  160. private:
  161. LLMutex* mMutex;
  162. };
  163. //============================================================================
  164. void LLThread::lockData()
  165. {
  166. mRunCondition->lock();
  167. }
  168. void LLThread::unlockData()
  169. {
  170. mRunCondition->unlock();
  171. }
  172. //============================================================================
  173. // see llmemory.h for LLPointer<> definition
  174. class LL_COMMON_API LLThreadSafeRefCount
  175. {
  176. public:
  177. static void initThreadSafeRefCount(); // creates sMutex
  178. static void cleanupThreadSafeRefCount(); // destroys sMutex
  179. private:
  180. static LLMutex* sMutex;
  181. private:
  182. LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
  183. LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
  184. protected:
  185. virtual ~LLThreadSafeRefCount(); // use unref()
  186. public:
  187. LLThreadSafeRefCount();
  188. void ref()
  189. {
  190. if (sMutex) sMutex->lock();
  191. mRef++;
  192. if (sMutex) sMutex->unlock();
  193. }
  194. S32 unref()
  195. {
  196. llassert(mRef >= 1);
  197. if (sMutex) sMutex->lock();
  198. S32 res = --mRef;
  199. if (sMutex) sMutex->unlock();
  200. if (0 == res)
  201. {
  202. delete this;
  203. return 0;
  204. }
  205. return res;
  206. }
  207. S32 getNumRefs() const
  208. {
  209. return mRef;
  210. }
  211. private:
  212. S32 mRef;
  213. };
  214. //============================================================================
  215. // Simple responder for self destructing callbacks
  216. // Pure virtual class
  217. class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
  218. {
  219. protected:
  220. virtual ~LLResponder();
  221. public:
  222. virtual void completed(bool success) = 0;
  223. };
  224. //============================================================================
  225. #endif // LL_LLTHREAD_H