• Main Page
  • Classes
  • Files
  • File List

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 BEGIN_GIGABASE_NAMESPACE
00015 
00016 #if defined(_WIN32) && !defined(__SYMBIAN32__)
00017 
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     static void sleep(time_t sec) { 
00060         Sleep((DWORD)(sec*1000));
00061     }
00062 
00063     typedef void (thread_proc* thread_proc_t)(void*);
00064 
00065     void create(thread_proc_t f, void* arg) {
00066         DWORD threadid;
00067         h = CreateThread(NULL, 0, LPTHREAD_START_ROUTINE(f), arg, 0, &threadid);
00068     }
00069     void join() {
00070         WaitForSingleObject(h, INFINITE);
00071         CloseHandle(h);
00072         h = NULL;
00073     }
00074     void detach() {
00075         if (h != NULL) {
00076             CloseHandle(h);
00077             h = NULL;
00078         }
00079     }
00080     dbThread() {
00081         h = NULL;
00082     }
00083     ~dbThread() {
00084         if (h != NULL) {
00085             CloseHandle(h);
00086         }
00087     }
00088     static int numberOfProcessors() {
00089         SYSTEM_INFO sysinfo;
00090         GetSystemInfo(&sysinfo);
00091         return sysinfo.dwNumberOfProcessors;
00092     }
00093 };
00094 
00095 const int dbMaxSemValue = 1000000;
00096 
00097 
00098 class GIGABASE_DLL_ENTRY dbSemaphore {
00099     HANDLE s;
00100   public:
00101     void wait(dbMutex& mutex, time_t timeout = INFINITE) {
00102         mutex.unlock();
00103         int rc = WaitForSingleObject(s, (DWORD)(timeout == (time_t)INFINITE ? timeout : timeout*1000));
00104         assert(rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT);
00105         mutex.lock();
00106     }
00107     void signal(unsigned inc = 1) {
00108         if (inc != 0) {
00109             ReleaseSemaphore(s, inc, NULL);
00110         }
00111     }
00112     void open(unsigned initValue = 0) {
00113         s = CreateSemaphore(NULL, initValue, dbMaxSemValue, NULL);
00114         assert(s != NULL);
00115     }
00116     void close() {
00117         CloseHandle(s);
00118     } 
00119     dbSemaphore() { 
00120         s = NULL;
00121     }
00122 };
00123 
00124 class GIGABASE_DLL_ENTRY dbEvent {
00125     HANDLE e;
00126     int    nWaitingThreads;
00127     int    nPulses;
00128   public:
00129     void wait(dbMutex& mutex, time_t timeout = INFINITE) {
00130         nWaitingThreads += 1;
00131         mutex.unlock();
00132         int rc = WaitForSingleObject(e, (DWORD)(timeout == (time_t)INFINITE ? timeout : timeout*1000));
00133         assert(rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT);
00134         mutex.lock();
00135         nWaitingThreads -= 1;
00136         if (nPulses > 0) { 
00137             nPulses -= 1;
00138             ResetEvent(e);
00139         }
00140     }
00141     void signal() {
00142         SetEvent(e);
00143     }
00144     void reset() {
00145         ResetEvent(e);
00146     }
00147     void pulse() { 
00148         if (nWaitingThreads > 0) { 
00149             nPulses += 1;
00150             SetEvent(e);
00151         }
00152     }    
00153     void open(bool initValue = false) {
00154         e = CreateEvent(NULL, true, initValue, NULL);
00155         nWaitingThreads = 0;
00156         nPulses = 0;
00157     }
00158     void close() {
00159         CloseHandle(e);
00160     }
00161     dbEvent() { 
00162         e = NULL;
00163     }
00164 };
00165 
00166 template<class T>
00167 class dbThreadContext {
00168     int index;
00169   public:
00170     T* get() {
00171         return (T*)TlsGetValue(index);
00172     }
00173     void set(T* value) {
00174         TlsSetValue(index, value);
00175     }
00176     dbThreadContext() {
00177         index = TlsAlloc();
00178         assert(index != (int)TLS_OUT_OF_INDEXES);
00179     }
00180     ~dbThreadContext() {
00181         TlsFree(index);
00182     }
00183 };
00184 
00185 #else // Unix
00186 
00187 #define thread_proc
00188 
00189 #if defined(NO_PTHREADS)
00190 
00191 class dbMutex {
00192     bool initialized;
00193 
00194    public:
00195     dbMutex() {
00196         initialized = true;
00197     }
00198 
00199     ~dbMutex() { 
00200         initialized = false;
00201     }
00202 
00203     bool isInitialized() { 
00204         return initialized;
00205     }
00206 
00207     void lock() {}
00208     void unlock() {}
00209 };
00210 
00211 class dbThread {
00212   public:
00213     typedef void (thread_proc* thread_proc_t)(void*);
00214     void create(thread_proc_t f, void* arg) { f(arg); }
00215     void join() {}
00216     void detach() {}
00217     
00218     enum ThreadPriority { 
00219         THR_PRI_LOW, 
00220         THR_PRI_HIGH
00221     };
00222     void setPriority(ThreadPriority) {}
00223 
00224     static int numberOfProcessors() { return 1; }
00225 };
00226 
00227 class dbSemaphore {
00228     int count;
00229   public:
00230     void wait(dbMutex&, time_t=0) {
00231         assert (count > 0);
00232         count -= 1;
00233     }
00234     void signal(unsigned inc = 1) {
00235         count += inc;
00236     }
00237     void open(unsigned initValue = 0) {
00238         count = initValue;
00239     }
00240     void close() {}
00241 };
00242 
00243 class dbEvent {
00244     bool signaled;
00245   public:
00246     void wait(dbMutex&, time_t=0) {
00247         assert(signaled);
00248     }
00249     void signal() {
00250         signaled = true;
00251     }
00252     void reset() {
00253         signaled = false;
00254     }
00255     void open(bool initValue = false) {
00256         signaled = initValue;
00257     }
00258     void pulse() {}
00259     void close() {}
00260 };
00261 
00262 template<class T>
00263 class dbThreadContext {
00264     T* value;
00265   public:
00266     T* get() {
00267         return value;
00268     }
00269     void set(T* value) {
00270         this->value = value;
00271     }
00272     dbThreadContext() { value = NULL; }
00273 };
00274 
00275 #elif defined(__SYMBIAN32__)
00276 
00277 class dbMutex 
00278 {
00279     friend class dbEvent;
00280     friend class dbSemaphore;
00281     RMutex cs;
00282     bool   initialized;
00283   public:
00284     dbMutex() {
00285         int rc = cs.CreateLocal();
00286         assert(rc == KErrNone);
00287         initialized = true;
00288     }
00289     ~dbMutex() {
00290         cs.Close();
00291         initialized = false;
00292     }
00293     bool isInitialized() { 
00294         return initialized;
00295     }
00296     void lock() {
00297         if (initialized) { 
00298             cs.Wait();
00299         }
00300     }
00301     void unlock() {
00302         if (initialized) { 
00303             cs.Signal();
00304         }
00305     }
00306 };    
00307     
00308 class dbThread 
00309 {
00310     RThread thread;
00311     static TInt count;
00312   public:
00313     static size_t heapMinSize;
00314     static size_t heapMaxSize;
00315     static size_t stackSize;
00316     
00317     typedef void (thread_proc* thread_proc_t)(void*);
00318     void create(thread_proc_t f, void* arg) { 
00319         TBuf<16> name;
00320         name.Format(_L("%d"), User::LockedInc(count));
00321         int rc = thread.Create(name, (TThreadFunction)f, stackSize, heapMinSize, heapMaxSize, arg);
00322         assert(rc == KErrNone);
00323     }
00324 
00325     void join() {
00326         TRequestStatus status;
00327         thread.Rendezvous(status);
00328         status.Int();        
00329     }
00330     void detach() {}
00331     
00332     enum ThreadPriority { 
00333         THR_PRI_LOW, 
00334         THR_PRI_HIGH
00335     };
00336 
00337     void setPriority(ThreadPriority pri) {
00338         thread.SetPriority(pri == THR_PRI_LOW ? EPriorityLess : EPriorityMore);
00339     }
00340 
00341     static int numberOfProcessors() { return 1; }
00342 };
00343 
00344 class dbEvent 
00345 {
00346     RCondVar cond;
00347     int      signaled;
00348     long     n_signals;
00349 
00350   public:
00351     void wait(dbMutex& mutex) {
00352         long before_n_signals = n_signals;
00353         while (!signaled && n_signals == before_n_signals) {
00354             int rc = cond.Wait(mutex.cs);
00355             assert(rc == KErrNone);
00356         }
00357     }
00358 
00359     bool wait(dbMutex& mutex, time_t timeout) {
00360         if (!signaled) {
00361             long before_n_signals = n_signals;
00362             do { 
00363                 int rc = cond.TimedWait(mutex.cs, timeout*1000000);
00364                 if (rc == KErrTimedOut) { 
00365                     return false;
00366                 }
00367                 assert(rc == KErrNone);
00368             } while (!signaled && n_signals == before_n_signals);
00369         }
00370         return true;
00371     }
00372 
00373     void signal() {
00374         signaled = true; 
00375         n_signals += 1;
00376         cond.Broadcast();
00377     }
00378 
00379     void pulse() { 
00380         n_signals += 1;
00381         cond.Broadcast();
00382     }
00383         
00384     void reset() {
00385         signaled = false;
00386     }
00387     void open(bool initValue = false) {
00388         signaled = initValue;
00389         n_signals = 0;
00390         int rc = cond.CreateLocal();
00391         assert(rc == KErrNone);
00392     }
00393     void close() {
00394         cond.Close();
00395     }
00396 };
00397 
00398 class dbSemaphore {
00399     RCondVar cond;
00400     int      count;
00401   public:
00402     void wait(dbMutex& mutex) {
00403         while (count == 0) {
00404             int rc = cond.Wait(mutex.cs);
00405             assert(rc == KErrNone);
00406         }
00407         count -= 1;
00408     }
00409 
00410     bool wait(dbMutex& mutex, time_t timeout) {
00411         if (count == 0) { 
00412             do { 
00413                 int rc = cond.TimedWait(mutex.cs, timeout*1000000);
00414                 if (rc == KErrTimedOut) { 
00415                     return false;
00416                 }
00417                 assert(rc == KErrNone);
00418             } while (count == 0);
00419         }
00420         count -= 1;
00421         return true;
00422     }
00423 
00424     void signal(unsigned inc = 1) {
00425         count += inc;
00426         if (inc > 1) {
00427             cond.Broadcast();
00428         } else if (inc == 1) {
00429             cond.Signal();
00430         }
00431     }
00432     void open(unsigned initValue = 0) {
00433         int rc = cond.CreateLocal();
00434         assert(rc == KErrNone);
00435         count = initValue;
00436     }
00437     void close() {
00438         cond.Close();
00439     }
00440 };
00441 
00442 extern int dbTlsIndex;
00443 
00444 template<class T>
00445 class dbThreadContext {
00446     int index;
00447   public:
00448     T* get() {
00449         return (T*)UserSvr::DllTls(index);
00450     }
00451     void set(T* value) {
00452         UserSvr::DllSetTls(index, value);
00453     }
00454     dbThreadContext() { 
00455         index = ++dbTlsIndex;
00456     }
00457     ~dbThreadContext() { 
00458         UserSvr::DllFreeTls(index);
00459     }
00460 };
00461 
00462 #else // Posix threads
00463 
00464 END_GIGABASE_NAMESPACE
00465 
00466 #include <unistd.h>
00467 #include <sys/time.h>
00468 #include <pthread.h>
00469 
00470 BEGIN_GIGABASE_NAMESPACE
00471 
00472 class dbMutex {
00473     friend class dbEvent;
00474     friend class dbSemaphore;
00475     pthread_mutex_t cs;
00476     bool            initialized;
00477   public:
00478     dbMutex() {
00479         pthread_mutex_init(&cs, NULL);
00480         initialized = true;
00481     }
00482     ~dbMutex() {
00483         pthread_mutex_destroy(&cs);
00484         initialized = false;
00485     }
00486     bool isInitialized() { 
00487         return initialized;
00488     }
00489     void lock() {
00490         if (initialized) { 
00491             pthread_mutex_lock(&cs);
00492         }
00493     }
00494     void unlock() {
00495         if (initialized) { 
00496             pthread_mutex_unlock(&cs);
00497         }
00498     }
00499 };
00500 
00501 
00502 const size_t dbThreadStackSize = 1024*1024;
00503 
00504 class dbThread {
00505     pthread_t thread;
00506   public:
00507     typedef void (thread_proc* thread_proc_t)(void*);
00508 
00509     void create(thread_proc_t f, void* arg) {
00510         pthread_attr_t attr;
00511         pthread_attr_init(&attr);
00512 #if !defined(__linux__)
00513         pthread_attr_setstacksize(&attr, dbThreadStackSize);
00514 #endif
00515 #if defined(_AIX41)
00516         // At AIX 4.1, 4.2 threads are by default created detached
00517         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED);
00518 #endif
00519         pthread_create(&thread, &attr, (void*(*)(void*))f, arg);
00520         pthread_attr_destroy(&attr);
00521     }
00522 
00523     enum ThreadPriority { 
00524         THR_PRI_LOW, 
00525         THR_PRI_HIGH
00526     };
00527 #if defined(PRI_OTHER_MIN) && defined(PRI_OTHER_MAX)
00528     void setPriority(ThreadPriority pri) { 
00529         struct sched_param sp;
00530         sp.sched_priority = pri == THR_PRI_LOW ? PRI_OTHER_MIN : PRI_OTHER_MAX;
00531         pthread_setschedparam(thread, SCHED_OTHER, &sp); 
00532     }
00533 #else
00534     void setPriority(ThreadPriority) {}
00535 #endif
00536 
00537     static void sleep(time_t sec) { 
00538         ::sleep(sec);
00539     }
00540 
00541     void join() {
00542         void* result;
00543         pthread_join(thread, &result);
00544     }
00545     void detach() {
00546         pthread_detach(thread);
00547     }
00548     static int numberOfProcessors();
00549 };
00550 
00551 #if defined(_SC_NPROCESSORS_ONLN)
00552 inline int dbThread::numberOfProcessors() {
00553     return sysconf(_SC_NPROCESSORS_ONLN);
00554 }
00555 #elif defined(__linux__)
00556 END_GIGABASE_NAMESPACE
00557 #include <linux/smp.h>
00558 BEGIN_GIGABASE_NAMESPACE
00559 inline int dbThread::numberOfProcessors() { return smp_num_cpus; }
00560 #elif defined(__FreeBSD__) || defined(__bsdi__) || defined(__OpenBSD__) || defined(__NetBSD__)
00561 #if defined(__bsdi__) || defined(__OpenBSD__)
00562 END_GIGABASE_NAMESPACE
00563 #include <sys/param.h>
00564 BEGIN_GIGABASE_NAMESPACE
00565 #endif
00566 END_GIGABASE_NAMESPACE
00567 #include <sys/sysctl.h>
00568 BEGIN_GIGABASE_NAMESPACE
00569 inline int dbThread::numberOfProcessors() {
00570     int mib[2],ncpus=0;
00571     size_t len=sizeof(ncpus);
00572     mib[0]= CTL_HW;
00573     mib[1]= HW_NCPU;
00574     sysctl(mib,2,&ncpus,&len,NULL,0);
00575     return ncpus;
00576 }
00577 #else
00578 #warning Do not know how to detect number of processors: assuming 1
00579 inline int dbThread::numberOfProcessors() { return 1; }
00580 #endif
00581 
00582 class dbEvent {
00583     pthread_cond_t   cond;
00584     int              signaled;
00585     long             n_signals;
00586 
00587   public:
00588     void wait(dbMutex& mutex) {
00589         long before_n_signals = n_signals;
00590         while (!signaled && n_signals == before_n_signals) {
00591             pthread_cond_wait(&cond, &mutex.cs);
00592         }
00593     }
00594 
00595     bool wait(dbMutex& mutex, time_t timeout) {
00596         if (!signaled) {
00597             struct timespec abs_ts; 
00598 #ifdef PTHREAD_GET_EXPIRATION_NP
00599             struct timespec rel_ts; 
00600             rel_ts.tv_sec = timeout; 
00601             rel_ts.tv_nsec = 0;
00602             pthread_get_expiration_np(&rel_ts, &abs_ts);
00603 #else
00604             struct timeval cur_tv;
00605             gettimeofday(&cur_tv, NULL);
00606             abs_ts.tv_sec = cur_tv.tv_sec + timeout; 
00607             abs_ts.tv_nsec = cur_tv.tv_usec*1000;
00608 #endif
00609             long before_n_signals = n_signals;
00610             do { 
00611                 int rc = pthread_cond_timedwait(&cond, &mutex.cs, &abs_ts);
00612                 if (rc != 0) {
00613                     return false;
00614                 }
00615             } while (!signaled && n_signals == before_n_signals);
00616         }
00617         return true;
00618     }
00619 
00620     void signal() {
00621         signaled = true; 
00622         n_signals += 1;
00623         pthread_cond_broadcast(&cond);
00624     }
00625 
00626     void pulse() { 
00627         n_signals += 1;
00628         pthread_cond_broadcast(&cond);
00629     }
00630         
00631     void reset() {
00632         signaled = false;
00633     }
00634     void open(bool initValue = false) {
00635         signaled = initValue;
00636         n_signals = 0;
00637         pthread_cond_init(&cond, NULL);
00638     }
00639     void close() {
00640         pthread_cond_destroy(&cond);
00641     }
00642 };
00643 
00644 class dbSemaphore {
00645     pthread_cond_t   cond;
00646     int              count;
00647   public:
00648     void wait(dbMutex& mutex) {
00649         while (count == 0) {
00650             pthread_cond_wait(&cond, &mutex.cs);
00651         }
00652         count -= 1;
00653     }
00654 
00655     bool wait(dbMutex& mutex, time_t timeout) {
00656         if (count == 0) { 
00657             struct timespec abs_ts; 
00658 #ifdef PTHREAD_GET_EXPIRATION_NP
00659             struct timespec rel_ts; 
00660             rel_ts.tv_sec = timeout; 
00661             rel_ts.tv_nsec = 0;
00662             pthread_get_expiration_np(&rel_ts, &abs_ts);
00663 #else
00664             struct timeval cur_tv;
00665             gettimeofday(&cur_tv, NULL);
00666             abs_ts.tv_sec = cur_tv.tv_sec + timeout; 
00667             abs_ts.tv_nsec = cur_tv.tv_usec*1000;
00668 #endif
00669             do { 
00670                 int rc = pthread_cond_timedwait(&cond, &mutex.cs, &abs_ts);
00671                 if (rc != 0) { 
00672                     return false;
00673                 }
00674             } while (count == 0);
00675         }
00676         count -= 1;
00677         return true;
00678     }
00679 
00680     void signal(unsigned inc = 1) {
00681         count += inc;
00682         if (inc > 1) {
00683             pthread_cond_broadcast(&cond);
00684         } else if (inc == 1) {
00685             pthread_cond_signal(&cond);
00686         }
00687     }
00688     void open(unsigned initValue = 0) {
00689         pthread_cond_init(&cond, NULL);
00690         count = initValue;
00691     }
00692     void close() {
00693         pthread_cond_destroy(&cond);
00694     }
00695 };
00696 
00697 template<class T>
00698 class dbThreadContext {
00699     pthread_key_t key;
00700   public:
00701     T* get() {
00702         return (T*)pthread_getspecific(key);
00703     }
00704     void set(T* value) {
00705         pthread_setspecific(key, value);
00706     }
00707     dbThreadContext() {
00708         pthread_key_create(&key, NULL);
00709     }
00710     ~dbThreadContext() {
00711         pthread_key_delete(key);
00712     }
00713 };
00714 
00715 #endif
00716 
00717 #endif
00718 
00719 class GIGABASE_DLL_ENTRY dbCriticalSection {
00720   private:
00721     dbMutex& mutex;
00722   public:
00723     dbCriticalSection(dbMutex& guard) : mutex(guard) {
00724         mutex.lock();
00725     }
00726     ~dbCriticalSection() {
00727         mutex.unlock();
00728     }
00729 };
00730 
00731 #define SMALL_BUF_SIZE 512
00732 
00733 template<class T>
00734 class dbSmallBuffer {
00735   protected:
00736     T      smallBuf[SMALL_BUF_SIZE];
00737     T*     buf;
00738     size_t used;
00739 
00740   public:
00741     dbSmallBuffer(size_t size) {
00742         if (size > SMALL_BUF_SIZE) {
00743             buf = new T[size];
00744         } else {
00745             buf = smallBuf;
00746         }
00747         used = size;
00748     }
00749 
00750     dbSmallBuffer() { 
00751         used = 0;
00752         buf = smallBuf;
00753     }
00754 
00755     void put(size_t size) { 
00756         if (size > SMALL_BUF_SIZE && size > used) { 
00757             if (buf != smallBuf) { 
00758                 delete[] buf;
00759             }
00760             buf = new T[size];
00761             used = size;
00762         }
00763     }
00764 
00765     operator T*() { return buf; }
00766     T* base() { return buf; }
00767 
00768     ~dbSmallBuffer() {
00769         if (buf != smallBuf) {
00770             delete[] buf;
00771         }
00772     }
00773 };
00774 
00775 class dbThreadPool;
00776 
00777 class GIGABASE_DLL_ENTRY dbPooledThread { 
00778   private:
00779     friend class dbThreadPool;
00780 
00781     dbThread                thread;
00782     dbThreadPool*           pool;
00783     dbPooledThread*         next;
00784     dbThread::thread_proc_t f;
00785     void*                   arg;
00786     bool                    running;
00787     dbSemaphore             startSem;
00788     dbSemaphore             readySem;
00789     
00790     static void thread_proc  pooledThreadFunc(void* arg);
00791 
00792     void run();
00793     void stop();
00794 
00795     dbPooledThread(dbThreadPool* threadPool); 
00796     ~dbPooledThread(); 
00797 };
00798 
00799 class GIGABASE_DLL_ENTRY dbThreadPool { 
00800     friend class dbPooledThread;
00801     dbPooledThread* freeThreads;
00802     dbMutex         mutex;
00803 
00804   public:
00805     dbPooledThread* create(dbThread::thread_proc_t f, void* arg);
00806     void join(dbPooledThread* thr);
00807     dbThreadPool();
00808     ~dbThreadPool();
00809 };    
00810 
00811 END_GIGABASE_NAMESPACE
00812 
00813 #endif

Generated on Mon Aug 23 2010 00:04:01 for GigaBASE by  doxygen 1.7.1