Update v0.01.1
Code: Select all
;-TOP
; Comment : ThreadSafe Counter as Object or Standard Call
; Author : mk-soft
; Version : v0.01.1
; Create : 13.02.2021
DeclareModule Counter
Interface iCounter
Free(Force = #False)
Incr()
Decr()
Get()
EndInterface
Declare New()
; For direct call without interface
Declare Free(*this, Force = #False)
Declare Incr(*this)
Declare Decr(*this)
Declare Get(*this)
EndDeclareModule
Module Counter
Structure udtCounter
*vTable
counter.i
mutex.i
EndStructure
Procedure New()
Protected *mem.udtCounter
*mem = AllocateStructure(udtCounter)
If *mem
*mem\vTable = ?vTable
*mem\mutex = CreateMutex()
EndIf
ProcedureReturn *mem
EndProcedure
Procedure Free(*this.udtCounter, Force = #False)
With *this
LockMutex(\mutex)
If Force Or \counter = 0
UnlockMutex(\mutex)
FreeMutex(\mutex)
FreeStructure(*this)
ProcedureReturn #True
Else
UnlockMutex(\mutex)
ProcedureReturn #False
EndIf
EndWith
EndProcedure
Procedure Incr(*this.udtCounter)
Protected r1
With *this
LockMutex(\mutex)
\counter + 1
r1 = \counter
UnlockMutex(\mutex)
ProcedureReturn r1
EndWith
EndProcedure
Procedure Decr(*this.udtCounter)
Protected r1
With *this
LockMutex(\mutex)
If \counter
\counter - 1
EndIf
r1 = \counter
UnlockMutex(\mutex)
ProcedureReturn r1
EndWith
EndProcedure
Procedure Get(*this.udtCounter)
Protected r1
With *this
LockMutex(\mutex)
r1 = \counter
UnlockMutex(\mutex)
ProcedureReturn r1
EndWith
EndProcedure
DataSection
vTable:
Data.i @Free()
Data.i @Incr()
Data.i @Decr()
Data.i @Get()
EndDataSection
EndModule
; ****
CompilerIf #PB_Compiler_IsMainFile
CompilerIf Not #PB_Compiler_Thread
CompilerError "Use Compiler Option ThreadSafe!"
CompilerEndIf
EnableExplicit
Global cntThreads.Counter::iCounter = Counter::New()
Procedure thWork(Number)
Debug "Start Thread Number " + Number
Delay(Random(1000, 200))
Debug "Stop Thread Number " + Number
cntThreads\Decr()
EndProcedure
Define i, thread
For i = 1 To 50
cntThreads\Incr()
thread = CreateThread(@thWork(), i)
If Not thread
cntThreads\Decr()
EndIf
Delay(10)
Next
While cntThreads\Get()
Delay(100)
Wend
cntThreads\Free()
CompilerEndIf