Skip to content

Feature request: non-blocking take! #45902

@mjg0

Description

@mjg0

It would be nice to have a non-blocking take! to pull work from a Channel without hanging.

My particular use case is for a program with small units of work that can't be grouped into larger sets because each iteration relies on the results of the last. With so little to do for each unit of work, spawning a task for every one is a lot of overhead, so I would like to use long-lived tasks that repeatedly pull work from a shared queue until the simulation is finished. Here's some pseudocode demonstrating the concept:

# Create a workqueue
workqueue = Channel{Blah}(blah)
# Spawn worker threads that repeatedly pull work from the queue
for _ in 2:Threads.nthreads()
    Threads.@spawn while true
        try
            work = take!(workqueue)
            dowork(work)
        catch e
            e isa InvalidStateException && e.state === :closed && break
            rethrow(e)
        end
    end
end
# Actual work loop
while whatever
    # Put work into the queue
    for i in something
        put!(i, workqueue)
    end
    # Do main thread stuff
    dosomethingwhilewaiting()
    # If there's still work, help out
    while workremains # using an atomic int as a counter, for example
        work = nonblockingtake!(workqueue) # <<< THE CALL
        work !== None && dowork(work)
    end
end
# Tell worker threads we're done
close(workqueue)

For this particular case, the body of the loop in which the main thread takes work from the queue could conceptually be replaced by yield(), but that doesn't seem to perform well from what I've seen. Even if yield() could work in that case, though, I have to imagine there are other cases where not having a non-blocking take! makes life harder.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureIndicates new feature / enhancement requestsmultithreadingBase.Threads and related functionality

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions