Using Reactors
In dealing with functional languages you get used to using functions as "glue" to tie pieces of functionality together in a sort of ad-hoc manner. This is very unusual for a normal imperative language programmer because that type of functional interfacing is usually paired with rigorous definitions if interface objects (be it abstract classes or function pointer structures).
In trying to replicate this I like to use a concept that mimics that type of interfacing that I call a Reactor.
The construction of a Reactor is very simple. There are two parts. For the caller side there is an interface pointer that has a method for the call operator operator(). That's all that is knows about. The bind side has the derived implementation of the interface where a binding between the execution environment and the function pointer is saved in a lightweight object. This is the actual closure object and can be a function with an environment bound to an argument or can be a member function bound to a specific object.
The binding object is created by simply subclassing the root interface that the caller will be aware of. This binding object can be mananged by being an automatic variable, a member object or a managed heap allocated object in an appropriate collection like boost::ptr_container collections.
Creating the interface pointer
The interface can be a pure virtual interface with effectively one virtual function. I like to use the call operator just to reinforce the function of the interface.
class reactor {
public:
virtual void operator()() = 0;
virtual ~reactor() = 0;
};
inline reactor::~reactor() {}
Also a functor can be created for useful calls into the STL algorithms and readable explicit calls.
struct call_reactor : public std::unary_function<void, reactor*> {
void operator()(reactor *r) {
r->operator()();
}
};
Creating Bindings
The basic pattern of binding definitions is to create an extension of the interface with some member variable that will be used to bind the functor creation paramters with the call of operator().
template<typename Class>
class mem_fun_reactor : public virtual reactor {
public:
typedef void (Class::*mem_fun_t)();
public:
mem_fun_reactor()
: object_(0),
handler_(0) {}
explicit mem_fun_reactor(Class *object, mem_fun_t handler)
: object_(object),
handler_(handler) {}
virtual ~mem_fun_reactor() {}
virtual void operator()() {
if (object_) ((object_)->*(handler_))();
}
Class *object_;
mem_fun_t handler_;
};
In the example above we take a member function address and bind it to the this pointer that was saved as Class *object_;.
