In my project I have a system of events. You can connect a callback to an event and any time the event is sent, your callback(s) is called.
Upon connecting to an event you get a token. As long as the token is not destroyed, the connection is active:
class A
{
A()
{
event_connection = get_dispatcher().connect(event, std::bind(member_function, this));
}
void member_function()
{
dummy_instance++; //any action that uses this field
}
// changed from shared to unique to avoid confusion
//std::shared_ptr<event_connection_token> event_connection;
std::unique_ptr<event_connection_token> event_connection;
dummy_type dummy_instance;
}
However, a problem arises in the following scenario:
- Deconstruction of class
A
starts - Field
dummy_instance
is destroyed - Now the event occurs
- The callback is called because
event_connection
wasn’t destroyed yet - The callback tries to access the deallocated memory and the program crashes
Therefore, I need my event_connection_token
to always be destroyed before any class members that callback is using. Now if I want 100 other programmers to use this event-callback system it would be unprofessional to expect them to always deallocate event_connection_token
first in all classes they ever make. We finally come to the question:
How can I enforce that every client removes event_connection_token
before anything else in client class gets destroyed?
I’m looking for either:
- a clever design that will make sure the token is always removed first without programmers even thinking about it, or
- a compile-time / run-time check that will let programmers know that they need to modify code so that the token is removed first.
EDIT: The question marked as duplicate does not address my problem. I know the order of destruction of objects, or even explicitly calling .reset()
in the destructor will fix my problem. That is however not the solution to my problem. The problem is I don’t want to rely on every developer in the project remembering this rule (as this event-callback system is to be used in many places in the code).
You could try excluding the actual callback implementation to a separate class, and then compose it into a "keeper" class: