lib/libuv/loop.rb in libuv-0.10.2 vs lib/libuv/loop.rb in libuv-0.10.3
- old
+ new
@@ -3,31 +3,41 @@
module Libuv
class Loop
include Resource, Assertions
+ LOOPS = ThreadSafe::Cache.new
+
+
module ClassMethods
# Get default loop
#
# @return [::Libuv::Loop]
def default
- create(::Libuv::Ext.default_loop)
+ return current || create(::Libuv::Ext.default_loop)
end
# Create new Libuv loop
#
# @return [::Libuv::Loop]
def new
- create(::Libuv::Ext.loop_new)
+ return current || create(::Libuv::Ext.loop_new)
end
# Build a Ruby Libuv loop from an existing loop pointer
#
# @return [::Libuv::Loop]
def create(pointer)
allocate.tap { |i| i.send(:initialize, FFI::AutoPointer.new(pointer, ::Libuv::Ext.method(:loop_delete))) }
end
+
+ # Checks for the existence of a loop on the current thread
+ #
+ # @return [::Libuv::Loop | nil]
+ def current
+ LOOPS[Thread.current]
+ end
end
extend ClassMethods
# Initialize a loop using an FFI::Pointer to a libuv loop
@@ -57,10 +67,12 @@
@queue_proc.call
end
# Create an async call for ending the loop
@stop_loop = Async.new @loop do
+ LOOPS.delete(@reactor_thread)
+ @reactor_thread = nil
@process_queue.close
@stop_loop.close
@next_tick.close
::Libuv::Ext.stop(@pointer)
@@ -73,21 +85,23 @@
#
# @param run_type [:UV_RUN_DEFAULT, :UV_RUN_ONCE, :UV_RUN_NOWAIT]
# @yieldparam promise [::Libuv::Q::Promise] Yields a promise that can be used for logging unhandled
# exceptions on the loop.
def run(run_type = :UV_RUN_DEFAULT)
- @loop_notify = @loop.defer
+ if @reactor_thread.nil?
+ @loop_notify = @loop.defer
- begin
- @reactor_thread = Thread.current
- yield @loop_notify.promise if block_given?
- ::Libuv::Ext.run(@pointer, run_type) # This is blocking
- ensure
- @reactor_thread = nil
- @run_queue.clear
+ begin
+ @reactor_thread = Thread.current
+ LOOPS[@reactor_thread] = @loop
+ yield @loop_notify.promise if block_given?
+ ::Libuv::Ext.run(@pointer, run_type) # This is blocking
+ ensure
+ @reactor_thread = nil
+ @run_queue.clear
+ end
end
-
@loop
end
# Creates a deferred result object for where the result of an operation may only be returned
@@ -137,11 +151,11 @@
# @return nil
def update_time
::Libuv::Ext.update_time(@pointer)
end
- # Get current time in microseconds
+ # Get current time in milliseconds
#
# @return [Fixnum]
def now
::Libuv::Ext.now(@pointer)
end
@@ -202,19 +216,19 @@
end
# Get a new Prepare handle
#
# @return [::Libuv::Prepare]
- def prepare
- Prepare.new(@loop)
+ def prepare(callback = nil, &blk)
+ Prepare.new(@loop, callback || blk)
end
# Get a new Check handle
#
# @return [::Libuv::Check]
- def check
- Check.new(@loop)
+ def check(callback = nil, &blk)
+ Check.new(@loop, callback || blk)
end
# Get a new Idle handle
#
# @param callback [Proc] the callback to be called on idle trigger
@@ -291,11 +305,11 @@
# @raise [ArgumentError] if block is not given
def schedule(callback = nil, &block)
callback ||= block
assert_block(callback)
- if @reactor_thread == Thread.current
+ if reactor_thread?
block.call
else
@run_queue << callback
@process_queue.call
end
@@ -308,11 +322,11 @@
def next_tick(callback = nil, &block)
callback ||= block
assert_block(callback)
@run_queue << callback
- if @reactor_thread == Thread.current
+ if reactor_thread?
# Create a next tick timer
if not @next_tick_scheduled
@next_tick.start(0)
@next_tick_scheduled = true
end
@@ -331,8 +345,29 @@
end
# Closes handles opened by the loop class and completes the current loop iteration (thread safe)
def stop
@stop_loop.call
+ end
+
+ # True if the calling thread is the same thread as the reactor.
+ #
+ # @return [Boolean]
+ def reactor_thread?
+ @reactor_thread == Thread.current
+ end
+
+ # Exposed to allow joining on the thread, when run in a multithreaded environment. Performing other actions on the thread has undefined semantics (read: a dangerous endevor).
+ #
+ # @return [Thread]
+ def reactor_thread
+ @reactor_thread
+ end
+
+ # Tells you whether the Libuv reactor loop is currently running.
+ #
+ # @return [Boolean]
+ def reactor_running?
+ !@reactor_thread.nil?
end
end
end