I'm working on a piece of software that is constructed from a series of "modules". Modules can be connected together to form the full application (one module might go to another, sort of an implied state machine). Each module can render to the screen, get updates and access state from other modules. Note that the modules are still within the same process, so no IPC needs to be designed into this.
However, these modules do not directly depend on each other. There is a singleton object that has the sole purpose of managing message passing between the modules. When you want to register for an event from any module:
CPostMaster::Instance().RegisterEvent("TheEventName", [](std::string const& data) { /* the callback */ });
The data variable is serialized data. Can be anything, but usually is XML or JSON. To send the event you do:
std::string serialized_data = /* serialized data, do this before calling */;
CPostMaster::Instance().SendEvent("TheEventName", serialized_data);
The 2nd parameter is optional.
Having a "master authority" for message passing has a drawback: The events themselves can't send varying parameters without utilizing some sort of serialization or type erasure (removes type safety from the picture and impacts performance).
But it also has the benefit of strict/strong coupling not being required, which means that at any given time a different module can be responsible for sending a specific event without the receiving modules having to change.
The alternative seems to be not using a singleton, and instead each module receives an object that it can use to subscribe to. This could get messy especially when you are passing them around everywhere, it will quickly mean that functions start taking boilerplate parameters.
What is a good design for message passing in a system such as this? How can it be improved and be made manageable? Type safety and open/close principles are important here. I think it's OK to have direct dependencies across modules so long as they can be mocked (for unit testing) and easily swapped out should modules change without severely impacting the whole system (but this is part of the open/close principle).
First: I dislike singletons. The only singleton I accept is a singleton manager (some sort of central instance distributor) that handles a defined init and deinit of all "singletons" in a defined order.
But back to your problem:
Your title already has the solution: Define a message interface. If you want type-safety define an IMessage with common attributes.
Then define specializations of IMessage which then are consumed by your callbacks.
The tricky part is: You will need RTTI for that, which is odd in c++, I know but might be worth the benefits, if you are restricted to gcc or visual studio, you could make use of those types, or implement some simple RTTI in the IMessage itself to avoid dynamic_cast.
To avoid boilerplate code in a callback which checks and casts around the IMessage I would provide a utility function (pseudo code, adjust for pointers, references, smart ptrs, const correctness etc.)
T SafeCast<T>(IMessage message);
depending on the implementation of your compiler you should add restrictions to T to be of a sub type of IMessage and what should happen when the cast fails (exception, nullptr, etc).
Alternatively: Check how others have solved this (maybe Qt's Signals&Slots or something in Boost)
I would make the sub modules dependent on a parent class (in your case the singleton). Then you could pass this object's reference along the line, to be used in the modules.
Module(Handler& h) : _h(h) { }
void do_stuff(){
_h.RegisterEvent("TheEventName", [](std::string const& data)
{ /* the callback */ })
Then I would register your Module class itself, or another class, as an Event, and on the Handler side, I would formalize the messaging in a way that you'd get multiple callbacks instead of just one. You'd have to formalize your message though, but you'd have type safety instead of passing strings.
For example the handler, while parsing a message, he'd call:
_callback.start(); //signals the start of a message
_callback.signalParam1(1); //calls Module.signalParam(int);
_callback.signalParam2("test"); //calls Module.signalParam2(const char*);
_callback.end();
Your Module would need to implement those.
Related
Event-driven systems are used to reduce dependencies in large systems with many-to-many object interactions of various types. As such, they aim to pass arbitrary information between arbitrary objects. This is typically done by registering event handlers with an event_manager, using type erasure in the handler, i.e.:
void handle_some_event(event *e) {/*Downcast e to an assumed appropriate type and work with it*/}
However, suppose we wanted to implement such a system without type erasure. It seems that certain language features, particularly generics, should make it possible. The handler registration in the event_manager could be templated, i.e. (loosely):
template<typename event_type>
void event_manager::register_handler(std::function<void(event_type)> handler) {
// Implementation
}
The struggle is, what should the //Implementation of this function be? After receiving the handler, it needs to be stored in some container related to event_type. But in order to avoid type erasure, there would have to be a container per event_type.
One possible option is to use static containers in template classes, i.e.:
template<typename event_type>
class handler_container {
public:
inline static std::vector<std::function<void(event_type)>> handlers;
};
The event_manager could store and execute handlers in the corresponding handler_container<event_type>::handlers container. However, this has the obvious disadvantage that there can only really be one event_manager, given that the containers are static and thus shared across all event_managers. Perhaps this is sufficient for most applications, but it's still an ugly solution.
Are there any design patterns that would allow for a cleaner solution to this problem?
Not a design pattern, but in theory it looks like a potential use case for std::variant. You can define your event type as an alias to a std::variant of all possible event options, and your handlers would be C++20's template lambdas that check for the type they want using constexpr if. Finally, the code that generates the event initializes the std::variant with an appropriate event type and all handlers are invoked with std::visit.
Use of std::variant might seem like a potential problem of scalability, but if the handlers are written sensibly they shouldn't break when adding more variants.
I don't know of any major project that uses this "technique", so I wouldn't jump ahead to use it in production code immediately. Also, it requires C++20 to write it without (too much) boilerplate, so it might not apply for most use cases out there. But it looks doable and doesn't require type erasure.
I'm working with a different team on a project. The other team is constructing a GUI, which, like most GUI frameworks is very inheritance driven. On the other hand, the code on this side ('bottom end', I guess one could say) is essentially C (though I believe it's all technically C++ via the MSVC2010 toolchain w/o the "treat as C" flag.
Both modules (UI and this) must be compiled separately and then linked together.
Problem:
A need has popped up for the bottom end to call a redraw function on the GUI side with some data given to it. Now here is where things go bad. How can you call INTO a set of member functions, especially one w/ complex dependencies? If I try to include the window header, there's an inheritance list for the GUI stuff a mile long, the bottom end obviously isn't build against the complex GUI libs...I can't forward declare my way out because I need to call a function on the window?
Now obviously this is a major communication design flaw, though we're in a bad position right now where major restructuring isn't really an option.
Questions:
How SHOULD have this been organized for the bottom end to contact the top for a redraw, going from a ball of C like code to a ball of C++ node.
What can I do now to circumvent this issue?
The only good way I can think of is with some sort of communication class...but I don't see how that won't run into the same issue as it will need to be built against both the GUI and the bottom end?
If you only need to call a single function, or even a small subset of functions, a callback is probably your best bet. If you're dealing with a member function, you can still call it with a pointer to the member function and a pointer to the object in question. See this answer for details on doing that. However, this could mean requiring that you include the entire mile-long list of dependencies for the GUI code.
Edit: After some thought, you could do a callback for a few functions without needing to include the dependencies for the GUI code. For example:
In the GUI code somewhere...
int DoFooInBar(int arg1, const char *arg2){
return MyForm.ChildContainer.ChildBox.ChildButton.Bar.DoFoo( arg1, arg2 );
}
Now in GUICallbacks.hpp...
int DoFooInBar(int arg1, const char *arg2);
You could then include GUICallbacks.hpp and call DoFooInBar() from anywhere in your C code. The only issue with this method is that you would need to make a new function for every callback you want to use.
A more general method of accomplishing such a task in bulk is via passing messages. A very cross-platform method for doing this involves a communication object, as you have mentioned. You wouldn't necessarily encounter any build issues if you provide a mechanism for obtaining a pointer to a shared communication object by a naming mechanism. A small example would be:
class CommObj{
public:
struct Message{
uint32_t type;
uint32_t flags;
std::string title;
std::string contents;
... //maybe a union here or something instead
};
private:
static map<std::string, CommObj*> InternalObjects;
std::deque<Message> Messages;
std::string MyName;
public:
CommObj(const char *name); //Registers the object in the map
~CommObj(); //Unregisters the object in the map
void PushMessage( uint32_t type, uint32_t flags, const char *title, const char *contents, ...);
Message GetMessage();
bool HasMessages();
static CommObj *GetObjByName(const char *name);
static bool ObjWithNameExists();
};
Obviously you can make a more C-like version, however this is in C++ for clarity. The implementation details are an exercise for the reader.
With this code, you may then simply build both the backend and frontend against this object, and you can run a check on both sides of the code to see if a CommObj with the name "Backend->GUI" has been made yet. If not, make it. You would then be able to start communicating with this object by grabbing a pointer to it with GetObjByName("Backend->GUI"); You would then continuously poll the object to see if there are any new messages. You can have another object for the GUI to post messages to the backend too, perhaps named "GUI->Backend", or you could build bi-directionality into the object itself.
An alternative method would be to use socket communication / shared file descriptors. You could then read and write data to the socket for the other side to pick up. For basic signalling, this may be a simple way to accomplish what you need, especially if you don't really need anything complex. A simple send() call to a socket descriptor would be all you need to signal the other side of the code.
Do be aware that using sockets could cause slowdowns if used incredibly heavily. It depends on the underlying implementation, but sockets on localhost are often slower than raw function calls. You probably aren't going to need interlocked signalling in a tight loop though, so you should be fine with either method. When I say slower, I mean it's maybe 50 microseconds vs 5 microseconds. It's not really anything to worry too much about for most situations, but something to be aware of. On the flipside, if the GUI code is running in a different thread from the backend code, you would likely want to mutex the communications object before posting/reading messages, which wouldn't be needed with a shared file descriptor. Mutexes/semaphors bring their own baggage along to deal with.
Using a communications object like the one I gave an outline for would allow for some automatic marshaling of types, which you might be interested in. Granted, you could also write an object to do that marshaling with a socket too, however at that point you might as well use a shared object.
I hope your project ends up going smoothly.
Developing a modular application, I want to inject some helper classes into each module. This should happen automated. Note that my helpers have state, so I can't just make them static and include them where needed.
I could store all helpers in a map with a string key and make it available to the abstract base class all modules inherit from.
std::unordered_map<std::string, void*> helpers;
RendererModule renderer = new RendererModule(helpers); // argument is passed to
// base class constructor
Then inside a module, I could access helpers like this.
std::string file = (FileHelper*)helpers["file"]->Read("C:/file.txt");
But instead, I would like to access the helpers like this.
std::string file = File->Read("C:/file.txt");
To do so, at the moment I separately define members for all helpers in the module base class, and set them for each specific module.
FileHelper file = new FileHelper(); // some helper instances are passed to
// multiple modules, while others are
// newly created for each one
RendererModule renderer = new RendererModule();
renderer->File = file;
Is there a way to automate this, so that I don't have to change to module code when adding a new helper to the application, while remaining with the second syntax? I an not that familiar with C macros, so I don't know if they are capable of that.
I think I see what your dilemma is, but I have no good solution for it. However, since there are no other answers, I will contribute my two cents.
I use the combination of a few strategies to help me with these kinds of problems:
If the helper instance is truly module-specific, I let the module itself create and manage it inside.
If I don't want the module to know about the creation or destruction of the helper(s), or if the lifetime of the helper instance is not tied to the module that is using it, or if I want to share a helper instance among several modules, I create it outside and pass the reference to the entry-point constructor of the module. Passing it to the constructor has the advantage of making the dependency explicit.
If the number of the helpers are high (say more than 2-3) I create an encompassing struct (or simple class) that just contains all the pointers and pass that struct into the constructor of the module or subsystem. For example:
struct Platform { // I sometimes call it "Environment", etc.
FileHelper * file;
LogHelper * log;
MemoryHelper * mem;
StatsHelper * stats;
};
Note: this is not a particularly nice or safe solution, but it's no worse than managing disparate pointers and it is straightforward.
All the above assumes that helpers have no dependency on modules (i.e. they are on a lower abstraction of dependency level and know nothing about modules.) If some helpers are closer to modules, that is, if you start to want to inject module-on-module dependencies into each other, the above strategies really break down.
In these cases (which obviously happen a lot) I have found that a centralized ModuleManager singleton (probably a global object) is the best. You explicitly register your modules into it, along with explicit order of initialization, and it constructs all the modules. The modules can ask this ModuleManager for a reference to other modules by name (kind of like a map of strings to module pointers,) but they do this once and store the pointers internally in any way they want for convenient and fast access.
However, to prevent messy lifetime and order-of-destruction issues, any time a module is constructed or destructed, the ModuleManager notifies all other modules via callbacks, so they have the chance to update their internal pointers to avoid dangling pointers and other problems.
That's it. By the way, you might want to investigate articles and implementations related to the "service locator" pattern.
I'm looking for a solution for this problem in C or C++.
edit: To clarify. This is on a linux system. Linux-specific solutions are absolutely fine. Cross-plaform is not a concern.
I have a service that runs in its own thread. This service is a class with several methods, some of which need to run in the own service's thread rather than in the caller's thread.
Currently I'm using wrapper methods that create a structure with input and output parameters, insert the structure on a queue and either return (if a "command" is asynchronous) or wait for its execution (if a "command" is synchronous).
On the thread side, the service wakes, pops a structure from the queue, figures out what to execute and calls the appropriate method.
This implementation works but adding new methods is quite cumbersome: define wrapper, structure with parameters, and handler. I was wondering if there is a more straightforward means of coding this kind of model: a class method that executes on the class's own thread, instead of in the caller's thread.
edit - kind of conclusion:
It seems that there's no de facto way to implement what I asked that doesn't involve extra coding effort.
I'll stick with what I came up with, it ensures type safeness, minimizes locking, allows sync and async calls and the overhead it fairly modest.
On the other hand it requires a bit of extra coding and the dispatch mechanism may become bloated as the number of methods increases. Registering the dispatch methods on construction, or having the wrappers do that work seem to solve the issue, remove a bit of overhead and also remove some code.
My standard reference for this problem is here.
Implementing a Thread-Safe Queue using Condition Variables
As #John noted, this uses Boost.Thread.
I'd be careful about the synchronous case you described here. It's easy to get perf problems if the producer (the sending thread) waits for a result from the consumer (the service thread). What happens if you get 1000 async calls, filling up the queue with a backlog, followed by a sync call from each of your producer threads? Your system will 'play dead' until the queue backlog clears, freeing up those sync callers. Try to decouple them using async only, if you can.
There are several ways to achieve this, depending upon the complexity you want to accept. Complexity of the code is directly proportional to the flexibility desired. Here's a simple one (and quite well used):
Define a classes corresponding to each functionality your server exposes.
Each of these classes implements a function called execute and take a basic structure called input args and output args.
Inside the service register these methods classes at the time of initialization.
Once a request comes to the thread, it will have only two args, Input and Ouput, Which are the base classes for more specialized arguments, required by different method classes.
Then you write you service class as mere delegation which takes the incoming request and passes on to the respective method class based on ID or the name of the method (used during initial registration).
I hope it make sense, a very good example of this approach is in the XmlRpc++ (a c++ implementation of XmlRpc, you can get the source code from sourceforge).
To recap:
struct Input {
virtual ~Input () = 0;
};
struct Ouput {
virtual ~Output () = 0;
};
struct MethodInterface {
virtual int32_t execute (Input* __input, Output* __output) = 0;
};
// Write specialized method classes and taking specialized input, output classes
class MyService {
void registerMethod (std::string __method_name, MethodInterface* __method);
//external i/f
int32_t execute (std::string __method, Input* __input, Output* __output);
};
You will still be using the queue mechanism, but you won't need any wrappers.
IMHO, If you want to decouple method execution and thread context, you should use Active Object Pattern (AOP)
However, you need to use ACE Framework, which supports many OSes, e.g. Windows, Linux, VxWorks
You can find detailed information here
Also, AOP is a combination of Command, Proxy and Observer Patterns, if you know the details of them, you may implement your own AOP. Hope it helps
In addition to using Boost.Thread, I would look at boost::function and boost::bind. That said, it seems fair to have untyped (void) arguments passed to the target methods, and let those methods cast to the correct type (a typical idiom for languages like C#).
Hey now Rajivji, I think you have it upside-down. Complexity of code is inversely proportional to flexibility. The more complex your data structures and algorithms are, the more restrictions you are placing on acceptable inputs and behaviour.
To the OP: your description seems perfectly general and the only solution, although there are different encodings of it. The simplest may be to derive a class from:
struct Xqt { virtual void xqt(){} virtual ~Xqt(){} };
and then have a thread-safe queue of pointers to Xqt. The service thread then just pops the queue to px and calls px->xqt(), and then delete px. The most important derived class is this one:
struct Dxqt : Xqt {
xqt *delegate;
Dxqt(xqt *d) : delegate(d) {}
void xqt() { delegate->xqt(); }
};
because "all problems in Computer Science can be solved by one more level of indirection" and in particular this class doesn't delete the delegate. This is much better than using a flag, for example, to determine if the closure object should be deleted by the server thread.
I am entering a realm that is new to me, but basically I need to implement callbacks in C++. I am designing a toolkit for myself to use to simplify my life. Basically it is a .dll plugin that will be exposing a lot of functions to my other .dll plugins.
One of these functions is HookEvent(const char *event_name, void *callback) which will allow me to hook different events that get fired. Here would be an example...
Example_Plugin1.dll does HookEvent("player_spawn", &Plugin1::Event_PlayerSpawn);
Example_Plugin2.dll does HookEvent("player_spawn", &Plugin2::Event_PlayerSpawn);
I need to figure out the best (and preferably easiest) method of setting up a callbacks system that will work well for this. I have been reading up on C++ callbacks for a few hours now, and found quite a few different approaches.
I assume the easiest thing to do would be make a template, and use typedef bool (ClassName::*EventHookCallback)(IGameEvent, bool); After that, I am a bit foggy.
I also read that Delegates or a .NET style events system are other possible approaches. I am already somewhat confused, so I don't want to confuse myself more, but figured it was worth asking.
Here is a link to the C++ .NET style events system I was reading about.
http://cratonica.wordpress.com/2010/02/19/implementing-c-net-events-in-c/
So what do you guys suggest? Any tips as far as implementing it would be most appreciated.
If you want generalized event firing Boost.Signals2 might be applicable.
The Boost.Signals2 library is an
implementation of a managed signals
and slots system. Signals represent
callbacks with multiple targets, and
are also called publishers or events
in similar systems. Signals are
connected to some set of slots, which
are callback receivers (also called
event targets or subscribers), which
are called when the signal is
"emitted."
Even if you don't need this level of flexibility you should be able to simplify the function binding in your code using Boost.Bind, or the C++0x equivalents.
EDIT:
There's an excellent discussion from Herb Sutter of the issues you could face here. You could use this for guidance if you decide you don't need the full Boost feature set, and so roll your own.
How about using Qt Signal and Slot? It does what callbacks do but without the messiness of making anything not part of your callback parameters global.
Boost.Signals would be my choice, combined with things like boost::bind and Boost.Function.
I would use an abstract base class as a plugin interface. (And in fact, I have used a pattern like the one below before.)
Library, PluginIfc.h:
class PluginIfc {
public:
virtual ~PluginIfc() = 0;
virtual bool EventCallback(const char* event_name, IGameEvent, bool) = 0;
};
// For Windows, add dllexport/dllimport magic to this declaration.
// This is the only symbol you will look up from the plugin and invoke.
extern "C" PluginIfc* GetPlugin();
Plugin:
#include <PluginIfc.h>
class Plugin1 : public PluginIfc {
public:
virtual bool EventCallback(const char* event_name, IGameEvent, bool);
Plugin1& get() { return the_plugin_obj; }
bool Event_PlayerSpawn(IGameEvent, bool);
// ...
private:
std::vector<std::string> _some_member;
static Plugin1 the_plugin_obj; // constructed when plugin loaded
};
Plugin1 Plugin1::the_plugin_obj;
PluginIfc* GetPlugin() { return &Plugin1::get(); }
This way, your plugin classes can easily have members, and C++'s virtual call mechanism takes care of giving you a good this pointer in EventCallback.
It may be tempting to make a virtual method per event type, say just make Event_PlayerSpawn and similar methods virtual. But then whenever you want to add an event type, if this means changing class PluginIfc, your old compiled plugins are no longer compatible. So it's safer to use a string event identifier (for extensibility) and have the main callback sort events off to more specific methods.
The major drawback here (as compared to a signal-slot type implementation) is that all callbacks must take the same set of arguments. But your question sounded like that would be adequate. And it's often possible to work within that limitation by making sure the set of arguments is very flexible, using strings to be parsed or Any-style objects.
Sounds like you might be interested in how to build your own plugin framework. The problems you'll encounter are likely the same. Have a look at this nice Dr Dobbs article Building Your Own Plugin Framework.
Hope this helps!
Implementing your own callback system is non-trivial.
My understanding is that your aim is to map event types to specific callback functions.
E.g. if "player_spawn" event is risen the &Plugin1::Event_PlayerSpawn will be called.
So what you should do is the following:
1) Define all the events of interest. Make them as generic as possible. They can
encapsulate any information you need
2) Create a Registrar. I.e. a class that all modules register their interest for specific
methods. E.g. Registrar.register(player_spawn,this,Event_PlayerSpawn);
3) Registrar has a queue of all subscribers.
4) You can also have a uniform interface for the modules. I.e. all module implement a specific function but based on event's data can do different things
5) When an event occurs, all the subscribers interested for the specific event get notified by calling the appropriate function
6)Subscriber can de-register when ever is need
Hope this helps.