Main Page   Class Hierarchy   Compound List   File List   Compound Members  

sync_unix.h

00001 //-< SYNC_UNIX.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 for Unix platforms
00009 //-------------------------------------------------------------------*--------*
00010 
00011 #ifndef __SYNC_UNIX_H__
00012 #define __SYNC_UNIX_H__
00013 
00014 // Standard includes for all Unix platforms
00015 #include <unistd.h>
00016 #include <string.h>
00017 #include <fcntl.h>
00018 #include <sys/time.h>
00019 #include <sys/types.h>
00020 #include <assert.h>
00021 #include <errno.h>
00022 
00023 #if !defined(USE_POSIX_SEMAPHORES) || !defined(USE_POSIX_MMAP) || !USE_POSIX_MMAP
00024 #include <sys/ipc.h> 
00025 extern char const* keyFileDir; // default value: "/tmp/" 
00026 #endif
00027 
00028 #if defined(USE_POSIX_SEMAPHORES)
00029 #include <semaphore.h>  // For POSIX style semaphores
00030 #else
00031 #include <sys/sem.h>    // For SysV style semaphores
00032 #endif
00033 
00034 #if defined(USE_POSIX_MMAP) && USE_POSIX_MMAP
00035 #include <sys/mman.h>   // For mmap()
00036 #else
00037 #include <sys/shm.h>    
00038 #include <sys/mman.h>
00039 #endif
00040 
00041 BEGIN_FASTDB_NAMESPACE
00042 
00043 #define thread_proc
00044 
00046 // If this system uses pthread based threads, then define
00047 //   dbMutex(), dbThread(), dbLocalEvent(), etc as pthread-based implemenations
00048 
00049 #ifndef NO_PTHREADS
00050 
00051 // Use pthread based implementation
00052 #include <pthread.h>
00053 
00054 class dbMutex { 
00055     friend class dbLocalEvent;
00056     friend class dbLocalSemaphore;
00057     pthread_mutex_t cs;
00058     bool            initialized;
00059   public:
00060     dbMutex() {
00061 #ifdef NDEBUG
00062         pthread_mutex_init(&cs, NULL);
00063 #else
00064         int rc = pthread_mutex_init(&cs, NULL);
00065         assert(rc == 0);
00066 #endif
00067         initialized = true;
00068     }
00069     ~dbMutex() {
00070 #ifdef NDEBUG
00071         pthread_mutex_destroy(&cs);
00072 #else
00073         int rc = pthread_mutex_destroy(&cs);
00074         assert(rc == 0);
00075 #endif
00076         initialized = false;
00077     }
00078     bool isInitialized() { 
00079         return initialized;
00080     }
00081     void lock() {
00082         if (initialized) { 
00083 #ifdef NDEBUG
00084             pthread_mutex_lock(&cs);
00085 #else
00086             int rc = pthread_mutex_lock(&cs);
00087             assert(rc == 0);
00088 #endif
00089         }
00090     }
00091     void unlock() {
00092         if (initialized) { 
00093 #ifdef NDEBUG
00094             pthread_mutex_unlock(&cs);
00095 #else
00096             int rc = pthread_mutex_unlock(&cs);
00097             assert(rc == 0);
00098 #endif
00099         }
00100     }
00101 };
00102 
00103 
00104 const size_t dbThreadStackSize = 1024*1024;
00105 
00106 class dbThread { 
00107     pthread_t thread;
00108   public:
00109     typedef void (thread_proc* thread_proc_t)(void*);
00110     
00111     static void sleep(time_t sec) { 
00112         ::sleep(sec);
00113     }
00114 
00115     void create(thread_proc_t f, void* arg) {
00116         pthread_attr_t attr;
00117         pthread_attr_init(&attr);
00118 #if !defined(__linux__)
00119         pthread_attr_setstacksize(&attr, dbThreadStackSize);
00120 #endif
00121 #if defined(_AIX41)
00122         // At AIX 4.1, 4.2 threads are by default created detached
00123         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED);
00124 #endif
00125         pthread_create(&thread, &attr, (void*(*)(void*))f, arg);
00126         pthread_attr_destroy(&attr);
00127     }
00128 
00129     void join() { 
00130         void* result;
00131         pthread_join(thread, &result);
00132     }
00133     void detach() { 
00134         pthread_detach(thread);
00135     }
00136 
00137     enum ThreadPriority { 
00138         THR_PRI_LOW, 
00139         THR_PRI_HIGH
00140     };
00141     void setPriority(ThreadPriority pri) { 
00142 #if defined(PRI_OTHER_MIN) && defined(PRI_OTHER_MAX)
00143         struct sched_param sp;
00144         sp.sched_priority = pri == THR_PRI_LOW ? PRI_OTHER_MIN : PRI_OTHER_MAX;
00145         pthread_setschedparam(thread, SCHED_OTHER, &sp); 
00146 #endif
00147     }
00148 
00149     static int numberOfProcessors();
00150 };
00151 
00152 
00153 class dbLocalEvent { 
00154     pthread_cond_t   cond;
00155     int              signaled;
00156   public:
00157     void wait(dbMutex& mutex) { 
00158         while (!signaled) { 
00159             pthread_cond_wait(&cond, &mutex.cs);
00160         }
00161     }
00162     bool wait(dbMutex& mutex, time_t timeout) {
00163         if (!signaled) { 
00164             struct timespec abs_ts; 
00165 #ifdef PTHREAD_GET_EXPIRATION_NP
00166             struct timespec rel_ts; 
00167             rel_ts.tv_sec = timeout/1000; 
00168             rel_ts.tv_nsec = timeout%1000*1000000;
00169             pthread_get_expiration_np(&rel_ts, &abs_ts);
00170 #else
00171             struct timeval cur_tv;
00172             gettimeofday(&cur_tv, NULL);
00173             abs_ts.tv_sec = cur_tv.tv_sec + timeout/1000; 
00174             abs_ts.tv_nsec = cur_tv.tv_usec*1000 + timeout%1000*1000000;
00175             if (abs_ts.tv_nsec > 1000000000) { 
00176                 abs_ts.tv_nsec -= 1000000000;
00177                 abs_ts.tv_sec += 1;
00178             }
00179 #endif
00180             do { 
00181                 int rc = pthread_cond_timedwait(&cond, &mutex.cs, &abs_ts);
00182                 if (rc != 0) {
00183                     return false;
00184                 }
00185             } while (!signaled);
00186 
00187         }
00188         return true;
00189     }
00190     void signal() {
00191         signaled = true;
00192         pthread_cond_broadcast(&cond);
00193     }
00194     void reset() {
00195         signaled = false;
00196     }
00197     void open(bool initValue = false) { 
00198         signaled = initValue;
00199         pthread_cond_init(&cond, NULL);
00200     }
00201     void close() {
00202         pthread_cond_destroy(&cond);
00203     }
00204 };
00205 
00206 class dbLocalSemaphore { 
00207     pthread_cond_t   cond;
00208     int              count;
00209   public:
00210     void wait(dbMutex& mutex) { 
00211         while (count == 0) { 
00212             pthread_cond_wait(&cond, &mutex.cs);
00213         }
00214         count -= 1;
00215     }
00216     bool wait(dbMutex& mutex, time_t timeout) {
00217         if (count == 0) { 
00218             struct timespec abs_ts; 
00219 #ifdef PTHREAD_GET_EXPIRATION_NP
00220             struct timespec rel_ts; 
00221             rel_ts.tv_sec = timeout/1000; 
00222             rel_ts.tv_nsec = timeout%1000*1000000;
00223             pthread_get_expiration_np(&rel_ts, &abs_ts);
00224 #else
00225             struct timeval cur_tv;
00226             gettimeofday(&cur_tv, NULL);
00227             abs_ts.tv_sec = cur_tv.tv_sec + timeout/1000; 
00228             abs_ts.tv_nsec = cur_tv.tv_usec*1000 + timeout%1000*1000000;
00229             if (abs_ts.tv_nsec > 1000000000) { 
00230                 abs_ts.tv_nsec -= 1000000000;
00231                 abs_ts.tv_sec += 1;
00232             }
00233 #endif
00234             do { 
00235                 int rc = pthread_cond_timedwait(&cond, &mutex.cs, &abs_ts);
00236                 if (rc != 0) { 
00237                     return false;
00238                 }
00239             } while (count == 0);
00240         }
00241         count -= 1;
00242         return true;
00243     }
00244     void signal(unsigned inc = 1) {
00245         count += inc;
00246         if (inc > 1) { 
00247             pthread_cond_broadcast(&cond);
00248         } else if (inc == 1) { 
00249             pthread_cond_signal(&cond);
00250         }
00251     }
00252     void open(unsigned initValue = 0) { 
00253         pthread_cond_init(&cond, NULL);
00254         count = initValue;
00255     }
00256     void close() {
00257         pthread_cond_destroy(&cond);
00258     }
00259 };
00260 
00261 template<class T> 
00262 class dbThreadContext { 
00263     pthread_key_t key;
00264   public:
00265     T* get() { 
00266         return (T*)pthread_getspecific(key);
00267     }
00268     void set(T* value) { 
00269         pthread_setspecific(key, value);
00270     }
00271     dbThreadContext() { 
00272         pthread_key_create(&key, NULL);
00273     }
00274     ~dbThreadContext() { 
00275         pthread_key_delete(key);
00276     }
00277 };
00278 
00279 class dbProcessId { 
00280     int       pid;
00281     pthread_t tid;
00282   public:
00283     bool operator != (dbProcessId const& other) const { 
00284         return pid != other.pid || tid != other.tid;
00285     }
00286 
00287     void clear() { 
00288         pid = 0;
00289         tid = 0;
00290     }
00291 
00292     static dbProcessId getCurrent() {
00293         dbProcessId curr;
00294         curr.pid = getpid();
00295         curr.tid = pthread_self();
00296         return curr;
00297     }
00298 };
00299 
00300 #else // NO_PTHREAD
00301 
00302 // Non pthread based threads, mutexes, etc.
00303 // Maps to skeleton  functions, this implementation isn't using threads.
00304 
00305 class dbMutex {
00306     bool initialized;
00307 
00308    public:
00309     dbMutex() {
00310         initialized = true;
00311     }
00312 
00313     ~dbMutex() { 
00314         initialized = false;
00315     }
00316 
00317     bool isInitialized() { 
00318         return initialized;
00319     }
00320 
00321     void lock() {}
00322     void unlock() {}
00323 };
00324 
00325 class dbThread { 
00326   public:
00327     typedef void (thread_proc* thread_proc_t)(void*);
00328     void create(thread_proc_t f, void* arg) { f(arg); }
00329     void join() {}
00330     void detach() {}
00331     enum ThreadPriority { 
00332         THR_PRI_LOW, 
00333         THR_PRI_HIGH
00334     };
00335     void setPriority(ThreadPriority pri) { }
00336     static int numberOfProcessors() { return 1; }
00337 };
00338 
00339 class dbLocalSemaphore { 
00340     int count;
00341   public:
00342     void wait(dbMutex&) { 
00343         assert (count > 0);
00344         count -= 1;
00345     }
00346     void signal(unsigned inc = 1) {
00347         count += inc;
00348     }
00349     void open(unsigned initValue = 0) {
00350         count = initValue;
00351     }
00352     void close() {}
00353 };
00354 
00355 class dbLocalEvent { 
00356     bool signaled;
00357   public:
00358     void wait(dbMutex&) { 
00359         assert(signaled);
00360     }
00361     bool wait(dbMutex& mutex, time_t timeout) {
00362         return true;
00363     }
00364     void signal() {
00365         signaled = true;
00366     }
00367     void reset() {
00368         signaled = false;
00369     }
00370     void open(bool initValue = false) {
00371         signaled = initValue;
00372     }
00373     void close() {}
00374 };
00375 
00376 template<class T>
00377 class dbThreadContext { 
00378     T* value;
00379   public:
00380     T* get() { 
00381         return value;
00382     }
00383     void set(T* value) { 
00384         this->value = value;
00385     }
00386     dbThreadContext() { value = NULL; }
00387 };
00388 
00389 
00390 class dbProcessId { 
00391     int       pid;
00392   public:
00393     bool operator != (dbProcessId const& other) const { 
00394         return pid != other.pid;
00395     }
00396     
00397     void clear() { 
00398         pid = 0;
00399     }
00400 
00401     static dbProcessId getCurrent() {
00402         dbProcessId curr;
00403         curr.pid = getpid();
00404         return curr;
00405     }
00406 };
00407 
00408 #endif // NO_PTHREAD
00409 
00410 
00411 #define INFINITE (~0U)
00412 
00413 
00414 #ifdef USE_POSIX_SEMAPHORES
00415 
00416 // Initialization Mutex using Posix based semaphores
00417 class dbInitializationMutex { 
00418     sem_t* sem;
00419     char*  name;
00420   public: 
00421     enum initializationStatus { 
00422         InitializationError, 
00423         AlreadyInitialized,
00424         NotYetInitialized
00425     };
00426     initializationStatus initialize(char const* name) { 
00427         initializationStatus status;
00428         this->name = new char[strlen(name)+2];
00429         if (*name != '/') { 
00430             strcpy(this->name+1, name);
00431             *this->name = '/';
00432         } else { 
00433             strcpy(this->name, name);
00434         }
00435         while (true) {
00436             sem = sem_open(this->name, 0);
00437             if (sem == SEM_FAILED) { 
00438                 if (errno == ENOENT) {
00439                     sem = sem_open(this->name, O_CREAT|O_EXCL, 0777, 0);
00440                     if (sem != SEM_FAILED) { 
00441                         status = NotYetInitialized;
00442                         break;
00443                     } else if (errno != EEXIST) { 
00444                         status = InitializationError;
00445                         break;
00446                     }
00447                 } else { 
00448                     status = InitializationError;
00449                     break;
00450                 }
00451             } else { 
00452                 status = (sem_wait(sem) == 0 && sem_post(sem) == 0) 
00453                     ? AlreadyInitialized : InitializationError;
00454                 break;
00455             }
00456         }
00457         return status;
00458     }
00459 
00460     void done() { 
00461         sem_post(sem);
00462     }
00463     bool close() {
00464         sem_close(sem);
00465         return true;
00466     }
00467     void erase() {
00468         sem_unlink(name);
00469         delete[] name;
00470     }
00471 };
00472 
00473 class dbSemaphore { 
00474   protected:
00475     sem_t* sem;
00476     char*  name;
00477   public:
00478     void wait() { 
00479 #ifdef NDEBUG
00480         sem_wait(sem);
00481 #else
00482         int rc = sem_wait(sem);
00483         assert(rc == 0);
00484 #endif
00485     }
00486 
00487     bool wait(unsigned msec) { 
00488 #ifdef POSIX_1003_1d
00489         struct timespec abs_ts;
00490         struct timeval  cur_tv;
00491         clock_gettime(CLOCK_REALTIME, &cur_tv);
00492         abs_ts.tv_sec = cur_tv.tv_sec + (msec + cur_tv.tv_usec / 1000) / 1000000; 
00493         abs_ts.tv_nsec = (msec + cur_tv.tv_usec / 1000) % 1000000 * 1000;
00494         int rc = sem_timedwait(sem, &abs_ts);
00495         if (rc < 0) { 
00496             assert(errno == ETIMEDOUT);
00497             return false;
00498         }
00499         return true;
00500 #else 
00501 #ifdef NDEBUG
00502         sem_wait(sem);
00503 #else
00504         int rc = sem_wait(sem);
00505         assert(rc == 0);
00506 #endif
00507         return true;
00508 #endif  
00509     }
00510 
00511     void signal(unsigned inc = 1) {
00512         while (inc-- > 0) { 
00513             sem_post(sem);
00514         }
00515     }
00516     void reset() { 
00517         while (sem_trywait(sem) == 0);
00518     }    
00519     bool open(char const* name, unsigned initValue = 0) {
00520         this->name = new char[strlen(name)+2];
00521         if (*name != '/') { 
00522             strcpy(this->name+1, name);
00523             *this->name = '/';
00524         } else { 
00525             strcpy(this->name, name);
00526         }
00527         sem = sem_open(this->name, O_CREAT, 0777, initValue);
00528         return sem != NULL; 
00529     }
00530     void close() {
00531         if (sem != NULL) { 
00532             sem_close(sem);
00533             sem = NULL;
00534         }
00535     }
00536     void erase() { 
00537         close();
00538         sem_unlink(name);
00539         delete[] name;
00540     }
00541 };
00542 
00543 class dbEvent : public dbSemaphore { 
00544   public:
00545     void wait() { 
00546         dbSemaphore::wait();
00547         sem_post(sem);
00548     }
00549     bool wait(unsigned msec) { 
00550         if (dbSemaphore::wait(msec)) { 
00551             sem_post(sem);
00552             return true;
00553         }
00554         return false;
00555     }
00556     void signal() {
00557         while (sem_trywait(sem) == 0);
00558         sem_post(sem);
00559     }
00560     void reset() {
00561         while (sem_trywait(sem) == 0);
00562     }
00563     bool open(char const* name, bool signaled = false) {
00564         return dbSemaphore::open(name, (int)signaled);
00565     }
00566 };
00567 #else // USE_POSIX_SEMAPHORES
00568 
00569 class FASTDB_DLL_ENTRY dbWatchDog { 
00570     bool open(char const* name, int flags);
00571   public:
00572     bool watch();
00573     void close(); 
00574     bool open(char const* name);
00575     bool create(char const* name);
00576     int id;
00577 };
00578 
00579 // Define local implemenation of InitializationMutex in sync.cpp
00580 class dbInitializationMutex { 
00581     int semid;
00582   public: 
00583     enum initializationStatus { 
00584         InitializationError, 
00585         AlreadyInitialized,
00586         NotYetInitialized
00587     };
00588     initializationStatus initialize(char const* name);
00589     void done(); 
00590     bool close();
00591     void erase();
00592 };
00593 
00594 
00595 class dbSemaphore { 
00596     int s;
00597   public:
00598     bool wait(unsigned msec = INFINITE);
00599     void signal(unsigned inc = 1);
00600     bool open(char const* name, unsigned initValue = 0);
00601     void reset();
00602     void close();
00603     void erase();
00604 };
00605 
00606 class dbEvent { 
00607     int e;
00608   public:
00609     bool wait(unsigned msec = INFINITE);
00610     void signal();
00611     void reset();
00612     bool open(char const* name, bool signaled = false);
00613     void close();
00614     void erase();
00615 };
00616 #endif // USE_POSIX_SEMAPHORES
00617 
00618 
00619 // Define dbSharedObject and dbSharedMemory
00620 #if defined(USE_POSIX_MMAP) && USE_POSIX_MMAP
00621 
00622 // For POSIX dbSharedObject, we use mmap()
00623 template<class T>
00624 class dbSharedObject { 
00625     char* name;
00626     T*  ptr;
00627     int fd;
00628   public:
00629 
00630     dbSharedObject() { 
00631         name = NULL;
00632         ptr = NULL;
00633         fd = -1;
00634     }
00635 
00636     bool open(char* fileName) { 
00637         delete[] name;
00638         name = new char[strlen(fileName) + 1];
00639         strcpy(name, fileName);
00640         fd = ::open(fileName, O_RDWR|O_CREAT, 0777);
00641         if (fd < 0) { 
00642             return false;
00643         }
00644         if (ftruncate(fd, sizeof(T)) < 0) {
00645             ::close(fd);
00646             return false;
00647         }
00648         ptr = (T*)mmap(NULL,
00649                        DOALIGN(sizeof(T), 4096),
00650                        PROT_READ|PROT_WRITE,
00651                        MAP_SHARED,
00652                        fd,
00653                        0);
00654         if (ptr == MAP_FAILED) { 
00655             ptr = NULL;
00656             ::close(fd);
00657             return false;
00658         }
00659         return true;
00660     }
00661 
00662     T* get() { return ptr; }
00663 
00664     void close() { 
00665         if (ptr != NULL) { 
00666             munmap((char*)ptr, DOALIGN(sizeof(T), 4096));
00667         }
00668         if (fd > 0) { 
00669             ::close(fd);
00670         }
00671     }
00672     void erase() {
00673         close();
00674         unlink(name);   
00675     }  
00676 
00677     ~dbSharedObject() { 
00678         delete[] name;
00679     }
00680 };
00681 
00682 #else // USE_POSIX_MMAP
00683 
00684 // Non POSIX, internal implementations of SharedMemory and SharedObject
00685 extern char const* keyFileDir; // default value: "/tmp/" 
00686 class dbSharedMemory { 
00687   protected:
00688     char*  ptr;
00689     int    shm;
00690 
00691   public:
00692     bool  open(char const* name, size_t size); 
00693     void  close();
00694     void  erase(); 
00695     char* get_base() { 
00696         return ptr;
00697     }
00698 };
00699 
00700 template<class T>
00701 class dbSharedObject : public dbSharedMemory { 
00702   public:
00703     bool open(char* name) { 
00704         return dbSharedMemory::open(name, sizeof(T));
00705     }
00706     T* get() { return (T*)ptr; }
00707 };
00708 
00709 #endif
00710 
00712 // Define dBGlobalCriticalSection for various platforms
00713 
00714 // QNX uses a pthread based mutex for its implementation
00715 //     Use only if pthread support is also enabled, else we'll use the default case
00716 #if defined(__QNX__) && !defined(NO_PTHREADS)
00717 typedef pthread_mutex_t sharedsem_t;
00718 
00719 class dbGlobalCriticalSection { 
00720     pthread_mutexattr_t attr;
00721     sharedsem_t* sem;
00722   public:
00723     void enter() {
00724 #ifdef NDEBUG
00725         pthread_mutex_lock(sem);
00726 #else
00727         int rc = pthread_mutex_lock(sem);
00728         assert(rc == 0);
00729 #endif
00730     }
00731     void leave() { 
00732 #ifdef NDEBUG
00733         pthread_mutex_unlock(sem);
00734 #else
00735         int rc = pthread_mutex_unlock(sem);
00736         assert(rc == 0);
00737 #endif
00738     }
00739     bool open(char const*, sharedsem_t* shr) { 
00740         sem = shr;
00741         return true;
00742     }
00743     bool create(char const*, sharedsem_t* shr) { 
00744         sem = shr;
00745         pthread_mutexattr_init(&attr);
00746         pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
00747         pthread_mutexattr_setrecursive(&attr, PTHREAD_RECURSIVE_ENABLE);
00748         pthread_mutex_init(sem, &attr);
00749         return true;
00750     }
00751     void close() {}
00752     void erase() {
00753         pthread_mutex_destroy(sem);
00754     }
00755 };
00756 
00757 
00758 #elif defined(__osf__) && !defined(RECOVERABLE_CRITICAL_SECTION)
00759 // OSF uses "shared memory semaphores", located within a region mapped with mmap().
00760 #include <errno.h>
00761 typedef msemaphore sharedsem_t;
00762 
00763 class dbGlobalCriticalSection { 
00764     sharedsem_t* sem;
00765   public:
00766     void enter() { 
00767         int rc;
00768         while ((rc = msem_lock(sem, 0)) < 0 && errno == EINTR);
00769         assert(rc == 0);
00770     }
00771     void leave() { 
00772         int rc = msem_unlock(sem, 0);
00773         assert(rc == 0);        
00774     }
00775     bool open(char const*, sharedsem_t* shr) { 
00776         sem = shr;
00777         return true;
00778     }
00779     bool create(char const*, sharedsem_t* shr) { 
00780         sem = shr;
00781         msem_init(shr, MSEM_UNLOCKED);
00782         return true;
00783     }
00784     void close() {}
00785     void erase() {
00786         msem_remove(sem);
00787     }
00788 };
00789         
00790 
00791 #elif defined(__sun) && !defined(RECOVERABLE_CRITICAL_SECTION)
00792 // Sun uses the Solaris style semaphore implemenation (sema_init(), sema_post())
00793 #include <synch.h>
00794 #include <errno.h>
00795 typedef sema_t sharedsem_t;
00796 
00797 class dbGlobalCriticalSection { 
00798     sharedsem_t* sem;
00799   public:
00800     void enter() { 
00801 #ifdef NDEBUG
00802         while (sema_wait(sem) < 0 && errno == EINTR);
00803 #else
00804         int rc;
00805         while ((rc = sema_wait(sem)) < 0 && errno == EINTR);
00806         assert(rc == 0);
00807 #endif
00808     }
00809     void leave() { 
00810 #ifdef NDEBUG
00811         sema_post(sem);
00812 #else
00813         int rc = sema_post(sem);
00814         assert(rc == 0);
00815 #endif
00816     }
00817     bool open(char const*, sharedsem_t* shr) { 
00818         sem = shr;
00819         return true;
00820     }
00821     bool create(char const*, sharedsem_t* shr) { 
00822         sem = shr;
00823         return sema_init(shr, 1, USYNC_PROCESS, NULL) == 0;
00824     }
00825     void close() {}
00826     void erase() {
00827         sema_destroy(sem);
00828     }
00829 };
00830 
00831 #elif defined(USE_POSIX_SEMAPHORES) && !defined(RECOVERABLE_CRITICAL_SECTION)
00832 // Everyone else uses the POSIX style semaphores (sem_wait(), sem_post(), etc) if defined
00833 typedef sem_t sharedsem_t;
00834 
00835 class dbGlobalCriticalSection { 
00836     sharedsem_t* sem;
00837 
00838   public:
00839     void enter() { 
00840 #ifdef NDEBUG
00841         sem_wait(sem);
00842 #else
00843         int rc = sem_wait(sem);
00844         assert(rc == 0);
00845 #endif
00846     }
00847     void leave() { 
00848 #ifdef NDEBUG
00849         sem_post(sem);
00850 #else
00851         int rc = sem_post(sem);
00852         assert(rc == 0);
00853 #endif
00854     }
00855     bool open(char const* name, sharedsem_t* shr) { 
00856         sem = shr;
00857         return true;
00858     }
00859 
00860     bool create(char const* name, sharedsem_t* shr) {   
00861         sem = shr;
00862         return sem_init(sem, 1, 1) == 0;
00863     }
00864 
00865     void close() {}
00866     void erase() { 
00867         sem_destroy(sem);
00868     }
00869 };
00870 
00871 #else
00872 
00873 #define USE_LOCAL_CS_IMPL
00874 
00875 #define GLOBAL_CS_DEBUG 1
00876 
00877 // Lastly, use the local implementation
00878 typedef long sharedsem_t;
00879 
00880 class dbGlobalCriticalSection { 
00881     int          semid;
00882     sharedsem_t* count;
00883 #if GLOBAL_CS_DEBUG
00884     pthread_t    owner;
00885 #endif
00886 
00887   public:
00888     void enter(); 
00889     void leave();
00890     bool open(char const* name, sharedsem_t* shr);
00891     bool create(char const* name, sharedsem_t* shr);
00892     void close() {}
00893     void erase();
00894 };
00895 #endif //dbGLobalCriticalSection switch
00896 
00897 END_FASTDB_NAMESPACE
00898 
00899 #endif //__SYNC_UNIX_H__

Generated on Thu Feb 14 12:42:30 2008 for FastDB by doxygen1.2.18