I’m trying to implement a number of classes based on a a common class that abstracts a thread-pool using boost.threadpool. I’ve got something that works (in Xcode on osx 10.7.2) but I’m really not sure its good design or if its even safe (largely because of what I’ve read on-line about the use of virtual member functions with templates). I’m looking for some style advice on the best way to implement something like this. I’m learning as I go along here so I know a lot of this will be ‘bad form’…
I have a base class called ‘workqueue’ like this:
template <typename T>
class Workqueue{
private:
pool *pThreadPool;
public:
Workqueue (int);
void Start (T);
void Schedule (T);
virtual bool Process(T) {return true;}
};
template <typename T> Workqueue<T>::Workqueue(int thread_count){
pThreadPool = new pool(thread_count);
}
template <typename T> void Workqueue<T>::Start(T data){
pThreadPool->schedule(boost::bind(&Workqueue::Process,this, data));
pThreadPool->wait();
}
template <typename T> void Workqueue<T>::Schedule(T data){
pThreadPool->schedule(boost::bind(&Workqueue::Process,this, data));
}
I then define a new service based on this class like this:
struct Service1Data{
string item_data;
};
class MyService : public Workqueue<Service1Data> {
public:
MyService (int);
bool Process (Service1Data);
};
MyService::MyService(int workers) : Workqueue<Service1Data>(workers) {}
bool MyService::Process(Service1Data service_data){
cout << "in process (" << service_data.item_data << ")" << endl;
return true;
}
(I’ve removed as much of the code to keep it simple so as shown would run forever as it continually submits new work). I use the service like this:
MyService *service1 = new MyService(5);
Service1Data x;
x.item_data = "testing";
service1->Start(x);
// will wait until no more work.
delete service1;
so my specific questions:
firstly (and please be gentle…) is this bad form and is there a much better way to do this? (and why?)
secondly – is this even safe given the virtual/template issues? I read somewhere that it should be safe if the class itself is templated and I think I understand the basic vtable issues – but really not sure of the specifics.
thirdly – the base workqueue class needs to have the member definitions in the ‘h’ file with the class definition for it to link. Not sure why that would be – I imagine it’s a linker issue to do with the virtual/template issues and so makes me nervous.
all help gratefully received..
Chris
I think, you shouldn’t mix processing of data with processing of queue.
I mean, you shouldn’t have
Processmethod in yourWorkqueue.Datamay process itself, or your queue can get processing function as (template?) parameter.Then you get rid of all your problems with virtual function.
YourServiceclass then should agregateWorkqueueand may provide process function.Also, I doubt if you really need
Workqueue. You can just usepThreadPoolinYourService.If you need a common interface for services, you should specify it explicitly & separately. Your inheritance chain looks unclear. inheritance means is. Why
YourServiceisWorkqueue. I do not believe! I thinkYourServicecan use any sort of queue. But usage is aggregation.EDIT:
Code will look like this:
EDIT: I originally considered usage as: