00001 00008 #define DKUTIL_C_THREAD_LOCK_C 00009 00010 #include "dkcThreadLock.h" 00011 #include "dkcStdio.h" 00012 00013 00014 00015 DKC_THREAD_LOCK * WINAPI dkcAllocThreadLock(){ 00016 DKC_THREAD_LOCK *p = (DKC_THREAD_LOCK *)dkcAllocate(sizeof(DKC_THREAD_LOCK)); 00017 if(NULL==p){ 00018 return NULL; 00019 } 00020 #ifdef WIN32 00021 InitializeCriticalSection(&(p->m_csCriticalSection)); 00022 00023 #else 00024 pthread_mutex_init(&(p->mMutex), NULL); // POSIX 00025 00026 #endif 00027 p->mLockedThread = dkcdINVALID_THREAD_ID; 00028 p->mLockCount = 0; 00029 00030 return p; 00031 } 00032 00033 int WINAPI dkcFreeThreadLock(DKC_THREAD_LOCK **pp){ 00034 const char *asstr = "dkcThreadLockをLockした回数だけUnlockしないまま終了している"; 00035 if(NULL==pp || NULL==*pp){ 00036 return edk_ArgumentException; 00037 } 00038 if ((*pp)->mLockCount!=0) { 00039 int i; 00040 dkcmNOT_ASSERT(asstr); 00041 for(i=0;i<(*pp)->mLockCount;i++){ 00042 dkcThreadLock_Unlock((*pp)); 00043 } 00044 } 00045 #ifdef WIN32 00046 DeleteCriticalSection(&((*pp)->m_csCriticalSection)); 00047 #else 00048 pthread_mutex_destroy(&((*pp)->mMutex)); 00049 #endif 00050 if ((*pp)->mLockCount!=0) { 00051 dkcmFORCE_NOT_ASSERT(asstr); 00052 } 00053 return dkcFree((void **)pp); 00054 } 00055 00056 void WINAPI dkcThreadLock_Lock(DKC_THREAD_LOCK *p){ 00057 dkcmFORCE_NOT_ASSERT(NULL==p); 00058 #ifdef WIN32 00059 EnterCriticalSection(&(p->m_csCriticalSection)); 00060 // ↑異なるスレッドからここに入ってくることはできない 00061 // (CriticalSectionの定義より) 00062 #else 00063 pthread_mutex_lock(&(p->mMutex)); 00064 00065 #endif 00066 p->mLockedThread = dkcGetThreadID(); 00067 00068 p->mLockCount++; 00069 } 00070 00071 00072 void WINAPI dkcThreadLock_Unlock(DKC_THREAD_LOCK *p){ 00073 dkcmFORCE_NOT_ASSERT(NULL==p); 00074 00075 if (p->mLockCount==0){ 00076 dkcmNOT_ASSERT("CriticalSectionManagerをEnterしていないのにLeaveしている"); 00077 } 00078 00079 if ((--(p->mLockCount))==0) { 00080 p->mLockedThread = dkcdINVALID_THREAD_ID; 00081 } 00082 #ifdef WIN32 00083 // ↑Leaveした直後に他スレッドがEnterする可能性がある 00084 LeaveCriticalSection(&(p->m_csCriticalSection)); 00085 #else 00086 pthread_mutex_unlock(&(p->mMutex)); 00087 #endif 00088 } 00089 00090 /* 00091 BOOL WINAPI dkcThreadLockIsInited(DKC_THREAD_LOCK *){ 00092 00093 } 00094 */ 00095 BOOL WINAPI dkcThreadLockIsLockedByThisThread(DKC_THREAD_LOCK *p) 00096 { 00097 dkctThreadID dw; 00098 00099 dkcmFORCE_NOT_ASSERT(NULL==p); 00100 dw = dkcGetThreadID(); 00101 00102 return (p->mLockedThread == dw); 00103 } 00104 00105 00106 /* 00107 static CRITICAL_SECTION g_csCriticalSection; 00108 static DWORD g_dwLockedThread = 0; // LockしているThreadId(0:非Lock) 00109 static int gLockCount = 0; // Lockされている回数 00110 // (同一スレッドならば複数回Lockできるので) 00111 //初期化しているかどうかフラグ。 00112 static BOOL gInited = FALSE; 00113 00114 00115 00116 static void Init(){ 00117 { 00118 if(TRUE==gInited){return;} 00119 } 00120 InitializeCriticalSection(&g_csCriticalSection); 00121 g_dwLockedThread = (DWORD)-1; 00122 gLockCount = 0; 00123 # ifdef DEBUG 00124 ODS("dkcLockThreadInit\n"); 00125 # endif 00126 gInited = TRUE; 00127 } 00128 00129 static void End(){ 00130 { 00131 if(FALSE==gInited){return;} 00132 } 00133 DeleteCriticalSection(&g_csCriticalSection); 00134 gInited = FALSE; 00135 memset(&g_csCriticalSection,0,sizeof(g_csCriticalSection)); 00136 if (gLockCount!=0) { 00137 dkcmNOT_ASSERT("dkcThreadLockをLockした回数だけUnlockしないまま終了している"); 00138 } 00139 # ifdef DEBUG 00140 ODS("dkcLockThreadEnd\n"); 00141 # endif 00142 } 00143 00144 00146 static void Enter(){ 00147 if(FALSE==gInited){ 00148 dkcmFORCE_NOT_ASSERT("dkcThreadLockInit()で初期化していない"); 00149 return; 00150 } 00151 EnterCriticalSection(&g_csCriticalSection); 00152 00153 g_dwLockedThread = GetCurrentThreadId(); 00154 // ↑異なるスレッドからここに入ってくることはできない 00155 // (CriticalSectionの定義より) 00156 gLockCount++; 00157 00158 } 00159 00161 static void Leave(){ 00162 if(FALSE==gInited){ 00163 dkcmFORCE_NOT_ASSERT("dkcThreadLockInit()で初期化していない"); 00164 return; 00165 } 00166 if (gLockCount==0){ 00167 dkcmNOT_ASSERT("CriticalSectionManagerをEnterしていないのにLeaveしている"); 00168 } 00169 00170 if (--gLockCount==0) { 00171 g_dwLockedThread = (DWORD)-1; 00172 } 00173 // ↑Leaveした直後に他スレッドがEnterする可能性がある 00174 LeaveCriticalSection(&g_csCriticalSection); 00175 } 00176 00177 BOOL WINAPI dkcThreadLockIsLockedByThisThread(){ 00178 DWORD dw = GetCurrentThreadId(); 00179 return (g_dwLockedThread == dw); 00180 } 00181 00182 BOOL WINAPI dkcThreadLockIsInited() 00183 { 00184 return gInited; 00185 } 00186 00187 void WINAPI dkcThreadLockInit(){ 00188 Init(); 00189 } 00190 00191 void WINAPI dkcThreadLock_Lock(){ 00192 Enter(); 00193 } 00194 00195 void WINAPI dkcThreadLock_Unlock(){ 00196 Leave(); 00197 } 00198 00199 void WINAPI dkcThreadLockEnd(){ 00200 End(); 00201 } 00202 */