19. Threads
- Method
_disable_threads
_disable_threads_disable_threads()- Description
This function first posts a notice to all threads that it is time to halt. It then waits until all threads actually have halted, and then then returns a lock object. All other threads will be blocked from running until that object has been freed/destroyed.
It's mainly useful to do things that require a temporary uid/gid change, since on many OSes the effective user and group apply to all threads.
- Note
You should make sure that the returned object is freed even if some kind of error is thrown. That means in practice that it should only have references (direct or indirect) from function local variables. Also, it shouldn't be referenced from cyclic memory structures, since those are only destructed by the periodic gc. (This advice applies to mutex locks in general, for that matter.)
- See also
gethrdtime()
Module Thread
- Description
This module contains classes and functions for interacting and synchronizing with threads.
- Note
For convenience some of the classes here are emulated (and are thus available) when threads are not supported.
Some of the classes that have such fallbacks are:
Condition,Fifo,Local,Mutex,MutexKeyandQueue.- See also
Thread,Mutex,Condition
- Constant
MUTEX_SUPPORTS_SHARED_LOCKS
constantThread.MUTEX_SUPPORTS_SHARED_LOCKS- Description
Recognition constant for support of shared locks.
If this symbol exists and is not
0then theMutexclass supports shared locks (ie hasMutex()->shared_lock()et al).
- Method
all_threads
array(Thread.Thread) all_threads()- Description
This function returns an array with the thread ids of all threads.
- See also
Thread()
- Method
get_thread_quanta
int(0..)get_thread_quanta()- Returns
Returns the current thread quanta in nanoseconds.
- See also
set_thread_quanta(),gethrtime()
- Method
set_thread_quanta
int(0..)set_thread_quanta(int(0..)ns)- Description
Set the thread quanta.
- Parameter
ns New thread quanta in nanoseconds. A value of zero (default) disables the thread quanta checks.
When enabled
MasterObject.thread_quanta_exceeded()will be called when a thread has spent more time than the quanta without allowing another thread to run.- Note
Setting a non-zero value that is too small to allow for
MasterObject.thread_quanta_exceeded()to run is NOT a good idea.- Returns
Returns the previous thread quanta in nanoseconds.
- See also
set_thread_quanta(),gethrtime()
- Method
this_thread
Thread.Threadthis_thread()- Description
This function returns the object that identifies this thread.
- See also
Thread()
Class Thread.Condition
- Description
Implementation of condition variables.
Condition variables are used by threaded programs to wait for events happening in other threads.
In order to prevent races (which is the whole point of condition variables), the modification of a shared resource and the signal notifying modification of the resource must be performed inside the same mutex lock, and the examining of the resource and waiting for a signal that the resource has changed based on that examination must also happen inside the same mutex lock.
Typical wait operation:
Take mutex lock
Read/write shared resource
Wait for the signal with the mutex lock in released state
Reacquire mutex lock
If needed, jump back to step 2 again
Release mutex lock
Typical signal operation:
Take mutex lock
Read/write shared resource
Send signal
Release mutex lock
- Example
You have some resource that multiple treads want to use. To protect this resource for simultaneous access, you create a shared mutex. Before you read or write the resource, you take the mutex so that you get a consistent and private view of / control over it. When you decide that the resource is not in the state you want it, and that you need to wait for some other thread to modify the state for you before you can continue, you wait on the conditional variable, which will temporarily relinquish the mutex during the wait. This way a different thread can take the mutex, update the state of the resource, and then signal the condition (which does not in itself release the mutex, but the signalled thread will be next in line once the mutex is released).
- Note
Condition variables are only available on systems with thread support. The Condition class is not simulated otherwise, since that can't be done accurately without continuations.
- Note
Signals may currently be sent without holding the lock, but this should be avoided as it may cause the signal to be lost (especially when the signal is not associated with a corresponding change of the shared resource).
- See also
Mutex
- Method
broadcast
voidbroadcast()- Description
broadcast()wakes up all threads currently waiting for this condition.- See also
signal()
- Method
create
Thread.ConditionThread.Condition(Thread.Mutex|voidmutex)- Parameter
mutex Optional
Mutexthat protects the resource that the condition signals for.
- Method
signal
voidsignal()- Description
signal()wakes up one of the threads currently waiting for the condition.- Note
Sometimes more than one thread is woken up.
- See also
broadcast()
- Method
wait
voidwait(Thread.MutexKeymutex_key)voidwait(Thread.MutexKeymutex_key,int(0..)|floatseconds)voidwait(Thread.MutexKeymutex_key,int(0..)seconds,int(0..999999999)nanos)- Description
Wait for condition.
This function makes the current thread sleep until the condition variable is signalled or the timeout is reached.
- Parameter
mutex_key A
Thread.MutexKeyobject for aThread.Mutex. It will be unlocked atomically before waiting for the signal and then relocked atomically when the signal is received or the timeout is reached. Note that it MUST be an exclusive lock.- Parameter
seconds Seconds to wait before the timeout is reached.
- Parameter
nanos Nano (1/1000000000) seconds to wait before the timeout is reached. This value is added to the number of seconds specified by
seconds.A timeout of zero seconds disables the timeout.
The thread that sends the signal should have the mutex locked while sending it. Otherwise it's impossible to avoid races where signals are sent while the listener(s) haven't arrived to the
waitcalls yet.- Note
The support for timeouts was added in Pike 7.8.121, which was after the first public release of Pike 7.8.
- Note
Note that the timeout is approximate (best effort), and may be exceeded if eg the mutex is busy after the timeout.
- Note
Note also that any threads waiting on the condition will be woken up when it gets destructed.
- See also
Mutex->lock()
Class Thread.Farm
- Description
A thread farm.
- See also
8.0::Thread.Farm
- Method
run
Concurrent.Futurerun(function(:void)f,mixed...args)- Description
Register a job for the thread farm.
- Parameter
f Function to call with @
argsto perform the job.- Parameter
args The parameters for
f.- Returns
Returns a
Resultobject for the job.- Note
In Pike 7.8 and earlier this function was broken and returned a
Resultobject that wasn't connected to the job.- See also
run_async()
- Method
run_async
voidrun_async(function(:void)f,mixed...args)- Description
Register a job for the thread farm where the return value from
fis ignored.- Parameter
f Function to call with @
argsto perform the job.- Parameter
args The parameters for
f.- Note
In some versions of Pike 8.0 and earlier, errors thrown by
fwere silently suppressed.- See also
run()
- Method
run_multiple
Concurrent.Future(<array>) run_multiple(array(array(function(:void)|array))fun_args)- Description
Register multiple jobs.
- Parameter
fun_args An array of arrays where the first element is a function to call, and the second is a corresponding array of arguments.
- Returns
Returns a
Concurrent.Futureobject with an array with one element for the result for each of the functions infun_args.- Note
Do not modify the elements of
fun_argsbefore the result is available.- Note
If any of the functions in
fun_argsthrows and error, all of the accumulated results (if any) will be dropped from the result, and the first backtrace be provided.- See also
run_multiple_async()
- Method
run_multiple_async
voidrun_multiple_async(arrayfun_args)- Description
Register multiple jobs where the return values are to be ignored.
- Parameter
fun_args An array of arrays where the first element is a function to call, and the second is a corresponding array of arguments.
- Note
Do not modify the elements of
fun_argsbefore the result is available.- See also
run_multiple()
- Method
set_max_num_threads
intset_max_num_threads(int(1..)to)- Description
Set the maximum number of worker threads that the thread farm may have.
- Parameter
to The new maximum number.
If there are more worker threads than
to, the function will wait until enough threads have finished, so that the total istoor less.The default maximum number of worker threads is
20.
- Method
set_thread_name_cb
voidset_thread_name_cb(function(object,string:void)cb,void|stringprefix)- Description
Provide a callback function to track names of threads created by the farm.
- Parameter
cb The callback function. This will get invoked with the thread as the first parameter and the name as the second whenever a thread is created. When the same thread terminates the callback is invoked again with
0as the second parameter. Setcbto0to stop any previously registered callbacks from being called.- Parameter
prefix An optional name prefix to distinguish different farms. If not given a prefix will be generated automatically.
Class Thread.Farm.Handler
- Description
A worker thread.
Class Thread.Fifo
- Description
Fifoimplements a fixed length first-in, first-out queue. A fifo is a queue of values and is often used as a stream of data between two threads.- See also
Queue
- Method
create
Thread.FifoThread.Fifo()Thread.FifoThread.Fifo(intsize)- Description
Create a fifo. If the optional
sizeargument is present it sets how many values can be written to the fifo without blocking. The defaultsizeis 128.
- Method
peek
mixedpeek()- Description
This function returns the next value in the fifo if there are any there. If there are no values present in the fifo then
UNDEFINEDwill be returned.- See also
read(),try_read()
- Method
read
mixedread()- Description
This function retrieves a value from the fifo. Values will be returned in the order they were written. If there are no values present in the fifo the current thread will sleep until some other thread writes one.
- See also
peek(),try_read(),read_array(),write()
- Method
read_array
arrayread_array()- Description
This function returns all values in the fifo as an array. The values in the array will be in the order they were written. If there are no values present in the fifo the current thread will sleep until some other thread writes one.
- See also
read(),try_read_array()
- Method
size
intsize()- Description
This function returns the number of elements currently in the fifo.
- See also
read(),write()
- Method
try_read
mixedtry_read()- Description
This function retrieves a value from the fifo if there are any there. Values will be returned in the order they were written. If there are no values present in the fifo then
UNDEFINEDwill be returned.- See also
peek(),read()
- Method
try_read_array
arraytry_read_array()- Description
This function returns all values in the fifo as an array but doesn't wait if there are no values there. The values in the array will be in the order they were written.
- See also
read_array()
- Method
try_write
inttry_write(mixedvalue)- Description
Append a
valueto the end of the fifo. If there is no more room in the fifo then zero will be returned, otherwise the number of items in the fifo after the write is returned.- See also
read()
Class Thread.Local (< ValueType >)
- Description
Thread local variable storage.
This class allows you to have variables which are separate for each thread that uses it. It has two methods:
get()andset(). A value stored in an instance ofLocalcan only be retrieved by that same thread.- Note
This class is simulated when Pike is compiled without thread support, so it's always available.
- Generic
ValueType
__generic__mixedValueType=mixed- Description
Type for the value to be stored in the thread local storage.
- Method
get
ValueTypeget()- Description
Get the thread local value.
- Returns
Returns the value prevoiusly stored in the
Localobject by theset()method by this thread (if set). ReturnsUNDEFINEDif no value has been set by the current thread.- See also
set()
- Method
set
ValueTypeset(ValueTypevalue)- Description
Set the thread local value.
This sets the value returned by the
getmethod.Calling this method does not affect the value returned by
get()when it's called by another thread (ie multiple values can be stored at the same time, but only one value per thread).- Returns
This function returns its argument.
- Note
Note that the value set can only be retreived by the same thread.
- See also
get()
Class Thread.Mutex
- Description
Mutexis a class that implements mutual exclusion and shared locks.Mutex locks are used to prevent multiple threads from simultaneously executing sections of code which access or change shared data. The basic operations for a mutex is locking and unlocking. If a thread attempts to lock an already locked mutex the thread will sleep until the mutex is unlocked.
- Note
This class is simulated when Pike is compiled without thread support, so it's always available.
- Note
Support for shared locks was added in Pike 8.1.14.
In POSIX threads, mutex locks can only be unlocked by the same thread that locked them. In Pike any thread can unlock a locked mutex.
- Method
_sprintf
stringsprintf(stringformat, ... Thread.Mutexarg ... )- Description
Describes the mutex including the thread that currently holds the lock (if any).
- Method
cond
Conditioncond()- Description
Create a
Condition.This function is equivalent to
Thread.Condition(mux);- See also
Condition
- Method
current_locking_key
Thread.MutexKeycurrent_locking_key()- Description
This mutex method returns the key object currently governing the lock on this mutex. 0 is returned if the mutex isn't locked.
- See also
Thread()
- Method
current_locking_thread
Thread.Threadcurrent_locking_thread()- Description
This mutex method returns the object that identifies the thread that has locked the mutex. 0 is returned if the mutex isn't locked.
- See also
Thread()
- Method
future_lock
Concurrent.Future(<Thread.MutexKey>) future_lock()- Description
This function is similar to
lock(), but will return aConcurrent.Future(<Thread.MutexKey>)that will complete successfully when theMutexis locked.- Note
Avoid having multiple
future_lock's for differentMutexes pending concurrently in the same conceptual thread as this will likely cause dead-locks.
- Method
future_shared_lock
Concurrent.Future(<Thread.MutexKey>) future_shared_lock()- Description
This function is similar to
shared_lock(), but will return aConcurrent.Future(<Thread.MutexKey>)that will complete successfully when theMutexis locked.- Note
Avoid having multiple
future_shared_lock's for differentMutexes pending concurrently in the same conceptual thread as this will likely cause dead-locks.
- Method
lock
MutexKeylock()MutexKeylock(inttype)MutexKeylock(inttype,int(0..)|floatseconds)MutexKeylock(inttype,int(0..)seconds,int(0..999999999)nanos)- Description
This function attempts to lock the mutex. If the mutex is already locked by a different thread the current thread will sleep until the mutex is unlocked. The value returned is the 'key' to the lock. When the key is destructed or has no more references the mutex will automatically be unlocked.
The
typeargument specifies whatlock()should do if the mutex is already locked by this thread:0Throw an error.
1Sleep until the mutex is unlocked. Useful if some other thread will unlock it.
2Return zero. This allows recursion within a locked region of code, but in conjunction with other locks it easily leads to unspecified locking order and therefore a risk for deadlocks.
- Parameter
seconds Seconds to wait before the timeout is reached.
- Parameter
nanos Nano (1/1000000000) seconds to wait before the timeout is reached. This value is added to the number of seconds specified by
seconds.A timeout of zero seconds disables the timeout.
- Returns
Returns a
MutexKeyon success and0(zero) on timeout.- Note
The support for timeouts was added in Pike 8.1.14, which was before the first public release of Pike 8.1.
- Note
Note that the timeout is approximate (best effort), and may be exceeded if eg the interpreter is busy after the timeout.
- Note
If the mutex is destructed while it's locked or while threads are waiting on it, it will continue to exist internally until the last thread has stopped waiting and the last
MutexKeyhas disappeared, but further calls to the functions in this class will fail as is usual for destructed objects.- Note
Pike 7.4 and earlier destructed any outstanding lock when the mutex was destructed, but threads waiting in
lockstill got functioning locks as discussed above. This is inconsistent no matter how you look at it, so it was changed in 7.6. The old behavior is retained in compatibility mode for applications that explicitly destruct mutexes to unlock them.- See also
trylock()
- Method
shared_lock
MutexKeyshared_lock()MutexKeyshared_lock(inttype)MutexKeyshared_lock(inttype,int(0..)|floatseconds)MutexKeyshared_lock(inttype,int(0..)seconds,int(0..999999999)nanos)- Description
This function attempts to lock the mutex. If the mutex is already locked by a different thread the current thread will sleep until the mutex is unlocked. The value returned is the 'key' to the lock. When the key is destructed or has no more references the mutex will automatically be unlocked.
The
typeargument specifies whatlock()should do if the mutex is already locked exclusively by this thread:0Throw an error.
1Sleep until the mutex is unlocked. Useful if some other thread will unlock it.
2Return zero. This allows recursion within a locked region of code, but in conjunction with other locks it easily leads to unspecified locking order and therefore a risk for deadlocks.
- Parameter
seconds Seconds to wait before the timeout is reached.
- Parameter
nanos Nano (1/1000000000) seconds to wait before the timeout is reached. This value is added to the number of seconds specified by
seconds.A timeout of zero seconds disables the timeout.
- Returns
Returns a
MutexKeyon success and0(zero) on timeout.- Note
Note that the timeout is approximate (best effort), and may be exceeded if eg the interpreter is busy after the timeout.
- Note
Note that if the current thread already holds a shared key, a new will be created without waiting, and regardless of the value of
type.- Note
If the mutex is destructed while it's locked or while threads are waiting on it, it will continue to exist internally until the last thread has stopped waiting and the last
MutexKeyhas disappeared, but further calls to the functions in this class will fail as is usual for destructed objects.- Note
Support for shared keys was added in Pike 8.1.
- See also
lock(),trylock(),try_shared_lock()
- Method
try_shared_lock
MutexKeytry_shared_lock()MutexKeytry_shared_lock(inttype)- Description
This function performs the same operation as
shared_lock(), but if the mutex is already locked exclusively, it will return zero instead of sleeping until it's unlocked.- Note
Support for shared keys was added in Pike 8.1.
- See also
shared_lock(),lock(),trylock()
Class Thread.MutexKey
- Description
Objects of this class are returned by
Mutex()->lock()andMutex()->trylock()et al. They are also passed as arguments toCondition()->wait().As long as they are held, the corresponding mutex will be locked.
The corresponding mutex will be unlocked when the object is destructed (eg by not having any references left).
- See also
Mutex,Condition
- Method
downgrade
voiddowngrade()- Description
Downgrade an exclusive lock into a shared lock.
A downgraded lock may be upgraded back to an exclusive lock by calling
upgrade()ortry_upgrade().- See also
upgrade(),try_upgrade()
- Method
try_upgrade
booltry_upgrade()- Description
Try to upgrade a downgraded lock into an exclusive lock.
- Returns
0Returns
0(zero) if there are other concurrent shared locks active.1Returns
1if this is the only active lock, and upgrading it to being exclusive succeeded.- See also
downgrade(),upgrade()
- Method
upgrade
boolupgrade()boolupgrade(int(0..)|floatseconds)boolupgrade(int(0..)seconds,int(0..999999999)nanos)- Description
Upgrade a downgraded lock into an exclusive lock.
- Parameter
seconds Seconds to wait before the timeout is reached.
- Parameter
nanos Nano (1/1000000000) seconds to wait before the timeout is reached. This value is added to the number of seconds specified by
seconds.A timeout of zero seconds disables the timeout.
- Note
Note that the timeout is approximate (best effort), and may be exceeded if eg the interpreter is busy after the timeout.
Waits until all concurrent shared locks are released, and upgrades this lock into being an exclusive lock. Any attempts to make new shared locks will block as soon as this function is called.
- See also
downgrade(),try_upgrade()
Class Thread.Queue
- Description
Queueimplements a queue, or a pipeline. The main difference betweenQueueandFifois thatQueuewill never block in write(), only allocate more memory.- FIXME
Ought to be made API-compatible with
ADT.Queue.- See also
Fifo,ADT.Queue
- Method
peek
mixedpeek()- Description
This function returns the next value in the queue if there are any there. If there are no values present in the queue then
UNDEFINEDwill be returned.- See also
peek(),read(),try_read(),write()
- Method
peek_array
arraypeek_array()- Description
Returns a snapshot of all the values in the queue, in the order they were written. The values are still left in the queue, so if other threads are reading from it, the returned value should be considered stale already on return.
- Method
read
mixedread()- Description
This function retrieves a value from the queue. Values will be returned in the order they were written. If there are no values present in the queue the current thread will sleep until some other thread writes one.
- See also
peek(),try_read(),write()
- Method
read_array
arrayread_array()- Description
This function returns all values in the queue as an array. The values in the array will be in the order they were written. If there are no values present in the queue the current thread will sleep until some other thread writes one.
- See also
read(),try_read_array()
- Method
size
intsize()- Description
This function returns the number of elements currently in the queue.
- See also
read(),write()
- Method
try_read
mixedtry_read()- Description
This function retrieves a value from the queue if there are any there. Values will be returned in the order they were written. If there are no values present in the queue then
UNDEFINEDwill be returned.- See also
peek(),read(),write()
- Method
try_read_array
arraytry_read_array()- Description
This function returns all values in the queue as an array but doesn't wait if there are no values there. The values in the array will be in the order they were written.
- See also
read_array()
Class Thread.ResourceCount
- Description
Implements an inverted-semaphore-like resource counter. A thread can poll or perform a blocking wait for the resource-count to drop below a certain
level.- See also
ResourceCountKey,Condition,Mutex
- Method
acquire
finalResourceCountKeyacquire()- Description
Increments the resource-counter.
- Returns
A
ResourceCountKeyto decrement the resource-counter again.
- Method
drained
finalbooldrained(void|intlevel)- Parameter
level The maximum level that is considered drained.
- Returns
True if the resource counter drops to equal or below
level.
Class Thread.ResourceCountKey
- Description
When this key is destroyed, the corresponding resource counter will be decremented.
- See also
ResourceCount,MutexKey
Class Thread.Thread
- Method
_sprintf
stringsprintf(stringformat, ... Thread.Threadarg ... )- Description
Returns a string identifying the thread.
- Method
backtrace
array(mixed) backtrace(int|voidflags)- Description
Returns the current call stack for the thread.
- Parameter
flags A bit mask of flags affecting generation of the backtrace.
Currently a single flag is defined:
1Return
LiveBacktraceFrames. This flag causes the frame objects to track changes (as long as they are in use), and makes eg local variables for functions available for inspection or change.Note that since these values are "live", they may change or dissapear at any time unless the corresponding thread has been halted or similar.
- Returns
The result has the same format as for
predef::backtrace().- See also
predef::backtrace()
- Method
create
Thread.ThreadThread.Thread(function(mixed... :mixed|void)f,mixed...args)- Description
This function creates a new thread which will run simultaneously to the rest of the program. The new thread will call the function
fwith the argumentsargs. Whenfreturns the thread will cease to exist.All Pike functions are 'thread safe' meaning that running a function at the same time from different threads will not corrupt any internal data in the Pike process.
- Returns
The returned value will be the same as the return value of
this_thread()for the new thread.- Note
This function is only available on systems with POSIX or UNIX or WIN32 threads support.
- See also
Mutex,Condition,this_thread()
- Method
gethrvtime
intgethrvtime(void|intnsec)- Returns
The CPU time consumed by this thread.
- See also
predef::gethrvtime()
- Method
interrupt
voidinterrupt()voidinterrupt(stringmsg)- Description
Interrupt the thread with the message
msg.This function causes the thread to throw an error where the message defaults to
"Interrupted.\n".- FIXME
The argument
msgis currently ignored.- Note
Interrupts are asynchronous, and are currently not queued.
- Note
Due to the asynchronous nature of interrupts, it may take some time before the thread reacts to the interrupt.
- Method
kill
voidkill(int|voidexit_value)- Description
Interrupt the thread, and terminate it as if it had terminated with the value
exit_value.- Note
Interrupts are asynchronous, and are currently not queued.
- Note
Due to the asynchronous nature of interrupts, it may take some time before the thread reacts to the interrupt.
- Note
Killing the backend thread (aka the main thread) is equivalent to calling
predef::kill().
- Method
status
intstatus()- Description
Returns the status of the thread.
- Returns
Thread.THREAD_NOT_STARTEDThe thread has not yet started executing.
Thread.THREAD_RUNNINGThe thread has started and has not yet terminated.
Thread.THREAD_EXITEDThe thread has terminated by returning a value from the thread function.
Thread.THREAD_ABORTEDThe thread has terminated by throwing an uncaught error.
- Method
_sprintf