Skip to content
This repository has been archived by the owner on Aug 29, 2024. It is now read-only.

Commit

Permalink
Use Channel to convey data for on_update
Browse files Browse the repository at this point in the history
  • Loading branch information
mattgreen committed Sep 27, 2013
1 parent 13c6237 commit ff7905d
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 59 deletions.
19 changes: 19 additions & 0 deletions lib/elevate/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Elevate
# A simple unidirectional stream of data with a single consumer.
#
# @api private
class Channel
def initialize(block)
@target = block
end

# Pushes data to consumers immediately
#
# @return [void]
#
# @api private
def <<(obj)
@target.call(obj)
end
end
end
16 changes: 3 additions & 13 deletions lib/elevate/operation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ class ElevateOperation < NSOperation
# newly initialized instance
#
# @api private
def initWithTarget(target, args: args, update: update_callback)
def initWithTarget(target, args: args, channel: channel)
if init
@coordinator = IOCoordinator.new
@context = TaskContext.new(target, args)
@update_callback = update_callback
@channel = WeakRef.new(channel)
end

self
Expand All @@ -29,15 +29,6 @@ def cancel
super
end

def invoke_update_callback(args)
unless NSThread.isMainThread
performSelectorOnMainThread(:"invoke_update_callback:", withObject: args, waitUntilDone: true)
return
end

@update_callback.call(*args)
end

# Runs the specified task.
#
# @return [void]
Expand All @@ -49,7 +40,7 @@ def main
begin
unless @coordinator.cancelled?
@result = @context.execute do |*args|
invoke_update_callback(args) if @update_callback
@channel << args if @channel
end
end

Expand All @@ -60,7 +51,6 @@ def main
@coordinator.uninstall

@context = nil
@update_callback = nil
end

# Returns the exception that terminated this task, if any.
Expand Down
26 changes: 14 additions & 12 deletions lib/elevate/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ def initialize(controller, active_tasks, body)
@controller = WeakRef.new(controller)
@active_tasks = active_tasks
@operation = nil
@channel = Channel.new(method(:on_update))

@body = body
@on_start = nil
Expand All @@ -30,7 +31,7 @@ def on_update=(block)
end

def start(args)
@operation = ElevateOperation.alloc.initWithTarget(@body, args: args, update: method(:on_update))
@operation = ElevateOperation.alloc.initWithTarget(@body, args: args, channel: @channel)

@operation.addObserver(self, forKeyPath: "isFinished", options: NSKeyValueObservingOptionNew, context: nil)
queue.addOperation(@operation)
Expand Down Expand Up @@ -58,20 +59,16 @@ def observeValueForKeyPath(path, ofObject: operation, change: change, context: c
end

def on_start
autorelease_pool do
if @on_start
@controller.instance_eval(&@on_start)
@on_start = nil
end
if @on_start
@controller.instance_eval(&@on_start)
@on_start = nil
end
end

def on_finish
autorelease_pool do
if @on_finish
@controller.instance_exec(@operation.result, @operation.exception, &@on_finish)
@on_finish = nil
end
if @on_finish
@controller.instance_exec(@operation.result, @operation.exception, &@on_finish)
@on_finish = nil
end

@operation.removeObserver(self, forKeyPath: "isFinished")
Expand All @@ -80,7 +77,12 @@ def on_finish
@active_tasks.delete(self)
end

def on_update(*args)
def on_update(args)
unless NSThread.isMainThread
performSelectorOnMainThread(:"on_update:", withObject: args, waitUntilDone: false)
return
end

@controller.instance_exec(*args, &@on_update) if @on_update
end
end
Expand Down
37 changes: 3 additions & 34 deletions spec/operation_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
describe Elevate::ElevateOperation do
before do
@target = lambda { @result }
@operation = Elevate::ElevateOperation.alloc.initWithTarget(@target, args: {}, update: nil)
@operation = Elevate::ElevateOperation.alloc.initWithTarget(@target, args: {}, channel: nil)
@queue = NSOperationQueue.alloc.init
end

Expand Down Expand Up @@ -55,7 +55,7 @@
describe "when an exception is raised" do
it "returns the exception" do
@target = lambda { raise IndexError }
@operation = Elevate::ElevateOperation.alloc.initWithTarget(@target, args: {}, update: nil)
@operation = Elevate::ElevateOperation.alloc.initWithTarget(@target, args: {}, channel: nil)

@queue.addOperation(@operation)
@operation.waitUntilFinished()
Expand All @@ -68,7 +68,7 @@
describe "#result" do
before do
@target = lambda { 42 }
@operation = Elevate::ElevateOperation.alloc.initWithTarget(@target, args: {}, update: nil)
@operation = Elevate::ElevateOperation.alloc.initWithTarget(@target, args: {}, channel: nil)
end

describe "before starting the operation" do
Expand Down Expand Up @@ -97,35 +97,4 @@
end
end
end

describe "update_callback" do
before do
@yielded = {}

@callback = lambda do |arg|
@yielded[:thread] = NSThread.currentThread
@yielded[:args] = arg

Dispatch::Queue.main.async do
resume
end
end

@target = lambda { yield 42 }
@operation = Elevate::ElevateOperation.alloc.initWithTarget(@target, args: {}, update: @callback)
@queue.addOperation(@operation)
end

it "invokes the block on the UI thread" do
wait_max 0.5 do
@yielded[:thread].should == NSThread.mainThread
end
end

it "invokes the block with whatever was yielded" do
wait_max 0.5 do
@yielded[:args].should == 42
end
end
end
end

0 comments on commit ff7905d

Please sign in to comment.