What is the idiomatic Ruby analog of a pattern that represents a potentially deferred asynchronous computation with the possibility to subscribe to its completion? i.e. something along the lines of .NET System.Threading.Task
, or Python 3.x concurrent.futures.future
.
Note that this does not necessarily imply multithreading - the actual implementation of the "future" object would just as likely use some other way of scheduling the work and obtaining result, and is out of scope of the question. The question concerns strictly with the API that is presented to the user of the object.
You can use a job queue like resque
Have coded some quick examples for pure ruby
by forking a child process
by having a callback on a thread
threads consume less memory than forking a child process but forking is robust. An unhandled error in a thread can bring down the whole system. while an unhandled error in a child process, will only bring down the child process
Other people have pointed out fibres and eventmachine (using EM::Deferrable and EM.defer) are another option
Fibres and threads need careful coding. code can be wrong in subtle ways.
Also fibres use pre-emptive multitasking so the codebase has to be well behaved
Eventmachine is fast but it is an exclusive world (like twisted in python). It has its own separate IO stack, so all the libraries have to be written to support eventmachine. Having said that, i do not think library support is a problem for eventmachine
Fiber?
Fibers are primitives for implementing light weight cooperative concurrency in Ruby. Basically they are a means of creating code blocks that can be paused and resumed, much like threads. The main difference is that they are never preempted and that the scheduling must be done by the programmer and not the VM. link
I am not sure about vanilla Ruby, but EventMachine has deferrables.
Also, check out this article.
lazy.rb provides "futures", but they don't seem to be exactly the same as you describe (or I would expect):
So, you can't compute them later, or insert values into them (from the network perhaps) by other means.
I found this to be extremely helpful:
https://github.com/wireframe/backgrounded
It is a gem that simply allows pushing methods onto a background task.
Maybe I'm missing something, but if the situation is as you describe in your response to deepak, then why not wrap the C API as a Ruby extension and provide a Ruby method that accepts a block corresponding to your needed callback? That would also be very idiomatic Ruby.
Here's a sample chapter dealing with extending Ruby with C from the "Pickaxe" Book updated for Ruby 1.9: http://media.pragprog.com/titles/ruby3/ext_ruby.pdf.
Update: Here are some links dealing with Ruby exceptions in Ruby and in it's C interface.