methodmissing-channel 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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