00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <winstd.H>
00028 #include <BoxLib.H>
00029 #include <Thread.H>
00030
00031 #ifdef WIN32
00032 #define _WIN32_WINNT 0x0400
00033 #include <windows.h>
00034 #else
00035 #include <unistd.h>
00036 #include <sys/resource.h>
00037 #include <sys/time.h>
00038 #endif
00039
00040 #include <iostream>
00041 #include <limits>
00042
00043 #if defined(BL_OLD_STL)
00044 #include <stdio.h>
00045 #include <time.h>
00046 #include <errno.h>
00047 #include <stdlib.h>
00048 #else
00049 #include <cstdio>
00050 #include <ctime>
00051 #include <cerrno>
00052 #include <cstdlib>
00053 #endif
00054
00055
00056
00057
00058
00059 namespace
00060 {
00061 const char*
00062 the_message_string(const char* file, int line, const char* call, int status = 0)
00063 {
00064
00065
00066
00067 const int DIM = 1024;
00068 static char buf[DIM];
00069 if ( status )
00070 {
00071 std::sprintf(buf, "BoxLib Thread Error: File %s, line %d, %s: %s",
00072 file, line, call, std::strerror(status));
00073 }
00074 else
00075 {
00076 std::sprintf(buf, "BoxLib Thread Error: File %s, line %d, %s",
00077 file, line, call);
00078 }
00079 buf[DIM-1] = '\0';
00080 return buf;
00081 }
00082
00083 }
00084
00085 namespace BoxLib
00086 {
00087 void
00088 Thread_Error(const char* file, int line, const char* call, int status = 0)
00089 {
00090 Error(the_message_string(file, line, call,status));
00091 }
00092
00093 }
00094
00095 #define THREAD_REQUIRE(x) \
00096 do \
00097 { \
00098 if ( int status = (x) ) \
00099 { \
00100 BoxLib::Thread_Error(__FILE__, __LINE__, #x, status); \
00101 } \
00102 } \
00103 while ( false )
00104
00105 #define THREAD_ASSERT(x) \
00106 do \
00107 { \
00108 if ( !(x) ) \
00109 { \
00110 BoxLib::Thread_Error(__FILE__,__LINE__,#x ); \
00111 } \
00112 } \
00113 while ( false )
00114
00115 void
00116 Thread::sleep(const BoxLib::Time& spec_)
00117 {
00118 #ifdef WIN32
00119 #else
00120 ::sleep(spec_.as_long());
00121 #endif
00122 }
00123
00124
00125
00126
00127
00128
00129 Barrier::Barrier(int i)
00130 : count(0), n_sleepers(0), releasing(false)
00131 {
00132 init(i);
00133 }
00134
00135 void
00136 Barrier::init(int i)
00137 {
00138 THREAD_ASSERT( !releasing );
00139 THREAD_ASSERT( n_sleepers == 0 );
00140 count = i;
00141 }
00142
00143 void
00144 Barrier::wait()
00145 {
00146 bool release = false;
00147 lock();
00148
00149
00150 while ( releasing )
00151 {
00152 ConditionVariable::wait();
00153 }
00154 if ( ++n_sleepers == count )
00155 {
00156 release = releasing = true;
00157 }
00158 else
00159 {
00160
00161 Thread::CancelState tmp = Thread::setCancelState(Thread::Disable);
00162 while ( !releasing )
00163 {
00164 ConditionVariable::wait();
00165 }
00166 Thread::setCancelState(tmp);
00167 }
00168 if ( --n_sleepers == 0 )
00169 {
00170 releasing = false;
00171 release = true;
00172 }
00173 unlock();
00174 if ( release )
00175 {
00176 broadcast();
00177 }
00178 }
00179
00180
00181
00182
00183
00184
00185 Semaphore::Semaphore(int val_)
00186 : value(val_)
00187 {
00188 }
00189
00190 void
00191 Semaphore::wait()
00192 {
00193 lock();
00194 while ( value == 0 )
00195 {
00196 ConditionVariable::wait();
00197 }
00198 value--;
00199 unlock();
00200 }
00201
00202 bool
00203 Semaphore::trywait()
00204 {
00205 lock();
00206 if ( value == 0 )
00207 {
00208 unlock();
00209 return false;
00210 }
00211 value--;
00212 unlock();
00213 return true;
00214 }
00215
00216 void
00217 Semaphore::post()
00218 {
00219 lock();
00220 value++;
00221 unlock();
00222 signal();
00223 }
00224
00225
00226
00227
00228
00229
00230 SemaphoreB::SemaphoreB(int val_)
00231 : val(val_)
00232 {}
00233
00234 int
00235 SemaphoreB::down()
00236 {
00237 lock();
00238 while (val <= 0)
00239 {
00240 wait();
00241 }
00242 int t = --val;
00243 unlock();
00244
00245 return t;
00246 }
00247
00248 int
00249 SemaphoreB::up()
00250 {
00251 lock();
00252 int t = ++val;
00253 unlock();
00254 signal();
00255 return t;
00256 }
00257
00258 int
00259 SemaphoreB::decrement()
00260 {
00261 lock();
00262 int t = --val;
00263 unlock();
00264 return t;
00265 }
00266
00267 int
00268 SemaphoreB::value()
00269 {
00270 lock();
00271 int t = val;
00272 unlock();
00273 return t;
00274 }
00275
00276
00277
00278
00279
00280 SingleBarrier::SingleBarrier(int i)
00281 : count(i), n_posters(0), n_waiters(0), releasing(false)
00282 {
00283 }
00284
00285 void
00286 SingleBarrier::wait()
00287 {
00288 bool release = false;
00289 lock();
00290 n_waiters++;
00291 while ( !releasing )
00292 {
00293 ConditionVariable::wait();
00294 }
00295 if ( --n_waiters == 0 )
00296 {
00297 releasing = false;
00298 release = true;
00299 n_posters=0;
00300 }
00301 unlock();
00302 if ( release )
00303 {
00304 broadcast();
00305 }
00306 }
00307
00308 void
00309 SingleBarrier::post()
00310 {
00311 bool release = false;
00312 lock();
00313
00314 while ( releasing )
00315 {
00316 ConditionVariable::wait();
00317 }
00318 if ( ++n_posters == count )
00319 {
00320 releasing = true;
00321 release = true;
00322 }
00323 unlock();
00324 if ( release )
00325 {
00326 broadcast();
00327 }
00328 }
00329
00330
00331
00332
00333
00334
00335 Gate::Gate()
00336 : closed(true)
00337 {
00338 }
00339
00340 void
00341 Gate::open()
00342 {
00343 lock();
00344 closed = false;
00345 broadcast();
00346 unlock();
00347 }
00348
00349 void
00350 Gate::close()
00351 {
00352 lock();
00353 closed = true;
00354 unlock();
00355 }
00356
00357 void
00358 Gate::release()
00359 {
00360 broadcast();
00361 }
00362
00363 void
00364 Gate::wait()
00365 {
00366 lock();
00367 while ( closed )
00368 {
00369 ConditionVariable::wait();
00370 }
00371 unlock();
00372 }
00373
00374
00375
00376
00377
00378
00379 Lock<Semaphore>::Lock(Semaphore& sem_)
00380 : sem(sem_)
00381 {
00382 sem.wait();
00383 }
00384
00385 Lock<Semaphore>::~Lock()
00386 {
00387 sem.post();
00388 }
00389
00390 void
00391 Thread::exit(void*)
00392 {
00393 std::exit(0);
00394 }
00395
00396 Thread::CancelState
00397 Thread::setCancelState(CancelState)
00398 {
00399 return Enable;
00400 }
00401
00402
00403
00404
00405
00406
00407 class ThreadSpecificData<void>::Implementation
00408 {
00409 public:
00410 Implementation(void (*tsd_)(void*));
00411 ~Implementation();
00412 void* set(const void* v_);
00413 void* get() const;
00414 void* v;
00415 void (*tsd)(void*);
00416 };
00417
00418 ThreadSpecificData<void>::Implementation::Implementation(void (*tsd_)(void*))
00419 : v(0), tsd(tsd_)
00420 {
00421 }
00422
00423 ThreadSpecificData<void>::Implementation::~Implementation()
00424 {
00425 }
00426
00427 void*
00428 ThreadSpecificData<void>::Implementation::set(const void* v_)
00429 {
00430 return v = const_cast<void*>(v_);
00431 }
00432
00433 void*
00434 ThreadSpecificData<void>::Implementation::get() const
00435 {
00436 return v;
00437 }
00438
00439
00440 ThreadSpecificData<void>::ThreadSpecificData(void (*tsd_)(void*))
00441 {
00442 m_impl = new Implementation(tsd_);
00443 }
00444
00445 ThreadSpecificData<void>::~ThreadSpecificData()
00446 {
00447 delete m_impl;
00448 }
00449
00450 void*
00451 ThreadSpecificData<void>::set(const void* v_)
00452 {
00453 return m_impl->set(v_);
00454 }
00455
00456 void*
00457 ThreadSpecificData<void>::get() const
00458 {
00459 return m_impl->get();
00460 }
00461
00462
00463 FunctionThread::FunctionThread(Thread_Function func, void* arg_, DetachState st, int stacksize)
00464 {
00465 func(arg_);
00466 }
00467
00468 FunctionThread::~FunctionThread()
00469 {
00470 detach();
00471 }
00472
00473 void*
00474 FunctionThread::join() const
00475 {
00476 return 0;
00477 }
00478
00479 void
00480 FunctionThread::detach() const
00481 {
00482 }
00483