Main Page | Class Hierarchy | Class List | File List | Class Members

sync.h

00001 //-< SYNC.H >--------------------------------------------------------*--------*
00002 // GigaBASE                  Version 1.0         (c) 1999  GARRET    *     ?  *
00003 // (Post Relational Database Management System)                      *   /\|  *
00004 //                                                                   *  /  \  *
00005 //                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
00006 //                          Last update:  8-Feb-99    K.A. Knizhnik  * GARRET *
00007 //-------------------------------------------------------------------*--------*
00008 // Intertask synchonization primitives
00009 //-------------------------------------------------------------------*--------*
00010 
00011 #ifndef __SYNC_H__
00012 #define __SYNC_H__
00013 
00014 
00015 BEGIN_GIGABASE_NAMESPACE
00016 
00017 #if defined(_WIN32)
00018 class GIGABASE_DLL_ENTRY dbMutex {
00019     CRITICAL_SECTION     cs;
00020     bool                 initialized;
00021   public:
00022     dbMutex() {
00023         InitializeCriticalSection(&cs);
00024         initialized = true;
00025     }
00026     ~dbMutex() {
00027         DeleteCriticalSection(&cs);
00028         initialized = false;
00029     }
00030     bool isInitialized() { 
00031         return initialized;
00032     }
00033     void lock() {
00034         if (initialized) { 
00035             EnterCriticalSection(&cs);
00036         }
00037     }
00038     void unlock() {
00039         if (initialized) { 
00040             LeaveCriticalSection(&cs);
00041         }
00042     }
00043 };
00044 
00045 #define thread_proc WINAPI
00046 
00047 class GIGABASE_DLL_ENTRY dbThread {
00048     HANDLE h;
00049   public:
00050     enum ThreadPriority { 
00051         THR_PRI_LOW, 
00052         THR_PRI_HIGH
00053     };
00054 
00055     void setPriority(ThreadPriority pri) { 
00056         SetThreadPriority(h, pri == THR_PRI_LOW ? THREAD_PRIORITY_IDLE : THREAD_PRIORITY_HIGHEST);
00057     }
00058 
00059     typedef void (thread_proc* thread_proc_t)(void*);
00060 
00061     void create(thread_proc_t f, void* arg) {
00062         DWORD threadid;
00063         h = CreateThread(NULL, 0, LPTHREAD_START_ROUTINE(f), arg, 0, &threadid);
00064     }
00065     void join() {
00066         WaitForSingleObject(h, INFINITE);
00067         CloseHandle(h);
00068         h = NULL;
00069     }
00070     void detach() {
00071         if (h != NULL) {
00072             CloseHandle(h);
00073             h = NULL;
00074         }
00075     }
00076     dbThread() {
00077         h = NULL;
00078     }
00079     ~dbThread() {
00080         if (h != NULL) {
00081             CloseHandle(h);
00082         }
00083     }
00084     static int numberOfProcessors() {
00085         SYSTEM_INFO sysinfo;
00086         GetSystemInfo(&sysinfo);
00087         return sysinfo.dwNumberOfProcessors;
00088     }
00089 };
00090 
00091 const int dbMaxSemValue = 1000000;
00092 
00093 
00094 class GIGABASE_DLL_ENTRY dbSemaphore {
00095     HANDLE s;
00096   public:
00097     void wait(dbMutex& mutex, time_t timeout = INFINITE) {
00098         mutex.unlock();
00099         int rc = WaitForSingleObject(s, (DWORD)(timeout == (time_t)INFINITE ? timeout : timeout*1000));
00100         assert(rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT);
00101         mutex.lock();
00102     }
00103     void signal(unsigned inc = 1) {
00104         if (inc != 0) {
00105             ReleaseSemaphore(s, inc, NULL);
00106         }
00107     }
00108     void open(unsigned initValue = 0) {
00109         s = CreateSemaphore(NULL, initValue, dbMaxSemValue, NULL);
00110         assert(s != NULL);
00111     }
00112     void close() {
00113         CloseHandle(s);
00114     } 
00115     dbSemaphore() { 
00116         s = NULL;
00117     }
00118 };
00119 
00120 class GIGABASE_DLL_ENTRY dbEvent {
00121     HANDLE e;
00122     int    nWaitingThreads;
00123     int    nPulses;
00124   public:
00125     void wait(dbMutex& mutex, time_t timeout = INFINITE) {
00126         nWaitingThreads += 1;
00127         mutex.unlock();
00128         int rc = WaitForSingleObject(e, (DWORD)(timeout == (time_t)INFINITE ? timeout : timeout*1000));
00129         assert(rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT);
00130         mutex.lock();
00131         nWaitingThreads -= 1;
00132         if (nPulses > 0) { 
00133             nPulses -= 1;
00134             ResetEvent(e);
00135         }
00136     }
00137     void signal() {
00138         SetEvent(e);
00139     }
00140     void reset() {
00141         ResetEvent(e);
00142     }
00143     void pulse() { 
00144         if (nWaitingThreads > 0) { 
00145             nPulses += 1;
00146             SetEvent(e);
00147         }
00148     }    
00149     void open(bool initValue = false) {
00150         e = CreateEvent(NULL, true, initValue, NULL);
00151         nWaitingThreads = 0;
00152         nPulses = 0;
00153     }
00154     void close() {
00155         CloseHandle(e);
00156     }
00157     dbEvent() { 
00158         e = NULL;
00159     }
00160 };
00161 
00162 template<class T>
00163 class dbThreadContext {
00164     int index;
00165   public:
00166     T* get() {
00167         return (T*)TlsGetValue(index);
00168     }
00169     void set(T* value) {
00170         TlsSetValue(index, value);
00171     }
00172     dbThreadContext() {
00173         index = TlsAlloc();
00174         assert(index != (int)TLS_OUT_OF_INDEXES);
00175     }
00176     ~dbThreadContext() {
00177         TlsFree(index);
00178     }
00179 };
00180 
00181 #else // Unix
00182 
00183 #define thread_proc
00184 
00185 #ifndef NO_PTHREADS
00186 
00187 END_GIGABASE_NAMESPACE
00188 
00189 #include <unistd.h>
00190 #include <sys/time.h>
00191 #include <pthread.h>
00192 
00193 BEGIN_GIGABASE_NAMESPACE
00194 
00195 class dbMutex {
00196     friend class dbEvent;
00197     friend class dbSemaphore;
00198     pthread_mutex_t cs;
00199     bool            initialized;
00200   public:
00201     dbMutex() {
00202         pthread_mutex_init(&cs, NULL);
00203         initialized = true;
00204     }
00205     ~dbMutex() {
00206         pthread_mutex_destroy(&cs);
00207         initialized = false;
00208     }
00209     bool isInitialized() { 
00210         return initialized;
00211     }
00212     void lock() {
00213         if (initialized) { 
00214             pthread_mutex_lock(&cs);
00215         }
00216     }
00217     void unlock() {
00218         if (initialized) { 
00219             pthread_mutex_unlock(&cs);
00220         }
00221     }
00222 };
00223 
00224 
00225 const size_t dbThreadStackSize = 1024*1024;
00226 
00227 class dbThread {
00228     pthread_t thread;
00229   public:
00230     typedef void (thread_proc* thread_proc_t)(void*);
00231 
00232     void create(thread_proc_t f, void* arg) {
00233         pthread_attr_t attr;
00234         pthread_attr_init(&attr);
00235 #if !defined(__linux__)
00236         pthread_attr_setstacksize(&attr, dbThreadStackSize);
00237 #endif
00238 #if defined(_AIX41)
00239         // At AIX 4.1, 4.2 threads are by default created detached
00240         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED);
00241 #endif
00242         pthread_create(&thread, &attr, (void*(*)(void*))f, arg);
00243         pthread_attr_destroy(&attr);
00244     }
00245 
00246     enum ThreadPriority { 
00247         THR_PRI_LOW, 
00248         THR_PRI_HIGH
00249     };
00250 #if defined(PRI_OTHER_MIN) && defined(PRI_OTHER_MAX)
00251     void setPriority(ThreadPriority pri) { 
00252         struct sched_param sp;
00253         sp.sched_priority = pri == THR_PRI_LOW ? PRI_OTHER_MIN : PRI_OTHER_MAX;
00254         pthread_setschedparam(thread, SCHED_OTHER, &sp); 
00255     }
00256 #else
00257     void setPriority(ThreadPriority) {}
00258 #endif
00259 
00260 
00261 
00262     void join() {
00263         void* result;
00264         pthread_join(thread, &result);
00265     }
00266     void detach() {
00267         pthread_detach(thread);
00268     }
00269     static int numberOfProcessors();
00270 };
00271 
00272 #if defined(_SC_NPROCESSORS_ONLN)
00273 inline int dbThread::numberOfProcessors() {
00274     return sysconf(_SC_NPROCESSORS_ONLN);
00275 }
00276 #elif defined(__linux__)
00277 END_GIGABASE_NAMESPACE
00278 #include <linux/smp.h>
00279 BEGIN_GIGABASE_NAMESPACE
00280 inline int dbThread::numberOfProcessors() { return smp_num_cpus; }
00281 #elif defined(__FreeBSD__) || defined(__bsdi__) || defined(__OpenBSD__)
00282 #if defined(__bsdi__) || defined(__OpenBSD__)
00283 END_GIGABASE_NAMESPACE
00284 #include <sys/param.h>
00285 BEGIN_GIGABASE_NAMESPACE
00286 #endif
00287 END_GIGABASE_NAMESPACE
00288 #include <sys/sysctl.h>
00289 BEGIN_GIGABASE_NAMESPACE
00290 inline int dbThread::numberOfProcessors() {
00291     int mib[2],ncpus=0;
00292     size_t len=sizeof(ncpus);
00293     mib[0]= CTL_HW;
00294     mib[1]= HW_NCPU;
00295     sysctl(mib,2,&ncpus,&len,NULL,0);
00296     return ncpus;
00297 }
00298 #else
00299 #warning Do not know how to detect number of processors: assuming 1
00300 inline int dbThread::numberOfProcessors() { return 1; }
00301 #endif
00302 
00303 class dbEvent {
00304     pthread_cond_t   cond;
00305     int              signaled;
00306     long             n_signals;
00307 
00308   public:
00309     void wait(dbMutex& mutex) {
00310         long before_n_signals = n_signals;
00311         while (!signaled && n_signals == before_n_signals) {
00312             pthread_cond_wait(&cond, &mutex.cs);
00313         }
00314     }
00315 
00316     void wait(dbMutex& mutex, time_t timeout) {
00317         long before_n_signals = n_signals;
00318         while (!signaled && n_signals == before_n_signals) {
00319             struct timespec abs_ts; 
00320 #ifdef PTHREAD_GET_EXPIRATION_NP
00321             struct timespec rel_ts; 
00322             rel_ts.tv_sec = timeout; 
00323             rel_ts.tv_nsec = 0;
00324             pthread_get_expiration_np(&rel_ts, &abs_ts);
00325 #else
00326             struct timeval cur_tv;
00327             gettimeofday(&cur_tv, NULL);
00328             abs_ts.tv_sec = cur_tv.tv_sec + timeout; 
00329             abs_ts.tv_nsec = cur_tv.tv_usec*1000;
00330 #endif
00331             pthread_cond_timedwait(&cond, &mutex.cs, &abs_ts);
00332         }
00333     }
00334 
00335     void signal() {
00336         signaled = true; 
00337         n_signals += 1;
00338         pthread_cond_broadcast(&cond);
00339     }
00340 
00341     void pulse() { 
00342         n_signals += 1;
00343         pthread_cond_broadcast(&cond);
00344     }
00345         
00346     void reset() {
00347         signaled = false;
00348     }
00349     void open(bool initValue = false) {
00350         signaled = initValue;
00351         n_signals = 0;
00352         pthread_cond_init(&cond, NULL);
00353     }
00354     void close() {
00355         pthread_cond_destroy(&cond);
00356     }
00357 };
00358 
00359 class dbSemaphore {
00360     pthread_cond_t   cond;
00361     int              count;
00362   public:
00363     void wait(dbMutex& mutex) {
00364         while (count == 0) {
00365             pthread_cond_wait(&cond, &mutex.cs);
00366         }
00367         count -= 1;
00368     }
00369 
00370     void wait(dbMutex& mutex, time_t timeout) {
00371         while (count == 0) {
00372             struct timespec abs_ts; 
00373 #ifdef PTHREAD_GET_EXPIRATION_NP
00374             struct timespec rel_ts; 
00375             rel_ts.tv_sec = timeout; 
00376             rel_ts.tv_nsec = 0;
00377             pthread_get_expiration_np(&rel_ts, &abs_ts);
00378 #else
00379             struct timeval cur_tv;
00380             gettimeofday(&cur_tv, NULL);
00381             abs_ts.tv_sec = cur_tv.tv_sec + timeout; 
00382             abs_ts.tv_nsec = cur_tv.tv_usec*1000;
00383 #endif
00384             pthread_cond_timedwait(&cond, &mutex.cs, &abs_ts);
00385         }
00386         count -= 1;
00387     }
00388 
00389     void signal(unsigned inc = 1) {
00390         count += inc;
00391         if (inc > 1) {
00392             pthread_cond_broadcast(&cond);
00393         } else if (inc == 1) {
00394             pthread_cond_signal(&cond);
00395         }
00396     }
00397     void open(unsigned initValue = 0) {
00398         pthread_cond_init(&cond, NULL);
00399         count = initValue;
00400     }
00401     void close() {
00402         pthread_cond_destroy(&cond);
00403     }
00404 };
00405 
00406 template<class T>
00407 class dbThreadContext {
00408     pthread_key_t key;
00409   public:
00410     T* get() {
00411         return (T*)pthread_getspecific(key);
00412     }
00413     void set(T* value) {
00414         pthread_setspecific(key, value);
00415     }
00416     dbThreadContext() {
00417         pthread_key_create(&key, NULL);
00418     }
00419     ~dbThreadContext() {
00420         pthread_key_delete(key);
00421     }
00422 };
00423 
00424 #else
00425 
00426 class dbMutex {
00427     bool initialized;
00428 
00429    public:
00430     dbMutex() {
00431         initialized = true;
00432     }
00433 
00434     ~dbMutex() { 
00435         initialized = false;
00436     }
00437 
00438     bool isInitialized() { 
00439         return initialized;
00440     }
00441 
00442     void lock() {}
00443     void unlock() {}
00444 };
00445 
00446 class dbThread {
00447   public:
00448     typedef void (thread_proc* thread_proc_t)(void*);
00449     void create(thread_proc_t f, void* arg) { f(arg); }
00450     void join() {}
00451     void detach() {}
00452     
00453     enum ThreadPriority { 
00454         THR_PRI_LOW, 
00455         THR_PRI_HIGH
00456     };
00457     void setPriority(ThreadPriority) {}
00458 
00459     static int numberOfProcessors() { return 1; }
00460 };
00461 
00462 class dbSemaphore {
00463     int count;
00464   public:
00465     void wait(dbMutex&, time_t=0) {
00466         assert (count > 0);
00467         count -= 1;
00468     }
00469     void signal(unsigned inc = 1) {
00470         count += inc;
00471     }
00472     void open(unsigned initValue = 0) {
00473         count = initValue;
00474     }
00475     void close() {}
00476 };
00477 
00478 class dbEvent {
00479     bool signaled;
00480   public:
00481     void wait(dbMutex&, time_t=0) {
00482         assert(signaled);
00483     }
00484     void signal() {
00485         signaled = true;
00486     }
00487     void reset() {
00488         signaled = false;
00489     }
00490     void open(bool initValue = false) {
00491         signaled = initValue;
00492     }
00493     void pulse() {}
00494     void close() {}
00495 };
00496 
00497 template<class T>
00498 class dbThreadContext {
00499     T* value;
00500   public:
00501     T* get() {
00502         return value;
00503     }
00504     void set(T* value) {
00505         this->value = value;
00506     }
00507     dbThreadContext() { value = NULL; }
00508 };
00509 
00510 
00511 #endif
00512 
00513 #endif
00514 
00515 class GIGABASE_DLL_ENTRY dbCriticalSection {
00516   private:
00517     dbMutex& mutex;
00518   public:
00519     dbCriticalSection(dbMutex& guard) : mutex(guard) {
00520         mutex.lock();
00521     }
00522     ~dbCriticalSection() {
00523         mutex.unlock();
00524     }
00525 };
00526 
00527 #define SMALL_BUF_SIZE 512
00528 
00529 template<class T>
00530 class dbSmallBuffer {
00531   protected:
00532     T      smallBuf[SMALL_BUF_SIZE];
00533     T*     buf;
00534     size_t used;
00535 
00536   public:
00537     dbSmallBuffer(size_t size) {
00538         if (size > SMALL_BUF_SIZE) {
00539             buf = new T[size];
00540         } else {
00541             buf = smallBuf;
00542         }
00543         used = size;
00544     }
00545 
00546     dbSmallBuffer() { 
00547         used = 0;
00548         buf = smallBuf;
00549     }
00550 
00551     void put(size_t size) { 
00552         if (size > SMALL_BUF_SIZE && size > used) { 
00553             if (buf != smallBuf) { 
00554                 delete[] buf;
00555             }
00556             buf = new T[size];
00557             used = size;
00558         }
00559     }
00560 
00561     operator T*() { return buf; }
00562     T* base() { return buf; }
00563 
00564     ~dbSmallBuffer() {
00565         if (buf != smallBuf) {
00566             delete[] buf;
00567         }
00568     }
00569 };
00570 
00571 class dbThreadPool;
00572 
00573 class GIGABASE_DLL_ENTRY dbPooledThread { 
00574   private:
00575     friend class dbThreadPool;
00576 
00577     dbThread                thread;
00578     dbThreadPool*           pool;
00579     dbPooledThread*         next;
00580     dbThread::thread_proc_t f;
00581     void*                   arg;
00582     bool                    running;
00583     dbSemaphore             startSem;
00584     dbSemaphore             readySem;
00585     
00586     static void thread_proc  pooledThreadFunc(void* arg);
00587 
00588     void run();
00589     void stop();
00590 
00591     dbPooledThread(dbThreadPool* threadPool); 
00592     ~dbPooledThread(); 
00593 };
00594 
00595 class GIGABASE_DLL_ENTRY dbThreadPool { 
00596     friend class dbPooledThread;
00597     dbPooledThread* freeThreads;
00598     dbMutex         mutex;
00599 
00600   public:
00601     dbPooledThread* create(dbThread::thread_proc_t f, void* arg);
00602     void join(dbPooledThread* thr);
00603     dbThreadPool();
00604     ~dbThreadPool();
00605 };    
00606 
00607 END_GIGABASE_NAMESPACE
00608 
00609 #endif

Generated on Thu Nov 24 23:14:30 2005 for GigaBASE by doxygen 1.3.5