All, I''ve been working on a new version of the event model for
pure-Ruby
event machine. I did a lot of thinking based on Jeff''s suggestions and
questions from the other day, and I''ll be posting some new code in SVN
shortly. I''ll send around another note when it''s up. Basically
I''m trying to
write a core event-processing engine, irrespective of I/O objects and
Protocol objects, timeouts and thread pools. Hopefully this will give us a
fully-general event-dispatch framework that can work with any kind of event
(program-generated or system-generated, and we''ll probably be able to
generalize it to multiprocess applications running on networks.
So far I have three classes: EventMachine::Reactor, which will be a
singleton that handles event-dispatch, EventMachine::Event, tha object that
gets passed around, and EventMachine::Eventable, which will be a module that
can be mixed into any class.
The key piece is Eventable, which (tentatively) will mix in something like
these methods:
#send_event( target, data, optional_timeout, callbacks, errbacks)
#post_event( same parameters)
#broadcast_event( same parameters)
#add_event_handler( event_type) {|event| ....} # event_type is a Symbol
#set_event_handler( event_type) {|event| ....}
That''s the essence of it, although there are additional helpers. Hope
this
is complete enough to elicit some commentary. All the IO and Protocol
handling will be layered above this basic framework, if it turns out to be
general enough and powerful enough. I''m assuming a development model of
pure
Ruby with (eventually) some performance-critical pieces rewritten in C++.
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://rubyforge.org/pipermail/eventmachine-talk/attachments/20060521/419cc089/attachment.htm
Awesome. This looks and sounds great. Can I add the Timers and Signal
handlers based on the new event module once you check this in? They are
already written with my old event code, so it will be a good way to try
out the Eventable module etc...
One problem I ran into when looking at this stuff is how to support
removal of handlers that are set with blocks passed as an argument. In
typed languages it''s typical to pass self in so that a pre-specified
handler can be called later. One nice side effect of this is that
handlers can be referenced uniquely by their parent object and event
type for removal.
add_event_handler(self, event_type)
remove_event_handler(self, event_type)
With blocks we don''t have that, explicitly at least, but I think I
found
a way to do it. First, I found out you can get the binding of any proc
object easily. This code shows the first test:
def block_parent(block)
eval("self", block.binding)
end
class Foo
def test
block = proc {}
puts block_parent(block).inspect
end
end
Foo.new.test
--------------
Prints out: #<Foo:0xb7d1fa18>
That will let us store the parent of each block passed in, but the
problem is in removal, where we don''t have a block to check for the
binding. Luckily I ran into a little library used in rails that was
written by Florian Gross for just this purpose. (binding_of_caller.rb
attached) This lets you access the binding of the caller in the same
way that you can get the binding of a proc. So we can now store
handlers keyed with their parent object, and remove them using the same.
require ''binding_of_caller''
module Eventable
def caller_object
Binding.of_caller do |binding|
eval("self", binding)
end
end
def add_event_handler(type, &block)
@handlers[type][caller_object] = block
end
def remove_event_handler(type)
@handlers[type].delete(caller_object)
end
end
What do you think?
-Jeff
Francis Cianfrocca wrote:> All, I''ve been working on a new version of the event model for
pure-Ruby
> event machine. I did a lot of thinking based on Jeff''s suggestions
and
> questions from the other day, and I''ll be posting some new code in
SVN
> shortly. I''ll send around another note when it''s up.
Basically I''m
> trying to write a core event-processing engine, irrespective of I/O
> objects and Protocol objects, timeouts and thread pools. Hopefully this
> will give us a fully-general event-dispatch framework that can work with
> any kind of event (program-generated or system-generated, and
we''ll
> probably be able to generalize it to multiprocess applications running
> on networks.
>
> So far I have three classes: EventMachine::Reactor, which will be a
> singleton that handles event-dispatch, EventMachine::Event, tha object
> that gets passed around, and EventMachine::Eventable, which will be a
> module that can be mixed into any class.
>
> The key piece is Eventable, which (tentatively) will mix in something
> like these methods:
>
> #send_event( target, data, optional_timeout, callbacks, errbacks)
> #post_event( same parameters)
> #broadcast_event( same parameters)
>
> #add_event_handler( event_type) {|event| ....} # event_type is a Symbol
> #set_event_handler( event_type) {|event| ....}
>
> That''s the essence of it, although there are additional helpers.
Hope
> this is complete enough to elicit some commentary. All the IO and
> Protocol handling will be layered above this basic framework, if it
> turns out to be general enough and powerful enough. I''m assuming a
> development model of pure Ruby with (eventually) some
> performance-critical pieces rewritten in C++.
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Eventmachine-talk mailing list
> Eventmachine-talk at rubyforge.org
> http://rubyforge.org/mailman/listinfo/eventmachine-talk
-------------- next part --------------
A non-text attachment was scrubbed...
Name: binding_of_caller.rb
Type: application/x-ruby
Size: 2882 bytes
Desc: not available
Url :
http://rubyforge.org/pipermail/eventmachine-talk/attachments/20060522/2543e9f0/attachment-0001.bin
Well, I guess we''ll have a proliferation of little implementations until we agree on the event-core, but here''s a start, in SVN under experiments/core-model-1. Feel free to add/change, or create completely new ones (core-model-2, 3, 4, etc.) I rather like this approach because it abstracts I/O and protocols out, and can easily become multi-process. An event is sent to a "target," which can be one of three things: 1) An Eventable object (or any object that returns true to respond_to?(:receive_event)) 2) The reactor itself 3) A symbol. Symbols can be program-defined event categories which may be subscribed to by any consumer. Additionally, there will be a large number of system-defined events (keypresses and the like) and library-defined events (IO etc). The event-sending calls will (eventually) be: 1) Eventable#post_event( evt, timeout). This schedules the event for consumption by at most one consumer. The event will be discarded (and its errbacks called) if it''s not consumed within the specified timeout period. 2) Eventable#send_event( evt ). Equivalent to post_event( evt, 0 ). Will fail immediately if there is no consumer available when the event is sent. 3) Eventable#broadcast_event( evt, timeout ). Will be sent to *every* subscriber which becomes available during the timeout interval. A timeout of 0 will broadcast to all subscribers which are present at the time the event is received by the reactor. Jeff, I didn''t specifically answer your questions. I''ll do so when I''ve had a chance to think them through. Meantime, please check the new code and criticize. Thanks, -f On 5/22/06, Jeff Rose <jeff at rosejn.net> wrote:> > Awesome. This looks and sounds great. Can I add the Timers and Signal > handlers based on the new event module once you check this in? They are > already written with my old event code, so it will be a good way to try > out the Eventable module etc... > > One problem I ran into when looking at this stuff is how to support > removal of handlers that are set with blocks passed as an argument. In > typed languages it''s typical to pass self in so that a pre-specified > handler can be called later. One nice side effect of this is that > handlers can be referenced uniquely by their parent object and event > type for removal. > > add_event_handler(self, event_type) > remove_event_handler(self, event_type) > > With blocks we don''t have that, explicitly at least, but I think I found > a way to do it. First, I found out you can get the binding of any proc > object easily. This code shows the first test: > > def block_parent(block) > eval("self", block.binding) > end > > class Foo > def test > block = proc {} > puts block_parent(block).inspect > end > end > > Foo.new.test > > -------------- > Prints out: #<Foo:0xb7d1fa18> > > That will let us store the parent of each block passed in, but the > problem is in removal, where we don''t have a block to check for the > binding. Luckily I ran into a little library used in rails that was > written by Florian Gross for just this purpose. (binding_of_caller.rb > attached) This lets you access the binding of the caller in the same > way that you can get the binding of a proc. So we can now store > handlers keyed with their parent object, and remove them using the same. > > require ''binding_of_caller'' > > module Eventable > def caller_object > Binding.of_caller do |binding| > eval("self", binding) > end > end > > def add_event_handler(type, &block) > @handlers[type][caller_object] = block > end > > def remove_event_handler(type) > @handlers[type].delete(caller_object) > end > end > > What do you think? > > -Jeff > > Francis Cianfrocca wrote: > > All, I''ve been working on a new version of the event model for pure-Ruby > > event machine. I did a lot of thinking based on Jeff''s suggestions and > > questions from the other day, and I''ll be posting some new code in SVN > > shortly. I''ll send around another note when it''s up. Basically I''m > > trying to write a core event-processing engine, irrespective of I/O > > objects and Protocol objects, timeouts and thread pools. Hopefully this > > will give us a fully-general event-dispatch framework that can work with > > any kind of event (program-generated or system-generated, and we''ll > > probably be able to generalize it to multiprocess applications running > > on networks. > > > > So far I have three classes: EventMachine::Reactor, which will be a > > singleton that handles event-dispatch, EventMachine::Event, tha object > > that gets passed around, and EventMachine::Eventable, which will be a > > module that can be mixed into any class. > > > > The key piece is Eventable, which (tentatively) will mix in something > > like these methods: > > > > #send_event( target, data, optional_timeout, callbacks, errbacks) > > #post_event( same parameters) > > #broadcast_event( same parameters) > > > > #add_event_handler( event_type) {|event| ....} # event_type is a Symbol > > #set_event_handler( event_type) {|event| ....} > > > > That''s the essence of it, although there are additional helpers. Hope > > this is complete enough to elicit some commentary. All the IO and > > Protocol handling will be layered above this basic framework, if it > > turns out to be general enough and powerful enough. I''m assuming a > > development model of pure Ruby with (eventually) some > > performance-critical pieces rewritten in C++. > > > > > > ------------------------------------------------------------------------ > > > > _______________________________________________ > > Eventmachine-talk mailing list > > Eventmachine-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/eventmachine-talk > > > > _______________________________________________ > Eventmachine-talk mailing list > Eventmachine-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/eventmachine-talk > > >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20060522/4a25f0ba/attachment.htm
Just starting to check out the new stuff now, but looking at it reminded me that I wanted to propose a name change for the module. What do you think about having it be "Machine" rather than "Evma"? It just seems a lot easier to remember, type and talk about - less syllables and easier to relate too... require ''machine'' include Machine Machine::Event.new Sort of has a little more flair, doesn''t it? Not a big deal, but in trying to get enthusiasm for a package having an easy name to think and talk about might help. -Jeff Francis Cianfrocca wrote:> Well, I guess we''ll have a proliferation of little implementations until > we agree on the event-core, but here''s a start, in SVN under > experiments/core-model-1. Feel free to add/change, or create completely > new ones (core-model-2, 3, 4, etc.) > > I rather like this approach because it abstracts I/O and protocols out, > and can easily become multi-process. An event is sent to a "target," > which can be one of three things: > 1) An Eventable object (or any object that returns true to > respond_to?(:receive_event)) > 2) The reactor itself > 3) A symbol. > > Symbols can be program-defined event categories which may be subscribed > to by any consumer. Additionally, there will be a large number of > system-defined events (keypresses and the like) and library-defined > events (IO etc). > > The event-sending calls will (eventually) be: > > 1) Eventable#post_event( evt, timeout). This schedules the event for > consumption by at most one consumer. The event will be discarded (and > its errbacks called) if it''s not consumed within the specified timeout > period. > 2) Eventable#send_event( evt ). Equivalent to post_event( evt, 0 ). Will > fail immediately if there is no consumer available when the event is sent. > 3) Eventable#broadcast_event( evt, timeout ). Will be sent to *every* > subscriber which becomes available during the timeout interval. A > timeout of 0 will broadcast to all subscribers which are present at the > time the event is received by the reactor. > > Jeff, I didn''t specifically answer your questions. I''ll do so when I''ve > had a chance to think them through. Meantime, please check the new code > and criticize. Thanks, > -f > > On 5/22/06, *Jeff Rose* <jeff at rosejn.net <mailto:jeff at rosejn.net>> wrote: > > Awesome. This looks and sounds great. Can I add the Timers and Signal > handlers based on the new event module once you check this in? They are > already written with my old event code, so it will be a good way to try > out the Eventable module etc... > > One problem I ran into when looking at this stuff is how to support > removal of handlers that are set with blocks passed as an argument. In > typed languages it''s typical to pass self in so that a pre-specified > handler can be called later. One nice side effect of this is that > handlers can be referenced uniquely by their parent object and event > type for removal. > > add_event_handler(self, event_type) > remove_event_handler(self, event_type) > > With blocks we don''t have that, explicitly at least, but I think I found > a way to do it. First, I found out you can get the binding of any proc > object easily. This code shows the first test: > > def block_parent(block) > eval("self", block.binding) > end > > class Foo > def test > block = proc {} > puts block_parent(block).inspect > end > end > > Foo.new.test > > -------------- > Prints out: #<Foo:0xb7d1fa18> > > That will let us store the parent of each block passed in, but the > problem is in removal, where we don''t have a block to check for the > binding. Luckily I ran into a little library used in rails that was > written by Florian Gross for just this purpose. (binding_of_caller.rb > attached) This lets you access the binding of the caller in the same > way that you can get the binding of a proc. So we can now store > handlers keyed with their parent object, and remove them using the > same. > > require ''binding_of_caller'' > > module Eventable > def caller_object > Binding.of_caller do |binding| > eval("self", binding) > end > end > > def add_event_handler(type, &block) > @handlers[type][caller_object] = block > end > > def remove_event_handler(type) > @handlers[type].delete(caller_object) > end > end > > What do you think? > > -Jeff > > Francis Cianfrocca wrote: > > All, I''ve been working on a new version of the event model for > pure-Ruby > > event machine. I did a lot of thinking based on Jeff''s > suggestions and > > questions from the other day, and I''ll be posting some new code > in SVN > > shortly. I''ll send around another note when it''s up. Basically I''m > > trying to write a core event-processing engine, irrespective of I/O > > objects and Protocol objects, timeouts and thread pools. > Hopefully this > > will give us a fully-general event-dispatch framework that can > work with > > any kind of event (program-generated or system-generated, and we''ll > > probably be able to generalize it to multiprocess applications > running > > on networks. > > > > So far I have three classes: EventMachine::Reactor, which will be a > > singleton that handles event-dispatch, EventMachine::Event, tha > object > > that gets passed around, and EventMachine::Eventable, which will > be a > > module that can be mixed into any class. > > > > The key piece is Eventable, which (tentatively) will mix in something > > like these methods: > > > > #send_event( target, data, optional_timeout, callbacks, errbacks) > > #post_event( same parameters) > > #broadcast_event( same parameters) > > > > #add_event_handler( event_type) {|event| ....} # event_type is a > Symbol > > #set_event_handler( event_type) {|event| ....} > > > > That''s the essence of it, although there are additional helpers. Hope > > this is complete enough to elicit some commentary. All the IO and > > Protocol handling will be layered above this basic framework, if it > > turns out to be general enough and powerful enough. I''m assuming a > > development model of pure Ruby with (eventually) some > > performance-critical pieces rewritten in C++. > > > > > > > ------------------------------------------------------------------------ > > > > > _______________________________________________ > > Eventmachine-talk mailing list > > Eventmachine-talk at rubyforge.org > <mailto:Eventmachine-talk at rubyforge.org> > > http://rubyforge.org/mailman/listinfo/eventmachine-talk > > > > _______________________________________________ > Eventmachine-talk mailing list > Eventmachine-talk at rubyforge.org <mailto:Eventmachine-talk at rubyforge.org> > http://rubyforge.org/mailman/listinfo/eventmachine-talk > > > > > ------------------------------------------------------------------------ > > _______________________________________________ > Eventmachine-talk mailing list > Eventmachine-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/eventmachine-talk
"Evma" is just a straw man, intended to go away when things are more stable :-). I like machine, but do we want to have the word Event in there to remind people what it''s all about? On 5/22/06, Jeff Rose <rosejn at gmail.com> wrote:> Just starting to check out the new stuff now, but looking at it reminded > me that I wanted to propose a name change for the module. What do you > think about having it be "Machine" rather than "Evma"? It just seems a > lot easier to remember, type and talk about - less syllables and easier > to relate too... > > require ''machine'' > include Machine > Machine::Event.new > > Sort of has a little more flair, doesn''t it? Not a big deal, but in > trying to get enthusiasm for a package having an easy name to think and > talk about might help. > > -Jeff > > Francis Cianfrocca wrote: > > Well, I guess we''ll have a proliferation of little implementations until > > we agree on the event-core, but here''s a start, in SVN under > > experiments/core-model-1. Feel free to add/change, or create completely > > new ones (core-model-2, 3, 4, etc.) > > > > I rather like this approach because it abstracts I/O and protocols out, > > and can easily become multi-process. An event is sent to a "target," > > which can be one of three things: > > 1) An Eventable object (or any object that returns true to > > respond_to?(:receive_event)) > > 2) The reactor itself > > 3) A symbol. > > > > Symbols can be program-defined event categories which may be subscribed > > to by any consumer. Additionally, there will be a large number of > > system-defined events (keypresses and the like) and library-defined > > events (IO etc). > > > > The event-sending calls will (eventually) be: > > > > 1) Eventable#post_event( evt, timeout). This schedules the event for > > consumption by at most one consumer. The event will be discarded (and > > its errbacks called) if it''s not consumed within the specified timeout > > period. > > 2) Eventable#send_event( evt ). Equivalent to post_event( evt, 0 ). Will > > fail immediately if there is no consumer available when the event is sent. > > 3) Eventable#broadcast_event( evt, timeout ). Will be sent to *every* > > subscriber which becomes available during the timeout interval. A > > timeout of 0 will broadcast to all subscribers which are present at the > > time the event is received by the reactor. > > > > Jeff, I didn''t specifically answer your questions. I''ll do so when I''ve > > had a chance to think them through. Meantime, please check the new code > > and criticize. Thanks, > > -f > > > > On 5/22/06, *Jeff Rose* <jeff at rosejn.net <mailto:jeff at rosejn.net>> wrote: > > > > Awesome. This looks and sounds great. Can I add the Timers and Signal > > handlers based on the new event module once you check this in? They are > > already written with my old event code, so it will be a good way to try > > out the Eventable module etc... > > > > One problem I ran into when looking at this stuff is how to support > > removal of handlers that are set with blocks passed as an argument. In > > typed languages it''s typical to pass self in so that a pre-specified > > handler can be called later. One nice side effect of this is that > > handlers can be referenced uniquely by their parent object and event > > type for removal. > > > > add_event_handler(self, event_type) > > remove_event_handler(self, event_type) > > > > With blocks we don''t have that, explicitly at least, but I think I found > > a way to do it. First, I found out you can get the binding of any proc > > object easily. This code shows the first test: > > > > def block_parent(block) > > eval("self", block.binding) > > end > > > > class Foo > > def test > > block = proc {} > > puts block_parent(block).inspect > > end > > end > > > > Foo.new.test > > > > -------------- > > Prints out: #<Foo:0xb7d1fa18> > > > > That will let us store the parent of each block passed in, but the > > problem is in removal, where we don''t have a block to check for the > > binding. Luckily I ran into a little library used in rails that was > > written by Florian Gross for just this purpose. (binding_of_caller.rb > > attached) This lets you access the binding of the caller in the same > > way that you can get the binding of a proc. So we can now store > > handlers keyed with their parent object, and remove them using the > > same. > > > > require ''binding_of_caller'' > > > > module Eventable > > def caller_object > > Binding.of_caller do |binding| > > eval("self", binding) > > end > > end > > > > def add_event_handler(type, &block) > > @handlers[type][caller_object] = block > > end > > > > def remove_event_handler(type) > > @handlers[type].delete(caller_object) > > end > > end > > > > What do you think? > > > > -Jeff > > > > Francis Cianfrocca wrote: > > > All, I''ve been working on a new version of the event model for > > pure-Ruby > > > event machine. I did a lot of thinking based on Jeff''s > > suggestions and > > > questions from the other day, and I''ll be posting some new code > > in SVN > > > shortly. I''ll send around another note when it''s up. Basically I''m > > > trying to write a core event-processing engine, irrespective of I/O > > > objects and Protocol objects, timeouts and thread pools. > > Hopefully this > > > will give us a fully-general event-dispatch framework that can > > work with > > > any kind of event (program-generated or system-generated, and we''ll > > > probably be able to generalize it to multiprocess applications > > running > > > on networks. > > > > > > So far I have three classes: EventMachine::Reactor, which will be a > > > singleton that handles event-dispatch, EventMachine::Event, tha > > object > > > that gets passed around, and EventMachine::Eventable, which will > > be a > > > module that can be mixed into any class. > > > > > > The key piece is Eventable, which (tentatively) will mix in something > > > like these methods: > > > > > > #send_event( target, data, optional_timeout, callbacks, errbacks) > > > #post_event( same parameters) > > > #broadcast_event( same parameters) > > > > > > #add_event_handler( event_type) {|event| ....} # event_type is a > > Symbol > > > #set_event_handler( event_type) {|event| ....} > > > > > > That''s the essence of it, although there are additional helpers. Hope > > > this is complete enough to elicit some commentary. All the IO and > > > Protocol handling will be layered above this basic framework, if it > > > turns out to be general enough and powerful enough. I''m assuming a > > > development model of pure Ruby with (eventually) some > > > performance-critical pieces rewritten in C++. > > > > > > > > > > > ------------------------------------------------------------------------ > > > > > > > > _______________________________________________ > > > Eventmachine-talk mailing list > > > Eventmachine-talk at rubyforge.org > > <mailto:Eventmachine-talk at rubyforge.org> > > > http://rubyforge.org/mailman/listinfo/eventmachine-talk > > > > > > > > _______________________________________________ > > Eventmachine-talk mailing list > > Eventmachine-talk at rubyforge.org <mailto:Eventmachine-talk at rubyforge.org> > > http://rubyforge.org/mailman/listinfo/eventmachine-talk > > > > > > > > > > ------------------------------------------------------------------------ > > > > _______________________________________________ > > Eventmachine-talk mailing list > > Eventmachine-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/eventmachine-talk > > _______________________________________________ > Eventmachine-talk mailing list > Eventmachine-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/eventmachine-talk >
I don''t know, Ruby On Rails or "rails" doesn''t mention web, application or framework anywhere. What do "apache", "linux" or "GNU" really mean for anyone? The word "event" will be all over api, documentation and high level description so that should be clear enough. If we like machine then lets go for it. About the new stuff... This is cool. I hadn''t thought much about abstracting the whole event dispatcher away from the select oriented IO aspect of the reactor, but it makes a lot of sense. Especially when we try to work with various other toolkits. For basic POSIX terminal apps we can use the stock select() call, but for GTK, for example, we''ll have to tie into their main loop. Having a way to do a single iteration like the run_dispatch_loop method will make that a lot easier. Why run the reactor in a different thread though? We will probably want to have all sorts of threading models to process the events, but shouldn''t the stock default be to just run everything in a single thread? -Jeff Francis Cianfrocca wrote:> "Evma" is just a straw man, intended to go away when things are more > stable :-). I like machine, but do we want to have the word Event in > there to remind people what it''s all about? > > On 5/22/06, Jeff Rose <rosejn at gmail.com> wrote: >> Just starting to check out the new stuff now, but looking at it reminded >> me that I wanted to propose a name change for the module. What do you >> think about having it be "Machine" rather than "Evma"? It just seems a >> lot easier to remember, type and talk about - less syllables and easier >> to relate too... >> >> require ''machine'' >> include Machine >> Machine::Event.new >> >> Sort of has a little more flair, doesn''t it? Not a big deal, but in >> trying to get enthusiasm for a package having an easy name to think and >> talk about might help. >> >> -Jeff >> >> Francis Cianfrocca wrote: >>> Well, I guess we''ll have a proliferation of little implementations until >>> we agree on the event-core, but here''s a start, in SVN under >>> experiments/core-model-1. Feel free to add/change, or create completely >>> new ones (core-model-2, 3, 4, etc.) >>> >>> I rather like this approach because it abstracts I/O and protocols out, >>> and can easily become multi-process. An event is sent to a "target," >>> which can be one of three things: >>> 1) An Eventable object (or any object that returns true to >>> respond_to?(:receive_event)) >>> 2) The reactor itself >>> 3) A symbol. >>> >>> Symbols can be program-defined event categories which may be subscribed >>> to by any consumer. Additionally, there will be a large number of >>> system-defined events (keypresses and the like) and library-defined >>> events (IO etc). >>> >>> The event-sending calls will (eventually) be: >>> >>> 1) Eventable#post_event( evt, timeout). This schedules the event for >>> consumption by at most one consumer. The event will be discarded (and >>> its errbacks called) if it''s not consumed within the specified timeout >>> period. >>> 2) Eventable#send_event( evt ). Equivalent to post_event( evt, 0 ). Will >>> fail immediately if there is no consumer available when the event is sent. >>> 3) Eventable#broadcast_event( evt, timeout ). Will be sent to *every* >>> subscriber which becomes available during the timeout interval. A >>> timeout of 0 will broadcast to all subscribers which are present at the >>> time the event is received by the reactor. >>> >>> Jeff, I didn''t specifically answer your questions. I''ll do so when I''ve >>> had a chance to think them through. Meantime, please check the new code >>> and criticize. Thanks, >>> -f >>> >>> On 5/22/06, *Jeff Rose* <jeff at rosejn.net <mailto:jeff at rosejn.net>> wrote: >>> >>> Awesome. This looks and sounds great. Can I add the Timers and Signal >>> handlers based on the new event module once you check this in? They are >>> already written with my old event code, so it will be a good way to try >>> out the Eventable module etc... >>> >>> One problem I ran into when looking at this stuff is how to support >>> removal of handlers that are set with blocks passed as an argument. In >>> typed languages it''s typical to pass self in so that a pre-specified >>> handler can be called later. One nice side effect of this is that >>> handlers can be referenced uniquely by their parent object and event >>> type for removal. >>> >>> add_event_handler(self, event_type) >>> remove_event_handler(self, event_type) >>> >>> With blocks we don''t have that, explicitly at least, but I think I found >>> a way to do it. First, I found out you can get the binding of any proc >>> object easily. This code shows the first test: >>> >>> def block_parent(block) >>> eval("self", block.binding) >>> end >>> >>> class Foo >>> def test >>> block = proc {} >>> puts block_parent(block).inspect >>> end >>> end >>> >>> Foo.new.test >>> >>> -------------- >>> Prints out: #<Foo:0xb7d1fa18> >>> >>> That will let us store the parent of each block passed in, but the >>> problem is in removal, where we don''t have a block to check for the >>> binding. Luckily I ran into a little library used in rails that was >>> written by Florian Gross for just this purpose. (binding_of_caller.rb >>> attached) This lets you access the binding of the caller in the same >>> way that you can get the binding of a proc. So we can now store >>> handlers keyed with their parent object, and remove them using the >>> same. >>> >>> require ''binding_of_caller'' >>> >>> module Eventable >>> def caller_object >>> Binding.of_caller do |binding| >>> eval("self", binding) >>> end >>> end >>> >>> def add_event_handler(type, &block) >>> @handlers[type][caller_object] = block >>> end >>> >>> def remove_event_handler(type) >>> @handlers[type].delete(caller_object) >>> end >>> end >>> >>> What do you think? >>> >>> -Jeff >>> >>> Francis Cianfrocca wrote: >>> > All, I''ve been working on a new version of the event model for >>> pure-Ruby >>> > event machine. I did a lot of thinking based on Jeff''s >>> suggestions and >>> > questions from the other day, and I''ll be posting some new code >>> in SVN >>> > shortly. I''ll send around another note when it''s up. Basically I''m >>> > trying to write a core event-processing engine, irrespective of I/O >>> > objects and Protocol objects, timeouts and thread pools. >>> Hopefully this >>> > will give us a fully-general event-dispatch framework that can >>> work with >>> > any kind of event (program-generated or system-generated, and we''ll >>> > probably be able to generalize it to multiprocess applications >>> running >>> > on networks. >>> > >>> > So far I have three classes: EventMachine::Reactor, which will be a >>> > singleton that handles event-dispatch, EventMachine::Event, tha >>> object >>> > that gets passed around, and EventMachine::Eventable, which will >>> be a >>> > module that can be mixed into any class. >>> > >>> > The key piece is Eventable, which (tentatively) will mix in something >>> > like these methods: >>> > >>> > #send_event( target, data, optional_timeout, callbacks, errbacks) >>> > #post_event( same parameters) >>> > #broadcast_event( same parameters) >>> > >>> > #add_event_handler( event_type) {|event| ....} # event_type is a >>> Symbol >>> > #set_event_handler( event_type) {|event| ....} >>> > >>> > That''s the essence of it, although there are additional helpers. Hope >>> > this is complete enough to elicit some commentary. All the IO and >>> > Protocol handling will be layered above this basic framework, if it >>> > turns out to be general enough and powerful enough. I''m assuming a >>> > development model of pure Ruby with (eventually) some >>> > performance-critical pieces rewritten in C++. >>> >
I''m still thinking about "Machine" :-)
Running the reactor in a different thread: I thought it might be nice
to avoid forcing people to "give up control" of their code. This
parallels what you find in GUI frameworks like Swing or Win32: there
is an internal thread that executes all the events. I also want to
have a very simple path to thread pools. Something like this:
Eventable#add_async_event_handler (evt_type) {|evt| handler }
This method would have change the processing of #receive_event. Rather
than running the whole handler on the reactor''s internal thread, this
variant would schedule the incoming event to run on an internal thread
spun by the add_async_event_handler call itself. This would be good
for handlers that incur external latencies (for example, they query a
database). If you also made it so the handler unsubscribed to the
event during the time in which it''s processing an event and then
resubscribed on completion, you have a quick and easy thread pool.
I hate to say this now that you''re reading core-model-1, but
I''m
writing up a core-model-2 which is somewhat simpler and cleans up the
method names. I want to end up with a clean, minimal core that we can
agree on before we start adding things above it.
On 5/22/06, Jeff Rose <rosejn at gmail.com> wrote:> I don''t know, Ruby On Rails or "rails" doesn''t
mention web, application
> or framework anywhere. What do "apache", "linux" or
"GNU" really mean
> for anyone? The word "event" will be all over api, documentation
and
> high level description so that should be clear enough. If we like
> machine then lets go for it.
>
> About the new stuff... This is cool. I hadn''t thought much about
> abstracting the whole event dispatcher away from the select oriented IO
> aspect of the reactor, but it makes a lot of sense. Especially when we
> try to work with various other toolkits. For basic POSIX terminal apps
> we can use the stock select() call, but for GTK, for example,
we''ll have
> to tie into their main loop. Having a way to do a single iteration like
> the run_dispatch_loop method will make that a lot easier. Why run the
> reactor in a different thread though? We will probably want to have all
> sorts of threading models to process the events, but shouldn''t the
stock
> default be to just run everything in a single thread?
>
> -Jeff
>
> Francis Cianfrocca wrote:
> > "Evma" is just a straw man, intended to go away when things
are more
> > stable :-). I like machine, but do we want to have the word Event in
> > there to remind people what it''s all about?
> >
> > On 5/22/06, Jeff Rose <rosejn at gmail.com> wrote:
> >> Just starting to check out the new stuff now, but looking at it
reminded
> >> me that I wanted to propose a name change for the module. What do
you
> >> think about having it be "Machine" rather than
"Evma"? It just seems a
> >> lot easier to remember, type and talk about - less syllables and
easier
> >> to relate too...
> >>
> >> require ''machine''
> >> include Machine
> >> Machine::Event.new
> >>
> >> Sort of has a little more flair, doesn''t it? Not a big
deal, but in
> >> trying to get enthusiasm for a package having an easy name to
think and
> >> talk about might help.
> >>
> >> -Jeff
> >>
> >> Francis Cianfrocca wrote:
> >>> Well, I guess we''ll have a proliferation of little
implementations until
> >>> we agree on the event-core, but here''s a start, in
SVN under
> >>> experiments/core-model-1. Feel free to add/change, or create
completely
> >>> new ones (core-model-2, 3, 4, etc.)
> >>>
> >>> I rather like this approach because it abstracts I/O and
protocols out,
> >>> and can easily become multi-process. An event is sent to a
"target,"
> >>> which can be one of three things:
> >>> 1) An Eventable object (or any object that returns true to
> >>> respond_to?(:receive_event))
> >>> 2) The reactor itself
> >>> 3) A symbol.
> >>>
> >>> Symbols can be program-defined event categories which may be
subscribed
> >>> to by any consumer. Additionally, there will be a large number
of
> >>> system-defined events (keypresses and the like) and
library-defined
> >>> events (IO etc).
> >>>
> >>> The event-sending calls will (eventually) be:
> >>>
> >>> 1) Eventable#post_event( evt, timeout). This schedules the
event for
> >>> consumption by at most one consumer. The event will be
discarded (and
> >>> its errbacks called) if it''s not consumed within the
specified timeout
> >>> period.
> >>> 2) Eventable#send_event( evt ). Equivalent to post_event( evt,
0 ). Will
> >>> fail immediately if there is no consumer available when the
event is sent.
> >>> 3) Eventable#broadcast_event( evt, timeout ). Will be sent to
*every*
> >>> subscriber which becomes available during the timeout
interval. A
> >>> timeout of 0 will broadcast to all subscribers which are
present at the
> >>> time the event is received by the reactor.
> >>>
> >>> Jeff, I didn''t specifically answer your questions.
I''ll do so when I''ve
> >>> had a chance to think them through. Meantime, please check the
new code
> >>> and criticize. Thanks,
> >>> -f
> >>>
> >>> On 5/22/06, *Jeff Rose* <jeff at rosejn.net <mailto:jeff
at rosejn.net>> wrote:
> >>>
> >>> Awesome. This looks and sounds great. Can I add the
Timers and Signal
> >>> handlers based on the new event module once you check this
in? They are
> >>> already written with my old event code, so it will be a
good way to try
> >>> out the Eventable module etc...
> >>>
> >>> One problem I ran into when looking at this stuff is how
to support
> >>> removal of handlers that are set with blocks passed as an
argument. In
> >>> typed languages it''s typical to pass self in so
that a pre-specified
> >>> handler can be called later. One nice side effect of this
is that
> >>> handlers can be referenced uniquely by their parent object
and event
> >>> type for removal.
> >>>
> >>> add_event_handler(self, event_type)
> >>> remove_event_handler(self, event_type)
> >>>
> >>> With blocks we don''t have that, explicitly at
least, but I think I found
> >>> a way to do it. First, I found out you can get the
binding of any proc
> >>> object easily. This code shows the first test:
> >>>
> >>> def block_parent(block)
> >>> eval("self", block.binding)
> >>> end
> >>>
> >>> class Foo
> >>> def test
> >>> block = proc {}
> >>> puts block_parent(block).inspect
> >>> end
> >>> end
> >>>
> >>> Foo.new.test
> >>>
> >>> --------------
> >>> Prints out: #<Foo:0xb7d1fa18>
> >>>
> >>> That will let us store the parent of each block passed in,
but the
> >>> problem is in removal, where we don''t have a
block to check for the
> >>> binding. Luckily I ran into a little library used in
rails that was
> >>> written by Florian Gross for just this purpose.
(binding_of_caller.rb
> >>> attached) This lets you access the binding of the caller
in the same
> >>> way that you can get the binding of a proc. So we can now
store
> >>> handlers keyed with their parent object, and remove them
using the
> >>> same.
> >>>
> >>> require ''binding_of_caller''
> >>>
> >>> module Eventable
> >>> def caller_object
> >>> Binding.of_caller do |binding|
> >>> eval("self", binding)
> >>> end
> >>> end
> >>>
> >>> def add_event_handler(type, &block)
> >>> @handlers[type][caller_object] = block
> >>> end
> >>>
> >>> def remove_event_handler(type)
> >>> @handlers[type].delete(caller_object)
> >>> end
> >>> end
> >>>
> >>> What do you think?
> >>>
> >>> -Jeff
> >>>
> >>> Francis Cianfrocca wrote:
> >>> > All, I''ve been working on a new version of
the event model for
> >>> pure-Ruby
> >>> > event machine. I did a lot of thinking based on
Jeff''s
> >>> suggestions and
> >>> > questions from the other day, and I''ll be
posting some new code
> >>> in SVN
> >>> > shortly. I''ll send around another note when
it''s up. Basically I''m
> >>> > trying to write a core event-processing engine,
irrespective of I/O
> >>> > objects and Protocol objects, timeouts and thread
pools.
> >>> Hopefully this
> >>> > will give us a fully-general event-dispatch
framework that can
> >>> work with
> >>> > any kind of event (program-generated or
system-generated, and we''ll
> >>> > probably be able to generalize it to multiprocess
applications
> >>> running
> >>> > on networks.
> >>> >
> >>> > So far I have three classes: EventMachine::Reactor,
which will be a
> >>> > singleton that handles event-dispatch,
EventMachine::Event, tha
> >>> object
> >>> > that gets passed around, and
EventMachine::Eventable, which will
> >>> be a
> >>> > module that can be mixed into any class.
> >>> >
> >>> > The key piece is Eventable, which (tentatively) will
mix in something
> >>> > like these methods:
> >>> >
> >>> > #send_event( target, data, optional_timeout,
callbacks, errbacks)
> >>> > #post_event( same parameters)
> >>> > #broadcast_event( same parameters)
> >>> >
> >>> > #add_event_handler( event_type) {|event| ....} #
event_type is a
> >>> Symbol
> >>> > #set_event_handler( event_type) {|event| ....}
> >>> >
> >>> > That''s the essence of it, although there
are additional helpers. Hope
> >>> > this is complete enough to elicit some commentary.
All the IO and
> >>> > Protocol handling will be layered above this basic
framework, if it
> >>> > turns out to be general enough and powerful enough.
I''m assuming a
> >>> > development model of pure Ruby with (eventually)
some
> >>> > performance-critical pieces rewritten in C++.
> >>> >
> _______________________________________________
> Eventmachine-talk mailing list
> Eventmachine-talk at rubyforge.org
> http://rubyforge.org/mailman/listinfo/eventmachine-talk
>