llthread.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llthread.cpp
  3.  *
  4.  * $LicenseInfo:firstyear=2004&license=viewergpl$
  5.  * 
  6.  * Copyright (c) 2004-2010, Linden Research, Inc.
  7.  * 
  8.  * Second Life Viewer Source Code
  9.  * The source code in this file ("Source Code") is provided by Linden Lab
  10.  * to you under the terms of the GNU General Public License, version 2.0
  11.  * ("GPL"), unless you have obtained a separate licensing agreement
  12.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  13.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15.  * 
  16.  * There are special exceptions to the terms and conditions of the GPL as
  17.  * it is applied to this Source Code. View the full text of the exception
  18.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  19.  * online at
  20.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21.  * 
  22.  * By copying, modifying or distributing this software, you acknowledge
  23.  * that you have read and understood your obligations described above,
  24.  * and agree to abide by those obligations.
  25.  * 
  26.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28.  * COMPLETENESS OR PERFORMANCE.
  29.  * $/LicenseInfo$
  30.  */
  31. #include "linden_common.h"
  32. #include "llapr.h"
  33. #include "apr_portable.h"
  34. #include "llthread.h"
  35. #include "lltimer.h"
  36. #if LL_LINUX || LL_SOLARIS
  37. #include <sched.h>
  38. #endif
  39. //----------------------------------------------------------------------------
  40. // Usage:
  41. // void run_func(LLThread* thread)
  42. // {
  43. // }
  44. // LLThread* thread = new LLThread();
  45. // thread->run(run_func);
  46. // ...
  47. // thread->setQuitting();
  48. // while(!timeout)
  49. // {
  50. //   if (thread->isStopped())
  51. //   {
  52. //     delete thread;
  53. //     break;
  54. //   }
  55. // }
  56. // 
  57. //----------------------------------------------------------------------------
  58. //
  59. // Handed to the APR thread creation function
  60. //
  61. void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
  62. {
  63. LLThread *threadp = (LLThread *)datap;
  64. // Set thread state to running
  65. threadp->mStatus = RUNNING;
  66. // Run the user supplied function
  67. threadp->run();
  68. llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl;
  69. // We're done with the run function, this thread is done executing now.
  70. threadp->mStatus = STOPPED;
  71. return NULL;
  72. }
  73. LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
  74. mPaused(FALSE),
  75. mName(name),
  76. mAPRThreadp(NULL),
  77. mStatus(STOPPED)
  78. {
  79. // Thread creation probably CAN be paranoid about APR being initialized, if necessary
  80. if (poolp)
  81. {
  82. mIsLocalPool = FALSE;
  83. mAPRPoolp = poolp;
  84. }
  85. else
  86. {
  87. mIsLocalPool = TRUE;
  88. apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
  89. }
  90. mRunCondition = new LLCondition(mAPRPoolp);
  91. mLocalAPRFilePoolp = NULL ;
  92. }
  93. LLThread::~LLThread()
  94. {
  95. shutdown();
  96. if(mLocalAPRFilePoolp)
  97. {
  98. delete mLocalAPRFilePoolp ;
  99. mLocalAPRFilePoolp = NULL ;
  100. }
  101. }
  102. void LLThread::shutdown()
  103. {
  104. // Warning!  If you somehow call the thread destructor from itself,
  105. // the thread will die in an unclean fashion!
  106. if (mAPRThreadp)
  107. {
  108. if (!isStopped())
  109. {
  110. // The thread isn't already stopped
  111. // First, set the flag that indicates that we're ready to die
  112. setQuitting();
  113. llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl;
  114. // Now wait a bit for the thread to exit
  115. // It's unclear whether I should even bother doing this - this destructor
  116. // should netver get called unless we're already stopped, really...
  117. S32 counter = 0;
  118. const S32 MAX_WAIT = 600;
  119. while (counter < MAX_WAIT)
  120. {
  121. if (isStopped())
  122. {
  123. break;
  124. }
  125. // Sleep for a tenth of a second
  126. ms_sleep(100);
  127. yield();
  128. counter++;
  129. }
  130. }
  131. if (!isStopped())
  132. {
  133. // This thread just wouldn't stop, even though we gave it time
  134. llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
  135. return;
  136. }
  137. mAPRThreadp = NULL;
  138. }
  139. delete mRunCondition;
  140. if (mIsLocalPool)
  141. {
  142. apr_pool_destroy(mAPRPoolp);
  143. }
  144. }
  145. void LLThread::start()
  146. {
  147. apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
  148. // We won't bother joining
  149. apr_thread_detach(mAPRThreadp);
  150. }
  151. //============================================================================
  152. // Called from MAIN THREAD.
  153. // Request that the thread pause/resume.
  154. // The thread will pause when (and if) it calls checkPause()
  155. void LLThread::pause()
  156. {
  157. if (!mPaused)
  158. {
  159. // this will cause the thread to stop execution as soon as checkPause() is called
  160. mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread
  161. }
  162. }
  163. void LLThread::unpause()
  164. {
  165. if (mPaused)
  166. {
  167. mPaused = 0;
  168. }
  169. wake(); // wake up the thread if necessary
  170. }
  171. // virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
  172. bool LLThread::runCondition(void)
  173. {
  174. // by default, always run.  Handling of pause/unpause is done regardless of this function's result.
  175. return true;
  176. }
  177. //============================================================================
  178. // Called from run() (CHILD THREAD).
  179. // Stop thread execution if requested until unpaused.
  180. void LLThread::checkPause()
  181. {
  182. mRunCondition->lock();
  183. // This is in a while loop because the pthread API allows for spurious wakeups.
  184. while(shouldSleep())
  185. {
  186. mRunCondition->wait(); // unlocks mRunCondition
  187. // mRunCondition is locked when the thread wakes up
  188. }
  189.   mRunCondition->unlock();
  190. }
  191. //============================================================================
  192. void LLThread::setQuitting()
  193. {
  194. mRunCondition->lock();
  195. if (mStatus == RUNNING)
  196. {
  197. mStatus = QUITTING;
  198. }
  199. mRunCondition->unlock();
  200. wake();
  201. }
  202. // static
  203. U32 LLThread::currentID()
  204. {
  205. return (U32)apr_os_thread_current();
  206. }
  207. // static
  208. void LLThread::yield()
  209. {
  210. #if LL_LINUX || LL_SOLARIS
  211. sched_yield(); // annoyingly, apr_thread_yield  is a noop on linux...
  212. #else
  213. apr_thread_yield();
  214. #endif
  215. }
  216. void LLThread::wake()
  217. {
  218. mRunCondition->lock();
  219. if(!shouldSleep())
  220. {
  221. mRunCondition->signal();
  222. }
  223. mRunCondition->unlock();
  224. }
  225. void LLThread::wakeLocked()
  226. {
  227. if(!shouldSleep())
  228. {
  229. mRunCondition->signal();
  230. }
  231. }
  232. //============================================================================
  233. LLMutex::LLMutex(apr_pool_t *poolp) :
  234. mAPRMutexp(NULL)
  235. {
  236. //if (poolp)
  237. //{
  238. // mIsLocalPool = FALSE;
  239. // mAPRPoolp = poolp;
  240. //}
  241. //else
  242. {
  243. mIsLocalPool = TRUE;
  244. apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
  245. }
  246. apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
  247. }
  248. LLMutex::~LLMutex()
  249. {
  250. #if MUTEX_DEBUG
  251. llassert_always(!isLocked()); // better not be locked!
  252. #endif
  253. apr_thread_mutex_destroy(mAPRMutexp);
  254. mAPRMutexp = NULL;
  255. if (mIsLocalPool)
  256. {
  257. apr_pool_destroy(mAPRPoolp);
  258. }
  259. }
  260. void LLMutex::lock()
  261. {
  262. apr_thread_mutex_lock(mAPRMutexp);
  263. #if MUTEX_DEBUG
  264. // Have to have the lock before we can access the debug info
  265. U32 id = LLThread::currentID();
  266. if (mIsLocked[id] != FALSE)
  267. llerrs << "Already locked in Thread: " << id << llendl;
  268. mIsLocked[id] = TRUE;
  269. #endif
  270. }
  271. void LLMutex::unlock()
  272. {
  273. #if MUTEX_DEBUG
  274. // Access the debug info while we have the lock
  275. U32 id = LLThread::currentID();
  276. if (mIsLocked[id] != TRUE)
  277. llerrs << "Not locked in Thread: " << id << llendl;
  278. mIsLocked[id] = FALSE;
  279. #endif
  280. apr_thread_mutex_unlock(mAPRMutexp);
  281. }
  282. bool LLMutex::isLocked()
  283. {
  284. apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
  285. if (APR_STATUS_IS_EBUSY(status))
  286. {
  287. return true;
  288. }
  289. else
  290. {
  291. apr_thread_mutex_unlock(mAPRMutexp);
  292. return false;
  293. }
  294. }
  295. //============================================================================
  296. LLCondition::LLCondition(apr_pool_t *poolp) :
  297. LLMutex(poolp)
  298. {
  299. // base class (LLMutex) has already ensured that mAPRPoolp is set up.
  300. apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
  301. }
  302. LLCondition::~LLCondition()
  303. {
  304. apr_thread_cond_destroy(mAPRCondp);
  305. mAPRCondp = NULL;
  306. }
  307. void LLCondition::wait()
  308. {
  309. apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
  310. }
  311. void LLCondition::signal()
  312. {
  313. apr_thread_cond_signal(mAPRCondp);
  314. }
  315. void LLCondition::broadcast()
  316. {
  317. apr_thread_cond_broadcast(mAPRCondp);
  318. }
  319. //============================================================================
  320. //----------------------------------------------------------------------------
  321. //static
  322. LLMutex* LLThreadSafeRefCount::sMutex = 0;
  323. //static
  324. void LLThreadSafeRefCount::initThreadSafeRefCount()
  325. {
  326. if (!sMutex)
  327. {
  328. sMutex = new LLMutex(0);
  329. }
  330. }
  331. //static
  332. void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
  333. {
  334. delete sMutex;
  335. sMutex = NULL;
  336. }
  337. //----------------------------------------------------------------------------
  338. LLThreadSafeRefCount::LLThreadSafeRefCount() :
  339. mRef(0)
  340. {
  341. }
  342. LLThreadSafeRefCount::~LLThreadSafeRefCount()
  343. if (mRef != 0)
  344. {
  345. llerrs << "deleting non-zero reference" << llendl;
  346. }
  347. }
  348. //============================================================================
  349. LLResponder::~LLResponder()
  350. {
  351. }
  352. //============================================================================