Right now we can limit the concurrency of something to N by starting N fibers with a channel. If it needs to return a value, we must pass a Sync::Future(T). For example:
# start workers:
N.times do
::spawn do
while message = channel.receive?
work, future = message
future.set(foobar(work))
rescue exception
future.fail(exception)
end
end
end
# somewhere else (called from different places):
future = Future(Foo).new
channel.send({new_work, future})
value = future.get
This is all nice, but rather complex, it needs to pre-initialize a bunch of resources and lots of communication. This is worth it when we want to put the computation in a specific execution context, or there are lots of computations to repeatedly calculate.
Yet, simpler usages to merely limit the concurrency of bcrypt hashes, might benefit from a simple counting semaphore. It would avoid all this boilerplate (no need for dedicated worker fibers, channels or futures), just by allowing up to N concurrent accesses to a critical section (from anywhere in the program) and putting the calling fiber into a wait list. For example:
SEM = Sync::Semaphore.new(N)
work = new_work
value = SEM.synchronize { foobar(work) }
Right now we can limit the concurrency of something to N by starting N fibers with a channel. If it needs to return a value, we must pass a
Sync::Future(T). For example:This is all nice, but rather complex, it needs to pre-initialize a bunch of resources and lots of communication. This is worth it when we want to put the computation in a specific execution context, or there are lots of computations to repeatedly calculate.
Yet, simpler usages to merely limit the concurrency of bcrypt hashes, might benefit from a simple counting semaphore. It would avoid all this boilerplate (no need for dedicated worker fibers, channels or futures), just by allowing up to N concurrent accesses to a critical section (from anywhere in the program) and putting the calling fiber into a wait list. For example: