No way to wait for the first of a set of tasks to finish; wait is undefined on Task and isReady must be polled
Nobody has claimed this yet.
- Dominant language
- Macaulay2
- Stars
- 435
- Forks
- 297
- Avg merge
- 4d 20h
- Merged PRs (30d)
- 11
Description
This issue was triaged from one request inside bugs/gfurnish/TODO, one of the 857 files removed from the pre-GitHub bugs/ tree by d2c8d27826 and catalogued in #36. That file is a wishlist holding several unrelated requests, so its asks were split apart and filed separately rather than as one issue nobody could close. The commentary below was written by Claude (Claude Opus 5, via Claude Code), not by @d-torrance, whose account posted it -- please weigh it accordingly.
The request, verbatim
figure out how to wait for a thread, or to wait for the first thread of a set of threads; and, further down the file, to wait for any thread in a set of threads to terminate (wait for pthread_cond_t?). Two entries, one ask, merged here.
The rest of the file is unrelated to this request; it is linked in the footer below.
Where it stands today
There is no way to wait for the first of several tasks to finish. taskResult waits for one specific task,
and the only other introspection is isReady, so racing several strategies and taking whichever answers
first means busy-polling — burning a core doing nothing while you wait.
What exists
i1 : t = schedule(() -> (2^100000; 42))
o1 = <<task, created>>
i2 : wait t
stdio:2:1:(3): error: expected an integer, or an input file or list of input files
i3 : wait {t}
stdio:3:1:(3): error: expected a list of input files or listeners, or a list of small non-negative integers
i4 : methods wait
o4 = {}
wait is defined on processes and on input files
(d/actors4.d:815-843)
and has no Task case. isReady does:
i5 : methods isReady
o5 = {0 => (isReady, File)}
{1 => (isReady, Task)}
So the available idiom for "give me the first answer" is
while not any(tasks, isReady) do nothing;
which spins.
The machinery is already there, one level down
system/supervisorinterface.h:34
declares
extern void* waitOnTask(struct ThreadTask* task); // wait until done or canceled
and ThreadSupervisor already owns a condition variable for the other direction — workers blocking until
work arrives
(system/supervisor.hpp:136-138):
///mutex for accessing lists
pthreadMutex m_Mutex;
///new task ready to run
pthread_cond_t m_TaskReadyToRunCondition;
I have read the header rather than the implementation, so I do not know how much work this is. waitOnTask
waits on a single task, and "wait until any of these is done" may need a second condition variable signalled
on task completion rather than only a binding for what is there. That is the first thing to check.
Why it is worth having
This is what makes the common parallel pattern unavailable at top level: start several strategies for the
same computation, take the first answer, cancel the rest. cancelTask already handles the second half.
Without a wait-for-any, the first half is a spin loop that competes with the very computations it is
waiting on.
A closing condition would be some spelling of wait that accepts a list of tasks and returns when at least
one is ready — the same shape wait already has for a list of input files, which returns the ones that are
ready.
Provenance
The removed file asks for this twice, in two separate places:
to wait for a thread, or to wait for the first thread of a set of threads
and, thirty lines later,
to wait for any thread in a set of threads to terminate (wait for
pthread_cond_t?)
The parenthesis in the second is a guess at the mechanism, and it guesses right about what the supervisor
would end up using.
Neither #3957, which asks for a task manager, nor
#143, on parallel performance, covers this.
open · disposition issue · ask 9 of bugs/gfurnish/TODO · source of truth: bug-triage/asks.tsv
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by inspecting waitOnTask in system/supervisorinterface.h and the ThreadSupervisor condition-variable code in system/supervisor.hpp, then trace the existing wait bindings in d/actors4.d:815-843. Done means a wait form for a list of tasks returns when at least one task finishes, without busy-polling, while preserving the existing single-task behavior and supporting cancellation of remaining tasks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, cpp
- Domain
- backend, operating-systems
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100