Happy New Year to the Poly/ML User Community!
I am trying to find a fix to a problem where we want to apply a function that sometimes takes far too long to execute. So I want to abort execution of the function after a specified time limit. I have a solution that seems to work by forking a worker thread to execute the function and store the result in a ref while the control thread goes into a loop that waits for 100ms and then either (1) returns the result from the ref if the worker thread is no longer active, (2) repeats if the thread is still active and we haven?t reaced the time limit or otherwise (3) kills the worker thread and returns a dummy value.
I am implementing this using Thread.ConditionVar.waitUntil and have two questions about that:
1) What does the bool returned by Thread.ConditionVar.waitUntil mean? That doesn?t seem to be documented.
2) In addition to the timeout, Thread.ConditionVar.waitUntil has a condition variable and a mutex as arguments. I am just creating these using Thread.ConditionVar.conditionVar and Thread.Mutex.mutex because I need some values to pass to Thread.ConditionVar.waitUntil. I am not doing any signalling or locking or unlocking. Is that going to cause any problems? (The condition variable and the mutex are local to the control thread function, so the worker thread function has no access to them.)
Regards,
Rob.
Rob Arthan wrote:
Happy New Year to the Poly/ML User Community!
I am trying to find a fix to a problem where we want to apply a function that sometimes takes far too long to execute. So I want to abort execution of the function after a specified time limit. I have a solution that seems to work by forking a worker thread to execute the function and store the result in a ref while the control thread goes into a loop that waits for 100ms and then either (1) returns the result from the ref if the worker thread is no longer active, (2) repeats if the thread is still active and we haven?t reaced the time limit or otherwise (3) kills the worker thread and returns a dummy value.
I am implementing this using Thread.ConditionVar.waitUntil and have two questions about that:
- What does the bool returned by Thread.ConditionVar.waitUntil mean? That doesn?t seem
to be documented.
While not a Poly/ML -specific answer, this would be the indication of whether, when execution continues after the wait, it is because the wait condition was satisfied OR the timeout expired (not 100% which value means which, but you should be able to determine that rather easily).
- In addition to the timeout, Thread.ConditionVar.waitUntil has a condition variable and a mutex
as arguments. I am just creating these using Thread.ConditionVar.conditionVar and Thread.Mutex.mutex because I need some values to pass to Thread.ConditionVar.waitUntil. I am not doing any signalling or locking or unlocking. Is that going to cause any problems? (The condition variable and the mutex are local to the control thread function, so the worker thread function has no access to them.)
The associated mutex is used to "protect" the condition variable itself, so that while it is examining the condition, things can't change out from under it - that's all.
Good luck, and feel free to request further clarification.
Robert Roessler
Happy New Year Rob and everyone else,
On 09/01/2025 22:02, Rob Arthan wrote:
Happy New Year to the Poly/ML User Community!
I am trying to find a fix to a problem where we want to apply a function that sometimes takes far too long to execute. So I want to abort execution of the function after a specified time limit. I have a solution that seems to work by forking a worker thread to execute the function and store the result in a ref while the control thread goes into a loop that waits for 100ms and then either (1) returns the result from the ref if the worker thread is no longer active, (2) repeats if the thread is still active and we haven?t reaced the time limit or otherwise (3) kills the worker thread and returns a dummy value.
I am implementing this using Thread.ConditionVar.waitUntil and have two questions about that:
- What does the bool returned by Thread.ConditionVar.waitUntil mean? That doesn?t seem
to be documented.
This indicates whether the wait has returned because the condition variable was signalled (true) or because it timed out (false).
- In addition to the timeout, Thread.ConditionVar.waitUntil has a condition variable and a mutex
as arguments. I am just creating these using Thread.ConditionVar.conditionVar and Thread.Mutex.mutex because I need some values to pass to Thread.ConditionVar.waitUntil. I am not doing any signalling or locking or unlocking. Is that going to cause any problems? (The condition variable and the mutex are local to the control thread function, so the worker thread function has no access to them.)
This is a standard paradigm but you do need to follow the rules if you want it to work properly. The condition variable and mutex need to be shared between the two threads. In the worker thread: When you're ready to return a result: Disable asynchronous interrupts if they're enabled, Lock the mutex, Store the result in the shared reference, Signal the condition variable, Unlock the mutex, Re-enable the asynchronous interrupts if you're continuing to process Or exit
In the control thread: Disable asynchronous interrupts if necessary, Lock the mutex, Start of loop: Read the shared reference. If the worker has stored the result, unlock the mutex, restore interrupts and exit the loop, Wait on the condition variable and mutex, Go to the start of the loop.
It's important that the worker thread locks the mutex for two reasons. It avoids any race conditions which could occur if the worker thread set the shared reference and signalled the condition variable in the time between the control thread deciding that the result had not been stored yet and blocking on the condition variable. That's not too much of a problem if you're using waitUntil with a short interval. More importantly, locking and unlocking the mutex also puts in memory barriers which are essential on machines such as the ARM with relaxed memory ordering. Without some sort of interlock between the worker thread and the control thread there is no guarantee that the control thread will ever see that the shared reference has been updated.
It's better to use Thread.interrupt rather than Thread.kill since it allows the worker thread to handle the Interrupt exception and free up resources where necessary and also to mask the exception in critical sections. The worker thread needs to be created with InterruptState InterruptAsynch for this to work or to set that with Thread.setAttributes once it is running.
David