Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

BlitzMax/Modules/System/Threads

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

Welcome to the weird and wonderful world of multithreading! Multithreading effectively allows your programs to do several things at the same time. The word 'thread' in this context means 'thread of execution' - or, the series of instructions, branches and so on executed by your program. Most programs are 'single threaded', meaning there is only one thread of execution. However, more and more programs are using multiple threads. Multithreading used to be achieved by software trickery, which made threading useful but not really faster - there was still only one CPU pretending to do multiple things at the same time! But these days, multicore CPUs mean that threading can be used to truly do multiple things at the same time (or 'in parallel'). Creating a thread is easy - just call CreateThread. You will need to provide a function for the thread to use as its 'entry point'. Once the thread is created, this function will start executing in parallel with the code that called CreateThread. When the thread function returns, that thread will be 'terminated'. Alas, threading turns out to be rather tricky due to an issue known as 'synchronization'. Synchronization is required when you need to prevent multiple threads from modifying or accessing the same data at the same time. Synchronization usually involves a thread 'blocking'. When a thread blocks, it completely halts execution until another thread does something that causes it to 'unblock' and resume execution. BlitzMax provides 2 primitives known as 'mutexes' and 'semaphores' to assist with synchronization: Mutexes provide a simple locking mechanism. Only one thread at a time can lock a mutex (using LockMutex or TryLockMutex), so this is an easy way to protect resources from simultaneous access. If a thread calls LockMutex and the mutex is already locked by another thread, the current thread will block until the other thread releases the mutex using UnlockMutex. So don't forget to UnlockMutex a mutex after you are finished with it! Semaphores provide a synchronized counting mechanism, and contain an internal integer counter. There are 2 operations you can perform on a semaphore - post and wait. Posting a semaphore (using PostSemaphore) causes the semaphore's internal counter to be incremented, while waiting for a semaphore (using WaitSemaphore) will cause the current thread to block until the semaphore's internal counter is greater than 0. When it is, the counter is decremented and the thread unblocks. Semaphores are very useful for producer/consumer type situations. Types TThread Thread Type Methods Detach Wait Running Functions Create Main Current TThread: Methods Detach Method Detach() Description: Detach this thread Wait Method Wait:Object() Description: Wait For this thread To finish Returns: The Object returned by the thread. Running Method Running() Description: Check if this thread is running TThread: Functions Create Function Create:TThread( entry:Object( data:Object),data:Object ) Description: Create a new thread Main Function Main:TThread() Description: Get Main thread Returns: A thread object representing the main application thread. Current Function Current:TThread() Description: Get current thread Returns: A thread object representing the current thread. TThreadData ThreadData type Methods SetValue GetValue Functions Create TThreadData: Methods SetValue Method SetValue( value:Object ) Description: Set thread data value GetValue Method GetValue:Object() Description: Get thread data value TThreadData: Functions Create Function Create:TThreadData() Description: Create thread data TMutex Mutex type Methods Close Lock TryLock Unlock Functions Create TMutex: Methods Close Method Close() Description: Close the mutex Lock Method Lock() Description: Lock the mutex TryLock Method TryLock() Description: Try to lock the mutex Returns: True if mutex was successfully locked; False if mutex was already locked by another thread. Unlock Method Unlock() Description: Unlock the mutex TMutex: Functions Create Function Create:TMutex() Description: Create a new mutex TSemaphore Semaphore Type Methods Close Wait Post Functions Create TSemaphore: Methods Close Method Close() Description: Close the semaphore Wait Method Wait() Description: Wait for the semaphore Post Method Post() Description: Post the semaphore TSemaphore: Functions Create Function Create:TSemaphore( count ) Description: Create a new semaphore TCondVar CondVar type Methods Close Wait Signal Broadcast Functions Create TCondVar: Methods Close Method Close() Description: Close the condvar Wait Method Wait( mutex:TMutex ) Description: Wait for the condvar Signal Method Signal() Description: Signal the condvar Broadcast Method Broadcast() Description: Broadcast the condvar TCondVar: Functions Create Function Create:TCondVar() Description: Create a new condvar Functions CreateThread Function CreateThread:TThread( entry:Object( data:Object ),data:Object ) Description: Create a thread Returns: A new thread object. Information: Creates a thread and returns a thread object. The value returned by the thread entry routine can be later retrieved using WaitThread. To 'close' a thread, call either DetachThread or WaitThread. This isn't strictly necessary as the thread will eventually be closed when it is garbage collected, however, it may be a good idea if you are creating many threads very often, as some operating systems have a limit on the number of threads that can be allocated at once. Example: 'Make sure to have 'Threaded build' enabled! ' Strict 'Custom print that shows which thread is doing the printing Function MyPrint( t$ ) If CurrentThread()=MainThread() Print "Main thread: "+t Else Print "Child thread: "+t EndIf End Function 'Our thread function Function MyThread:Object( data:Object ) 'show data we were passed Myprint data.ToString() 'do some work For Local i=1 To 1000 MyPrint "i="+i Next 'return a value from the thread Return "Data returned from child thread." End Function MyPrint "About to start child thread." 'create a thread! Local thread:TThread=CreateThread( MyThread,"Data passed to child thread." ) 'wait for thread to finish and print value returned from thread MyPrint WaitThread( Thread ).ToString() MainThread Function MainThread:TThread() Description: Get Main thread Returns: A thread Object representing the Main application thread. CurrentThread Function CurrentThread:TThread() Description: Get current thread Returns: A thread object representing the current thread. DetachThread Function DetachThread( thread:TThread ) Description: Detach a thread Information: DetachThread closes a thread's handle, but does not halt or otherwise affect the target thread. Once one a thread has been detached, it wil no longer be possible to use WaitThread to get its return value. This allows the thread to run without your program having to continually check whether it has completed in order to close it. WaitThread Function WaitThread:Object( thread:TThread ) Description: Wait for a thread to finish Returns: The object returned by the thread entry routine. Information: WaitThread causes the calling thread to block until the target thread has completed execution. If the target thread has already completed execution, WaitThread returns immediately. The returned object is the object returned by the thread's entry routine, as passed to CreateThread. ThreadRunning Function ThreadRunning( thread:TThread ) Description: Check if a thread is running Returns: True if thread is still running, otherwise False. CreateThreadData Function CreateThreadData:TThreadData() Description: Create thread data Returns: A new thread data object. SetThreadDataValue Function SetThreadDataValue( data:TThreadData,value:Object ) Description: Set thread data value GetThreadDataValue Function GetThreadDataValue:Object( data:TThreadData ) Description: Get thread data value CreateMutex Function CreateMutex:TMutex() Description: Create a mutex Returns: A new mutex object Example: 'Make sure to have 'Threaded build' enabled! ' Strict 'a global list that multiple threads want to modify Global list:TList=New TList 'a mutex controlling access to the global list Global listMutex:TMutex=CreateMutex() Function MyThread:Object( data:Object ) For Local item=1 To 10 'simulate 'other' processing... Delay Rand( 10,50 ) 'lock mutex so we can safely modify global list LockMutex listMutex 'modify list list.AddLast "Thread "+data.ToString()+" added item "+item 'unlock mutex UnlockMutex listMutex Next End Function Local threads:TThread[10] 'Create worker threads For Local i=0 Until 10 threads[i]=CreateThread( MyThread,String( i+1 ) ) Next Print "Waiting for worker threads..." 'Wait for worker threads to finish For Local i=0 Until 10 WaitThread threads[i] Next 'Show the resulting list ' 'Note: We don't really have to lock the mutex here, as there are no other threads running. 'Still, it's a good habit to get into. LockMutex listMutex For Local t$=EachIn list Print t Next UnlockMutex listMutex CloseMutex Function CloseMutex( mutex:TMutex ) Description: Close a mutex LockMutex Function LockMutex( mutex:TMutex ) Description: Lock a mutex TryLockMutex Function TryLockMutex( mutex:TMutex ) Description: Try to lock a mutex Returns: True if mutex was successfully locked; False if mutex was already locked by another thread. UnlockMutex Function UnlockMutex( mutex:TMutex ) Description: Unlock a mutex CreateSemaphore Function CreateSemaphore:TSemaphore( count ) Description: Create a semaphore Returns: A new semaphore object Example: 'Make sure to have 'Threaded build' enabled! ' Strict 'a simple queue Global queue$[100],put,get 'a counter semaphore Global counter:TSemaphore=CreateSemaphore( 0 ) Function MyThread:Object( data:Object ) 'process 100 items For Local item=1 To 100 'add an item to the queue queue[put]="Item "+item put:+1 'increment semaphore count. PostSemaphore counter Next End Function 'create worker thread Local thread:TThread=CreateThread( MyThread,Null ) 'receive 100 items For Local i=1 To 100 'Wait for semaphore count to be non-0, then decrement. WaitSemaphore counter 'Get an item from the queue Local item$=queue[get] get:+1 Print item Next CloseSemaphore Function CloseSemaphore( semaphore:TSemaphore ) Description: Close a semaphore WaitSemaphore Function WaitSemaphore( semaphore:TSemaphore ) Description: Wait for a semaphore PostSemaphore Function PostSemaphore( semaphore:TSemaphore ) Description: Post a semaphore CreateCondVar Function CreateCondVar:TCondVar() Description: Create a condvar Returns: A new condvar object CloseCondVar Function CloseCondVar( condvar:TCondVar ) Description: Close a condvar WaitCondVar Function WaitCondVar( condvar:TCondVar,mutex:TMutex ) Description: Wait for a condvar SignalCondVar Function SignalCondVar( condvar:TCondVar ) Description: Signal a condvar BroadcastCondVar Function BroadcastCondVar( condvar:TCondVar ) Description: Broadcast a condvar CompareAndSwap Function CompareAndSwap( target Var,oldValue,newValue ) Description: Compare and swap Returns: True if target was updated Information: Atomically replace target with new_value if target equals old_value. AtomicAdd Function AtomicAdd( target Var,value ) Description: Atomic add Returns: Previous value of target Information: Atomically add value to target. AtomicSwap Function AtomicSwap( target Var,value ) Description: Atomically swap values Returns: The old value of target