00001
00031 #include "linden_common.h"
00032 #include "llapr.h"
00033
00034 #include "llthread.h"
00035
00036 #include "lltimer.h"
00037
00038 #if LL_LINUX || LL_SOLARIS
00039 #include <sched.h>
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
00066 {
00067 LLThread *threadp = (LLThread *)datap;
00068
00069
00070 threadp->mStatus = RUNNING;
00071
00072
00073 threadp->run();
00074
00075 llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl;
00076
00077
00078 threadp->mStatus = STOPPED;
00079
00080 return NULL;
00081 }
00082
00083
00084 LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
00085 mPaused(FALSE),
00086 mName(name),
00087 mAPRThreadp(NULL),
00088 mStatus(STOPPED)
00089 {
00090
00091 if (poolp)
00092 {
00093 mIsLocalPool = FALSE;
00094 mAPRPoolp = poolp;
00095 }
00096 else
00097 {
00098 mIsLocalPool = TRUE;
00099 apr_pool_create(&mAPRPoolp, NULL);
00100 }
00101 mRunCondition = new LLCondition(mAPRPoolp);
00102 }
00103
00104
00105 LLThread::~LLThread()
00106 {
00107 shutdown();
00108 }
00109
00110 void LLThread::shutdown()
00111 {
00112
00113
00114 if (mAPRThreadp)
00115 {
00116 if (!isStopped())
00117 {
00118
00119
00120 setQuitting();
00121
00122 llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl;
00123
00124
00125
00126 S32 counter = 0;
00127 const S32 MAX_WAIT = 600;
00128 while (counter < MAX_WAIT)
00129 {
00130 if (isStopped())
00131 {
00132 break;
00133 }
00134
00135 ms_sleep(100);
00136 yield();
00137 counter++;
00138 }
00139 }
00140
00141 if (!isStopped())
00142 {
00143
00144 llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
00145 return;
00146 }
00147 mAPRThreadp = NULL;
00148 }
00149
00150 delete mRunCondition;
00151
00152 if (mIsLocalPool)
00153 {
00154 apr_pool_destroy(mAPRPoolp);
00155 }
00156 }
00157
00158
00159 void LLThread::start()
00160 {
00161 apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
00162
00163
00164 apr_thread_detach(mAPRThreadp);
00165 }
00166
00167
00168
00169
00170
00171
00172 void LLThread::pause()
00173 {
00174 if (!mPaused)
00175 {
00176
00177 mPaused = 1;
00178 }
00179 }
00180
00181 void LLThread::unpause()
00182 {
00183 if (mPaused)
00184 {
00185 mPaused = 0;
00186 }
00187
00188 wake();
00189 }
00190
00191
00192 bool LLThread::runCondition(void)
00193 {
00194
00195 return true;
00196 }
00197
00198
00199
00200
00201 void LLThread::checkPause()
00202 {
00203 mRunCondition->lock();
00204
00205
00206 while(shouldSleep())
00207 {
00208 mRunCondition->wait();
00209
00210 }
00211
00212 mRunCondition->unlock();
00213 }
00214
00215
00216
00217 void LLThread::setQuitting()
00218 {
00219 mRunCondition->lock();
00220 if (mStatus == RUNNING)
00221 {
00222 mStatus = QUITTING;
00223 }
00224 mRunCondition->unlock();
00225 wake();
00226 }
00227
00228
00229
00230 void LLThread::yield()
00231 {
00232 #if LL_LINUX || LL_SOLARIS
00233 sched_yield();
00234 #else
00235 apr_thread_yield();
00236 #endif
00237 }
00238
00239 void LLThread::wake()
00240 {
00241 mRunCondition->lock();
00242 if(!shouldSleep())
00243 {
00244 mRunCondition->signal();
00245 }
00246 mRunCondition->unlock();
00247 }
00248
00249 void LLThread::wakeLocked()
00250 {
00251 if(!shouldSleep())
00252 {
00253 mRunCondition->signal();
00254 }
00255 }
00256
00257
00258
00259 LLMutex::LLMutex(apr_pool_t *poolp) :
00260 mAPRMutexp(NULL)
00261 {
00262 if (poolp)
00263 {
00264 mIsLocalPool = FALSE;
00265 mAPRPoolp = poolp;
00266 }
00267 else
00268 {
00269 mIsLocalPool = TRUE;
00270 apr_pool_create(&mAPRPoolp, NULL);
00271 }
00272 apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
00273 }
00274
00275
00276 LLMutex::~LLMutex()
00277 {
00278 #if _DEBUG
00279 llassert(!isLocked());
00280 #endif
00281 apr_thread_mutex_destroy(mAPRMutexp);
00282 mAPRMutexp = NULL;
00283 if (mIsLocalPool)
00284 {
00285 apr_pool_destroy(mAPRPoolp);
00286 }
00287 }
00288
00289
00290 void LLMutex::lock()
00291 {
00292 apr_thread_mutex_lock(mAPRMutexp);
00293 }
00294
00295 void LLMutex::unlock()
00296 {
00297 apr_thread_mutex_unlock(mAPRMutexp);
00298 }
00299
00300 bool LLMutex::isLocked()
00301 {
00302 apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
00303 if (APR_STATUS_IS_EBUSY(status))
00304 {
00305 return true;
00306 }
00307 else
00308 {
00309 apr_thread_mutex_unlock(mAPRMutexp);
00310 return false;
00311 }
00312 }
00313
00314
00315
00316 LLCondition::LLCondition(apr_pool_t *poolp) :
00317 LLMutex(poolp)
00318 {
00319
00320
00321 apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
00322 }
00323
00324
00325 LLCondition::~LLCondition()
00326 {
00327 apr_thread_cond_destroy(mAPRCondp);
00328 mAPRCondp = NULL;
00329 }
00330
00331
00332 void LLCondition::wait()
00333 {
00334 apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
00335 }
00336
00337 void LLCondition::signal()
00338 {
00339 apr_thread_cond_signal(mAPRCondp);
00340 }
00341
00342 void LLCondition::broadcast()
00343 {
00344 apr_thread_cond_broadcast(mAPRCondp);
00345 }
00346
00347
00348
00349
00350
00351
00352 LLMutex* LLThreadSafeRefCount::sMutex = 0;
00353
00354
00355 void LLThreadSafeRefCount::initClass()
00356 {
00357 if (!sMutex)
00358 {
00359 sMutex = new LLMutex(0);
00360 }
00361 }
00362
00363
00364 void LLThreadSafeRefCount::cleanupClass()
00365 {
00366 delete sMutex;
00367 sMutex = NULL;
00368 }
00369
00370
00371
00372
00373 LLThreadSafeRefCount::LLThreadSafeRefCount() :
00374 mRef(0)
00375 {
00376 }
00377
00378 LLThreadSafeRefCount::~LLThreadSafeRefCount()
00379 {
00380 if (mRef != 0)
00381 {
00382 llerrs << "deleting non-zero reference" << llendl;
00383 }
00384 }
00385
00386
00387
00388 LLResponder::~LLResponder()
00389 {
00390 }
00391
00392