Main Page   Class Hierarchy   Compound List   File List   Compound Members  

sync.h

00001 //-< SYNC.H >--------------------------------------------------------*--------*
00002 // FastDB                    Version 1.0         (c) 1999  GARRET    *     ?  *
00003 // (Main Memory Database Management System)                          *   /\|  *
00004 //                                                                   *  /  \  *
00005 //                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
00006 //                          Last update: 20-Dec-98    K.A. Knizhnik  * GARRET *
00007 //-------------------------------------------------------------------*--------*
00008 // Intertask synchonization primitives
00009 //-------------------------------------------------------------------*--------*
00010 
00011 #ifndef __SYNC_H__
00012 #define __SYNC_H__
00013 
00014 class FASTDB_DLL_ENTRY dbSystem { 
00015   public:
00016     static unsigned getCurrentTimeMsec();
00017 };
00018 
00019 #ifdef _WIN32
00020 
00021 #ifdef SET_NULL_DACL
00022 class FASTDB_DLL_ENTRY dbNullSecurityDesciptor { 
00023   public:
00024     SECURITY_DESCRIPTOR sd;
00025     SECURITY_ATTRIBUTES sa; 
00026 
00027     dbNullSecurityDesciptor() { 
00028         InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
00029         SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
00030         sa.nLength = sizeof(sa);
00031         sa.bInheritHandle = TRUE; 
00032         sa.lpSecurityDescriptor = &sd;
00033     }
00034     
00035     static dbNullSecurityDesciptor instance;
00036 };
00037 #define FASTDB_SECURITY_ATTRIBUTES &dbNullSecurityDesciptor::instance.sa
00038 #else    
00039 #define FASTDB_SECURITY_ATTRIBUTES NULL
00040 #endif
00041 
00042 class FASTDB_DLL_ENTRY dbMutex { 
00043     CRITICAL_SECTION cs;
00044   public:
00045     dbMutex() { 
00046         InitializeCriticalSection(&cs);
00047     }
00048     ~dbMutex() { 
00049         DeleteCriticalSection(&cs);
00050     }
00051     void lock() { 
00052         EnterCriticalSection(&cs);
00053     }
00054     void unlock() { 
00055         LeaveCriticalSection(&cs);
00056     }
00057 };
00058 
00059 #define thread_proc WINAPI
00060 
00061 class FASTDB_DLL_ENTRY dbThread { 
00062     HANDLE h;
00063   public:
00064     typedef void (thread_proc* thread_proc_t)(void*);
00065 
00066     void create(thread_proc_t f, void* arg) { 
00067         DWORD threadid;
00068         h = CreateThread(FASTDB_SECURITY_ATTRIBUTES, NULL, LPTHREAD_START_ROUTINE(f), arg,
00069                          0, &threadid);
00070     }
00071     enum ThreadPriority { 
00072         THR_PRI_LOW, 
00073         THR_PRI_HIGH
00074     };
00075 
00076     void setPriority(ThreadPriority pri) { 
00077         SetThreadPriority(h, pri == THR_PRI_LOW ? THREAD_PRIORITY_IDLE : THREAD_PRIORITY_HIGHEST);
00078     }
00079         
00080     void join() { 
00081         WaitForSingleObject(h, INFINITE);
00082         CloseHandle(h);
00083         h = NULL;
00084     }
00085     void detach() { 
00086         if (h != NULL) { 
00087             CloseHandle(h);
00088             h = NULL;
00089         }
00090     }   
00091     dbThread() { 
00092         h = NULL; 
00093     }
00094     ~dbThread() { 
00095         if (h != NULL) { 
00096             CloseHandle(h);
00097         }
00098     }
00099     static int numberOfProcessors() { 
00100 #ifdef PHAR_LAP
00101         return 1;
00102 #else
00103         SYSTEM_INFO sysinfo;
00104         GetSystemInfo(&sysinfo);
00105         return sysinfo.dwNumberOfProcessors;
00106 #endif
00107     }
00108 };
00109     
00110 class FASTDB_DLL_ENTRY dbProcessId { 
00111     DWORD tid;
00112   public:
00113     bool operator != (dbProcessId const& other) const { 
00114         return tid != other.tid;
00115     }
00116 
00117     void clear() { 
00118         tid = 0;
00119     }
00120 
00121     static dbProcessId getCurrent() {
00122         dbProcessId curr;
00123         curr.tid = GetCurrentThreadId();
00124         return curr;
00125     }
00126 };
00127 
00128 class FASTDB_DLL_ENTRY dbInitializationMutex { 
00129     HANDLE m;
00130   public: 
00131     enum initializationStatus { 
00132         InitializationError, 
00133         AlreadyInitialized,
00134         NotYetInitialized
00135     };
00136     initializationStatus initialize(char const* name) { 
00137         initializationStatus status;
00138         m = CreateMutex(FASTDB_SECURITY_ATTRIBUTES, true, name);
00139         if (GetLastError() == ERROR_ALREADY_EXISTS) { 
00140             status = WaitForSingleObject(m, INFINITE) == WAIT_OBJECT_0 
00141                    ? AlreadyInitialized : InitializationError;
00142             ReleaseMutex(m);
00143         } else if (m != NULL) { 
00144             status = NotYetInitialized;
00145         } else { 
00146             status = InitializationError;
00147         }
00148         return status;
00149     }
00150     void done() { 
00151         ReleaseMutex(m);
00152     }
00153     bool close() {
00154         CloseHandle(m);
00155         return false;
00156     }
00157     void erase() { 
00158         close();
00159     }
00160 };
00161 
00162 
00163 const int dbMaxSemValue = 1000000;
00164 
00165 
00166 class FASTDB_DLL_ENTRY dbSemaphore { 
00167   protected:
00168     HANDLE s;
00169   public:
00170     bool wait(unsigned msec = INFINITE) { 
00171         int rc = WaitForSingleObject(s, msec);
00172         assert(rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT);
00173         return rc == WAIT_OBJECT_0;
00174     }
00175     void signal(unsigned inc = 1) {
00176         if (inc != 0) { 
00177             ReleaseSemaphore(s, inc, NULL);
00178         }
00179     }
00180     void reset() { 
00181         while (WaitForSingleObject(s, 0) == WAIT_OBJECT_0);
00182     }    
00183     bool open(char const* name, unsigned initValue = 0) {
00184         s = CreateSemaphore(FASTDB_SECURITY_ATTRIBUTES, initValue, dbMaxSemValue, name);
00185         return s != NULL; 
00186     }
00187     void close() {
00188         CloseHandle(s);
00189     }
00190     void erase() { 
00191         close();
00192     }
00193 };
00194 
00195 class FASTDB_DLL_ENTRY dbEvent { 
00196   protected:
00197     HANDLE e;
00198   public:
00199     bool wait(unsigned msec = INFINITE) { 
00200         int rc = WaitForSingleObject(e, msec);
00201         assert(rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT);
00202         return rc == WAIT_OBJECT_0;
00203     }
00204     void signal() {
00205         SetEvent(e);
00206     }
00207     void reset() {
00208         ResetEvent(e);
00209     }
00210     bool open(char const* name, bool signaled = false) {
00211         e = CreateEvent(FASTDB_SECURITY_ATTRIBUTES, true, signaled, name);
00212         return e != NULL; 
00213     }
00214     void close() {
00215         CloseHandle(e);
00216     }
00217     void erase() { 
00218         close();
00219     }
00220 };
00221 
00222 class FASTDB_DLL_ENTRY dbLocalSemaphore : public dbSemaphore { 
00223   public:
00224     bool wait(dbMutex& mutex, time_t timeoutMsec) { 
00225         mutex.unlock();
00226         int rc = WaitForSingleObject(s, timeoutMsec);
00227         assert(rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT);
00228         mutex.lock();
00229         return rc == WAIT_OBJECT_0;
00230     }
00231     void wait(dbMutex& mutex) { 
00232         mutex.unlock();
00233         int rc = WaitForSingleObject(s, INFINITE);
00234         assert(rc == WAIT_OBJECT_0);
00235         mutex.lock();
00236     }
00237     bool open(unsigned initValue = 0) {
00238         return dbSemaphore::open(NULL, initValue);
00239     }
00240 };
00241 
00242 class FASTDB_DLL_ENTRY dbLocalEvent : public dbEvent { 
00243   public:
00244     bool wait(dbMutex& mutex, time_t timeoutMsec) { 
00245         mutex.unlock();
00246         int rc = WaitForSingleObject(e, timeoutMsec);
00247         assert(rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT);
00248         mutex.lock();
00249         return rc == WAIT_OBJECT_0;
00250     }
00251     void wait(dbMutex& mutex) { 
00252         mutex.unlock();
00253         int rc = WaitForSingleObject(e, INFINITE);
00254         assert(rc == WAIT_OBJECT_0);
00255         mutex.lock();
00256     }
00257     bool open(bool signaled = false) {
00258          return dbEvent::open(NULL, signaled);
00259      }
00260 };
00261 
00262 template<class T>
00263 class dbThreadContext { 
00264     int index;
00265   public:
00266     T* get() { 
00267         return (T*)TlsGetValue(index);
00268     }
00269     void set(T* value) { 
00270         TlsSetValue(index, value);
00271     }
00272     dbThreadContext() { 
00273         index = TlsAlloc();
00274         assert(index != TLS_OUT_OF_INDEXES);
00275     }
00276     ~dbThreadContext() { 
00277         TlsFree(index);
00278     }
00279 };
00280 
00281 template<class T>
00282 class dbSharedObject { 
00283     T*     ptr;
00284     HANDLE h;
00285   public:
00286 
00287     bool open(char* name) { 
00288 #ifdef NO_MMAP
00289         ptr = new T();
00290 #else
00291         h = CreateFileMapping(INVALID_HANDLE_VALUE,
00292                               FASTDB_SECURITY_ATTRIBUTES, PAGE_READWRITE, 0, 
00293                               sizeof(T), name);
00294         if (h == NULL) { 
00295             return false;
00296         }
00297         ptr = (T*)MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
00298         if (ptr == NULL) { 
00299             CloseHandle(h);
00300             return false;
00301         }
00302 #endif
00303         return true;
00304     }
00305 
00306     T* get() { return ptr; }
00307 
00308     void close() { 
00309 #ifdef NO_MMAP
00310         delete[] ptr;
00311 #else
00312         UnmapViewOfFile(ptr);
00313         CloseHandle(h);
00314 #endif
00315     }
00316     void erase() { 
00317         close();
00318     }
00319 };
00320 
00321 typedef long sharedsem_t;
00322 
00323 class FASTDB_DLL_ENTRY dbGlobalCriticalSection { 
00324     HANDLE       event;
00325     sharedsem_t* count;
00326 
00327   public:
00328     void enter() { 
00329         if (InterlockedDecrement(count) != 0) { 
00330             // another process is in critical section
00331             int rc = WaitForSingleObject(event, INFINITE);
00332             assert (rc == WAIT_OBJECT_0);
00333         }
00334     }
00335 
00336     void leave() { 
00337         if (InterlockedIncrement(count) <= 0) { 
00338             // some other processes try to enter critical section
00339             SetEvent(event);
00340         }
00341     }
00342 
00343     bool open(char const* name, long* count) { 
00344         this->count = count;
00345         event = OpenEvent(EVENT_ALL_ACCESS, FALSE, name);
00346         return event != NULL;
00347     }
00348     bool create(char const* name, long* count) { 
00349         this->count = count;
00350         *count = 1;
00351         event = CreateEvent(FASTDB_SECURITY_ATTRIBUTES, false, false, name);
00352         return event != NULL;
00353     }
00354     void close() { 
00355         CloseHandle(event);
00356     }
00357     void erase() { 
00358         close();
00359     }
00360 };
00361         
00362     
00363 #else // Unix
00364 
00365 #include <unistd.h>
00366 #include <string.h>
00367 #include <fcntl.h>
00368 #include <sys/time.h>
00369 #include <sys/types.h>
00370 #include <errno.h>
00371 
00372 #ifdef USE_POSIX_API
00373 #include <semaphore.h>
00374 #include <sys/mman.h>
00375 #else
00376 #include <sys/ipc.h>
00377 #include <sys/sem.h>
00378 #include <sys/shm.h>
00379 #include <sys/mman.h>
00380 #endif
00381 
00382 #define thread_proc
00383 
00384 #ifndef NO_PTHREADS
00385 
00386 #include <pthread.h>
00387 
00388 class dbMutex { 
00389     friend class dbLocalEvent;
00390     friend class dbLocalSemaphore;
00391     pthread_mutex_t cs;
00392   public:
00393     dbMutex() { 
00394         pthread_mutex_init(&cs, NULL);
00395     }
00396     ~dbMutex() { 
00397         pthread_mutex_destroy(&cs);
00398     }
00399     void lock() { 
00400         pthread_mutex_lock(&cs);
00401     }
00402     void unlock() { 
00403         pthread_mutex_unlock(&cs);
00404     }
00405 };
00406 
00407 const size_t dbThreadStackSize = 1024*1024;
00408 
00409 class dbThread { 
00410     pthread_t thread;
00411   public:
00412     typedef void (thread_proc* thread_proc_t)(void*);
00413     void create(thread_proc_t f, void* arg) {
00414         pthread_attr_t attr;
00415         pthread_attr_init(&attr);
00416 #if !defined(__linux__)
00417         pthread_attr_setstacksize(&attr, dbThreadStackSize);
00418 #endif
00419 #if defined(_AIX41)
00420         // At AIX 4.1, 4.2 threads are by default created detached
00421         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED);
00422 #endif
00423         pthread_create(&thread, &attr, (void*(*)(void*))f, arg);
00424         pthread_attr_destroy(&attr);
00425     }
00426 
00427     void join() { 
00428         void* result;
00429         pthread_join(thread, &result);
00430     }
00431     void detach() { 
00432         pthread_detach(thread);
00433     }
00434 
00435     enum ThreadPriority { 
00436         THR_PRI_LOW, 
00437         THR_PRI_HIGH
00438     };
00439     void setPriority(ThreadPriority pri) { 
00440 #if defined(PRI_OTHER_MIN) && defined(PRI_OTHER_MAX)
00441         struct sched_param sp;
00442         sp.gsched_priority = pri == THR_PRI_LOW ? PRI_OTHER_MIN : PRI_OTHER_MAX;
00443         pthread_setschedparam(thread, SCHED_OTHER, &sp); 
00444 #endif
00445     }
00446 
00447     static int numberOfProcessors();
00448 };
00449 
00450 
00451 class dbLocalEvent { 
00452     pthread_cond_t   cond;
00453     int              signaled;
00454   public:
00455     void wait(dbMutex& mutex) { 
00456         while (!signaled) { 
00457             pthread_cond_wait(&cond, &mutex.cs);
00458         }
00459     }
00460     bool wait(dbMutex& mutex, time_t timeout) {
00461         while (!signaled) {
00462             struct timespec abs_ts; 
00463 #ifdef PTHREAD_GET_EXPIRATION_NP
00464             struct timespec rel_ts; 
00465             rel_ts.tv_sec = timeout/1000; 
00466             rel_ts.tv_nsec = timeout%1000*1000000;
00467             pthread_get_expiration_np(&rel_ts, &abs_ts);
00468 #else
00469             struct timeval cur_tv;
00470             gettimeofday(&cur_tv, NULL);
00471             abs_ts.tv_sec = cur_tv.tv_sec + timeout/1000; 
00472             abs_ts.tv_nsec = cur_tv.tv_usec*1000 + timeout%1000*1000000;
00473             if (abs_ts.tv_nsec > 1000000000) { 
00474                 abs_ts.tv_nsec -= 1000000000;
00475                 abs_ts.tv_sec += 1;
00476             }
00477 #endif
00478             int rc = pthread_cond_timedwait(&cond, &mutex.cs, &abs_ts);
00479             if (rc == ETIMEDOUT) { 
00480                 return false;
00481             }
00482         }
00483         return true;
00484     }
00485     void signal() {
00486         signaled = true;
00487         pthread_cond_broadcast(&cond);
00488     }
00489     void reset() {
00490         signaled = false;
00491     }
00492     void open(bool initValue = false) { 
00493         signaled = initValue;
00494         pthread_cond_init(&cond, NULL);
00495     }
00496     void close() {
00497         pthread_cond_destroy(&cond);
00498     }
00499 };
00500 
00501 class dbLocalSemaphore { 
00502     pthread_cond_t   cond;
00503     int              count;
00504   public:
00505     void wait(dbMutex& mutex) { 
00506         while (count == 0) { 
00507             pthread_cond_wait(&cond, &mutex.cs);
00508         }
00509         count -= 1;
00510     }
00511     void wait(dbMutex& mutex, time_t timeout) {
00512         while (count == 0) {
00513             struct timespec abs_ts; 
00514 #ifdef PTHREAD_GET_EXPIRATION_NP
00515             struct timespec rel_ts; 
00516             rel_ts.tv_sec = timeout/1000; 
00517             rel_ts.tv_nsec = timeout%1000*1000000;
00518             pthread_get_expiration_np(&rel_ts, &abs_ts);
00519 #else
00520             struct timeval cur_tv;
00521             gettimeofday(&cur_tv, NULL);
00522             abs_ts.tv_sec = cur_tv.tv_sec + timeout/1000; 
00523             abs_ts.tv_nsec = cur_tv.tv_usec*1000 + timeout%1000*1000000;
00524             if (abs_ts.tv_nsec > 1000000000) { 
00525                 abs_ts.tv_nsec -= 1000000000;
00526                 abs_ts.tv_sec += 1;
00527             }
00528 #endif
00529             pthread_cond_timedwait(&cond, &mutex.cs, &abs_ts);
00530         }
00531         count -= 1;
00532     }
00533      void signal(unsigned inc = 1) {
00534         count += inc;
00535         if (inc > 1) { 
00536             pthread_cond_broadcast(&cond);
00537         } else if (inc == 1) { 
00538             pthread_cond_signal(&cond);
00539         }
00540     }
00541     void open(unsigned initValue = 0) { 
00542         pthread_cond_init(&cond, NULL);
00543         count = initValue;
00544     }
00545     void close() {
00546         pthread_cond_destroy(&cond);
00547     }
00548 };
00549 
00550 template<class T> 
00551 class dbThreadContext { 
00552     pthread_key_t key;
00553   public:
00554     T* get() { 
00555         return (T*)pthread_getspecific(key);
00556     }
00557     void set(T* value) { 
00558         pthread_setspecific(key, value);
00559     }
00560     dbThreadContext() { 
00561         pthread_key_create(&key, NULL);
00562     }
00563     ~dbThreadContext() { 
00564         pthread_key_delete(key);
00565     }
00566 };
00567 
00568 class dbProcessId { 
00569     int       pid;
00570     pthread_t tid;
00571   public:
00572     bool operator != (dbProcessId const& other) const { 
00573         return pid != other.pid || tid != other.tid;
00574     }
00575 
00576     void clear() { 
00577         pid = 0;
00578         tid = 0;
00579     }
00580 
00581     static dbProcessId getCurrent() {
00582         dbProcessId curr;
00583         curr.pid = getpid();
00584         curr.tid = pthread_self();
00585         return curr;
00586     }
00587 };
00588 
00589 #else
00590 
00591 class dbMutex { 
00592    public:
00593     void lock() {}
00594     void unlock() {}
00595 };
00596 
00597 class dbThread { 
00598   public:
00599     typedef void (thread_proc* thread_proc_t)(void*);
00600     void create(thread_proc_t f, void* arg) { f(arg); }
00601     void join() {}
00602     void detach() {}
00603     static int numberOfProcessors() { return 1; }
00604 };
00605 
00606 class dbLocalSemaphore { 
00607     int count;
00608   public:
00609     void wait(dbMutex&) { 
00610         assert (count > 0);
00611         count -= 1;
00612     }
00613     void signal(unsigned inc = 1) {
00614         count += inc;
00615     }
00616     void open(unsigned initValue = 0) {
00617         count = initValue;
00618     }
00619     void close() {}
00620 };
00621 
00622 class dbLocalEvent { 
00623     bool signaled;
00624   public:
00625     void wait(dbMutex&) { 
00626         assert(signaled);
00627     }
00628     void signal() {
00629         signaled = true;
00630     }
00631     void reset() {
00632         signaled = false;
00633     }
00634     void open(bool initValue = false) {
00635         signaled = initValue;
00636     }
00637     void close() {}
00638 };
00639 
00640 template<class T>
00641 class dbThreadContext { 
00642     T* value;
00643   public:
00644     T* get() { 
00645         return value;
00646     }
00647     void set(T* value) { 
00648         this->value = value;
00649     }
00650     dbThreadContext() { value = NULL; }
00651 };
00652 
00653 
00654 class dbProcessId { 
00655     int       pid;
00656   public:
00657     bool operator != (dbProcessId const& other) const { 
00658         return pid != other.pid;
00659     }
00660     
00661     void clear() { 
00662         pid = 0;
00663     }
00664 
00665     static dbProcessId getCurrent() {
00666         dbProcessId curr;
00667         curr.pid = getpid();
00668         return curr;
00669     }
00670 };
00671 
00672 #endif
00673 
00674 #define INFINITE (~0U)
00675 
00676 #ifdef USE_POSIX_API
00677 
00678 class dbInitializationMutex { 
00679     sem_t* sem;
00680   public: 
00681     enum initializationStatus { 
00682         InitializationError, 
00683         AlreadyInitialized,
00684         NotYetInitialized
00685     };
00686     initializationStatus initialize(char const* name) { 
00687         initializationStatus status;
00688         char* tmp = NULL;
00689         if (*name != '/') { 
00690             tmp = new char[strlen(name)+2];
00691             strcpy(tmp+1, name);
00692             *tmp = '/';
00693             name = tmp;
00694         }
00695         while (true) {
00696             sem = sem_open(name, 0);
00697             if (sem == NULL) { 
00698                 if (errno == ENOENT) {
00699                     sem = sem_open(name, O_CREAT|O_EXCL, 0777, 0);
00700                     if (sem != NULL) { 
00701                         status = NotYetInitialized;
00702                         break;
00703                     } else if (errno != EEXIST) { 
00704                         status = InitializationError;
00705                         break;
00706                     }
00707                 } else { 
00708                     status = InitializationError;
00709                     break;
00710                 }
00711             } else { 
00712                 status = (sem_wait(sem) == 0 && sem_post(sem) == 0) 
00713                     ? AlreadyInitialized : InitializationError;
00714                 break;
00715             }
00716         }
00717         delete[] tmp;
00718         return status;
00719     }
00720 
00721     void done() { 
00722         sem_post(sem);
00723     }
00724     bool close() {
00725         sem_close(sem);
00726         return false;
00727     }
00728     void erase() { 
00729         close();
00730     }
00731 };
00732 
00733 
00734 class dbSemaphore { 
00735   protected:
00736     sem_t* sem;
00737   public:
00738     void wait() { 
00739         int rc = sem_wait(sem);
00740         assert(rc == 0);
00741     }
00742 
00743     bool wait(unsigned msec) { 
00744 #ifdef POSIX_1003_1d
00745         struct timespec abs_ts;
00746         struct timeval  cur_tv;
00747         clock_gettime(CLOCK_REALTIME, &cur_tv);
00748         abs_ts.tv_sec = cur_tv.tv_sec + (msec + tv.tv_usec / 1000) / 1000000; 
00749         abs_ts.tv_nsec = (msec + tv.tv_usec / 1000) % 1000000 * 1000;
00750         int rc = sem_timedwait(sem, &abs_ts);
00751         if (rc < 0) { 
00752             assert(errno == ETIMEDOUT);
00753             return false;
00754         }
00755         return true;
00756 #else 
00757         int rc = sem_wait(sem);
00758         assert(rc == 0);
00759         return true;
00760 #endif  
00761     }
00762 
00763     void signal(unsigned inc = 1) {
00764         while (--inc > 0) { 
00765             sem_post(sem);
00766         }
00767     }
00768     void reset() { 
00769         while (sem_trywait(sem) == 0);
00770     }    
00771     bool open(char const* name, unsigned initValue = 0) {
00772         char* tmp = NULL;
00773         if (*name != '/') { 
00774             tmp = new char[strlen(name)+2];
00775             strcpy(tmp+1, name);
00776             *tmp = '/';
00777             name = tmp;
00778         }
00779         sem = sem_open(name, O_CREAT, 0777, initValue);
00780         delete[] tmp;
00781         return sem != NULL; 
00782     }
00783     void close() {
00784         sem_close(sem);
00785     }
00786     void erase() { 
00787         close();
00788     }
00789 };
00790 
00791 class dbEvent : public dbSemaphore { 
00792   public:
00793     void wait() { 
00794         dbSemaphore::wait();
00795         sem_post(sem);
00796     }
00797     bool wait(unsigned msec) { 
00798         if (dbSemaphore::wait(msec)) { 
00799             sem_post(sem);
00800             return true;
00801         }
00802         return false;
00803     }
00804     void signal() {
00805         while (sem_trywait(sem) == 0);
00806         sem_post(sem);
00807     }
00808     void reset() {
00809         while (sem_trywait(sem) == 0);
00810     }
00811     bool open(char const* name, bool signaled = false) {
00812         return dbSemaphore::open(name, (int)signaled);
00813     }
00814 };
00815 
00816 template<class T>
00817 class dbSharedObject { 
00818     char* name;
00819     T*  ptr;
00820     int fd;
00821   public:
00822 
00823     dbSharedObject() { 
00824         name = NULL;
00825         ptr = NULL;
00826         fd = -1;
00827     }
00828 
00829     bool open(char* fileName) { 
00830         delete[] name;
00831         name = new char[strlen(fileName) + 1];
00832         strcpy(name, fileName);
00833         fd = ::open(fileName, O_RDWR|O_CREAT, 0777);
00834         if (fd < 0) { 
00835             return false;
00836         }
00837         ptr = (T*)mmap(NULL,
00838                        DOALIGN(sizeof(T), 4096),
00839                        PROT_READ|PROT_WRITE,
00840                        MAP_SHARED,
00841                        fd,
00842                        0);
00843         if (ptr == MAP_FAILED) { 
00844             ptr = NULL;
00845             ::close(fd);
00846             return false;
00847         }
00848         return true;
00849     }
00850 
00851     T* get() { return ptr; }
00852 
00853     void close() { 
00854         if (ptr != NULL) { 
00855             munmap(ptr, DOALIGN(sizeof(T), 4096));
00856         }
00857         if (fd > 0) { 
00858             ::close(fd);
00859         }
00860     }
00861     void erase() {
00862         close();
00863         unlink(name);   
00864     }  
00865 
00866     ~dbSharedObject() { 
00867         delete[] name;
00868     }
00869 };
00870 
00871 #else // USE_POSIX_API
00872 
00873 extern char const* keyFileDir; // default value: "/tmp/" 
00874 
00875 class dbInitializationMutex { 
00876     int semid;
00877   public: 
00878     enum initializationStatus { 
00879         InitializationError, 
00880         AlreadyInitialized,
00881         NotYetInitialized
00882     };
00883     initializationStatus initialize(char const* name);
00884     void done(); 
00885     bool close();
00886     void erase();
00887 };
00888 
00889 
00890 class dbSemaphore { 
00891     int s;
00892   public:
00893     bool wait(unsigned msec = INFINITE);
00894     void signal(unsigned inc = 1);
00895     bool open(char const* name, unsigned initValue = 0);
00896     void reset();
00897     void close();
00898     void erase();
00899 };
00900 
00901 class dbEvent { 
00902     int e;
00903   public:
00904     bool wait(unsigned msec = INFINITE);
00905     void signal();
00906     void reset();
00907     bool open(char const* name, bool signaled = false);
00908     void close();
00909     void erase();
00910 };
00911 
00912 
00913 class dbSharedMemory { 
00914   protected:
00915     char*  ptr;
00916     int    shm;
00917 
00918   public:
00919     bool  open(char const* name, size_t size); 
00920     void  close();
00921     void  erase(); 
00922     char* get_base() { 
00923         return ptr;
00924     }
00925 };
00926 
00927 template<class T>
00928 class dbSharedObject : public dbSharedMemory { 
00929   public:
00930     bool open(char* name) { 
00931         return dbSharedMemory::open(name, sizeof(T));
00932     }
00933     T* get() { return (T*)ptr; }
00934 };
00935 
00936 #endif
00937 
00938 #if defined(__QNX__)
00939 
00940 typedef pthread_mutext_t sharedsem_t;
00941 
00942 class dbGlobalCriticalSection { 
00943     pthread_mutexattr_t attr;
00944     sharedsem_t* sem;
00945   public:
00946     void enter() {
00947         int rc = pthread_mutex_lock(sem);
00948         assert(rc == 0);
00949     }
00950     void leave() { 
00951         int rc = pthread_mutex_unlock(sem);
00952         assert(rc == 0);
00953     }
00954     bool open(char const*, sharedsem_t* shr) { 
00955         sem = shr;
00956         return true;
00957     }
00958     bool create(char const*, sharedsem_t* shr) { 
00959         sem = shr;
00960         pthread_mutexattr_init(&attr);
00961         pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
00962         pthread_mutexattr_setrecursive(&attr, PTHREAD_RECURSIVE_ENABLE);
00963         pthread_mutex_init(sem, &attr);
00964         return true;
00965     }
00966     void close() {}
00967     void erase() {
00968         pthread_mutex_destroy(sem);
00969     }
00970 };
00971 
00972 
00973 #elif defined(__osf__)
00974 
00975 #include <errno.h>
00976 typedef msemaphore sharedsem_t;
00977 
00978 class dbGlobalCriticalSection { 
00979     sharedsem_t* sem;
00980   public:
00981     void enter() { 
00982         int rc;
00983         while ((rc = msem_lock(sem, 0)) < 0 && errno == EINTR);
00984         assert(rc == 0);
00985     }
00986     void leave() { 
00987         int rc = msem_unlock(sem, 0);
00988         assert(rc == 0);        
00989     }
00990     bool open(char const*, sharedsem_t* shr) { 
00991         sem = shr;
00992         return true;
00993     }
00994     bool create(char const*, sharedsem_t* shr) { 
00995         sem = shr;
00996         msem_init(shr, MSEM_UNLOCKED);
00997         return true;
00998     }
00999     void close() {}
01000     void erase() {
01001         msem_remove(sem);
01002     }
01003 };
01004         
01005 
01006 #elif defined(__sun)
01007 
01008 #include <synch.h>
01009 #include <errno.h>
01010 typedef sema_t sharedsem_t;
01011 
01012 class dbGlobalCriticalSection { 
01013     sharedsem_t* sem;
01014   public:
01015     void enter() { 
01016         int rc;
01017         while ((rc = sema_wait(sem)) < 0 && errno == EINTR);
01018         assert(rc == 0);
01019     }
01020     void leave() { 
01021         int rc = sema_post(sem);
01022         assert(rc == 0);
01023     }
01024     bool open(char const*, sharedsem_t* shr) { 
01025         sem = shr;
01026         return true;
01027     }
01028     bool create(char const*, sharedsem_t* shr) { 
01029         sem = shr;
01030         return sema_init(shr, 1, USYNC_PROCESS, NULL) == 0;
01031     }
01032     void close() {}
01033     void erase() {
01034         sema_destroy(sem);
01035     }
01036 };
01037 
01038 #elif defined(USE_POSIX_API)
01039 
01040 typedef sem_t sharedsem_t;
01041 
01042 class dbGlobalCriticalSection { 
01043     sharedsem_t* sem;
01044 
01045   public:
01046     void enter() { 
01047         int rc = sem_wait(sem);
01048         assert(rc == 0);
01049     }
01050     void leave() { 
01051         int rc = sem_post(sem);
01052         assert(rc == 0);
01053     }
01054     bool open(char const* name, sharedsem_t* shr) { 
01055         sem = shr;
01056         return true;
01057     }
01058     bool create(char const* name, sharedsem_t* shr) {   
01059         sem = shr;
01060         return sem_init(sem, 1, 1) == 0;
01061     }
01062     void close() {}
01063     void erase() { 
01064         sem_destroy(sem);
01065     }
01066 };
01067 
01068 #else
01069 
01070 typedef long sharedsem_t;
01071 
01072 class dbGlobalCriticalSection { 
01073     int          semid;
01074     sharedsem_t* count;
01075 
01076   public:
01077     void enter(); 
01078     void leave();
01079     bool open(char const* name, sharedsem_t* shr);
01080     bool create(char const* name, sharedsem_t* shr);
01081     void close() {}
01082     void erase();
01083 };
01084 #endif
01085 
01086 #endif
01087 
01088 class FASTDB_DLL_ENTRY dbCriticalSection { 
01089   private:
01090     dbMutex& mutex;
01091   public:
01092     dbCriticalSection(dbMutex& guard) : mutex(guard) {
01093         mutex.lock();
01094     }
01095     ~dbCriticalSection() { 
01096         mutex.unlock();
01097     }
01098 };
01099         
01100 #define SMALL_BUF_SIZE 1024
01101 
01102 class FASTDB_DLL_ENTRY dbSmallBuffer { 
01103   protected:
01104     char* buf;
01105     char  smallBuf[SMALL_BUF_SIZE];
01106 
01107   public:
01108     dbSmallBuffer(size_t size) { 
01109         if (size > SMALL_BUF_SIZE) { 
01110             buf = new char[size];
01111         } else { 
01112             buf = smallBuf;
01113         }
01114     }
01115 
01116     operator char*() { return buf; }
01117     char* base() { return buf; }
01118 
01119     ~dbSmallBuffer() { 
01120         if (buf != smallBuf) { 
01121             delete[] buf;
01122         }
01123     }
01124 };
01125 
01126 
01127 class FASTDB_DLL_ENTRY dbPooledThread { 
01128   private:
01129     friend class dbThreadPool;
01130 
01131     dbThread                thread;
01132     dbThreadPool*           pool;
01133     dbPooledThread*         next;
01134     dbThread::thread_proc_t f;
01135     void*                   arg;
01136     bool                    running;
01137     dbLocalSemaphore        startSem;
01138     dbLocalSemaphore        readySem;
01139     
01140     static void thread_proc  pooledThreadFunc(void* arg);
01141 
01142     void run();
01143     void stop();
01144 
01145     dbPooledThread(dbThreadPool* threadPool); 
01146     ~dbPooledThread(); 
01147 };
01148 
01149 class FASTDB_DLL_ENTRY dbThreadPool { 
01150     friend class dbPooledThread;
01151     dbPooledThread* freeThreads;
01152     dbMutex         mutex;
01153 
01154   public:
01155     dbPooledThread* create(dbThread::thread_proc_t f, void* arg);
01156     void join(dbPooledThread* thr);
01157     dbThreadPool();
01158     ~dbThreadPool();
01159 };    
01160     
01161 #endif
01162 
01163 

Generated on Fri Nov 15 21:06:29 2002 for FastDB by doxygen1.2.15