Multiple threads cannot access the same pointer without error [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I am making an application with GLFW3 (window library), and I my OS is Windows 8.1.
My error: I make a pointer in my main thread and the window's thread gets an access violation when it tries to use it.
In my application I am trying to make an input handler class that takes in events from the window and sends them to all objects that subscribe to the event.
To do this, I have all objects that want to listen inherit InputListener:
class InputListener{
public:
virtual void onKeyDown(int key) = 0;
};
To subscribe to an event, a object must use a pseudo-global (reference passed to classes on construction) wrapper variable which contains my InputHandler:
// My global wrapper
#include "InputHandler.h"
class Centrum{
public:
InputHandler inputHandler;
public:
Centrum(){}
};
InputHandler
class InputHandler{
private:
unsigned numEvents;
InputListener* key_down; // Only trying to test on one subscriber for now.
public:
InputHandler();
void registerKeyDown(InputListener* listener, int key);
void key_event(int key, int action); // Is indirectly called by glfw window (same thread though)
};
// Implementation
InputHandler::InputHandler(){
numEvents = 0;
}
void InputHandler::registerKeyDown(InputListener* listener, int key){
// This is called from my main thread
key_down = listener;
key_down->onKeyDown(key); // Properly calls function on my Camera class which inherits InputListener
numEvents++;
printf("yes %u\n", numEvents);
}
void InputHandler::key_event(int key, int action){
// This is called by the window's thread (glfw automatically makes this thread)
printf("failure %u\n", numEvents); // Properly prints out numEvents
key_down->onKeyDown(key); // Runtime error here, access violation
}
Example of subscribing to input:
Camera::Camera(Centrum& g_centrum){
this->g_centrum = g_centrum;
[...]
g_centrum.inputHandler.registerKeyDown(this, GLFW_KEY_W);
}

The variable being pointed to was dying before it could be used. So, when the thread tried to use it, it threw a runtime error.

In this line you are copying the Centrum:
this->g_centrum = g_centrum;
You then register with the copy (which makes the first call to onKeyDown which naturally works). But you haven't registered with the original Centrum, so it has no key_down to call, so when it attempts to do so, without checking if the pointer is valid, it fails.
I'd make g_centrum a pointer, and probably use pointers rather than references to Centrum throughout.

Threads have separate stacks, so objects can only be accessed by several thread if they are heap-allocated.
Furthermore you should protect against concurrent access to those objects (or at least to the concurrent data) via mutexes.
If Camera is instanciated in the windows thread, you will create a copy of centrum.
Camera::Camera(Centrum& g_centrum){
this->g_centrum = g_centrum;
[...]
g_centrum.inputHandler.registerKeyDown(this, GLFW_KEY_W);
}
You should instanciate your Centrumlike so Centrum *mycentrum = new Centrum() and pass it as a pointer to your Camera.

Related

is it safe to delete std::function from withing its stored callback [duplicate]

This question already has answers here:
Is "delete this" allowed in C++?
(10 answers)
Closed 3 years ago.
I have a class which stores a callback in std::function and does some operations then notify the callback target with the results . if the target sees the results invaild or doesn't want to continue doing the work it will delete the caller class which contains the std::function callback .
I know if std::function doesn't access its members after deletetion this will be safe but I didin't see such guarantee . The thing I have is that the caller class doesn't access its members after invoking the callback , but the callback can choose to do more work again and in this case it won't delete the caller .
this example illustrates the problem :
using callback = std::function<void(Caller& c, bool failed)>;
class Caller
{
callback cb;
bool Work()
{
return true;
}
public:
Caller(const callback& cb) : cb{ cb } {}
void DoWork()
{
bool result = Work();
cb(*this, result);
}
};
int main(int argc, char **argv)
{
for (int i = 0; i < 1000; ++i)
{
Caller *c = new Caller{
[](Caller& c, bool failed)
{
if (failed)
delete &c;
else
c.DoWork();
}
};
c->DoWork();
}
}
I compiled the code on windows using msvc and it's working without issuses (or may be some hidden heap corruption ?)
I don't want suggestion to use another design as the real code I'm using is complicating and the caller class is like a proky between the worker and the callback and is allocated per operation , also refactoring the code will be much work
EDIT : I know it is'nt the best c++ practice but I'm dealing with c api particularly iocp. my code works like this : the io object (socket) issue an io request which requires allocating memory for the overlapped structure and op data , this structure will hold the callback and when the op is done it will invoke the callback and if there is an error the callback may not continue otherwise it will issue the next request . after invoking the callback the structure will delete itself and the new operation started from the callback will continue like this .
now suppose I have a sessionn of half-duplex protocol, like http, then there is only one operation at a time so I may use the same stucture for all operations without allocating again , so when the second operation starts I destruct the old strucutre and construct in place the new one and this is done inside the callback of the first structre
Looks OK. I would replace Caller& reference in the callback with a pointer, but that’s not important.
The only potential issue I see in your code, the recursion you have there can cause stack overflow. If your Work() function will return false = not failed few hundred thousand times (or just 600 times in debug builds, they consume much more stack space due to the lack of optimizations), your app will exhaust the stack and crash. If you know your Work() function only returns false a few times before returning true, you’re good. But if your work function needs to be able to run many iterations, consider replacing recursion with a loop.

SDL Multithreading with variables -- Doesn't work as expected [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have in a namespace called Main an static integer, and a static class variable called other, like this:
namespace Main {
void test();
static Client other;
static int v = 0;
}
Then, when the program starts, Main::test() is called, and creates a thread via SDL:
void test() {
SDL_CreateThread(Client::test, (const char*)"Client", (void*)NULL);
v = 1;
std::cout << v << std::endl;
...
}
This makes the Client start a function called test, which prints the vector size forever, like so:
int Client::test(void* data)
{
while(1) {std::cout << Main::v << std::endl; }
}
Now, here's the problem! Main returns 1 and Client returns a lot of zeros! What happened there? The variable is static, so it should be the same for Client!
std::vector.size() is, by definition, the number of elements in the vector.
Any situation where you think that isn't the case, or you see symptoms of that not being the case, you are probably experiencing undefined behavior due to memory corruption or out-of-bounds accesses.
Note that assigning to an indexed location of a vector v[n] = x; does not extend the vector, and is undefined behavior if n >= v.size().
Without explicit synchronization, the compiler is allowed to optimize the Client::test method by assuming that v never changes.
This is because it obviously doesn't change in that thread, it's your responsibility to tell the compiler if it could change in a different thread, and you did no such thing.
You are using a standard container in two threads, so you need to protect every access with a mutex. That creates a memory fence (which solves the problem you've seen), and protects from internal corruption when you perform actions on the container from different threads simultaneously (which your answer does not attempt to solve).

c++ class method thread [duplicate]

This question already has answers here:
Start thread with member function
(5 answers)
Closed 6 years ago.
i have a class that has a method that needs to be running continuously but also be able to receive input from user. So i thought i would make the method run separately using a thread.
the code looks something like this(just the backbone):
class SystemManager
{
private:
int command;
bool commandAcK;
bool running;
//other vars
public:
SystemManager()
{
//initialisation
}
void runningAlgorithm()
{
while (running)
{
if (commandAcK)
{
//solve command
}
//run algorithm
//print results
}
}
void readCmd()
{
cin >> command;
commandAcK = true;
}
};
int main()
{
SystemManager *SM = new SystemManager;
thread tRunning = SM->runningAlgorithm();
}
now the errors look like this:
no suitable constructor exists to convert from "void" to "std::thread"
Error C2440 'initializing': cannot convert from 'void' to 'std::thread'
i have found a new method and it doesn't give me any errors
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
the first thing i don't understand is that this method doesn't use an instance of the class just the generic function. How can i link it to a specific instance? I need it so it can read the values of the variables.
Secondly what does "&" in front of SystemManager do?
(&SystemManager::runningAlgorithm)
Thirdly is there a better way of doing it? Do you have any ideas?
Thank you in advance.
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager()); does use an instance of your class. The instance it uses is SystemManager() which is a temporary and only available to the thread. If you need to share the instance then you need to create one yourself and pass it by reference to the thread like
SystemManager sys_manager;
std::thread tRunning([&](){sys_manager.runningAlgorithm();});
And now your call site and your thread have the same instance.
Also note that command and commandAck need to be protected by some sort of synchronization since you can write to them while reading causing a data race and subsequently undefined behavior. Using std::atmoic should work for you.
The constructor for std::thread accepts a functor, and optionally it's arguments. A functor is anything that can be "called" using operator().
Then it starts a thread and inside that thread calls your functor.
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
This will call the member function SystemManager::runningAlgorithm, passing in the only argument being this (SystemManager() creates a temporary instance).
Remember that member functions always accept this as the first argument.
&SystemManager::runningAlgorithm returns the address of the member function runningAlgorithm from the class SystemManager.
In modern C++ this code can be simplified (i.e. made more readable) with a lambda:
std::thread tRunning([]{ SystemManager().runningAlgorithm(); });
The line
thread tRunning = SM->runningAlgorithm();
takes the result of running SM->runningAlgorithm() (a void), and tries to construct a thread from it. If you look at the relevant constructor, though, you can see it needs a function-like argument (with possibly arguments).
One way of running it is through a lambda function:
thread tRunning(
[SM](){SM->runningAlgorithm();});
Two other things to note:
You should join the thread before its destructor is called, in this case:
tRunning.join();
You have a (short lived) memory leak. Why not just create it on the stack?
SystemManager SM;
thread tRunning(
[&](){SM.runningAlgorithm();});
tRunning.join();
Uhm... I guesss you need to study some of the basic concepts of c++, before going multithread.
However... In your code,
thread tRunning = SM->runningAlgorithm();
tries to put the result of your function (that is void... ) inside a variable of type thread... Non likely to be right.
Instead, your second code takes 2 arguments:
std::thread tRunning(
&SystemManager::runningAlgorithm, //a pointer to a method (a pointer to the code of your function, and that is why you use the "&", even though you could have left that out)
SystemManager()); // An instance of the value, built on the stack.
I guest that you are confused by the lack of the word "new" (coming from higher level language?), but that's how it works here:
SystemManager sm = SystemManager(); // <- variable created on the stack, will be automatically destroyed when out of scope
SystemManager *psm = new SystemManager(); // Created in the heap, while in the stack remains just a pointer to it.
//You will need to delete it when done with :
delete psm;
To answer the question
How can i link it to a specific instance? I need it so it can read the values of the variables.
You can do:
int main()
{
SystemManager SM; // = SystemManager(); // <- this is not needed
std::thread tRunning(SystemManager::runningAlgorithm, SM);
// Access SM as you need
// REMEMBER TO CLOSE & JOIN THE THREAD!
tRunning.join();
}
I still think you should first get used to the underlying concepts or it will be really difficult to go on.

Accessing and modifying automatic variables on another thread's stack

I want to pass some data around threads but want to refrain from using global variables if I can manage it. The way I wrote my thread routine has the user passing in a separate function for each "phase" of a thread's life cycle: For instance this would be a typical usage of spawning a thread:
void init_thread(void *arg) {
graphics_init();
}
void process_msg_thread(message *msg, void *arg) {
if (msg->ID == MESSAGE_DRAW) {
graphics_draw();
}
}
void cleanup_thread(void *arg) {
graphics_cleanup();
}
int main () {
threadCreator factory;
factory.createThread(init_thread, 0, process_msg_thread, 0, cleanup_thread, 0);
// even indexed arguments are the args to be passed into their respective functions
// this is why each of those functions must have a fixed function signature is so they can be passed in this way to the factory
}
// Behind the scenes: in the newly spawned thread, the first argument given to
// createThread() is called, then a message pumping loop which will call the third
// argument is entered. Upon receiving a special exit message via another function
// of threadCreator, the fifth argument is called.
The most straightforward way to do it is using globals. I'd like to avoid doing that though because it is bad programming practice because it generates clutter.
A certain problem arises when I try to refine my example slightly:
void init_thread(void *arg) {
GLuint tex_handle[50]; // suppose I've got 50 textures to deal with.
graphics_init(&tex_handle); // fill up the array with them during graphics init which loads my textures
}
void process_msg_thread(message *msg, void *arg) {
if (msg->ID == MESSAGE_DRAW) { // this message indicates which texture my thread was told to draw
graphics_draw_this_texture(tex_handle[msg->texturehandleindex]); // send back the handle so it knows what to draw
}
}
void cleanup_thread(void *arg) {
graphics_cleanup();
}
I am greatly simplifying the interaction with the graphics system here but you get the point. In this example code tex_handle is an automatic variable, and all its values are lost when init_thread completes, so will not be available when process_msg_thread needs to reference it.
I can fix this by using globals but that means I can't have (for instance) two of these threads simultaneously since they would trample on each other's texture handle list since they use the same one.
I can use thread-local globals but is that a good idea?
I came up with one last idea. I can allocate storage on the heap in my parent thread, and send a pointer to in to the children to mess with. So I can just free it when parent thread leaves away since I intend for it to clean up its children threads before it exits anyway. So, something like this:
void init_thread(void *arg) {
GLuint *tex_handle = (GLuint*)arg; // my storage space passed as arg
graphics_init(tex_handle);
}
void process_msg_thread(message *msg, void *arg) {
GLuint *tex_handle = (GLuint*)arg; // same thing here
if (msg->ID == MESSAGE_DRAW) {
graphics_draw_this_texture(tex_handle[msg->texturehandleindex]);
}
}
int main () {
threadCreator factory;
GLuint *tex_handle = new GLuint[50];
factory.createThread(init_thread, tex_handle, process_msg_thread, tex_handle, cleanup_thread, 0);
// do stuff, wait etc
...
delete[] tex_handle;
}
This looks more or less safe because my values go on the heap, my main thread allocates it then lets children mess with it as they wish. The children can use the storage freely since the pointer was given to all the functions that need access.
So this got me thinking why not just have it be an automatic variable:
int main () {
threadCreator factory;
GLuint tex_handle[50];
factory.createThread(init_thread, &tex_handle, process_msg_thread, &tex_handle, cleanup_thread, 0);
// do stuff, wait etc
...
} // tex_handle automatically cleaned up at this point
This means children thread directly access parent's stack. I wonder if this is kosher.
I found this on the internets: http://software.intel.com/sites/products/documentation/hpc/inspectorxe/en-us/win/ug_docs/olh/common/Problem_Type__Potential_Privacy_Infringement.htm
it seems Intel Inspector XE detects this behavior. So maybe I shouldn't do it? Is it just simply a warning of potential privacy infringement as suggested by the the URL or are there other potential issues that may arise that I am not aware of?
P.S. After thinking through all this I realize that maybe this architecture of splitting a thread into a bunch of functions that get called independently wasn't such a great idea. My intention was to remove the complexity of requiring coding up a message handling loop for each thread that gets spawned. I had anticipated possible problems, and if I had a generalized thread implementation that always checked for messages (like my custom one that specifies the thread is to be terminated) then I could guarantee that some future user could not accidentally forget to check for that condition in each and every message loop of theirs.
The problem with my solution to that is that those individual functions are now separate and cannot communicate with each other. They may do so only via globals and thread local globals. I guess thread local globals may be my best option.
P.P.S. This got me thinking about RAII and how the concept of the thread at least as I have ended up representing it has a certain similarity with that of a resource. Maybe I could build an object that represents a thread more naturally than traditional ways... somehow. I think I will go sleep on it.
Put your thread functions into a class. Then they can communicate using instance variables. This requires your thread factory to be changed, but is the cleanest way to solve your problem.
Your idea of using automatic variables will work too as long as you can guarantee that the function whose stack frame contains the data will never return before your child threads exit. This is not really easy to achieve, even after main() returns child threads can still run.

Game Objects Talking To Each Other [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
What is a good way of dealing with objects and having them talk to each other?
Up until now all my games hobby/student have been small so this problem was generally solved in a rather ugly way, which lead to tight integration and circular dependencies. Which was fine for the size of projects I was doing.
However my projects have been getting bigger in size and complexity and now I want to start re-using code, and making my head a simpler place.
The main problem I have is generally along the lines of Player needs to know about the Map and so does the Enemy, this has usually descended into setting lots of pointers and having lots of dependencies, and this becomes a mess quickly.
I have thought along the lines of a message style system. but I cant really see how this reduces the dependencies, as I would still be sending the pointers everywhere.
PS: I guess this has been discussed before, but I don't know what its called just the need I have.
EDIT: Below I describe a basic event messaging system I have used over and over. And it occurred to me that both school projects are open source and on the web. You can find the second version of this messaging system (and quite a bit more) at http://sourceforge.net/projects/bpfat/ .. Enjoy, and read below for a more thorough description of the system!
I've written a generic messaging system and introduced it into a handful of games that have been released on the PSP as well as some enterprise level application software. The point of the messaging system is to pass only the data around that is needed for processing a message or event, depending on the terminology you want to use, so that objects do not have to know about each other.
A quick rundown of the list of objects used to accomplish this is something along the lines of:
struct TEventMessage
{
int _iMessageID;
}
class IEventMessagingSystem
{
Post(int iMessageId);
Post(int iMessageId, float fData);
Post(int iMessageId, int iData);
// ...
Post(TMessageEvent * pMessage);
Post(int iMessageId, void * pData);
}
typedef float(*IEventMessagingSystem::Callback)(TEventMessage * pMessage);
class CEventMessagingSystem
{
Init ();
DNit ();
Exec (float fElapsedTime);
Post (TEventMessage * oMessage);
Register (int iMessageId, IEventMessagingSystem* pObject, FObjectCallback* fpMethod);
Unregister (int iMessageId, IEventMessagingSystem* pObject, FObjectCallback * fpMethod);
}
#define MSG_Startup (1)
#define MSG_Shutdown (2)
#define MSG_PlaySound (3)
#define MSG_HandlePlayerInput (4)
#define MSG_NetworkMessage (5)
#define MSG_PlayerDied (6)
#define MSG_BeginCombat (7)
#define MSG_EndCombat (8)
And now a bit of an explanation. The first object, TEventMessage, is the base object to represent data sent by the messaging system. By default it will always have the Id of the message being sent so if you want to make sure you have received a message you were expecting you can (Generally I only do that in debug).
Next up is the Interface class that gives a generic object for the messaging system to use for casting while doing callbacks. Additionally this also provides an 'easy to use' interface for Post()ing different data types to the messaging system.
After that we have our Callback typedef, Simply put it expects an object of the type of the interface class and will pass along a TEventMessage pointer... Optionally you can make the parameter const but I've used trickle up processing before for things like stack debugging and such of the messaging system.
Last and at the core is the CEventMessagingSystem object. This object contains an array of callback object stacks (or linked lists or queues or however you want to store the data). The callback objects, not shown above, need to maintain (and are uniquely defined by) a pointer to the object as well as the method to call on that object. When you Register() you add an entry on the object stack under the message id's array position. When you Unregister() you remove that entry.
That is basically it. Now this does have the stipulation that everything needs to know about the IEventMessagingSystem and the TEventMessage object... but this object should Not be changing that often and only passes the parts of information that are vital to the logic dictated by the event being called. This way a player doesn't need to know about the map or the enemy directly for sending events off to it. A managed object can call an API to a larger system also, without needing to know anything about it.
For example: When an enemy dies you want it to play a sound effect. Assuming you have a sound manager that inherits the IEventMessagingSystem interface, you would set up a callback for the messaging system that would accept a TEventMessagePlaySoundEffect or something of that ilk. The Sound Manager would then register this callback when sound effects are enabled (or unregister the callback when you want to mute all sound effects for easy on/off abilities). Next, you would have the enemy object also inherit from the IEventMessagingSystem, put together a TEventMessagePlaySoundEffect object (would need the MSG_PlaySound for its Message ID and then the ID of the sound effect to play, be it an int ID or the name of the sound effect) and simply call Post(&oEventMessagePlaySoundEffect).
Now this is just a very simple design with no implementation. If you have immediate execution then you have no need to buffer the TEventMessage objects (What I used mostly in console games). If you are in a multi-threaded environment then this is a very well defined way for objects and systems running in separate threads to talk to each other, but you will want to preserve the TEventMessage objects so the data is available when processing.
Another alteration is for objects that only ever need to Post() data, you can create a static set of methods in the IEventMessagingSystem so they do not have to inherit from them (That is used for ease of access and callback abilities, not -directly- needed for Post() calls).
For all the people who mention MVC, it is a very good pattern, but you can implement it in so many different manners and at different levels. The current project I am working on professionally is an MVC setup about 3 times over, there is the global MVC of the entire application and then design wise each M V and C also is a self-contained MVC pattern. So what I have tried to do here is explain how to make a C that is generic enough to handle just about any type of M without the need to get into a View...
For example, an object when it 'dies' might want to play a sound effect.. You would make a struct for the Sound System like TEventMessageSoundEffect that inherits from the TEventMessage and adds in a sound effect ID (Be it a preloaded Int, or the name of the sfx file, however they are tracked in your system). Then all the object just needs to put together a TEventMessageSoundEffect object with the appropriate Death noise and call Post(&oEventMessageSoundEffect); object.. Assuming the sound is not muted (what you would want to Unregister the Sound Managers.
EDIT: To clarify this a bit in regards to the comment below:
Any object to send or receive a message just needs to know about the IEventMessagingSystem interface, and this is the only object the EventMessagingSystem needs to know of all the other objects. This is what gives you the detachment. Any object who wants to receive a message simply Register(MSG, Object, Callback)s for it. Then when an object calls Post(MSG,Data) it sends that to the EventMessagingSystem via the interface it knows about, the EMS will then notify each registered object of the event. You could do a MSG_PlayerDied that other systems handle, or the player can call MSG_PlaySound, MSG_Respawn, etc to let things listening for those messages to act upon them. Think of the Post(MSG,Data) as an abstracted API to the different systems within a game engine.
Oh! One other thing that was pointed out to me. The system I describe above fits the Observer pattern in the other answer given. So if you want a more general description to make mine make a bit more sense, that is a short article that gives it a good description.
Hope this helps and Enjoy!
the generic solutions for communication between objects avoiding tight coupling:
Mediator pattern
Observer pattern
Here is a neat event system written for C++11 you can use. It uses templates and smart pointers as well as lambdas for the delegates. It's very flexible. Below you will also find an example. Email me at info#fortmax.se if you have questions about this.
What these classes gives you is a way to send events with arbitrary data attached to them and an easy way to directly bind functions that accept already converted argument types that the system casts and checks for correct conversion prior to calling your delegate.
Basically, every event is derived from IEventData class (you can call it IEvent if you want). Each "frame" you call ProcessEvents() at which point the event system loops through all the delegates and calls the delegates that have been supplied by other systems that have subscribed to each event type. Anyone can pick which events they would like to subscribe to, as each event type has a unique ID. You can also use lambdas to subscribe to events like this: AddListener(MyEvent::ID(), [&](shared_ptr ev){
do your thing }..
Anyway, here is the class with all the implementation:
#pragma once
#include <list>
#include <memory>
#include <map>
#include <vector>
#include <functional>
class IEventData {
public:
typedef size_t id_t;
virtual id_t GetID() = 0;
};
typedef std::shared_ptr<IEventData> IEventDataPtr;
typedef std::function<void(IEventDataPtr&)> EventDelegate;
class IEventManager {
public:
virtual bool AddListener(IEventData::id_t id, EventDelegate proc) = 0;
virtual bool RemoveListener(IEventData::id_t id, EventDelegate proc) = 0;
virtual void QueueEvent(IEventDataPtr ev) = 0;
virtual void ProcessEvents() = 0;
};
#define DECLARE_EVENT(type) \
static IEventData::id_t ID(){ \
return reinterpret_cast<IEventData::id_t>(&ID); \
} \
IEventData::id_t GetID() override { \
return ID(); \
}\
class EventManager : public IEventManager {
public:
typedef std::list<EventDelegate> EventDelegateList;
~EventManager(){
}
//! Adds a listener to the event. The listener should invalidate itself when it needs to be removed.
virtual bool AddListener(IEventData::id_t id, EventDelegate proc) override;
//! Removes the specified delegate from the list
virtual bool RemoveListener(IEventData::id_t id, EventDelegate proc) override;
//! Queues an event to be processed during the next update
virtual void QueueEvent(IEventDataPtr ev) override;
//! Processes all events
virtual void ProcessEvents() override;
private:
std::list<std::shared_ptr<IEventData>> mEventQueue;
std::map<IEventData::id_t, EventDelegateList> mEventListeners;
};
//! Helper class that automatically handles removal of individual event listeners registered using OnEvent() member function upon destruction of an object derived from this class.
class EventListener {
public:
//! Template function that also converts the event into the right data type before calling the event listener.
template<class T>
bool OnEvent(std::function<void(std::shared_ptr<T>)> proc){
return OnEvent(T::ID(), [&, proc](IEventDataPtr data){
auto ev = std::dynamic_pointer_cast<T>(data);
if(ev) proc(ev);
});
}
protected:
typedef std::pair<IEventData::id_t, EventDelegate> _EvPair;
EventListener(std::weak_ptr<IEventManager> mgr):_els_mEventManager(mgr){
}
virtual ~EventListener(){
if(_els_mEventManager.expired()) return;
auto em = _els_mEventManager.lock();
for(auto i : _els_mLocalEvents){
em->RemoveListener(i.first, i.second);
}
}
bool OnEvent(IEventData::id_t id, EventDelegate proc){
if(_els_mEventManager.expired()) return false;
auto em = _els_mEventManager.lock();
if(em->AddListener(id, proc)){
_els_mLocalEvents.push_back(_EvPair(id, proc));
}
}
private:
std::weak_ptr<IEventManager> _els_mEventManager;
std::vector<_EvPair> _els_mLocalEvents;
//std::vector<_DynEvPair> mDynamicLocalEvents;
};
And the Cpp file:
#include "Events.hpp"
using namespace std;
bool EventManager::AddListener(IEventData::id_t id, EventDelegate proc){
auto i = mEventListeners.find(id);
if(i == mEventListeners.end()){
mEventListeners[id] = list<EventDelegate>();
}
auto &list = mEventListeners[id];
for(auto i = list.begin(); i != list.end(); i++){
EventDelegate &func = *i;
if(func.target<EventDelegate>() == proc.target<EventDelegate>())
return false;
}
list.push_back(proc);
}
bool EventManager::RemoveListener(IEventData::id_t id, EventDelegate proc){
auto j = mEventListeners.find(id);
if(j == mEventListeners.end()) return false;
auto &list = j->second;
for(auto i = list.begin(); i != list.end(); ++i){
EventDelegate &func = *i;
if(func.target<EventDelegate>() == proc.target<EventDelegate>()) {
list.erase(i);
return true;
}
}
return false;
}
void EventManager::QueueEvent(IEventDataPtr ev) {
mEventQueue.push_back(ev);
}
void EventManager::ProcessEvents(){
size_t count = mEventQueue.size();
for(auto it = mEventQueue.begin(); it != mEventQueue.end(); ++it){
printf("Processing event..\n");
if(!count) break;
auto &i = *it;
auto listeners = mEventListeners.find(i->GetID());
if(listeners != mEventListeners.end()){
// Call listeners
for(auto l : listeners->second){
l(i);
}
}
// remove event
it = mEventQueue.erase(it);
count--;
}
}
I use an EventListener class for the sake of convenience as base class for any class that would like to listen to events. If you derive your listening class from this class and supply it with your event manager, you can use the very convenient function OnEvent(..) to register your events. And the base class will automatically unsubscribe your derived class from all events when it is destroyed. This is very convenient since forgetting to remove a delegate from event manager when your class is destroyed will almost certainly cause your program to crash.
A neat way to get a unique type id for an event by simply declaring a static function in the class and then casting it's address into an int. Since every class will have this method on different addresses, it can be used for unique identification of class events. You can also cast typename() to an int to get a unique id if you want. There are different ways to do this.
So here is an example on how to use this:
#include <functional>
#include <memory>
#include <stdio.h>
#include <list>
#include <map>
#include "Events.hpp"
#include "Events.cpp"
using namespace std;
class DisplayTextEvent : public IEventData {
public:
DECLARE_EVENT(DisplayTextEvent);
DisplayTextEvent(const string &text){
mStr = text;
}
~DisplayTextEvent(){
printf("Deleted event data\n");
}
const string &GetText(){
return mStr;
}
private:
string mStr;
};
class Emitter {
public:
Emitter(shared_ptr<IEventManager> em){
mEmgr = em;
}
void EmitEvent(){
mEmgr->QueueEvent(shared_ptr<IEventData>(
new DisplayTextEvent("Hello World!")));
}
private:
shared_ptr<IEventManager> mEmgr;
};
class Receiver : public EventListener{
public:
Receiver(shared_ptr<IEventManager> em) : EventListener(em){
mEmgr = em;
OnEvent<DisplayTextEvent>([&](shared_ptr<DisplayTextEvent> data){
printf("It's working: %s\n", data->GetText().c_str());
});
}
~Receiver(){
mEmgr->RemoveListener(DisplayTextEvent::ID(), std::bind(&Receiver::OnExampleEvent, this, placeholders::_1));
}
void OnExampleEvent(IEventDataPtr &data){
auto ev = dynamic_pointer_cast<DisplayTextEvent>(data);
if(!ev) return;
printf("Received event: %s\n", ev->GetText().c_str());
}
private:
shared_ptr<IEventManager> mEmgr;
};
int main(){
auto emgr = shared_ptr<IEventManager>(new EventManager());
Emitter emit(emgr);
{
Receiver receive(emgr);
emit.EmitEvent();
emgr->ProcessEvents();
}
emit.EmitEvent();
emgr->ProcessEvents();
emgr = 0;
return 0;
}
This probably does not only apply to game classes but to classes in the general sense. the MVC (model-view-controller) pattern together with your suggested message pump is all you need.
"Enemy" and "Player" will probably fit into the Model part of MVC, it does not matter much, but the rule of thumb is have all models and views interact via the controller. So, you would want to keep references (better than pointers) to (almost) all other class instances from this 'controller' class, let's name it ControlDispatcher. Add a message pump to it (varies depending on what platform you are coding for), instantiate it firstly (before any other classes and have the other objects part of it) or lastly (and have the other objects stored as references in ControlDispatcher).
Of course, the ControlDispatcher class will probably have to be split down further into more specialized controllers just to keep the code per file at around 700-800 lines (this is the limit for me at least) and it may even have more threads pumping and processing messages depending on your needs.
Cheers
Be careful with "a message style system", it probably depends on implementation, but usually you would loose static type checking, and can then make some errors very difficult to debug. Note that calling object's methods it is already a message-like system.
Probably you are simply missing some levels of abstraction, for example for navigation a Player could use a Navigator instead of knowing all about the Map itself. You also say that this has usually descended into setting lots of pointers, what are those pointers? Probably, you are giving them to a wrong abstraction?.. Making objects know about others directly, without going through interfaces and intermediates, is a straight way to getting a tightly coupled design.
Messaging is definitely a great way to go, but messaging systems can have a lot of differences. If you want to keep your classes nice and clean, write them to be ignorant of a messaging system and instead have them take dependencies on something simple like a 'ILocationService' which can then be implemented to publish/request information from things like the Map class. While you'll end up with more classes, they'll be small, simple and encourage clean design.
Messaging is about more than just decoupling, it also lets you move towards a more asynchronous, concurrent and reactive architecture. Patterns of Enterprise Integration by Gregor Hophe is a great book that talks about good messaging patterns. Erlang OTP or Scala's implementation of the Actor Pattern have provided me with a lot of guidance.
#kellogs suggestion of MVC is valid, and used in a few games, though its much more common in web apps and frameworks. It might be overkill and too much for this.
I would rethink your design, why does the Player need to talk to Enemies? Couldn't they both inherit from an Actor class? Why do Actors need to talk to the Map?
As I read what I wrote it starts to fit into an MVC framework...I have obviously done too much rails work lately. However, I would be willing to bet, they only need to know things like, they are colliding with another Actor, and they have a position, which should be relative to the Map anyhow.
Here is an implementation of Asteroids that I worked on. You're game may be, and probably is, complex.