Threading with Inheritence

I've made a background worker which uses a queue to hold events. If an event is added, a conditional notifies the worker to started processing events until there aren't anymore.

The danger was that it would be possible for the main thread to finish ( thus calling the destructor of the queue ) before the thread was broken from its loop.

This was solved with the following:
1
2
3
4
5
6
~EventQueue( void )
{
  running = false;          // will break the thread from its loop
  conditional.notify_all(); // tell the thread to stop waiting for a push
  thread.join();            // wait for the thread to finish
}


I decided to template out the EventQueue, I end up with something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename T>
class ThreadSafeProcessor
{
  virtual void process( T ) const = 0; // this gets called for every T popped from the queue
};

class EventQueue : public ThreadSafeProcessor< Event >
{
  void process( Event event ) const 
  {
    event.fire();
  }
};


Now the trouble. When the main thread exits, it calls the destructor of EventQueue and removes the process override from the v-table. The ThreadSafeProcessor knows not to destruct without closing the thread, so it is possible that it calls process with an Event. The error is as such:
pure virtual method called

So I cut/pasted the code from the ThreadSafeProcessor's destructor into the EventQueue's, and now the problem seems to be gone.

Is there a better way to solve this? How can I tell the derived class not to destruct without having to copy/paste that code into every derived class?
Last edited on
Lemme make sure I am understanding the problem...

- ThreadSafeProcessor owns a thread
- EventQueue derives from ThreadSafeProcessor
- The thread uses EventQueue
- Upon destruction of the EventQueue object, it is destroyed while the thread is still using it.

Am I understanding correctly?


I would separate this so that one object owns the thread and does the logic. IE, rather than having ThreadSafeProcessor be the parent to the EventQueue, it would own it. That way it can ensure the order of destruction.

Something similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <typename T>
class EventProcessor   // or something
{/*...*/};

template <typename T>
class EventQueue : public EventProcessor<T>
{/*...*/};

template <typename T>
class ThreadSafePrcoessor
{
    //...
    EventProcessor<T> processor;  // own the processor
    std::thread thread;  // own the thread
};



This is better anyway because then outside code does not have direct access to an object that is operating in another thread. ThreadSafeProcessor then controls all interaction with the processing thread (and the object that is running in it), and can put locks up where necessary.

Likewise, the event handler does not need to concern itself with any thread issues. It can just do its work.
Am I understanding correctly?

Indeed.

That is an interesting idea, thanks.
Topic archived. No new replies allowed.