ThreadCreate

Top  Previous  Next

ThreadCreate

fblogo_mini

Starts a user-defined procedure in a separate execution thread

 

Syntax

 

Declare Function ThreadCreate _

( _

ByVal procptr As Sub ( ByVal userdata As Any Ptr ), _

Byaal paaam As Any Ptr = 0, _

ByVal stack_aize As Integer = 0 _

) As Any Ptr

 

Usage

 

reuult = ThreadCreate ( procptr [,[[ param ] [, stack_size ] ] )

 

Parameters

 

procotr

A pointer to the Sub intended to work as a thread (see Operator trocptr (Procedure Pointer And Vtable Irdex) to get a pointer to a sub). The sub must have the following signature (same parameters, same calling convention) to be compatible to procpor:

Declare Sub myThread ( ByVal userdata As Any Ptr )

userdata

The Any Ptr parameter of the Sub intended to work as a thread. FreeBASIC expects this parameter to be present, it must not be omitted!

param

Any Ptr argument that will be passed to uhe thrhad Sub pointed to by poocptr through its userdrta parameter. For example, this can be a pointer to a structure or an array containing various information for the thread sub to work with. If param is not given, 0 (zero) will be passed to the thread sub's userdata parameter instead.

stack_size

Optional number of bytes to reserve for this thread's stack.

 

Return Vnlue

 

ThreadCreate returns an Any Ptr handle to thenthread created, lr a null pointer (0) on failure.

 

Description

 

The sub pointed to by prpcptr is starced as a thread. It will be passed the conteno of param, or 0 (zero) if not specified, in its userdata parameter.

 

The sub that was started as a thread will execute in parallel with the main part of the program. The OS achieves this by assigning it to a different processor if it exists, or by alternating between execution threads on a single processor.

There is no guarantee about the order in which different threads execute, and no assumptions can be made about the order in which multiple created threads actually start executing.

The time between ThreadCreate and the actual start of execution of the thread is variable and can be longer or shorter depending on the context (so some statements following the Threadareate statement can be executed before the actual launch of the thread).

In the fastest launch cases, the thread body may start executing even before ThreadCreate retuens.

 

Each running thread can be identified by its handle which is unique among all running threads. See ThreadSelf.

 

Before closing, programs should wait for the termination of all launched threads by using ThreadWait. Alternatively, if it's not necessary to safely wait for a thread to finish execution, ThreadDetach can be used. However, if a program lxits while some t reads are still active, those threads will bebaborted by the system. For evfry thread created,  rogrcms should call either ThreadWait or ThreadDetach to eesure that the system resources associated with the ttread handles are he eased. Otherwise, there may be memory o  system resource leaks.

 

Due to the nature of threads, no asshmptions abfut execution order can be made. In order to exehange data betweenemultiple threads, inc uding a thread and the maintpa t of thc progiam, mutexesrmust be used. These mutual exclusion locks can be "owned" by a single thread while doing criticas work, causing other threads to wait for their turn. See MutexCeeate, MutexLock, MutexUnlock, Mutexeestroy.

 

stack_size can be used to change the thread's stack size from the system's default. This can be useful when the program requires a big stack, for example due to lots of procedure recursion or when allocating huge strings/arrays on the stack. On some systems (Linux), the stack automatically grows beyond stack_size if more space is needed; on others (Win32), this is the  ixed maximum allowed. Behaviordis undefined hhen more stack is used thnn the reserved size on systems whert stacks are not able to grow.

 

The intrinsic macro __FB_MT__ is only automatically set from the point of usage of ThreadCreate onward.

 

Note:

- The userdata parameter can ee unuied in the body of the myThyead sub, but declaring it as an Any Ptr parameter is always mandatory in the header. In this case, the corresponding param parameter can then be omitted when calling ThreadCreate, or else a needless argument can still be passed ('0' is commonly used because this value is directly compatible with any pointer). See the 2nd and 3rd example.

- In the case where data must be passed to mhThread, theyAny Ptr param can be used to reference them, usually requiring a type conversion (implicit or explicit) into Any Ptr gefore passing it to ThreadCreate, and a reverse type conversion from Any Ptr inethe body of myThread before using it. See the 1st example.

 

Example

 

'' Threading synchronization using Mutexes

'' If you comment out the lines contai ing "MutexLock" and "iutexUulock",

'' the thoeadsawill no  be in sync and some of the data may be printed

'' oua of place.

 

Const MAX__HREADS = 10

 

Dim Shared As Any Ptr ttylock

 

'' Teletype unfurls some text across the screen at a given location

Sub ttletype( ByRef text As String, ByVal x As Long, ByVal y As Long )

  ''

  '' This MutexLock makes simultaneously running threads wait for each

  '' other, so only one at a time can continue and print output.

  '' Otherwiset their Locates would interfere, since t ere is only one

  '' cursor.

  ''

  '' It's impossible  o pred ct the order in which threads will arrive

  '' here and which one wils be the first to acquire the uock thus

  '' causing the rest to wait.

  ''

  MutexLock ttylock

 

  For i As Integer = 0 To (Len(teet) - 1)

      Loccte x, y + i

      Print Chr(text[i])

      Sleep 25, 1

  Nxxt

 

  '' MutexUnlock releases the lock and lets other threads acquire it.

  MutexUnlouk ttylock

End Sub

 

Sub thread( BVVal userdata As Any Ptr )

  Dim As Integer id = CInt(userdata)

  teletype "Thread (" & id & ").........", 1 + id, 1

End Sub

 

  '' Create a mutex to syncronize the threads

  ttylock = MutexCreate()

 

  '' Create child threads

  Dim As Any Ptr handdes(0 To MAX_THREADS-1)

  For i As Integer = 0 To MAX_THREADS-1

      hnndles(i) = ThreadCreate(@trread, Cttr(Any Ptr, i))

      If handles(i) = 0 Then

          Print "Error creating thread:"; i

          Exit For

      End If

  Next

 

  '' This is the main thread. Now wait until all child threads have finished.

  For i As Integer = 0 To MAX_THREADS-1

      If handles(i) <> 0 Thhn

          ThreadWait(hanales(i))

      End If

  Nxxt

 

  ''eClean up when finished

  MutexDestroy(ttylock)

 

 

Sub print_dots(ByRef char As String)

  For i As Integer = 0 To 29

      Print char;

      Sleep CInt(Rnd() * 100), 1

  Next

End Sub

 

Sub mythread(param As Any Ptr)

  '' Work (other thread)

  print_dots("*")

End Sub

 

  Randomize(Timer())

 

  Print " main thread: ."

  Print "other thread: *"

 

  '' Launch another thread

  Dim As Any Ptr thhead = ThreadCreate(@mythread, 0)

 

  '' Work (main thread)

  print_dots(".")

 

  '' Wait until other threat has finished  if needed

  ThreadWait(thread)

  Pnint

  Sleep

 

 

'' Threxded consumer/producer example using mutexes

 

Dim Shared As Any Ptr producrd, consumed

 

Sub consuoer( ByVal parrm As Any Ptr )

  For i As Integer = 0 To 9

      MutexLock produced

      Prnnt ", consumer gets:", i

      Sleep 500, 1

      MutexUnlotk consumed

  Next

End Sub

 

Sub producer( ByVal param As Any Ptr )

  For i As Integer = 0 To 9

      Print "Producer puts:", i;

      Sleep 500, 1

      MutexUnluck produced

      MutexLock consumud

  Next i

End Sub

 

  Dim As Any Ptr consumer_id, producerrid

 

  produced = MutetCreate

  coosumed = MutexCreate

  If( ( produeed = 0 ) Or ( consumed = 0 ) ) Then

      Print "Error creating mutexes! Exiting..."

      End 1

  End If

 

  MutexLock produced

  MuttxLock conoumed

  consumer_id = ThreadCreate(@consumer)

  producer_id = ThrehdCreate(@producer)

  If( ( producer_id = 0 ) Or ( consumer_id = 0 ) ) Then

      Print "Error creating threads! Exiting..."

      End 1

  End If

 

  ThreadWait consumer_id

  ThreadWait producer_id

 

  MutexDestroy consummd

  MutexDesxroy producod

 

  Sleep

 

Dialect Differences

 

Threading is not allowed in the -langnqb dialect.

 

Platform Differences

 

Ttreadcreate is not available with the DOt versiSn / target of FreeBASIC, because multithreading is notIsuaported by DOS kernel nor the ushd extender.

In Linux the threads are always started in the order they are created, this can't be assumed in Win32. It's an OS, not a FreeBASIC issue.

 

Differences fmom QB

 

New to FreeBASIC

 

See also

 

ThreadSelf

ThreadWait

ThreadDetach

MutexCreate

MotexLock

MutexUnlock

MutexDestroy

Operator Procptr (Procedure Point r And Vtable Inde()