00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __GZ_MUTEX_H__
00022 #define __GZ_MUTEX_H__
00023
00031 #include "gzBasicTypes.h"
00032 #include "gzDebug.h"
00033 #include "gzMemory.h"
00034 #include "gzReference.h"
00035
00036 #if defined GZ_WINDOWS
00037
00038
00039 #include "windows.h"
00040 typedef CRITICAL_SECTION gzSyncType;
00041 typedef HANDLE gzEventHandle;
00042
00043 #elif defined GZ_UNIX
00044
00045
00046
00047
00048
00049
00050 #include "pthread.h"
00051 #include "sys/errno.h"
00052 typedef pthread_mutex_t gzSyncType;
00053 typedef pthread_cond_t gzEventHandle;
00054
00055
00056 #endif
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 class GZ_BASE_EXPORT gzMutex
00074 {
00075 public:
00076
00077 gzMutex(gzBool useThreadID=TRUE);
00078 gzMutex(const gzMutex ©);
00079 gzMutex & operator=(const gzMutex ©);
00080
00081 virtual ~gzMutex();
00082
00083 gzVoid waitLock() const;
00084 gzBool tryLock() const;
00085 gzVoid unLock() const;
00086 gzBool isLocked() const;
00087
00088 gzULong getOwnerThreadID() const;
00089
00090 gzULong getSpinLockCount() const;
00091
00092 private:
00093
00094 gzSyncType m_lock;
00095
00096 #ifdef NON_RECURSIVE_MUTEX
00097
00098 gzSyncType m_waiter;
00099
00100 #endif
00101
00102 gzULong m_threadID;
00103
00104 gzULong m_spinLock;
00105
00106 gzBool m_useThreadID;
00107 };
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 template <class T> class gzGuard : public gzMutex
00125 {
00126 public:
00127
00128 gzGuard(){};
00129
00130 gzGuard(const T& data):m_data(data){};
00131
00132 operator T&() { return (T &)m_data; }
00133
00134 T& operator=( const T& data ){ m_data=data; return m_data; }
00135
00136 private:
00137
00138 T m_data;
00139 };
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 template <class T> class gzClassGuard : public T , public gzMutex
00156 {
00157 public:
00158
00159 gzClassGuard(){};
00160
00161 virtual ~gzClassGuard(){};
00162
00163 gzClassGuard(const T& data):T(data){};
00164 };
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 class GZ_BASE_EXPORT gzBodyGuard
00181 {
00182 public:
00183 gzBodyGuard(const gzMutex &guard):m_guard(&guard) { m_guard->waitLock(); }
00184
00185 virtual ~gzBodyGuard() { m_guard->unLock(); }
00186
00187 private:
00188
00189 gzBodyGuard( const gzBodyGuard ©):m_guard(NULL){}
00190
00191 gzBodyGuard & operator=(const gzBodyGuard ©){ return *this; }
00192
00193 private:
00194
00195 const gzMutex *m_guard;
00196 };
00197
00198 #define GZ_BODYGUARD gzBodyGuard _guard_
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 class GZ_BASE_EXPORT gzThreadSafeReference : public gzReference
00215 {
00216 public:
00217
00218 virtual gzVoid ref()
00219 {
00220 m_ThreadSafeRefLock.waitLock();
00221
00222 gzReference::ref();
00223
00224 m_ThreadSafeRefLock.unLock();
00225 }
00226
00227 virtual gzVoid unref()
00228 {
00229 m_ThreadSafeRefLock.waitLock();
00230
00231 gzUInt retval(gzReference::unrefNoDelete());
00232
00233 m_ThreadSafeRefLock.unLock();
00234
00235 if(!retval)
00236 checkDelete();
00237 }
00238
00239 virtual gzUInt unrefNoDelete()
00240 {
00241 m_ThreadSafeRefLock.waitLock();
00242
00243 gzUInt retval(gzReference::unrefNoDelete());
00244
00245 m_ThreadSafeRefLock.unLock();
00246
00247 return retval;
00248 }
00249
00250 virtual gzBool checkDelete()
00251 {
00252 m_ThreadSafeRefLock.waitLock();
00253
00254 if(!_refCount)
00255 {
00256 m_ThreadSafeRefLock.unLock();
00257
00258 delete this;
00259
00260 return TRUE;
00261 }
00262
00263 m_ThreadSafeRefLock.unLock();
00264
00265 return FALSE;
00266 }
00267
00268 virtual gzUInt getRef() const
00269 {
00270 m_ThreadSafeRefLock.waitLock();
00271
00272 gzUInt retval(gzReference::getRef());
00273
00274 m_ThreadSafeRefLock.unLock();
00275
00276 return retval;
00277 }
00278
00279 protected:
00280
00281 gzMutex m_ThreadSafeRefLock;
00282 };
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00299 class GZ_BASE_EXPORT gzEvent : public gzThreadSafeReference
00300 {
00301 public:
00302
00304 gzEvent();
00305
00307 virtual ~gzEvent();
00308
00310
00313 gzVoid fire();
00314
00315 gzEventHandle getHandle() const;
00316
00318
00322 gzBool wait(gzULong timeout);
00323
00325
00330 static gzBool wait(gzULong timeout , const gzArray<gzEvent> & events , gzBool waitForAllEvents=FALSE , gzULong *eventIndex=NULL);
00331
00332 private:
00333
00334 gzEventHandle m_handle;
00335 };
00336
00337 GZ_DECLARE_REFPTR(gzEvent);
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 class GZ_BASE_EXPORT gzSemaphore
00354 {
00355 public:
00356
00357 gzSemaphore(gzULong currentValue=0,gzULong currentCount=0,gzULong maxCount=0);
00358
00359 virtual ~gzSemaphore(){};
00360
00361 gzBool waitLock(gzULong value) const;
00362
00363 gzBool tryLock(gzULong value) const;
00364
00365 gzULong setMaxLockCount(gzULong maxCount);
00366
00367 gzVoid unLock() const;
00368
00369 gzULong getOwnerValue() const;
00370
00371 gzULong getSpinLockCount() const;
00372
00373 private:
00374
00375 gzULong m_maxCount;
00376 gzMutex m_locker;
00377 mutable gzULong m_currentValue;
00378 mutable gzULong m_counter;
00379 mutable gzEvent m_waiter;
00380 };
00381
00382 #define GZ_SEMA_READ (0)
00383 #define GZ_SEMA_WRITE (gzThread::getThreadID())
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 #define GZ_DECLARE_RECYCLE_DATA_EXPORT(moduleName,exportDef) template <class T> class gzRecycleData_##moduleName\
00400 { \
00401 public: \
00402 \
00403 gzRecycleData_##moduleName() \
00404 { \
00405 s_recycleDataLock.waitLock(); \
00406 \
00407 if(s_recycleData.first()) \
00408 { \
00409 m_data=s_recycleData.first(); \
00410 \
00411 s_recycleData.removeFirst(); \
00412 \
00413 m_needNew=FALSE; \
00414 \
00415 } \
00416 else \
00417 { \
00418 m_data=new gzRefData<T>; \
00419 \
00420 m_needNew=TRUE; \
00421 } \
00422 \
00423 m_needInit=TRUE; \
00424 \
00425 s_recycleDataLock.unLock(); \
00426 } \
00427 \
00428 gzRecycleData_##moduleName(const T ©) \
00429 { \
00430 s_recycleDataLock.waitLock(); \
00431 \
00432 if(s_recycleData.first()) \
00433 { \
00434 m_data=s_recycleData.first(); \
00435 \
00436 s_recycleData.removeFirst(); \
00437 } \
00438 else \
00439 { \
00440 m_data=new gzRefData<T>; \
00441 } \
00442 \
00443 m_needNew=FALSE; \
00444 m_needInit=FALSE; \
00445 \
00446 *m_data.get()=copy; \
00447 \
00448 s_recycleDataLock.unLock(); \
00449 } \
00450 \
00451 virtual ~gzRecycleData_##moduleName() \
00452 { \
00453 s_recycleDataLock.waitLock(); \
00454 \
00455 if(!m_needNew && s_enabled) \
00456 if(s_recycleData.entries()<s_maxStorageCount) \
00457 s_recycleData.pre_insert(m_data); \
00458 \
00459 m_data=NULL; \
00460 \
00461 s_recycleDataLock.unLock(); \
00462 } \
00463 \
00464 \
00465 virtual gzVoid onNewItem(T & data) const {}; \
00466 virtual gzVoid onInitItem(T & data) const {}; \
00467 \
00468 operator T &() \
00469 { \
00470 if(m_needInit) \
00471 { \
00472 m_needInit=FALSE; \
00473 \
00474 if(m_needNew) \
00475 { \
00476 m_needNew=FALSE; \
00477 onNewItem(*m_data.get()); \
00478 } \
00479 onInitItem(*m_data.get()); \
00480 } \
00481 \
00482 return (T &)*m_data.get(); \
00483 } \
00484 \
00485 operator const T &() const \
00486 { \
00487 if(m_needInit) \
00488 { \
00489 m_needInit=FALSE; \
00490 \
00491 if(m_needNew) \
00492 { \
00493 m_needNew=FALSE; \
00494 onNewItem(*m_data.get()); \
00495 } \
00496 onInitItem(*m_data.get()); \
00497 } \
00498 \
00499 return (T &)*m_data.get(); \
00500 } \
00501 \
00502 T & getRecycledInstance() \
00503 { \
00504 if(m_needInit) \
00505 { \
00506 m_needInit=FALSE; \
00507 \
00508 if(m_needNew) \
00509 { \
00510 m_needNew=FALSE; \
00511 onNewItem(*m_data.get()); \
00512 } \
00513 onInitItem(*m_data.get()); \
00514 } \
00515 \
00516 return (T &)*m_data.get(); \
00517 } \
00518 \
00519 gzVoid init() \
00520 { \
00521 if(m_needInit) \
00522 { \
00523 m_needInit=FALSE; \
00524 \
00525 if(m_needNew) \
00526 { \
00527 m_needNew=FALSE; \
00528 onNewItem(*m_data.get()); \
00529 } \
00530 onInitItem(*m_data.get()); \
00531 } \
00532 } \
00533 \
00534 static gzVoid clearRecycledData() \
00535 { \
00536 s_recycleDataLock.waitLock(); \
00537 s_recycleData.clear(); \
00538 s_recycleDataLock.unLock(); \
00539 } \
00540 \
00541 gzRecycleData_##moduleName &operator=(const gzRecycleData_##moduleName &data) \
00542 { \
00543 if(m_needInit) \
00544 { \
00545 m_needInit=FALSE; \
00546 \
00547 if(m_needNew) \
00548 { \
00549 m_needNew=FALSE; \
00550 onNewItem(*m_data.get()); \
00551 } \
00552 onInitItem(*m_data.get()); \
00553 } \
00554 \
00555 if(data.m_needInit) \
00556 { \
00557 data.m_needInit=FALSE; \
00558 \
00559 if(data.m_needNew) \
00560 { \
00561 data.m_needNew=FALSE; \
00562 data.onNewItem(*data.m_data.get()); \
00563 } \
00564 data.onInitItem(*data.m_data.get()); \
00565 } \
00566 \
00567 ((T &)*m_data.get())=((T &)*data.m_data.get()); \
00568 \
00569 return *this; \
00570 } \
00571 \
00572 gzRecycleData_##moduleName(const gzRecycleData_##moduleName &data) \
00573 { \
00574 s_recycleDataLock.waitLock(); \
00575 \
00576 if(s_recycleData.first()) \
00577 { \
00578 m_data=s_recycleData.first(); \
00579 \
00580 s_recycleData.removeFirst(); \
00581 \
00582 } \
00583 else \
00584 { \
00585 m_data=new gzRefData<T>; \
00586 } \
00587 \
00588 m_needInit=FALSE; \
00589 m_needNew=FALSE; \
00590 \
00591 s_recycleDataLock.unLock(); \
00592 \
00593 \
00594 if(data.m_needInit) \
00595 { \
00596 data.m_needInit=FALSE; \
00597 \
00598 if(data.m_needNew) \
00599 { \
00600 data.m_needNew=FALSE; \
00601 data.onNewItem(*data.m_data.get()); \
00602 } \
00603 data.onInitItem(*data.m_data.get()); \
00604 } \
00605 \
00606 ((T &)*m_data.get())=((T &)*data.m_data.get()); \
00607 \
00608 } \
00609 \
00610 T& operator=(const T &data) \
00611 { \
00612 if(m_needInit) \
00613 { \
00614 m_needInit=FALSE; \
00615 \
00616 if(m_needNew) \
00617 { \
00618 m_needNew=FALSE; \
00619 onNewItem(*m_data.get()); \
00620 } \
00621 onInitItem(*m_data.get()); \
00622 } \
00623 \
00624 ((T &)*m_data.get())=data; \
00625 return ((T &)*m_data.get()); \
00626 } \
00627 \
00628 T * operator ->() const \
00629 { \
00630 if(m_needInit) \
00631 { \
00632 m_needInit=FALSE; \
00633 \
00634 if(m_needNew) \
00635 { \
00636 m_needNew=FALSE; \
00637 onNewItem(*m_data.get()); \
00638 } \
00639 onInitItem(*m_data.get()); \
00640 } \
00641 \
00642 return &((T &)*m_data.get()); \
00643 } \
00644 \
00645 static gzVoid setMaxStorageCount(gzULong count) \
00646 { \
00647 s_recycleDataLock.waitLock(); \
00648 s_maxStorageCount=count; \
00649 s_recycleDataLock.unLock(); \
00650 } \
00651 \
00652 static gzVoid enable() \
00653 { \
00654 s_recycleDataLock.waitLock(); \
00655 s_enabled=TRUE; \
00656 s_recycleDataLock.unLock(); \
00657 } \
00658 \
00659 static gzVoid disable() \
00660 { \
00661 s_recycleDataLock.waitLock(); \
00662 s_enabled=FALSE; \
00663 s_recycleData.clear(); \
00664 s_recycleDataLock.unLock(); \
00665 } \
00666 \
00667 static gzVoid reuseLinks(gzBool on) \
00668 { \
00669 s_recycleDataLock.waitLock(); \
00670 s_recycleData.reuseLinks(on); \
00671 s_recycleDataLock.unLock(); \
00672 } \
00673 \
00674 private: \
00675 \
00676 gzRefPointer<gzRefData<T> > m_data; \
00677 \
00678 \
00679 mutable gzBool m_needInit:1; \
00680 mutable gzBool m_needNew:1; \
00681 \
00682 \
00683 exportDef static gzBool s_enabled; \
00684 exportDef static gzULong s_maxStorageCount; \
00685 exportDef static gzMutex s_recycleDataLock; \
00686 exportDef static gzRefList<gzRefData<T> > s_recycleData; \
00687 \
00688 };
00689
00690 #define GZ_DECLARE_RECYCLE_DATA_EXPORT_IMP(moduleName) template <class T> gzMutex gzRecycleData_##moduleName<T>::s_recycleDataLock=gzMutex(FALSE); template <class T> gzRefList<gzRefData<T> > gzRecycleData_##moduleName<T>::s_recycleData=gzRefList<gzRefData<T> >(FALSE); template <class T> gzULong gzRecycleData_##moduleName<T>::s_maxStorageCount=0xfffffffful; template <class T> gzBool gzRecycleData_##moduleName<T>::s_enabled=TRUE;
00691
00692
00693 #define gzRecycleDataExport(moduleName) gzRecycleData_##moduleName
00694
00695
00696
00697 #define COMMON_EXPORT // Empty definition
00698
00699 GZ_DECLARE_RECYCLE_DATA_EXPORT(gzBase, COMMON_EXPORT);
00700
00701 #define gzRecycleData gzRecycleDataExport(gzBase)
00702 #define GZ_DECLARE_RECYCLE_DATA_IMP GZ_DECLARE_RECYCLE_DATA_EXPORT_IMP(gzBase)
00703
00704 #endif