C++ – Thread class design

boostcdesignmultithreading

I have a method like this in my UI code:

void MyDialog::OnCommandSaveData()
{
    std::list<MyClass*> objects;
    service_->GetAll(objects);
    dataService_->SaveObjects(objects);
    AddMessage("Saved data.\n");
}

Because this method can take some time, I want to kick off a thread to do this. I'm using C++ and I plan on using Boost.Thread. So my question is how to best do this. My understanding is that I need to create a static function, static method, or functor which will contain the above code. Where should this live, in the dialog class? That just seems wrong, but then again maybe not.

And then I will need a mutex and lock around at least the SaveObjects method. Where should the mutex live and where do I put the lock?

Most examples of threading, as with examples of so many things, don't show the threading in the context of a real application. They show a main method with a global function and that's it. So if you can point me to example of a class that manages threading for an operation that would be great.

I buy the logic in the accepted answer to this question: Is It "Wrong"/Bad Design To Put A Thread/Background Worker In A Class? However, the answer only tells you why to do it, not how.

UPDATE

I've refactored my code using MVP (Model View Presenter)/Humble Dialog Box pattern:

void MyDialog::OnCommandSaveData()
{
    presenter_->SaveData();
}

So now I will need to look at adding multi-threading in the context of MVP.

UPDATE 2

I found this article which talks about creating mulithreaded winforms using MVP. It's in C# so I'll have to translate it into C++ but it looks good:

http://aresterline.wordpress.com/2007/04/17/multi-threaded-winforms-application-mvp/

Basically it involves 1) creating a ThreadSafeView which is a wrapper or proxy around your view that allows your view to be updated from a worker thread. And 2) creating a ThreadedPresenter which allows presenter methods to spawned in a new thread. I really like how this isolates the threading code from the view and the presenter code.

Best Answer

My understanding is that I need to create a static function, static method, or functor which will contain the above code. Where should this live, in the dialog class?

It doesn't have to live anywhere; you can simply create a functor and pass it to the thread. To spawn a thread that executes that member function on the current object, and then exits:

boost::thread thread(boost::bind(&MyDialog::OnCommandSaveData, this));

And then I will need a mutex and lock around at least the SaveObjects method. Where should the mutex live and where do I put the lock?

It's usually best to keep a mutex next to the object it's protecting; in this case, a member of MyDialog.