UWSCで排他制御
いろいろ検討したけど、CreateMutexが良い模様。
以下は、検討したスクリプト。
SemaphoreとCriticalSectionは面倒になった。
ただの排他なら、Mutexで良いことがわかった。
パラメーターでの排他は、アトミックじゃないことはわかってるけど、大きく違うなら優位かと思ったのだけど、、、。
今後必要になったら、Mutex部分のみ切り出せばOK。
OPTION EXPLICIT CONST num = 16 PUBLIC _bThread[num] DIM i Mutex.Init(4) FOR i = 1 TO num _bThread[i] = TRUE THREAD TestThread(i) NEXT DIM loop = TRUE WHILE loop loop = FALSE FOR i = 1 TO num loop = loop OR _bThread[i] IF loop THEN BREAK NEXT SLEEP(1) WEND Mutex.Release() FUNCTION Log(msg, t=0) DIM n = GETTIME() * 1000 + G_TIME_ZZ DIM buf = G_TIME_NN2 + ":" + G_TIME_SS2 + "." + G_TIME_ZZ2 + " " + msg IF t > 0 THEN buf = buf + "(" + (n - t) + ")" PRINT buf RESULT = n FEND PROCEDURE TestThread(id) DIM s = Log("TestThread init " + id) Log("TestThread start " + id + " " + Mutex.Lock(id)) SLEEP(0.1) Log("TestThread end " + id, s) Log("TestThread fin " + id + " " + Mutex.Unlock(id), s) _bThread[id] = FALSE FEND MODULE Mutex CONST _wait = 0.001 // ロック機構は、Mutex/Semaphore/Event/CriticalSection等がある PUBLIC _mode = 1 DIM _id = 0 DIM _handle DEF_DLL CloseHandle(dword): bool: kernel32.dll DEF_DLL GetLastError(): dword: kernel32.dll DEF_DLL WaitForSingleObject(dword, dword): dword: kernel32.dll CONST WAIT_FAILED = $FFFFFFFF CONST WAIT_OBJECT_0 = 0 CONST WAIT_ABANDONED = $80 CONST WAIT_TIMEOUT = 258 // Mutex用 DEF_DLL CreateMutexA(dword, bool, string): dword: kernel32.dll DEF_DLL ReleaseMutex(dword): bool: kernel32.dll // Event用 DEF_DLL CreateEventA(dword, bool, bool, string): dword: kernel32.dll DEF_DLL SetEvent(dword): bool: kernel32.dll // CriticalSection、、、はちょっと断念 // 3.812 PROCEDURE InitPara() _mode = 1 _id = 0 FEND FUNCTION TryLockPara(id) RESULT = FALSE IFB _id = 0 THEN _id = id SLEEP(_wait) RESULT = (_id = id) ENDIF FEND FUNCTION UnlockPara(id) RESULT = (_id = id) IF RESULT THEN _id = 0 FEND FUNCTION ReleasePara() RESULT = TRUE FEND // 優位差は見られない PROCEDURE InitMutex() _mode = 2 _id = 0 _handle = CreateMutexA(NULL, FALSE, NULL) FEND FUNCTION TryLockMutex(id) RESULT = FALSE DIM ret = WaitForSingleObject(_handle, 0) IFB ret = WAIT_OBJECT_0 THEN _id = id RESULT = TRUE ENDIF FEND FUNCTION UnlockMutex(id) RESULT = (_id = id) IFB RESULT THEN IF !ReleaseMutex(_handle) THEN Log("UnlockMutex ReleaseMutex Error " + GetLastError()) _id = 0 ENDIF FEND FUNCTION CloseMutex() RESULT = CloseHandle(_handle) IF !RESULT THEN Log("CloseMutex CloseHandle Error " + GetLastError()) FEND PROCEDURE InitSemaphore() _mode = 3 _id = 0 FEND FUNCTION TryLockSemaphore(id) RESULT = FALSE SLEEP(_wait) IFB _id = 0 THEN _id = id SLEEP(_wait) IFB _id = id THEN RESULT = TRUE ENDIF ENDIF FEND FUNCTION UnlockSemaphore(id) RESULT = (_id = id) IF RESULT THEN _id = 0 FEND FUNCTION ReleaseSemaphore() RESULT = TRUE FEND // 優位差は見られない PROCEDURE InitEvent() _mode = 4 _id = 0 _handle = CreateEventA(NULL, FALSE, TRUE, NULL) FEND FUNCTION TryLockEvent(id) RESULT = FALSE DIM ret = WaitForSingleObject(_handle, 0) IFB ret = WAIT_OBJECT_0 THEN _id = id RESULT = TRUE ENDIF FEND FUNCTION UnlockEvent(id) RESULT = (_id = id) IFB RESULT THEN IF !SetEvent(_handle) THEN Log("UnlockEvent SetEvent Error " + GetLastError()) _id = 0 ENDIF FEND FUNCTION ReleaseEvent() RESULT = CloseHandle(_handle) IF !RESULT THEN Log("ReleaseEvent CloseHandle Error " + GetLastError()) FEND PROCEDURE InitCriticalSection() _mode = 5 _id = 0 FEND FUNCTION TryLockCriticalSection(id) RESULT = FALSE SLEEP(_wait) IFB _id = 0 THEN _id = id SLEEP(_wait) IFB _id = id THEN RESULT = TRUE ENDIF ENDIF FEND FUNCTION UnlockCriticalSection(id) RESULT = (_id = id) IF RESULT THEN _id = 0 FEND FUNCTION ReleaseCriticalSection() RESULT = TRUE FEND PROCEDURE Init(mode) SELECT mode CASE 1 InitPara() CASE 2 InitMutex() CASE 3 InitSemaphore() CASE 4 InitEvent() CASE 5 InitCriticalSection() SELEND FEND FUNCTION TryLock(id) SELECT _mode CASE 1 RESULT = TryLockPara(id) CASE 2 RESULT = TryLockMutex(id) CASE 3 RESULT = TryLockSemaphore(id) CASE 4 RESULT = TryLockEvent(id) CASE 5 RESULT = TryLockCriticalSection(id) SELEND FEND FUNCTION Lock(id) RESULT = TRUE WHILE !TryLock(id) SLEEP(_wait) WEND FEND FUNCTION Unlock(id) SELECT _mode CASE 1 RESULT = UnlockPara(id) CASE 2 RESULT = UnlockMutex(id) CASE 3 RESULT = UnlockSemaphore(id) CASE 4 RESULT = UnlockEvent(id) CASE 5 RESULT = UnlockCriticalSection(id) SELEND FEND FUNCTION Release() SELECT _mode CASE 1 RESULT = ReleasePara() CASE 2 RESULT = CloseMutex() CASE 3 RESULT = ReleaseSemaphore() CASE 4 RESULT = ReleaseEvent() CASE 5 RESULT = ReleaseCriticalSection() SELEND FEND ENDMODULE