diff --git a/luprex/core/cpp/drivenengine.hpp b/luprex/core/cpp/drivenengine.hpp index eb08d184..3583ad2d 100644 --- a/luprex/core/cpp/drivenengine.hpp +++ b/luprex/core/cpp/drivenengine.hpp @@ -27,11 +27,11 @@ // functions like "read" or "write" or "connect." They don't call the operating // system at all - not even indirectly, through a wrapper. Therefore, they // can't really do any I/O. When you use one of these I/O functions to (say) -// write some data to a communication channel, the only thing that happens -// is that the data is put into a buffer. The actual transmission of the -// data happens elsewhere, in what is called the "Driver." Likewise, when you -// use one of these I/O functions to read data, it only returns data that -// was previously stored by the "Driver." +// write some data to a communication channel, the only thing that happens is +// that the data is put into a buffer. The actual transmission of the data +// happens elsewhere, in what is called the "Driver." Likewise, when you use +// one of these I/O functions to read data, it only returns data that was +// previously stored by the "Driver." // // The "Driver" is a module that implements the actual I/O. It is highly // OS-dependent code, because it contains code to manipulate sockets, time @@ -47,38 +47,64 @@ // DrivenEngine, it's the other way around: the driver calls into class // DrivenEngine to drive it forward. I/O routines drive computation. // -// So the upshot of all this is that the DrivenEngine is a deterministic -// state machine, free of all OS-specific code. -// -////////////////////////////////////////////////////////////// -// -// -// * List all existing channels using drv_list_channels. -// -// * If there are any new channels in the channel list, use -// drv_get_channel_target to fetch the target host, then create a socket and -// open the connection. Associate the socket with the channel. -// -// * Do an OS 'poll'. The poll should include the sockets for all channels in -// the channel list, all listening ports, and stdio. -// -// * If the poll indicates that a listening port has acceptable connections, -// accept and call drv_notify_accept. Associate the accepted socket with the -// channel. -// -// * If the poll indicates that a connection can accept outgoing data, use -// drv_peek_outgoing to fetch some data to write, and write it. Use -// drv_sent_outgoing_bytes to indicate that the data was sent. -// -// * If the poll indicates that a connection has incoming data, read the data -// then push it into the channel using drv_recv_incoming. -// -// * If the poll indicates that STDIO can be read/written, use -// drv_peek_outgoing, drv_sent_outgoing, and drv_recv_incoming in the same -// manner as you would for a socket. +// So the upshot of all this is that the DrivenEngine is a deterministic state +// machine, free of all OS-specific code. +// +////////////////////////////////////////////////////////////// +// +// Here are the rules for what the driver must do: +// +// * Before doing anything else, the driver must select one of the three +// logmodes. +// +// * If 'logmode_replay' is selected, then the driver must proceed to invoke +// 'drv_step_logfile' over and over until it returns false. In replay mode, +// the driver should not do anything else. +// +// * If 'logmode_write' or 'logmode_none' is selected, the driver must proceed +// to drive the application. Follow the remainder of these steps. +// +// * Read the lua source from disk, and call 'drv_set_lua_source'. +// +// * Invoke the DrivenEngine's init callback by calling +// 'drv_invoke_engine_init'. +// +// * Open a hardwired list of ports for listening. +// +// * Repeat the following steps over and over: +// +// - List all existing channels using drv_list_channels. +// +// - If there are any new channels in the channel list, use +// drv_get_channel_target to fetch the target host, then create a socket +// and open the connection. Associate the socket with the channel. +// +// - If the channel list is missing a previously-known channel, then that +// channel was deleted by the engine. Clean up the channel's data and +// close the socket, if any. +// +// - Do an OS 'poll'. The poll should include the sockets for all channels +// in the channel list, all listening ports, and stdio. +// +// - If the poll indicates that a listening port has acceptable +// connections, accept and call drv_notify_accept. Associate the +// accepted socket with the channel. +// +// - If the poll indicates that a connection can accept outgoing data, use +// drv_peek_outgoing to fetch some data to write, and write it. Use +// drv_sent_outgoing_bytes to indicate that the data was sent. +// +// - If the poll indicates that a connection has incoming data, read the +// data then push it into the channel using drv_recv_incoming. +// +// - If the poll indicates that STDIO can be read/written, use +// drv_peek_outgoing, drv_sent_outgoing, and drv_recv_incoming in the +// same manner as you would for a socket. +// +// - Use 'drv_invoke_engine_update' to invoke the engine's update +// callback. // ////////////////////////////////////////////////////////////// - #ifndef DRIVENENGINE_HPP #define DRIVENENGINE_HPP