00001
00002
00003
00004
00005
00006
00007
00008
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
00331 int rc = WaitForSingleObject(event, INFINITE);
00332 assert (rc == WAIT_OBJECT_0);
00333 }
00334 }
00335
00336 void leave() {
00337 if (InterlockedIncrement(count) <= 0) {
00338
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
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;
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