Threads within C++ class - c++

I used to code on C++ long ago, but now decided to recall old skills and achieve some new ones :D
For now I am trying to rewrite my C# program in C++ and one problem occured - I don't know how to manage threads, or even how to create them, using class methods and calling methods from the class.
class MyObj {
private:
void thread() {
while (true) {
std::string a;
cin >> a;
}
}
static DWORD static_entry(LPVOID* param) {
MyObj *myObj = (MyObj*)param;
myObj->thread();
return 0;
}
public:
void start() {
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)static_entry, this, 0, NULL);
}
};
That is sample, I've found here, on StackOverflow but 'void thread()' was empty function, I've added code, given above, but the thread seems to start and close immediately.

I've added code, given above, but the thread seems to start and close immediately.
That's because you don't wait for threads to finish in your main thread.
As from their documentation, you'll need to add something like
// Wait until all threads have terminated.
WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
For std::thread this should be a call to std::thread::join().
I'd rather recommend using std::thread as a member of the MyObj class:
class MyObj {
private:
void thread_fn() {
while (true) {
std::string a;
cin >> a;
}
}
std::thread t;
public:
void start() {
t = std::thread(&MyObj::thread_fn,*this);
}
~MyObj() {
if(t.joinable())
t.join();
}
};

Thank you for your answers.
Using std::thread turned out to be easier than using CLI Tread class.
static void input() {
while (true) {
std::string a;
cin >> a;
secureProg::execute_command(a);
}
}
auto start() {
std::thread thread(secureProg::input);
thread.join();
return thread.get_id();
}
Thread start from main
secureProg a;
auto thread_ptr = a.start();
Final version (I hope) of two methods within class

Related

Wrapping std::thread for reuse as a class member

I want my class to spawn two threads, that will run in a loop and interact with the owner class. This was easy, when I had my class with single thread at first: one atomic flag, one mutex etc. But as the requirement for second thread rose, I am thinking of some more elegant solution, that will encapsulate the thread and its utilities. Such as: a ThreadWrapper class, that could be instantiated in the owner class.
So far, I came up with the following, however I am not certain if this is the right way to go:
class ThreadWrapper
{
public:
ThreadWrapper()
: m_threadShouldRun(false)
, m_threadRunning(false)
{
}
ThreadWrapper(std::function<void()> fn)
: m_threadShouldRun(true)
, m_threadRunning(false)
, m_threadFunction(fn)
{
m_threadPointer = std::make_shared<std::thread>(std::thread([&] { this->threadLoop(); }));
}
virtual ~ThreadWrapper()
{
if (m_threadRunning)
m_threadShouldRun = false;
m_threadPointer->join();
m_threadPointer = nullptr;
}
private:
void threadLoop()
{
m_threadRunning = true;
while(m_threadShouldRun)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
m_threadFunction();
}
m_threadRunning = false;
}
std::function<void()> m_threadFunction = []{};
std::shared_ptr<std::thread> m_threadPointer;
std::atomic<bool> m_threadShouldRun;
std::atomic<bool> m_threadRunning;
};
Usage (fixed):
class Foo
{
Foo()
: t1(std::function<void()>(std::bind(&Foo::internalLoop1, this)))
, t2(std::function<void()>(std::bind(&Foo::internalLoop2, this)))
{
}
ThreadWrapper t1;
ThreadWrapper t2;
std::mutex mtx;
void internalLoop1()
{
// looped task
{
std::scoped_lock lock(mtx);
// write'n'read data to tx/rx queues
}
}
void internalLoop2()
{
// looped task
{
std::scoped_lock lock(mtx);
// process the rx queue
}
}
};
This is somewhat similar to a Wrapper that I found here.
The shortcoming is that the sleep period needs to be passed to the ThreadWrapper object.
Is this a correct approach? Or maybe it should be done with a basis class and just inherited virtual method instead? As shown on the pic below.
Source: https://www.codeproject.com/Articles/18383/A-thread-wrapper-class
Ideally I would like to use a template here, however the only "different" part between both ThreadWrapper is a single method, which rather suggests me inheritance/function pointers. Or am I wrong here?
EDIT: Motivation. In C# one could do the following: var t1 = new Thread(() => internalLoop1()); In the end I am looking after such one-liner in my main class. Where the other ThreadWrapper class would take care of the thread safety management. Hence, being easily replicable if multiple threads were to be spawned.

Callable function C++

I've read various answer on SO and still didn't understood how I should make an object method to be callable in this case:
Considering:
Class A
{
void generator(void)
{
int i = 1;
while(1)
{
if(i == 1)
{
one(/***/);//Should be a flag
i = 2;
}
else
{
two(/**/);//Should be a flag
i = 1;
}
}
}
template <typename CallbackFunction>
void one(CallbackFunction&& func)
{
}
template <typename CallbackFunction>
void two(CallbackFunction&& func)
{
}
A()
{
std::thread t(&A::generator, this);
t.detach();
}
};
and a simple main file:
void pOne(/**/)
{
std::cout<<"1"<<std::endl;
}
void pTwo(/**/)
{
std::cout<<"2"<<std::endl;
}
A myA;
A.One(pOne);
A.Two(pTwo);
int main(int argc, char** argv)
{
while(1){}
}
Here are where I'm at:
generator() should update a flag, and both one() & two() should poll on that flag & loop forever.
One() (two() also) should have a function pointer as parameters and if necessary other parameters, pOne() should have the same parameters except the function pointer.
So my questions are:
1) Is my understanding correct?
2) Is there a clean way to make generator() to start one() or two() ? (flags, semaphore, mutex, or anything that is a standard way to do it)
3) Assuming that the code was working, is it behaving as I expect ? i.e. printing 1 and 2?
if it matters, I'm on ubuntu
Disclaimer 1: Like everyone else, I'm interpreting the question as:
-> You need an event handler
-> You want callback methods on those events
And the only reason I think that is because I helped you on a i2c handler sequence before.
Also, there are better logic than this, its provided following your stubs "rules".
You mentioned that you are on Ubuntu, so you will be lacking windows event system.
Disclaimer 2:
1- To avoid going to deep I'm going to use a simple way to handle events.
2- Code is untested & provided for logic only
class Handler
{
private:
std::mutex event_one;
event_one.lock();
void stubEventGenerator(void)
{
for(;;)
{
if(!event_one.try_lock())
{
event_one.unlock();
}
sleep(15); //you had a sleep so I added one
}
}
template <typename CallbackFunction>
void One__(CallbackFunction && func)
{
while(1)
{
event_one.lock();
func();
}
}
public:
Handler()
{
std::thread H(&Handler::stubEventGenerator, this);
}
~Handler()
{
//clean threads, etc
//this should really have a quit handler
}
template <typename CallbackFunction>
void One(CallbackFunction && func) //I think you have it right, still I'm not 100% sure
{
std::thread One_thread(&Handler::One__, this, func); //same here
}
};
Some points:
One() as to be a wrapper for the thread calling One__() if you want it to be non-blocking.
mutex can be a simple way to handle events as long as the same event doesn't occur during its previous occurence (you are free to use a better/more suitable tool for your use case, or use boost:: only if necessary)
Prototype of One() & One__() are probably wrong, that's some research for you.
Finally: How it works:
std::mutex.lock() is blocking as long as it can't lock the mutex, thus One__ will wait as long as your event generator won't unlock it.
Once unlock One__ will execute your std::function & wait for the event (mutex) to be raised (unlock) again.
far from a perfect answer, but lack of time, and not being able to put that in a comment made me post it, will edit later
With whatever limited information you provided this code can be made compilable in following manner:
#include <iostream>
#include <thread>
typedef void(*fptr)();
void pOne(/**/)
{
std::cout<<"1"<<std::endl;
}
void pTwo(/**/)
{
std::cout<<"2"<<std::endl;
}
class A
{
public:
void generator(void)
{
int i = 1;
while(1)
{
if(i == 1)
{
fptr func = pOne;
one(func);//Should be a flag
i = 2;
}
else
{
fptr func = pTwo;
two(func);//Should be a flag
i = 1;
}
}
}
template <typename CallbackFunction>
void one(CallbackFunction&& func)
{
func();
}
template <typename CallbackFunction>
void two(CallbackFunction&& func)
{
func();
}
A()
{
std::thread t(&A::generator, this);
t.detach();
}
};
int main()
{
A myA;
while(1)
{
}
return 0;
}
If you want that one and two should accept any type/number of arguments then pass second argument as variadic template.Also I could not understand why you want one and two to be called from main as your generator function is for this purpose only and this generator function is called from thread which is detached in class constructor

Start a daemon thread that's a private method of the class?

I'm new to C++11 threading and I'm trying to do something as follows:
class Something {
public:
void start() {
this->task_ = std::thread(&Something::someTask, this);
this->isRunning_ = true;
this->task_.detach(); // I read detach will stop it from hanging
}
void stop() {
this->isRunning = false;
}
~Something() {
this->stop();
}
private:
std::atomic<bool> isRunning_;
std::thread task_;
void someTask()
{
while(this->isRunning_) {
// do something forever
}
}
};
Something whatever;
whatever.start();
However, the thread keeps getting blocked. Like nothing after whatever.start() executes. It just hangs while the loop runs.
The usual pattern to do this is
class Something {
public:
void start() {
this->task_ = std::thread(&Something::someTask, this);
// this->task_.detach(); <<<<<< Don't do that.
}
void stop() {
this->isRunning_ = false;
task_.join(); // <<< Instead of detaching the thread, join() it.
}
~Something() {
this->stop();
}
private:
std::atomic<bool> isRunning_;
std::thread task_;
void someTask()
{
this->isRunning_ = true;
while(this->isRunning_) {
// do something forever
}
}
};
Detaching a std::thread usually isn't a good idea, unless there's some kind of synchronization set up, that allows to wait for the thread execution to end before the process ends as a whole.
Demonizing a process usually is realized with a fork() to create a background child process, and leave the parent process to return control to the caller.
I recently wrote a generic class that does just this
#include<functional>
#include<thread>
//do action asynchronously until condition is false
class do_async_until{
public:
do_async_until(std::function<void(void)> action,
std::function<bool(void)> condition);
~do_async_until();
void start();
void stop();
private:
void _do();
std::thread _worker;
std::function<void(void)> _action;
std::function<bool(void)> _condition;
};
//implementation
do_async_until::do_async_until(std::function<void(void)> action,
std::function<bool(void)> condition):_action(action),
_condition(condition){
}
do_async_until::~do_async_until(){
stop();
}
void do_async_until::start(){
_worker = std::thread(std::bind(&do_async_until::_do,this));
}
void do_async_until::stop(){
if(_worker.joinable()){
_worker.join();
}
}
void do_async_until::_do(){
while (_condition())
{
_action();
}
}
this will run any function with the signiture void(void) until the condition function bool(void) returns true
example usage:
int main(int agrc,char** argv){
bool running = true;
auto do_this = [](){
std::cout<<"hello world"<<std::endl;
};
auto condition = [&](){
return running;
};
do_async_until async(do_this,condition);
async.start();
std::this_thread::sleep_for(std::chrono::seconds(1));
running=false;
return 0;
}
The example should print "hello world" a bunch of times for one seconds then exit.
EDIT: to make this work with a member function you simply need to have an instance of do_async_until inside you class and pass the member function to the constructor of do_async_until using std::bind(&foo::func,this)

Multithreaded event system

I am trying to design a multithreaded event system in C++. In it, the objects may be located in different threads and every object should be able to queue events for other threads. Each thread has its own event queue and event dispatcher, as well as an event loop. It should be possible to change the thread affinity of the objects.
Let's say we have two threads: A and B, and an object myobj, which belongs to B. Obviously, A needs a pointer to myobj in order to be able to send events to it. A doesn't have any pointer to B, but it needs some way to get a reference to it in order to be able to lock the event queue and add the event to it.
I could store a pointer to B in myobj, but then I obviously need to protect myobj. If I place a mutex in myobj, myobj could be destructed while the mutex is being locked, thus causing a segmentation fault.
I could also use a global table where I associate each object with its corresponding thread. However, this would consume a lot of memory and cause any thread that wants to send an event to block until A has finish
ed.
What is the most efficient safe strategy to implement this? Is there perhaps some kind of design pattern for this?
Thanks in advance.
I've implemented a thread wrapper base class ThreadEventComponent for sending and processing events between instances of itself. Each ThreadEventComponent has it's own event queue that is automatically locked internally whenever used. The events themselves are negotiated by a static map of type map<EventKey, vector<ThreadEventComponent*>> that is also automatically locked whenever used. As you can see, multiple ThreadEventComponent derived instances can subscribe to the same event. Each event sent with SendEvent(Event*) is copied per instance to insure that multiple threads aren't fighting over the same data held within the event.
Admittedly, this is not the most efficient strategy, opposed to sharing memory. There are optimizations to be made regarding the addEvent(Event&)method. With drawbacks aside, it does work well for configuring a thread to do some operation outside of the main thread.
Both MainLoop() and ProcessEvent(Event*) are virtual functions to be implemented by the derived class. ProcessEvent(Event*) is called whenever an event is available in the queue. After that, MainLoop() is called regardless of the event queue state. MainLoop() is where you should tell your thread to sleep and where any other operations such as file reading/writing or network reading/writing should go.
The following code is something I've been working on for my own person use to get my head wrapped around threading in C++. This code has never been reviewed, so I'd love to hear any suggestions you have. I am aware of two elements that are less than desirable in this code sample. 1) I'm using new at run-time, the drawback being that finding memory takes time, but this can be mitigated by creating a memory buffer to construct new events over in the ThreadEventComponent base class. 2)Event casting to TEvent<T> can cause run-time errors if not implemented correctly in ProcessEvent. I'm not sure what the best solution for this is.
Note: I have EventKey implemented as a string, but you can change it to whatever type you wish as long as it has a default value along with the equality and assignment operators available.
Event.h
#include <string>
using namespace std;
typedef string EventKey;
class Event
{
public:
Event()
: mKey()
{
}
Event(EventKey key)
: mKey(key)
{
}
Event(const Event& e)
: mKey(e.mKey)
{
}
virtual ~Event()
{
}
EventKey GetKey()
{
return mKey;
}
protected:
EventKey mKey;
};
template<class T>
class TEvent : public Event
{
public:
TEvent()
: Event()
{
}
TEvent(EventKey type, T& object)
: Event(type), mObject(object)
{
}
TEvent(const TEvent<T>& e)
: Event(e.mKey), mObject(e.mObject)
{
}
virtual ~TEvent()
{
}
T& GetObject()
{
return mObject;
}
private:
T mObject;
};
ThreadEventComponent.h
#include "Event.h"
#include <thread>
#include <atomic>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <mutex>
#include <assert.h>
class ThreadEventComponent
{
public:
ThreadEventComponent();
~ThreadEventComponent();
void Start(bool detached = false);
void Stop();
void ForceStop();
void WaitToFinish();
virtual void Init() = 0;
virtual void MainLoop() = 0;
virtual void ProcessEvent(Event* incoming) = 0;
template<class T>
void SendEvent(TEvent<T>& e)
{
sEventListLocker.lock();
EventKey key = e.GetKey();
for (unsigned int i = 0; i < sEventList[key].size(); i++)
{
assert(sEventList[key][i] != nullptr);
sEventList[key][i]->addEvent<T>(e);
}
sEventListLocker.unlock();
}
void SendEvent(Event& e);
void Subscribe(EventKey key);
void Unsubscribe(EventKey key);
protected:
template<class T>
void addEvent(TEvent<T>& e)
{
mQueueLocker.lock();
// The event gets copied per thread
mEventQueue.push(new TEvent<T>(e));
mQueueLocker.unlock();
}
void addEvent(Event& e);
thread mThread;
atomic<bool> mShouldExit;
private:
void threadLoop();
queue<Event*> mEventQueue;
mutex mQueueLocker;
typedef map<EventKey, vector<ThreadEventComponent*>> EventMap;
static EventMap sEventList;
static mutex sEventListLocker;
};
ThreadEventComponent.cpp
#include "ThreadEventComponent.h"
ThreadEventComponent::EventMap ThreadEventComponent::sEventList = ThreadEventComponent::EventMap();
std::mutex ThreadEventComponent::sEventListLocker;
ThreadEventComponent::ThreadEventComponent()
{
mShouldExit = false;
}
ThreadEventComponent::~ThreadEventComponent()
{
}
void ThreadEventComponent::Start(bool detached)
{
mShouldExit = false;
mThread = thread(&ThreadEventComponent::threadLoop, this);
if (detached)
mThread.detach();
}
void ThreadEventComponent::Stop()
{
mShouldExit = true;
}
void ThreadEventComponent::ForceStop()
{
mQueueLocker.lock();
while (!mEventQueue.empty())
{
delete mEventQueue.front();
mEventQueue.pop();
}
mQueueLocker.unlock();
mShouldExit = true;
}
void ThreadEventComponent::WaitToFinish()
{
if(mThread.joinable())
mThread.join();
}
void ThreadEventComponent::SendEvent(Event& e)
{
sEventListLocker.lock();
EventKey key = e.GetKey();
for (unsigned int i = 0; i < sEventList[key].size(); i++)
{
assert(sEventList[key][i] != nullptr);
sEventList[key][i]->addEvent(e);
}
sEventListLocker.unlock();
}
void ThreadEventComponent::Subscribe(EventKey key)
{
sEventListLocker.lock();
if (find(sEventList[key].begin(), sEventList[key].end(), this) == sEventList[key].end())
{
sEventList[key].push_back(this);
}
sEventListLocker.unlock();
}
void ThreadEventComponent::Unsubscribe(EventKey key)
{
sEventListLocker.lock();
// Finds event listener of correct type
EventMap::iterator mapIt = sEventList.find(key);
assert(mapIt != sEventList.end());
// Finds the pointer to itself
std::vector<ThreadEventComponent*>::iterator elIt =
std::find(mapIt->second.begin(), mapIt->second.end(), this);
assert(elIt != mapIt->second.end());
// Removes it from the event list
mapIt->second.erase(elIt);
sEventListLocker.unlock();
}
void ThreadEventComponent::addEvent(Event& e)
{
mQueueLocker.lock();
// The event gets copied per thread
mEventQueue.push(new Event(e));
mQueueLocker.unlock();
}
void ThreadEventComponent::threadLoop()
{
Init();
bool shouldExit = false;
while (!shouldExit)
{
if (mQueueLocker.try_lock())
{
if (mEventQueue.empty())
{
mQueueLocker.unlock();
if(mShouldExit)
shouldExit = true;
}
else
{
Event* e = mEventQueue.front();
mEventQueue.pop();
mQueueLocker.unlock();
ProcessEvent(e);
delete e;
}
}
MainLoop();
}
}
Example Class - A.h
#include "ThreadEventComponent.h"
class A : public ThreadEventComponent
{
public:
A() : ThreadEventComponent()
{
}
void Init()
{
Subscribe("a stop");
Subscribe("a");
}
void MainLoop()
{
this_thread::sleep_for(50ms);
}
void ProcessEvent(Event* incoming)
{
if (incoming->GetKey() == "a")
{
auto e = static_cast<TEvent<vector<int>>*>(incoming);
mData = e->GetObject();
for (unsigned int i = 0; i < mData.size(); i++)
{
mData[i] = sqrt(mData[i]);
}
SendEvent(TEvent<vector<int>>("a done", mData));
}
else if(incoming->GetKey() == "a stop")
{
StopWhenDone();
}
}
private:
vector<int> mData;
};
Example Class - B.h
#include "ThreadEventComponent.h"
int compare(const void * a, const void * b)
{
return (*(int*)a - *(int*)b);
}
class B : public ThreadEventComponent
{
public:
B() : ThreadEventComponent()
{
}
void Init()
{
Subscribe("b stop");
Subscribe("b");
}
void MainLoop()
{
this_thread::sleep_for(50ms);
}
void ProcessEvent(Event* incoming)
{
if (incoming->GetKey() == "b")
{
auto e = static_cast<TEvent<vector<int>>*>(incoming);
mData = e->GetObject();
qsort(&mData[0], mData.size(), sizeof(int), compare);
SendEvent(TEvent<vector<int>>("b done", mData));
}
else if (incoming->GetKey() == "b stop")
{
StopWhenDone();
}
}
private:
vector<int> mData;
};
Test Example - main.cpp
#include <iostream>
#include <random>
#include "A.h"
#include "B.h"
class Master : public ThreadEventComponent
{
public:
Master() : ThreadEventComponent()
{
}
void Init()
{
Subscribe("a done");
Subscribe("b done");
}
void MainLoop()
{
this_thread::sleep_for(50ms);
}
void ProcessEvent(Event* incoming)
{
if (incoming->GetKey() == "a done")
{
TEvent<vector<int>>* e = static_cast<TEvent<vector<int>>*>(incoming);
cout << "A finished" << endl;
mDataSetA = e->GetObject();
for (unsigned int i = 0; i < mDataSetA.size(); i++)
{
cout << mDataSetA[i] << " ";
}
cout << endl << endl;
}
else if (incoming->GetKey() == "b done")
{
TEvent<vector<int>>* e = static_cast<TEvent<vector<int>>*>(incoming);
cout << "B finished" << endl;
mDataSetB = e->GetObject();
for (unsigned int i = 0; i < mDataSetB.size(); i++)
{
cout << mDataSetB[i] << " ";
}
cout << endl << endl;
}
}
private:
vector<int> mDataSetA;
vector<int> mDataSetB;
};
int main()
{
srand(time(0));
A a;
B b;
a.Start();
b.Start();
vector<int> data;
for (int i = 0; i < 100; i++)
{
data.push_back(rand() % 100);
}
Master master;
master.Start();
master.SendEvent(TEvent<vector<int>>("a", data));
master.SendEvent(TEvent<vector<int>>("b", data));
master.SendEvent(TEvent<vector<int>>("a", data));
master.SendEvent(TEvent<vector<int>>("b", data));
master.SendEvent(Event("a stop"));
master.SendEvent(Event("b stop"));
a.WaitToFinish();
b.WaitToFinish();
// cin.get();
master.StopWhenDone();
master.WaitToFinish();
return EXIT_SUCCESS;
}
I have not used it myself, but Boost.Signals2 claims to be thread-safe.
The primary motivation for Boost.Signals2 is to provide a version of the original Boost.Signals library which can be used safely in a multi-threaded environment.
Of course, using this would make your project depend on boost, which might not be in your interest.
[edit] It seems slots are executed in the emitting thread (no queue), so this might not be what you had in mind after all.
I'd consider making the thread part of classes to encapsulate them. That way you can easily design your interfaces around the thread loops (provided as member functions of these classes) and have defined entry points to send data to the thread loop (e.g. using a std::queue protected with a mutex).
I don't know if this is a designated, well known design pattern, but that's what I'm using for my all day productive code at work, and I (and my colleagues) feel and experience pretty good with it.
I'll try to give you a point:
class A {
public:
A() {}
bool start();
bool stop();
bool terminate() const;
void terminate(bool value);
int data() const;
void data(int value);
private:
std::thread thread_;
void threadLoop();
bool terminate_;
mutable std::mutex internalDataGuard_;
int data_;
};
bool A::start() {
thread_ = std::thread(std::bind(this,threadLoop));
return true;
}
bool A::stop() {
terminate(true);
thread_.join();
return true;
}
bool A::terminate() const {
std::lock_guard<std::mutex> lock(internalDataGuard_);
return terminate_;
}
void A::terminate(bool value) {
std::lock_guard<std::mutex> lock(internalDataGuard_);
terminate_ = value;
}
int A::data() const {
std::lock_guard<std::mutex> lock(internalDataGuard_);
return data_;
}
void A::data(int value) {
std::lock_guard<std::mutex> lock(internalDataGuard_);
data_ = value;
// Notify thread loop about data changes
}
void A::threadLoop() {
while(!terminate())
{
// Wait (blocking) for data changes
}
}
To setup signalling of data changes there are several choices and (OS) constraints:
The simplest thing you could use to wake up the thread loop to process changed/new data is a semaphore. In c++11 the nearest approx for a semaphore is a condition variable. Advanced versions of the pthreads API also provide condition variable support. Anyway since only one thread should be waiting there, and no kind of event broadcasing is necessary, it should be easy to implement with simple locking mechanisms.
If you have the choice to use an advanced OS, you might prefer implementing event signalling using s.th. like poll(), which provides lock-free implementation at the user space.
Some frameworks like boost, Qt, Platinum C++, and others also support event handling by signal/slot abstractions, you might have a look at their documentation and implementation to get a grip what's necessary/state of the art.
Obviously, A needs a pointer to myobj in order to be able to send
events to it.
I question the above assumption -- To me, allowing thread A to have a pointer to an object that is controlled/owned/accessed by thread B is kind of asking for trouble... in particular, some code running in thread A might be tempted later on to use that pointer to directly call methods on myobj, causing race conditions and discord; or B might delete myobj, at which point A is holding a dangling-pointer and is thereby in a precarious state.
If I was designing the system, I would try to do it in such a way that cross-thread messaging was done without requiring pointers-to-objects-in-other-threads, for the reasons you mention -- they are unsafe, in particular such a pointer might become a dangling-pointer at any time.
So then the question becomes, how do I send a message to an object in another thread, if I don't have a pointer to that object?
One way would be to give each object a unique ID by which it can be specified. This ID could be an integer (either hard-coded or dynamically assigned using an atomic counter or similar), or perhaps a short string if you wanted it to be more easily human-readable.
Then instead of the code in thread A sending the message directly to myobj, it would send a message to thread B, and the message would include a field indicating the ID of the object that is intended to receive the message.
When thread B's event loop receives the message, it would use the included ID value to look up the appropriate object (using an efficient key-value lookup mechanism such as std::unordered_map) and call the appropriate method on that object. If the object had already been destroyed, then the key-value lookup would fail (because you'd have a mechanism to make sure that the object removed itself from its thread's object-map as part of its destructor), and thus trying to send a message to a destroyed-object would fail cleanly (as opposed to invoking undefined behavior).
Note that this approach does mean that thread A's code has to know which thread myobj is owned by, in order to know which thread to send the message to. Typically thread A would need to know that anyway, but if you're going for a design that abstracts away even the knowledge about which thread a given object is running in, you could include an owner-thread-ID as part of the object-ID, so that your postMessage() method could examine the destination-object-ID to figure out which thread to send the message to.

Joining a boost::thread instance in the destructor

I'm seeing an issue where a call to boost's thread->join in a destructor leads to a deadlock. I don't understand why, and I'm not too keen on keeping code that just works (and I don't understand why it does) in the project.
Class declaration (I've stripped the run() method of try/catch for brevity: according to the boost thread documentation, the result should be the same with or without it):
class B
{
public:
void operator()(){run();}
void run();
void shutdown();
~B();
B();
boost::thread *thr;
bool shutdown_requested;
};
void B::shutdown()
{
shutdown_requested = true;
if (thr != NULL)
{
thr->interrupt();
thr->join(); // deadlock occurs here!
delete thr;
thr = NULL;
}
}
B::~B()
{
shutdown();
}
B::B()
{
thr = new boost::thread(boost::ref(*this));
}
void B::run()
{
while (!shutdown_requested)
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 30;
boost::this_thread::sleep(xt);
}
}
Snippet which does not work:
int main()
{
B *b = new B;
Sleep(5000);
printf("deleting \n");fflush(stdout);
// b->shutdown();
delete b;
printf("done\n");fflush(stdout);
return 0;
}
Snippet which works:
int main()
{
B *b = new B;
Sleep(5000);
printf("deleting \n");fflush(stdout);
b->shutdown();
delete b;
printf("done\n");fflush(stdout);
return 0;
}
I think the reason for this behavior has something to do with this snippet of the boost documentation:
the user of Boost.Thread must ensure
that the referred-to object outlives
the newly-created thread of execution.
But I don't really understand why the deadlock - joining the thread would not call the destructor on B and the object itself is not deleted when the run() method is supposed to exit.
I've found the issue: it boils down to an over-zealous programmer.
I had originally compiled my project using DUMA (http://sourceforge.net/projects/duma/) to see if my implementation of the current module was leak-free. Unfortunately, my test sandbox also had the duma settings on, which I did not realize until I stepped through the code in a debugger.
After removing all memory leak-detection, everything works as expected.