#include #include #include #include #include #include #include #include #include #include #include #include "message.h" #ifndef GHOST_LINK_H #define GHOST_LINK_H using namespace std; // WARNING: The Link system relies on bound member functions, a g++ extended feature, // you must compile with -Wno-pmf-conversions. // TODO change to use input and output operators? << >> // TODO use only a single method for link handling, not push, pull? (must alternate anyway) template <> struct hash { size_t operator()(void* __x) const { return (size_t)__x; } }; class _Link { public: typedef void (*sig_h_t)(void *); void *m; void *data; // this is closure data - can be a void * or an int - TODO nice way to get an int into it? sig_h_t push_h; sig_h_t pull_h; _Link(void *data) : data(data) {} }; typedef hash_map links_t; extern links_t links; template class Link : _Link { public: typedef void (M::*member_t)(); typedef void (*func_t)(M *); O& o; Link(O& object, M* machine, member_t push, member_t pull, void *data = 0) : o(object), _Link(data) { hash_map::iterator it = links.find(&o); // TODO use g++ typeof in a macro here? if (it == links.end()) { links[&object] = this; m = machine; push_h = (sig_h_t)(func_t)(machine->*push); pull_h = (sig_h_t)(func_t)(machine->*pull); } else { _Link *peer_link = it->second; if (peer_link == 0) { fatal("already linked"); } else { m = peer_link->m; push_h = peer_link->push_h; pull_h = peer_link->pull_h; peer_link->m = machine; peer_link->push_h = (sig_h_t)(func_t)(machine->*push); peer_link->pull_h = (sig_h_t)(func_t)(machine->*pull); it->second = 0; } } } inline void push(); inline void pull(); }; #include "kernel.h" // NOTE: have changed to use event queues - there is no idea of priority (yet) void Link::push() { // kernel.to_push.push(this); (*push_h)(m); } void Link::pull() { // kernel.to_pull.push(this); (*pull_h)(m); } #endif