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 >