QuitThread() to safely quit a thread instead of killing it.
Posted: Sun Sep 13, 2009 4:47 pm
I really wish PureBasic had a loop check like Until QuitThread you know kinda like Until ForEver
And a QuitThread(thread) function that is similar to setting QuitThread to #True
But for now, the way I do it here kinda simulate such behaviour.
As to ThreadPriority, Maybe PB could do a ThreadPriority(#PB_Any,priority) for the thread to refer to itself?
There's a silly hack in this source, hence why I didn't post this in Tips'n'Tricks,
I guess I could have used a global list of threads, but this is just a proof of concept really.
And a QuitThread(thread) function that is similar to setting QuitThread to #True
But for now, the way I do it here kinda simulate such behaviour.
As to ThreadPriority, Maybe PB could do a ThreadPriority(#PB_Any,priority) for the thread to refer to itself?
There's a silly hack in this source, hence why I didn't post this in Tips'n'Tricks,
I guess I could have used a global list of threads, but this is just a proof of concept really.
Code: Select all
EnableExplicit
;Public Domain, created by Rescator.
Structure ThreadEx
*thismemory
ThreadID.i
QuitThread.i
Parameter.i
EndStructure
Procedure.i CreateThreadEx(*proc,param.i)
Protected *ThreadEx.ThreadEx
*ThreadEx=AllocateMemory(SizeOf(ThreadEx))
If *ThreadEx
*ThreadEx\QuitThread=#False
*ThreadEx\Parameter=param
*ThreadEx\ThreadID=CreateThread(*proc,*ThreadEx)
If Not *ThreadEx\ThreadID
FreeMemory(*ThreadEx)
*ThreadEx=#Null
EndIf
EndIf
ProcedureReturn *ThreadEx
EndProcedure
Procedure.i QuitThreadEx(*ThreadEx.ThreadEx,TimeOut.l=-1)
Protected result.i
If *ThreadEx
If *ThreadEx=*ThreadEx\thismemory ;Silly "hack" to avoid double freeing and crashes etc.
If IsThread(*ThreadEx\ThreadID)
*ThreadEx\QuitThread=#True
If TimeOut=-1
result=WaitThread(*ThreadEx\ThreadID)
Else
result=WaitThread(*ThreadEx\ThreadID,TimeOut)
EndIf
Else
result=#True
EndIf
If result
*ThreadEx\thismemory=#Null
FreeMemory(*ThreadEx)
EndIf
EndIf
EndIf
ProcedureReturn result
EndProcedure
Procedure.i ThreadPriorityEx(*ThreadEx.ThreadEx,Priority.i)
Protected result.i
result=ThreadPriority(*ThreadEx\ThreadID,Priority)
ProcedureReturn result
EndProcedure
Procedure.i IsThreadEx(*ThreadEx.ThreadEx)
Protected result.i
ThreadPriorityEx(*ThreadEx,16) ;<-- a neat bonus feature huh?
If *ThreadEx
result=IsThread(*ThreadEx\ThreadID)
EndIf
ProcedureReturn result
EndProcedure
;Let's do a simple example to show how this works.
Procedure.i test(*ThreadEx.ThreadEx)
Repeat
Delay(1000)
Debug "WooHoo!"
Until *ThreadEx\QuitThread
EndProcedure
;If the thread itself need to quit use Break (preffered) or *ThreadEx\QuitThread=#True or similar methods.
;Remember to use QuitThread() later though to free the memory we allocated earlier etc.
Define event.i,quit.i,threadex.i
threadex=CreateThreadEx(@test(),#Null)
If OpenWindow(1,100,200,195,260,"PureBasic Window",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget)
Repeat
event=WaitWindowEvent()
If event=#PB_Event_CloseWindow
quit=#True
EndIf
Until quit=#True
EndIf
QuitThreadEx(threadex)
;Look, no crash, no forced thread termination at program end, a very nicely behaved program here :)