Boss-Worker model design
-
04-07-2021 - |
Question
I am developing a code using Boss-Worker model pattern. I have a doubt. The list which the Boss will be adding to, is a member of the Boss class. In order for the Worker to access it, I am making the Worker class inherit from Boss.
1) Is this the right way to share the list between the Boss & Worker?
2) I am facing ambiguous inheritance in my code. How can I solve it?
ThreadClass
#include <pthread.h>
class ThreadClass
{
public:
virtual int start();
virtual void join();
virtual void execute() = 0; //Each derived class will implement this
virtual ~ThreadClass() {}
ThreadClass() {}
private:
ThreadClass* Tptr;
};
Boss
#include "ThreadClass.h"
#include <list>
class Boss : public virtual ThreadClass
{
public:
virtual void execute();
Boss() {}
~Boss() {}
protected:
std::list<int> Mylist; //To be shared with the worker
};
Worker
#include "ThreadClass.h"
#include "Boss.h"
class Worker : public Boss, public ThreadClass //Getting error:Ambiguous ThreadClass
{
public:
virtual void execute();
Worker() {}
~Worker() {}
};
Worker is inheriting from Boss & ThreadClass because:
1) Worker needs access to the list from Boss
2) Worker needs threading functions from ThreadClass
Solution
The list which the Boss will be adding to, is a member of the Boss class. In order for the Worker to access it, I am making the Worker class inherit from Boss.
This is categorically not a good reason for one class to inherit from another. Usually, Worker
should inherit from Boss
if and only if you can substitute a Worker
in any place that you could use a Boss
. Conceptually, this is not the case here.
If you want to provide access to Boss
's list of int
then, if the Worker
knows about the Boss
provide and accessor for it in Boss
or (possibly) make Worker
a friend
of Boss
.
If you don't want Worker
to know about Boss
but instead have Boss
know about Worker
s then make Boss
pass the list to the Worker
either at construction time or at a suitable time later.
Providing access to something is not a reason for making one class derive from another.
OTHER TIPS
I would de-couple all the classes and favour composition. Both Worker
and Boss
can share an externally created list, by holding a reference to it. Concerning the thread functionality, the C++11 and boost.thread approach is to have thread types that take "callable" entities. I think this de-coupled approach is cleaner than the double inheritance you propose.
By the way, you may need to roll out your own concurrent list class for this. std::list
will not be safe against writes from at least one of the threads threads, if a different threads are reading concurrently.
class ConcurrentList { .... };
class Boss
{
ConcurrentList& list_;
public:
Boss(ConcurrentList& l) : list_(l)
// other methods
};
class Worker
{
ConcurrentList& list_;
public:
Worker(ConcurrentList& l) : list_(l)
// other methods
};
class Thread
{
// implement a call-cack mechanism
};