18. 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
,MutexKey
andQueue
.- See also
Thread
,Mutex
,Condition
- ConstantMUTEX_SUPPORTS_SHARED_LOCKS
constant
Thread.MUTEX_SUPPORTS_SHARED_LOCKS
- Description
Recognition constant for support of shared locks.
If this symbol exists and is not
0
then theMutex
class supports shared locks (ie hasMutex()->shared_lock()
et al).
- Methodall_threads
array
(Thread.Thread
) all_threads()- Description
This function returns an array with the thread ids of all threads.
- See also
Thread()
- Methodget_thread_quanta
int(0..)
get_thread_quanta()- Returns
Returns the current thread quanta in nanoseconds.
- See also
set_thread_quanta()
,gethrtime()
- Methodset_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()
- Methodthis_thread
Thread.Thread
this_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
- Methodbroadcast
void
broadcast()- Description
broadcast()
wakes up all threads currently waiting for this condition.- See also
signal()
- Methodcreate
Thread.ConditionThread.Condition(
Thread.Mutex
|void
mutex
)- Parameter
mutex
Optional
Mutex
that protects the resource that the condition signals for.
- Methodsignal
void
signal()- 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()
- Methodwait
void
wait(Thread.MutexKey
mutex_key
)void
wait(Thread.MutexKey
mutex_key
,int(0..)
|float
seconds
)void
wait(Thread.MutexKey
mutex_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.MutexKey
object 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
wait
calls 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
- Methodrun
Concurrent.Future
run(function
(:void
)f
,mixed
...args
)- Description
Register a job for the thread farm.
- Parameter
f
Function to call with @
args
to perform the job.- Parameter
args
The parameters for
f
.- Returns
Returns a
Result
object for the job.- Note
In Pike 7.8 and earlier this function was broken and returned a
Result
object that wasn't connected to the job.- See also
run_async()
- Methodrun_async
void
run_async(function
(:void
)f
,mixed
...args
)- Description
Register a job for the thread farm where the return value from
f
is ignored.- Parameter
f
Function to call with @
args
to perform the job.- Parameter
args
The parameters for
f
.- See also
run()
- Methodrun_multiple
Concurrent.Future
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.Future
object with an array with one element for the result for each of the functions infun_args
.- Note
Do not modify the elements of
fun_args
before the result is available.- Note
If any of the functions in
fun_args
throws 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()
- Methodrun_multiple_async
void
run_multiple_async(array
fun_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_args
before the result is available.- See also
run_multiple()
- Methodset_max_num_threads
int
set_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 isto
or less.The default maximum number of worker threads is
20
.
- Methodset_thread_name_cb
void
set_thread_name_cb(function
(object
,string
:void
)cb
,void
|string
prefix
)- 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
0
as the second parameter. Setcb
to0
to 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
Fifo
implements 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
- Methodcreate
Thread.FifoThread.Fifo()
Thread.FifoThread.Fifo(
int
size
)- Description
Create a fifo. If the optional
size
argument is present it sets how many values can be written to the fifo without blocking. The defaultsize
is 128.
- Methodpeek
mixed
peek()- 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
UNDEFINED
will be returned.- See also
read()
,try_read()
- Methodread
mixed
read()- 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()
- Methodread_array
array
read_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()
- Methodsize
int
size()- Description
This function returns the number of elements currently in the fifo.
- See also
read()
,write()
- Methodtry_read
mixed
try_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
UNDEFINED
will be returned.- See also
peek()
,read()
- Methodtry_read_array
array
try_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()
- Methodtry_write
int
try_write(mixed
value
)- Description
Append a
value
to 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 ofLocal
can only be retrieved by that same thread.- Note
This class is simulated when Pike is compiled without thread support, so it's always available.
- GenericValueType
__generic__
mixed
ValueType
=mixed
- Description
Type for the value to be stored in the thread local storage.
- Methodget
ValueType
get()- Description
Get the thread local value.
This returns the value prevoiusly stored in the
Local
object by theset()
method by this thread.- See also
set()
- Methodset
ValueType
set(ValueType
value
)- Description
Set the thread local value.
This sets the value returned by the
get
method.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
Mutex
is 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).
- Methodcond
Condition
cond()- Description
Create a
Condition
.This function is equivalent to
Thread.Condition(mux);
- See also
Condition
- Methodcurrent_locking_key
Thread.MutexKey
current_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()
- Methodcurrent_locking_thread
Thread.Thread
current_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()
- Methodfuture_lock
Concurrent.Future
future_lock()- Description
This function is similar to
lock()
, but will return aConcurrent.Future(<Thread.MutexKey>)
that will complete successfully when theMutex
is locked.- Note
Avoid having multiple
future_lock
's for differentMutex
es pending concurrently in the same conceptual thread as this will likely cause dead-locks.
- Methodfuture_shared_lock
Concurrent.Future
future_shared_lock()- Description
This function is similar to
shared_lock()
, but will return aConcurrent.Future(<Thread.MutexKey>)
that will complete successfully when theMutex
is locked.- Note
Avoid having multiple
future_shared_lock
's for differentMutex
es pending concurrently in the same conceptual thread as this will likely cause dead-locks.
- Methodlock
MutexKey
lock()MutexKey
lock(int
type
)MutexKey
lock(int
type
,int(0..)
|float
seconds
)MutexKey
lock(int
type
,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
type
argument specifies whatlock()
should do if the mutex is already locked by this thread:0
Throw an error.
1
Sleep until the mutex is unlocked. Useful if some other thread will unlock it.
2
Return 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
MutexKey
on 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
MutexKey
has 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
lock
still 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()
- Methodshared_lock
MutexKey
shared_lock()MutexKey
shared_lock(int
type
)MutexKey
shared_lock(int
type
,int(0..)
|float
seconds
)MutexKey
shared_lock(int
type
,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
type
argument specifies whatlock()
should do if the mutex is already locked exclusively by this thread:0
Throw an error.
1
Sleep until the mutex is unlocked. Useful if some other thread will unlock it.
2
Return 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
MutexKey
on 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
MutexKey
has 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()
- Methodtry_shared_lock
MutexKey
try_shared_lock()MutexKey
try_shared_lock(int
type
)- 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
- Methoddowngrade
void
downgrade()- 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()
- Methodtry_upgrade
bool
try_upgrade()- Description
Try to upgrade a downgraded lock into an exclusive lock.
- Returns
0
Returns
0
(zero) if there are other concurrent shared locks active.1
Returns
1
if this is the only active lock, and upgrading it to being exclusive succeeded.- See also
downgrade()
,upgrade()
- Methodupgrade
bool
upgrade()bool
upgrade(int(0..)
|float
seconds
)bool
upgrade(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
Queue
implements a queue, or a pipeline. The main difference betweenQueue
andFifo
is thatQueue
will never block in write(), only allocate more memory.- FIXME
Ought to be made API-compatible with
ADT.Queue
.- See also
Fifo
,ADT.Queue
- Methodpeek
mixed
peek()- 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
UNDEFINED
will be returned.- See also
peek()
,read()
,try_read()
,write()
- Methodpeek_array
array
peek_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.
- Methodread
mixed
read()- 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()
- Methodread_array
array
read_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()
- Methodsize
int
size()- Description
This function returns the number of elements currently in the queue.
- See also
read()
,write()
- Methodtry_read
mixed
try_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
UNDEFINED
will be returned.- See also
peek()
,read()
,write()
- Methodtry_read_array
array
try_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
- Methodacquire
final
ResourceCountKey
acquire()- Description
Increments the resource-counter.
- Returns
A
ResourceCountKey
to decrement the resource-counter again.
- Methoddrained
final
bool
drained(void
|int
level
)- 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.
- Methodbacktrace
array
(mixed
) backtrace(int
|void
flags
)- 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:
1
Return
LiveBacktraceFrame
s. 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()
- Methodcreate
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
f
with the argumentsargs
. Whenf
returns 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()
- Methodgethrvtime
int
gethrvtime(void
|int
nsec
)- Returns
The CPU time consumed by this thread.
- See also
predef::gethrvtime()
- Methodinterrupt
void
interrupt()void
interrupt(string
msg
)- 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
msg
is 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.
- Methodkill
void
kill()- Description
Interrupt the thread, and terminate it.
- 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.
- Methodstatus
int
status()- Description
Returns the status of the thread.
- Returns
Thread.THREAD_NOT_STARTED
The thread has not yet started executing.
Thread.THREAD_RUNNING
The thread has started and has not yet terminated.
Thread.THREAD_EXITED
The thread has terminated by returning a value from the thread function.
Thread.THREAD_ABORTED
The thread has terminated by throwing an uncaught error.
- Method_sprintf