methodmissing-channel 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README CHANGED
@@ -32,7 +32,7 @@ Caveats :
32
32
  Examples :
33
33
 
34
34
  counter = 0
35
- ch = Channel.new.subscribe{|obj| @counter += obj }
35
+ ch = Channel.new.subscribe{|obj| counter += obj }
36
36
  ch << 3
37
37
  ch << -2
38
38
  counter #=> 1
@@ -41,6 +41,7 @@ Todo :
41
41
 
42
42
  * A deferrable mode that notifies on a background thread
43
43
  * More flexible notification mechanism through integration with http://github.com/methodmissing/callback/tree/master
44
+ * Filters
44
45
 
45
46
  To run the test suite:
46
47
 
data/Rakefile CHANGED
@@ -63,6 +63,7 @@ task :setup => %w(clean build install)
63
63
 
64
64
  desc "run benchmarks"
65
65
  task :bench do |t|
66
- ruby "bench/bench.rb"
66
+ ruby "bench/bench.rb"
67
+ ruby "bench/bench_deferred.rb"
67
68
  end
68
69
  task :bench => :build
data/bench/bench.rb CHANGED
@@ -5,7 +5,7 @@ require File.dirname(__FILE__) + "/ruby_channel"
5
5
 
6
6
  channel = Channel.new(16)
7
7
  16.times{ channel.subscribe{|o| o } }
8
- rb_channel = RubyChannel.new
8
+ rb_channel = RubyChannel.new(16)
9
9
  16.times{ rb_channel.subscribe{|o| o } }
10
10
 
11
11
  TESTS = 10_000
@@ -1,12 +1,19 @@
1
1
  class RubyChannel
2
- def initialize
2
+ def initialize(size = 1,defer = false)
3
+ @size = size
3
4
  @subscribers = []
5
+ @defer = defer
4
6
  end
5
7
  def subscribe(&b)
8
+ raise ArgumentError.new("Maximum number of subscribers exceeded!") unless @subscribers.size < @size
6
9
  @subscribers << b
7
10
  self
8
11
  end
9
12
  def <<(o)
10
- @subscribers.each { |s| s.call(o) }
13
+ unless @defer
14
+ @subscribers.each { |s| s.call(o) }
15
+ else
16
+ Thread.new{ @subscribers.each { |s| s.call(o) } }
17
+ end
11
18
  end
12
19
  end
data/channel.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "channel"
3
- s.version = "1.0.0"
3
+ s.version = "1.0.1"
4
4
  s.date = "2009-08-28"
5
5
  s.summary = "Native MRI channel"
6
6
  s.email = "lourens@methodmissing.com"
@@ -1,8 +1,9 @@
1
1
  #include "ruby.h"
2
2
 
3
3
  typedef struct {
4
- int size;
5
- int sbs;
4
+ int size;
5
+ int defer;
6
+ int sbs;
6
7
  VALUE *subscribers;
7
8
  } RChannel;
8
9
 
@@ -33,6 +34,7 @@ channel_alloc( VALUE klass )
33
34
  RChannel* chs;
34
35
  ch = Data_Make_Struct(klass, RChannel, mark_channel, free_channel, chs);
35
36
  chs->size = 0;
37
+ chs->defer = 0;
36
38
  chs->sbs = 0;
37
39
  chs->subscribers = 0;
38
40
 
@@ -40,7 +42,7 @@ channel_alloc( VALUE klass )
40
42
  }
41
43
 
42
44
  static VALUE
43
- rb_channel_new(VALUE ch, int size)
45
+ rb_channel_new(VALUE ch, int size, int defer)
44
46
  {
45
47
  RChannel* chs = GetChannelStruct(ch);
46
48
  if (size < 0 || size > MAX_CHANNEL_SIZE){
@@ -48,6 +50,7 @@ rb_channel_new(VALUE ch, int size)
48
50
  }
49
51
  if (size == 0) size++;
50
52
  chs->size = size;
53
+ chs->defer = defer;
51
54
  chs->subscribers = ALLOC_N(VALUE, size);
52
55
  return ch;
53
56
  }
@@ -55,11 +58,12 @@ rb_channel_new(VALUE ch, int size)
55
58
  static VALUE
56
59
  rb_channel_initialize( int argc, VALUE *argv, VALUE ch )
57
60
  {
58
- VALUE size;
59
- int channel_size;
60
- rb_scan_args(argc, argv, "01", &size);
61
+ VALUE size, defer;
62
+ int channel_size, def;
63
+ rb_scan_args(argc, argv, "02", &size, &defer);
61
64
  channel_size = NIL_P(size) ? 0 : FIX2INT(size);
62
- return rb_channel_new(ch, channel_size);
65
+ def = (defer == Qtrue) ? 1 : 0;
66
+ return rb_channel_new(ch, channel_size, def);
63
67
  }
64
68
 
65
69
  static VALUE
@@ -76,25 +80,47 @@ rb_channel_subscribers( VALUE ch )
76
80
  return INT2FIX(chs->sbs);
77
81
  }
78
82
 
83
+ static VALUE
84
+ rb_channel_deferrable_p( VALUE ch )
85
+ {
86
+ RChannel* chs = GetChannelStruct(ch);
87
+ return (chs->defer == 1) ? Qtrue : Qfalse;
88
+ }
89
+
79
90
  static VALUE
80
91
  rb_channel_subscribe( int argc, VALUE *argv, VALUE ch )
81
92
  {
82
93
  VALUE cb;
83
94
  RChannel* chs = GetChannelStruct(ch);
84
95
  if (!rb_block_given_p()) rb_raise(rb_eArgError, "Block callback required!");
96
+ if (chs->sbs == chs->size) rb_raise(rb_eArgError, "Maximum number of subscribers exceeded!");
85
97
  cb = rb_block_proc();
86
98
  chs->subscribers[chs->sbs] = cb;
87
99
  chs->sbs++;
88
100
  return ch;
89
101
  }
90
102
 
103
+ static void
104
+ rb_channel_push0( RChannel* chs, VALUE *ch, VALUE *obj )
105
+ {
106
+ int i;
107
+ for (i=0; i < chs->sbs; i++) {
108
+ rb_funcall(chs->subscribers[i],id_call,1,*obj);
109
+ }
110
+ }
111
+
91
112
  static VALUE
92
113
  rb_channel_push( VALUE ch, VALUE obj )
93
114
  {
94
- int i;
95
- RChannel* chs = GetChannelStruct(ch);
96
- for (i=0; i < chs->sbs; i++) {
97
- rb_funcall(chs->subscribers[i],id_call,1,obj);
115
+ void *args[3];
116
+ RChannel* chs = GetChannelStruct(ch);
117
+ if (chs->defer == 1){
118
+ args[0] = chs;
119
+ args[1] = &ch;
120
+ args[2] = &obj;
121
+ rb_thread_create( rb_channel_push0, &args);
122
+ }else{
123
+ rb_channel_push0(chs,&ch,&obj);
98
124
  }
99
125
  return ch;
100
126
  }
@@ -110,6 +136,7 @@ Init_channel()
110
136
  rb_define_method(rb_cChannel,"initialize", rb_channel_initialize, -1);
111
137
  rb_define_method(rb_cChannel,"size", rb_channel_size, 0);
112
138
  rb_define_method(rb_cChannel,"subscribers", rb_channel_subscribers, 0);
139
+ rb_define_method(rb_cChannel,"deferrable?", rb_channel_deferrable_p, 0);
113
140
  rb_define_method(rb_cChannel,"subscribe", rb_channel_subscribe, -1);
114
141
  rb_define_method(rb_cChannel,"<<", rb_channel_push, 1);
115
142
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: methodmissing-channel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Lourens Naud\xC3\xA9 (methodmissing)"
@@ -32,6 +32,7 @@ files:
32
32
  - channel.gemspec
33
33
  has_rdoc: true
34
34
  homepage: http://github.com/methodmissing/channel
35
+ licenses:
35
36
  post_install_message:
36
37
  rdoc_options:
37
38
  - --main
@@ -53,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
53
54
  requirements: []
54
55
 
55
56
  rubyforge_project:
56
- rubygems_version: 1.2.0
57
+ rubygems_version: 1.3.5
57
58
  signing_key:
58
59
  specification_version: 2
59
60
  summary: Native MRI channel