wires 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eac9a387ed62e4acf7fc95260c323ace017c0f01
4
- data.tar.gz: 97b7e1f9b746f68cd801d293bc126427df8e819f
3
+ metadata.gz: b10bb4a5abcff971b03e3ed715141508e21059b8
4
+ data.tar.gz: b2e95646c96b287a988ed2f0608b7b7159bce712
5
5
  SHA512:
6
- metadata.gz: d423c7af695a85c07f48e6b0e5d1ba5be178205f09bb5588ea550fd40409ec775708959f64a1335a3ab72a6dff42f6a67d70834d5cb023bd04669ea1d2267594
7
- data.tar.gz: f98fa6910fc0bd8418f8c8421bc25a48fb183e93689aa9dcd5134d03c5cfccb9a97f6128758bfa32d459e0a4e466f1f17c6c96d91a8f1497e1d0f68593e5201e
6
+ metadata.gz: b92ae83348fd8024b84324ab06d7f73978ffc516738201519e49898dd2ebd8469529792f99dbf7e3a4d1a0d26eb49bcace82e42cf4dabad279490b9d91c8ba70
7
+ data.tar.gz: 788c6c1ef24826e7b94661f0b5a7db4f30bcd83584e48c41c6438bd0e900f54dd7ad441702629723783c3218b66d2883b3edc0baa5eeab7aa4b1f9a5af8e17fe
data/lib/wires.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'set'
2
2
  require 'thread'
3
+ require 'active_support/core_ext' # For time convenience functions
3
4
 
4
5
  require 'wires/events'
5
6
  require 'wires/hub'
6
- require 'wires/channels'
7
+ require 'wires/channels'
8
+ require 'wires/time'
data/lib/wires/hub.rb CHANGED
@@ -6,68 +6,104 @@ def puts(x) $stdout.puts(x) end
6
6
  # An Event Hub. Event/proc associations come in, and the procs
7
7
  # get called in new threads in the order received
8
8
  class Hub
9
- @@queue = Queue.new
10
- @@running = false
9
+ @queue = Queue.new
10
+ @running = false
11
+
12
+ @before_kills = Queue.new
13
+ @after_kills = Queue.new
14
+
15
+ # Operate on the metaclass as a type of singleton pattern
16
+ class << self
11
17
 
12
- def self.running?; @@running; end
18
+ def running?; @running; end
13
19
 
14
20
  # Start the Hub event loop in a new thread
15
- def self.run
16
- if not @@running
17
- @@running = true
18
- @@thread = Thread.new() {Hub.run_loop}
19
- at_exit { @@thread.join if not $! }
20
- end
21
+ def run
22
+ if not @running
23
+ @running = true
24
+ @thread = Thread.new() {self.send(:run_loop)};
25
+ at_exit { @thread.join if not $! }
26
+ end
21
27
  nil end
22
28
 
23
29
  # Start the Hub event loop in the current thread
24
- def self.run_in_place()
25
- self.run_loop() unless @@running
30
+ def run_in_place()
31
+ self.send(:run_loop) unless @running
26
32
  nil end
27
33
 
28
34
  # Kill the Hub event loop (softly)
29
- def self.kill() @@running=false end
35
+ def kill();
36
+ # Call the before kill hooks
37
+ while not @before_kills.empty?
38
+ @before_kills.shift.call
39
+ end
40
+ # Stop the main event loop
41
+ @running=false;
42
+ end
43
+
44
+ # Register hook to execute before kill - can call multiple times
45
+ def before_kill(proc=nil, &block)
46
+ func = (block or proc)
47
+ if not func.is_a?(Proc)
48
+ raise TypeError, "Expected a Proc or code block to execute."
49
+ end
50
+ @before_kills << func
51
+ end
52
+
53
+ # Register hook to execute after kill - can call multiple times
54
+ def after_kill(proc=nil, &block)
55
+ func = (block or proc)
56
+ if not func.is_a?(Proc)
57
+ raise TypeError, "Expected a Proc or code block to execute."
58
+ end
59
+ @after_kills << func
60
+ end
30
61
 
31
62
  # Put x in the queue, and block until x is processed
32
- def self.fire(x)
33
- @@queue << [x, Thread.current]
34
- # yield to event loop thread until awoken by it later
35
- sleep unless not @@running
63
+ def fire(x)
64
+ @queue << [x, Thread.current]
65
+ # yield to event loop thread until awoken by it later
66
+ sleep unless not @running
36
67
  end
37
- def self.<<(x) fire(x) end
68
+ def <<(x); fire(x); end
38
69
 
39
- private
70
+ private
40
71
 
41
- def self.run_loop
42
- @@running = true
43
-
44
- while @@running
45
- if @@queue.empty? then sleep(0)
46
- else process_item(@@queue.shift) end
47
- end
72
+ def run_loop
73
+ @running = true
74
+
75
+ while @running
76
+ if @queue.empty? then sleep(0)
77
+ else process_item(@queue.shift) end
78
+ end
79
+
80
+ while not @after_kills.empty?
81
+ @after_kills.shift.call
82
+ end
48
83
  end
49
84
 
50
- def self.process_item(x)
51
- x, waiting_thread = x
52
- string, event, blocking, proc = x
53
- Thread.new do
54
- begin
55
- waiting_thread.wakeup unless blocking
56
- proc.call($event = event)
57
- waiting_thread.wakeup if blocking
58
-
59
- rescue Interrupt, SystemExit => e
60
- @running = false
61
- unhandled_exception(e)
62
-
63
- rescue Exception => e
64
- unhandled_exception(e)
65
- end
85
+ def process_item(x)
86
+ x, waiting_thread = x
87
+ string, event, blocking, proc = x
88
+ Thread.new do
89
+ begin
90
+ waiting_thread.wakeup unless blocking
91
+ proc.call($event = event)
92
+ waiting_thread.wakeup if blocking
93
+
94
+ rescue Interrupt, SystemExit => e
95
+ @running = false
96
+ unhandled_exception(e)
97
+
98
+ rescue Exception => e
99
+ unhandled_exception(e)
66
100
  end
101
+ end
67
102
  end
68
103
 
69
- def self.unhandled_exception(x)
70
- $stderr.puts $!
71
- $stderr.puts $@
104
+ def unhandled_exception(x)
105
+ $stderr.puts $!
106
+ $stderr.puts $@
72
107
  end
108
+ end
73
109
  end
data/lib/wires/time.rb ADDED
@@ -0,0 +1,75 @@
1
+
2
+
3
+ # class StartSchedulerEvent < Event; end
4
+
5
+ # # A singleton class to schedule future firing of events
6
+ # class TimeScheduler
7
+ # @schedule = Array.new
8
+ # @schedule_lock = Mutex.new
9
+ # @grain = 0.2.seconds
10
+
11
+ # # Operate on the metaclass as a type of singleton pattern
12
+ # class << self
13
+
14
+ # # Get or set the time grain from outside the class
15
+ # attr_accessor :grain
16
+
17
+ # # Fire an event delayed by time value
18
+ # def fire(time, event, channel='*')
19
+ # if not time.is_a? Time
20
+ # raise TypeError, "Expected #{time.inspect} to be an instance of Time."
21
+ # end
22
+
23
+ # # Under mutex, push the event into the schedule and sort
24
+ # @schedule_lock.synchronize do
25
+ # @schedule << [time, event, channel]
26
+ # @schedule.sort! { |a,b| a[0] <=> b[0] }
27
+ # end
28
+
29
+ # end
30
+
31
+ # private
32
+
33
+ # def main_loop
34
+
35
+ # pending = Array.new
36
+
37
+ # while true
38
+
39
+ # pending.clear
40
+ # this_time = Time.now
41
+
42
+ # # Under mutex, pull any events that are ready
43
+ # @schedule_lock.synchronize do
44
+ # while ((not @schedule.empty?) and (this_time > @schedule[0][0]))
45
+ # puts 'thing'
46
+ # pending << @schedule.shift
47
+ # end
48
+ # end
49
+
50
+ # # Fire pending events
51
+ # pending.each { |x| Channel(x[2]).fire(x[1]) }
52
+
53
+ # # Calculate the time to sleep based on the time left in the "grain"
54
+ # sleep [@grain-(Time.now-this_time), 0].max
55
+
56
+ # end
57
+ # end
58
+
59
+ # end
60
+
61
+ # # Use fired event to only start scheduler when Hub is running
62
+ # # This also gets the scheduler loop its own thread within the Hub's threads
63
+ # on :start_scheduler, self do; main_loop; end;
64
+ # Channel(self).fire(:start_scheduler)
65
+
66
+ # # Channel(self).fire(:start_scheduler, blocking=true)
67
+ # end
68
+
69
+ # # Reopen the Time class and add the fire method to enable nifty syntax like:
70
+ # # 32.minutes.from_now.fire :event
71
+ # class Time
72
+ # def fire(*args)
73
+ # TimeScheduler.fire(self, *args)
74
+ # end
75
+ # end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wires
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-26 00:00:00.000000000 Z
11
+ date: 2013-06-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: An asynchronous (threaded) event routing framework in Ruby. Patch your
14
14
  objects together with wires. Inspired by the python 'circuits' framework.
@@ -18,6 +18,7 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - lib/wires.rb
21
+ - lib/wires/time.rb
21
22
  - lib/wires/hub.rb
22
23
  - lib/wires/events.rb
23
24
  - lib/wires/channels.rb