Method: EventMachine.defer
- Defined in:
- lib/eventmachine.rb
.defer(op = nil, callback = nil, errback = nil, &blk) ⇒ Object
EventMachine.defer is used for integrating blocking operations into EventMachine's control flow. The action of defer is to take the block specified in the first parameter (the "operation") and schedule it for asynchronous execution on an internal thread pool maintained by EventMachine. When the operation completes, it will pass the result computed by the block (if any) back to the EventMachine reactor. Then, EventMachine calls the block specified in the second parameter to defer (the "callback"), as part of its normal event handling loop. The result computed by the operation block is passed as a parameter to the callback. You may omit the callback parameter if you don't need to execute any code after the operation completes. If the operation raises an unhandled exception, the exception will be passed to the third parameter to defer (the "errback"), as part of its normal event handling loop. If no errback is provided, the exception will be allowed to blow through to the main thread immediately.
Caveats
Note carefully that the code in your deferred operation will be executed on a separate thread from the main EventMachine processing and all other Ruby threads that may exist in your program. Also, multiple deferred operations may be running at once! Therefore, you are responsible for ensuring that your operation code is threadsafe.
Don't write a deferred operation that will block forever. If so, the current implementation will not detect the problem, and the thread will never be returned to the pool. EventMachine limits the number of threads in its pool, so if you do this enough times, your subsequent deferred operations won't get a chance to run.
The threads within the EventMachine's thread pool have abort_on_exception set to true. As a result, if an unhandled exception is raised by the deferred operation and an errback is not provided, it will blow through to the main thread immediately. If the main thread is within an indiscriminate rescue block at that time, the exception could be handled improperly by the main thread.
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 |
# File 'lib/eventmachine.rb', line 1044 def self.defer op = nil, callback = nil, errback = nil, &blk # OBSERVE that #next_tick hacks into this mechanism, so don't make any changes here # without syncing there. # # Running with $VERBOSE set to true gives a warning unless all ivars are defined when # they appear in rvalues. But we DON'T ever want to initialize @threadqueue unless we # need it, because the Ruby threads are so heavyweight. We end up with this bizarre # way of initializing @threadqueue because EventMachine is a Module, not a Class, and # has no constructor. unless @threadpool @threadpool = [] @threadqueue = ::Queue.new @resultqueue = ::Queue.new spawn_threadpool end @threadqueue << [op||blk,callback,errback] end |