(Whoops, sent from the wrong email address... Please don''t accept the
first message.)
Protocols & Servers, Classes & Modules:
* Why modules for everything, as opposed to classes? It seems like for
a given instance of a machine you might want to do some configuration
and other things that would require state. (Same for the protocols
(servers) too. SSL keys, for example...) Why not derive from some base
class or mixin some functionality from the library, and then run a
configured server and associated protocols?
* I think the Twisted design seems pretty reasonable here. They would
define your EchoServer, for example, as a protocol.
class Echo < EventMachine::Protocol::Base
def receive_data data
send_data ">>>you sent: #{data}"
close_connection if data =~ /quit/i
end
end
They would then require a factory that spits out that protocol for each
connection. Maybe we could do something in between to make it easy for
the common case, but allow for custom factories when needed.
class EchoFactory < EventMachine::Protocol::Factory
def new_connection(con)
Echo.new(my_configuration_here)
end
end
server = EventMachine::Server.new
# Simple version for typical protocol handlers
server.add_protocol "121.123.232.232", 8888, Echo
# Fancier version when a custom factory is needed
server.add_protocol "121.123.232.232", 8888,
EchoFactory.new(config...)
server.run
2) Languages: The language issue is probably going to come up lots. On
ruby-talk both C and ruby versions were mentioned... It seems like the
ideal situation would be to have an all ruby version, and then a
straight C binding that could be used to add some features and/or
improve performance. Any major reasons for going with C++? Does that
make it easier in windows? (On that note, I should warn that I have
minimal knowledge and experience with windows programming...) Since the
OS system calls as well as the rest of ruby are both in C I''d vote to
go
in that direction...
3) AIO: One big question is how far to go with the asynchronicity
(probably not a real word, but you get what I mean :-) of the library.
In Twisted and ACE they use referred objects or tokens. The Twisted
model seems pretty intriguing. You get a referred back from any method
that could take time (connect, send, read, etc...), and then you attach
handlers to the object. One for success and one for an error, I think.
Multiple handlers can be attached also, and the output is pipelined
through the chain of handlers. Have you thought about this end of
things? I think the natural usage of blocks in ruby could lend itself
nicely to an asynchronous system made up of callbacks (at least compared
to python), but it will probably take a bit of thought to get right.
4) Event Loops: We would probably need to provide mechanisms to connect
the event loops of various gui systems to that in the machine. I don''t
know if you make gtk''s main loop, for example, iterate inside of the
machine loop or vice versa. Maybe it depends on whether you want to
favor gui responsiveness or IO performance?
This all makes me think that the best way to work out these issues is
going to be using the library. It''s always obvious when you use a
library that was designed without being used, and with something like
this it seems vital that the core is really clean. For that reason, I
was thinking of getting started by implementing something on top of the
machine so I have more concrete thoughts. Reading all these wishy washy
design pattern discussions is making me want to get back to the code :-)