00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef UT_LOCKUTILS_H
00020 #define UT_LOCKUTILS_H
00021
00022 #include "UT_API.h"
00023 #include "UT_PtrArray.h"
00024 #include <stdio.h>
00025
00026
00027
00028 class UT_NullLock {
00029 public:
00030 explicit UT_NullLock(int = 0, bool = false) {}
00031
00032 bool lock(int) { return true; }
00033 bool lockLW(int) { return true; }
00034 bool lockNap(int) { return true; }
00035 void lock() {}
00036 void lockLW() {}
00037 void lockNap() {}
00038 void unlock() {}
00039 bool isLocked() { return false; }
00040 };
00041
00042
00043
00044
00045
00046
00047 template <class Lock>
00048 class UT_AutoLockType
00049 {
00050 public:
00051 UT_AutoLockType(Lock &lock)
00052 : myLock(lock)
00053 { lock.lockLW(); }
00054
00055 ~UT_AutoLockType() { myLock.unlock(); }
00056
00057 private:
00058 Lock &myLock;
00059 };
00060
00061 template <class Lock>
00062 class UT_DebugLockType
00063 {
00064 public:
00065 UT_DebugLockType(const char *name, int lockstate=0, bool threadlock=false)
00066 : myLock(lockstate, threadlock),
00067 myName(name)
00068 { }
00069 UT_DebugLockType(const UT_DebugLockType &rhs)
00070 : myLock(rhs.myLock),
00071 myName(rhs.myName)
00072 { }
00073 ~UT_DebugLockType()
00074 {
00075 fprintf(stderr, "Lock[%s]: %d collisions\n",
00076 myName, myLock.getCollisions());
00077 }
00078
00079 bool lock(int ntrials) { return myLock.lock(ntrials); }
00080 bool lockLW(int ntrials) { return myLock.lockLW(ntrials); }
00081 bool lockNap(int ntrials) { return myLock.lockNap(ntrials); }
00082
00083 void lock() { myLock.lock(); }
00084 void lockLW() { myLock.lockLW(); }
00085 void lockNap() { myLock.lockNap(); }
00086
00087 void unlock() { myLock.unlock(); }
00088
00089 bool isLocked() { return myLock.isLocked(); }
00090 private:
00091 Lock myLock;
00092 const char *myName;
00093 };
00094
00095
00096
00097 template <class Lock>
00098 class UT_ObjLockType {
00099 public:
00100 UT_ObjLockType(int capacity = 256)
00101 {
00102 setCapacity(capacity);
00103 }
00104 ~UT_ObjLockType()
00105 {
00106 clear();
00107 }
00108
00109 void setCapacity(int capacity)
00110 {
00111 if (myObjs.entries() < capacity)
00112 {
00113 myCapacity = capacity;
00114 myObjs.resize(myCapacity);
00115 }
00116 }
00117 int lock(void *obj)
00118 {
00119 int ident = -1;
00120 int i;
00121
00122 myAccessLock.lock();
00123 for (i = 0; i < myObjs.entries(); i++)
00124 {
00125 if (myObjs(i)->myObj == obj)
00126 {
00127 ident = i;
00128 break;
00129 }
00130 if (!myObjs(i)->myRefCount)
00131 ident = i;
00132 }
00133 if (ident < 0)
00134 {
00135 UT_ASSERT(myObjs.entries() < myCapacity);
00136 myObjs.append(new ut_ObjLockEntry());
00137 ident = myObjs.entries()-1;
00138 }
00139
00140
00141 myObjs(ident)->myObj = obj;
00142 myObjs(ident)->myRefCount++;
00143 myAccessLock.unlock();
00144 myObjs(ident)->myLock.lock();
00145 return ident;
00146 }
00147
00148 void unlock(void *obj, int ident)
00149 {
00150
00151 myObjs(ident)->myLock.unlock();
00152 myAccessLock.lock();
00153 UT_ASSERT(myObjs(ident)->myObj == obj);
00154 myObjs(ident)->myRefCount--;
00155 if (!myObjs(ident)->myRefCount)
00156 myObjs(ident)->myObj = 0;
00157 myAccessLock.unlock();
00158 }
00159
00160 private:
00161 void clear()
00162 {
00163 int i;
00164
00165 for (i = 0; i < myObjs.entries(); i++)
00166 delete myObjs(i);
00167 myObjs.entries(0);
00168 }
00169
00170 class ut_ObjLockEntry
00171 {
00172 public:
00173 ut_ObjLockEntry()
00174 {
00175 myObj = 0;
00176 myRefCount = 0;
00177 }
00178
00179 Lock myLock;
00180 void *myObj;
00181 int myRefCount;
00182 };
00183
00184 public:
00185 Lock myAccessLock;
00186 UT_PtrArray<ut_ObjLockEntry *> myObjs;
00187 int myCapacity;
00188 };
00189
00190 template <class Lock>
00191 class UT_AutoObjLockType
00192 {
00193 public:
00194 UT_AutoObjLockType(UT_ObjLockType<Lock> &lock, void *obj)
00195 : myLock(lock)
00196 , myObj(obj)
00197 { myId = lock.lock(myObj); }
00198
00199 ~UT_AutoObjLockType() { myLock.unlock(myObj, myId); }
00200
00201 private:
00202 UT_ObjLockType<Lock> &myLock;
00203 void *myObj;
00204 int myId;
00205 };
00206
00207 #endif
00208