Best way to protect a callback function from deconstructed classes - c++

What would be a good/best to ensure thread safety for callback objects? Specifically, I'm trying to prevent a callback object from being deconstructed before all the threads are finished with it.
It is easy to code the client code to ensure thread safety, but I'm looking for a way that is a bit more streamlined. For example, using a factory object to generate the callback objects. The trouble then lies in tracking the usage of the callback object.
Below is an example code that I'm trying to improve.
class CHandlerCallback
{
public:
CHandlerCallback(){ ... };
virtual ~CHandlerCallback(){ ... };
virtual OnBegin(UINT nTotal ){ ... };
virtual OnStep (UINT nIncrmt){ ... };
virtual OnEnd(UINT nErrCode){ ... };
protected:
...
}
static DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
CHandler* phandler = (CHandler*)lpParameter;
phandler ->ThreadProc();
return 0;
};
class CHandler
{
public:
CHandler(CHandlerCallback * sink = NULL) {
m_pSink = sink;
// Start the server thread. (ThreadProc)
};
~CHandler(){...};
VOID ThreadProc(LPVOID lpParameter) {
... do stuff
if (m_pSink) m_pSink->OnBegin(..)
while (not exit) {
... do stuff
if (m_pSink) m_pSink->OnStep(..)
... do stuff
}
if (m_pSink) m_pSink->OnEnd(..);
};
private:
CHandlerCallback * m_pSink;
}
class CSpecial1Callback: public CHandlerCallback
{
public:
CSpecial1Callback(){ ... };
virtual ~CBaseHandler(){ ... };
virtual OnStep (UINT nIncrmt){ ... };
}
class CSpecial2Callback: public CHandlerCallback...
Then the code that runs everything in a way similar to the following:
int main {
CSpecial2Callback* pCallback = new CSpecial2Callback();
CHandler handler(pCallback );
// Right now the client waits for CHandler to finish before deleting
// pCallback
}
Thanks!

If you're using C++11 you can use smart pointers to keep the object around until the last reference to the object disappears. See shared_pointer. If you're not in C++11 you could use boost's version. If you don't want to include that library and aren't in C++11 you can resort to keeping an internal count of threads using that object and destroy the object when that count reaches 0. Note that trying to track the counter yourself can be difficult as you'll need atomic updates to the counter.
shared_ptr<CSpecial2Callback> pCallback(new CSpecial2Callback());
CHandler handler(pCallback); // You'll need to change this to take a shared_ptr
... //Rest of code -- when the last reference to
... //pCallback is used up it will be destroyed.

Related

shared_from_this() causes std::bad_weak_ptr even when correctly using make_shared

I am creating a C++ server application using standalone Asio and C++11 and am getting an error, which is why I am asking for help.
The error
In the class worker_thread, during the call to shared_from_this(), a bad_weak_ptr exception is raised, which causes the program to crash.
The layout
The class connection_manager creates and stores objects of type std::shared_ptr<worker_thread> inside a std::vector container
The class worker_thread inherits from std::enable_shared_from_this<worker_thread>.
The class worker_thread creates objects of type std::shared_ptr<connection>.
The class connection requires a pointer (which is a shared pointer) to the class worker_thread, so that in can call the void handle_finish(std::shared_ptr<connection>)
Program flow
The class worker_thread is created via its constructor, from the class connection_manager using std::make_shared<worker_thread> with two shared pointers as parameters.
void init() is called from worker_thread by connection_manager
Later in the program, connection_manager calls std::shared_ptr<connection> get_available_connection() from worker_thread
During this method's execution, a new connection is created via std::make_shared<connection>, and one of the arguments is the shared pointer to the current worker_thread obtained via shared_from_this()
During the shared_from_this() call, the program crashes with a bad_weak_ptr exception.
Research
From my research, the most common causes of this error are:
When shared_from_this() is called within a constructor (or a function which is called by the constructor)
When there is no existing std::shared_ptr pointing to the object.
In my program:
The call to the constructor and the get_available_connection() are separate, and through outputing lines in the terminal, it seems that the worker_thread is constructed and initialised by the time the call to get_available_connection() occurs
The connection_manager class holds a shared pointer to every worker_thread object.
Code
All something_ptr are std::shared_ptr<something>
Header files
connection_manager.hpp
typedef asio::executor_work_guard<asio::io_context::executor_type>
io_context_work;
std::vector<worker_thread_ptr> workers;
std::vector<io_context_ptr> io_contexts;
std::vector<io_context_work> work;
worker_thread.hpp
class worker_thread : std::enable_shared_from_this<worker_thread> {
public:
/// Create a worker thread.
explicit worker_thread(io_context_ptr io, config_ptr vars_global);
void init();
void join();
connection_ptr get_available_connection();
//...
connection.hpp
explicit connection(std::shared_ptr<worker_thread> worker,
std::shared_ptr<asio::io_context> io,
config_ptr vars_parent);
Source files
connection_manager.cpp
connection_manager::connection_manager(config_ptr vars) {
std::size_t number_of_threads = vars->worker_threads;
while(number_of_threads > 0) {
io_context_ptr io_context(new asio::io_context);
io_contexts.push_back(io_context);
work.push_back(asio::make_work_guard(*io_context));
worker_thread_ptr worker =
std::make_shared<worker_thread>(io_context, vars);
workers.push_back(worker);
worker->init();
--number_of_threads;
}
}
connection_ptr connection_manager::get_available_connection() {
std::size_t index_of_min_thread = 0;
std::size_t worker_count = workers.size();
for(std::size_t i = 1; i < worker_count; ++i) {
if(workers[i]->active_connection_count() <
workers[index_of_min_thread]->active_connection_count())
index_of_min_thread = i;
}
return workers[index_of_min_thread]->get_available_connection();
}
worker_thread.cpp
worker_thread::worker_thread(io_context_ptr io,
config_ptr vars_global)
:io_context(io), active_conn_count(0), vars(vars_global),
worker(
[this]() {
if(io_context)
io_context->run();
}
) {}
void worker_thread::init() {
//Additional initialisation, this is called by connection_manager
//after this thread's construction
}
connection_ptr worker_thread::get_available_connection() {
connection_ptr conn;
if(!available_connections.empty()) {
conn = available_connections.front();
available_connections.pop();
active_connections.insert(conn);
return conn;
} else {
conn = std::make_shared<connection>(shared_from_this(), io_context, vars);
active_connections.insert(conn);
return conn;
}
}
I am sorry if this question has been answered before, but I tried to resolve this, and after trying for some time, I decided it would be better to ask for help.
EDIT
Here is a minimum test, which fails. It requires CMake, and you might have to change the minimum required version.
Google Drive link
I think your problem might be that you use default private inheritance.
here is a simple example of a program that crashes:
class GoodUsage : public std::enable_shared_from_this<GoodUsage>
{
public:
void DoSomething()
{
auto good = shared_from_this();
}
};
class BadUsage : std::enable_shared_from_this<BadUsage> // private inheritance
{
public:
void DoSomething()
{
auto bad = shared_from_this();
}
};
int main()
{
auto good = std::make_shared<GoodUsage>();
auto bad = std::make_shared<BadUsage>();
good->DoSomething(); // ok
bad->DoSomething(); // throws std::bad_weak_ptr
}

Communication between 2 threads C++ UNIX

I need your help with wxWidgets. I have 2 threads (1 wxTimer and 1 wxThread), I need communicate between this 2 threads. I have a class that contains methods to read/write variable in this class. (Share Memory with this object)
My problem is: I instanciate with "new" this class in one thread but I don't know that necessary in second thread. Because if instanciate too, adress of variable are differents and I need communicate so I need even value in variable :/
I know about need wxSemaphore to prevent error when to access same time.
Thanks you for your help !
EDIT: My code
So, I need make a link with my code. Thanks you for all ;)
It's my declaration for my wxTimer in my class: EvtFramePrincipal (IHM)
In .h
EvtFramePrincipal( wxWindow* parent );
#include <wx/timer.h>
wxTimer m_timer;
in .cpp -Constructor EvtFramePrincipal
EvtFramePrincipal::EvtFramePrincipal( wxWindow* parent )
:
FramePrincipal( parent ),m_timer(this)
{
Connect(wxID_ANY,wxEVT_TIMER,wxTimerEventHandler(EvtFramePrincipal::OnTimer),NULL,this);
m_timer.Start(250);
}
So I call OnTimer method every 250ms with this line.
For my second thread start from EvtFramePrincipal (IHM):
in .h EvtFramePrincipal
#include "../Client.h"
Client *ClientIdle;
in .cpp EvtFramePrincipal
ClientIdle= new Client();
ClientIdle->Run();
In .h Client (Thread)
class Client: public wxThread
public:
Client();
virtual void *Entry();
virtual void OnExit();
In .cpp Client (Thread)
Client::Client() : wxThread()
{
}
So here, no probleme, thread are ok ?
Now I need that this class that use like a messenger between my 2 threads.
#ifndef PARTAGE_H
#define PARTAGE_H
#include "wx/string.h"
#include <iostream>
using std::cout;
using std::endl;
class Partage
{
public:
Partage();
virtual ~Partage();
bool Return_Capteur_Aval()
{ return Etat_Capteur_Aval; }
bool Return_Capteur_Amont()
{ return Etat_Capteur_Amont; }
bool Return_Etat_Barriere()
{ return Etat_Barriere; }
bool Return_Ouverture()
{ return Demande_Ouverture; }
bool Return_Fermeture()
{ return Demande_Fermeture; }
bool Return_Appel()
{ return Appel_Gardien; }
void Set_Ouverture(bool Etat)
{ Demande_Ouverture=Etat; }
void Set_Fermeture(bool Etat)
{ Demande_Fermeture=Etat; }
void Set_Capteur_Aval(bool Etat)
{ Etat_Capteur_Aval=Etat; }
void Set_Capteur_Amont(bool Etat)
{ Etat_Capteur_Amont=Etat; }
void Set_Barriere(bool Etat)
{ Etat_Barriere=Etat; }
void Set_Appel(bool Etat)
{ Appel_Gardien=Etat; }
void Set_Code(wxString valeur_code)
{ Code=valeur_code; }
void Set_Badge(wxString numero_badge)
{ Badge=numero_badge; }
void Set_Message(wxString message)
{
Message_Affiche=wxT("");
Message_Affiche=message;
}
wxString Get_Message()
{
return Message_Affiche;
}
wxString Get_Code()
{ return Code; }
wxString Get_Badge()
{ return Badge; }
protected:
private:
bool Etat_Capteur_Aval;
bool Etat_Capteur_Amont;
bool Etat_Barriere;
bool Demande_Ouverture;
bool Demande_Fermeture;
bool Appel_Gardien;
wxString Code;
wxString Badge;
wxString Message_Affiche;
};
#endif // PARTAGE_H
So in my EvtFramePrincipal(wxTimer), I make a new for this class. But in other thread (wxThread), what I need to do to communicate ?
If difficult to understand so sorry :/
Then main thread should create first the shared variable. After it, you can create both threads and pass them a pointer to the shared variable.
So, both of them, know how interact with the shared variable. You need to implement a mutex or wxSemaphore in the methods of the shared variable.
You can use a singleton to get access to a central object.
Alternatively, create the central object before creating the threads and pass the reference to the central object to threads.
Use a mutex in the central object to prevent simultaneous access.
Creating one central object on each thread is not an option.
EDIT 1: Adding more details and examples
Let's start with some assumptions. The OP indicated that
I have 2 threads (1 wxTimer and 1 wxThread)
To tell the truth, I know very little of the wxWidgets framework, but there's always the documentation. So I can see that:
wxTimer provides a Timer that will execute the wxTimer::Notify() method when the timer expires. The documentation doesn't say anything about thread-execution (although there's a note A timer can only be used from the main thread which I'm not sure how to understand). I can guess that we should expect the Notify method will be executed in some event-loop or timer-loop thread or threads.
wxThread provides a model for Thread execution, that runs the wxThread::Entry() method. Running a wxThread object will actually create a thread that runs the Entry method.
So your problem is that you need same object to be accessible in both wxTimer::Notify() and wxThread::Entry() methods.
This object:
It's not one variable but a lot of that store in one class
e.g.
struct SharedData {
// NOTE: This is very simplistic.
// since the information here will be modified/read by
// multiple threads, it should be protected by one or more
// mutexes
// so probably a class with getter/setters will be better suited
// so that access with mutexes can be enforced within the class.
SharedData():var2(0) { }
std::string var1;
int var2;
};
of which you have somewhere an instance of that:
std::shared_ptr<SharedData> myData=std::make_shared<SharedData>();
or perhaps in pointer form or perhaps as a local variable or object attribute
Option 1: a shared reference
You're not really using wxTimer or wxThread, but classes that inherit from them (at least the wxThread::Entry() is pure virtual. In the case of wxTimer you could change the owner to a different wxEvtHandler that will receive the event, but you still need to provide an implementation.
So you can have
class MyTimer: public wxTimer {
public:
void Notify() {
// Your code goes here
// but it can access data through the local reference
}
void setData(const std::shared_ptr<SharedData> &data) {
mLocalReference=data
}
private:
std::shared_ptr<SharedData> mLocalReferece
};
That will need to be set:
MyTimer timer;
timer.setData(myData);
timer.StartOnece(10000); // wake me up in 10 secs.
Similarly for the Thread
class MyThread: public wxThread {
public:
void Entry() {
// Your code goes here
// but it can access data through the local reference
}
void setData(const std::shared_ptr<SharedData> &data) {
mLocalReference=data
}
private:
std::shared_ptr<SharedData> mLocalReferece
};
That will need to be set:
MyThread *thread=new MyThread();
thread->setData(myData);
thread->Run(); // threads starts running.
Option2 Using a singleton.
Sometimes you cannot modify MyThread or MyTimer... or it is too difficult to route the reference to myData to the thread or timer instances... or you're just too lazy or too busy to bother (beware of your technical debt!!!)
We can tweak the SharedData into:
struct SharedData {
std::string var1;
int var2;
static SharedData *instance() {
// NOTE that some mutexes are needed here
// to prevent the case where first initialization
// is executed simultaneously from different threads
// allocating two objects, one of them leaked.
if(!sInstance) {
sInstance=new SharedData();
}
return sInstance
}
private:
SharedData():var2(0) { } // Note we've made the constructor private
static SharedData *sInstance=0;
};
This object (because it only allows the creation of a single object) can be accessed from
either MyTimer::Notify() or MyThread::Entry() with
SharedData::instance()->var1;
Interlude: why Singletons are evil
(or why the easy solution might bite you in the future).
What is so bad about singletons?
Why Singletons are Evil
Singletons Are Evil
My main reasons are:
There's one and only one instance... and you might think that you only need one now, but who knows what the future will hold, you've taken an easy solution for a coding problem that has far reaching consequences architecturally and that might be difficult to revert.
It will not allow doing dependency injection (because the actual class is used in the accessing the object).
Still, I don't think is something to completely avoid. It has its uses, it can solve your problem and it might save your day.
Option 3. Some middle ground.
You could still organize your data around a central repository with methods to access different instances (or different implementations) of the data.
This central repository can be a singleton (it is really is central, common and unique), but is not the shared data, but what is used to retrieve the shared data, e.g. identified by some ID (that might be easier to share between the threads using option 1)
Something like:
CentralRepository::instance()->getDataById(sharedId)->var1;
EDIT 2: Comments after OP posted (more) code ;)
It seems that your object EvtFramePrincipal will execute both the timer call back and it will contain the ClientIdle pointer to a Client object (the thread)... I'd do:
Make the Client class contain a Portage attribute (a pointer or a smart pointer).
Make the EvtFramePrincipal contain a Portage attribute (a pointer or smart pointer). I guess this will have the lifecycle of the whole application, so the Portage object can share that lifecycle too.
Add Mutexes locking to all methods setting and getting in the Portage attribute, since it can be accessed from multiple threads.
After the Client object is instantiated set the reference to the Portage object that the EvtFramePrincipal contains.
Client can access Portage because we've set its reference when it was created. When the Entry method is run in its thread it will be able to access it.
EvtFramePrincipal can access the Portage (because it is one of its attributes), so the event handler for the timer event will be able to access it.

std::thread : how to declare a thread in class body as a normal member?

I want to have a thread for each instance of Page object. At a time only one of them can execute (simply checks if pointer to current running thread is joinable or not..)
class Page : public std::vector<Step>
{
// ....
void play();
void start(); // check if no other thread is running. if there is a running thread, return. else join starter
std::thread starter; // std::thread running this->play()
static std::thread* current; // pointer to current running thread
// ...
};
I want to be able to fire-up starter threads of Page objects. for example like this:
Page x , y , z;
// do some stuff for initialize pages..
x.start();
// do some other work
y.start(); // if x is finished, start y otherwise do nothing
// do some other lengthy work
z.start(); // if x and y are not running, start z
I can't manage to declare started as a member of Page. I found that it's because of the fact std::threads can only initialized at declaration time. (or something like that, cause it's not possible to copy a thread)
void x()
{
}
//...
std::thread t(x); // this is ok
std::thread r; // this is wrong, but I need this !
r = std::thread(this->y); // no hope
r = std::thread(y); // this is wrong too
You can initialize the thread to the function to run by using a member initializer list. For example, consider this constructor for Page:
class Page {
public:
Page(); // For example
private:
std::thread toRun;
};
Page::Page() : toRun(/* function to run */) {
/* ... */
}
Notice how we use the initialization list inside the Page constructor to initialize toRun to the function that ought to be run. This way, toRun is initialized as if you had declared it as a local variable
std::string toRun(/* function to run */);
That said, there are two major problems I think that you must address in your code. First, you should not inherit from std::vector or any of the standard collections classes. Those classes don't have their destructors marked virtual, which means that you can easily invoke undefined behavior if you try to treat your Page as a std::vector. Instead, consider making Page hold a std::vector as a direct subobject. Also, you should not expose the std::thread member of the class. Data members should, as a general rule, be private to increase encapsulation, make it easier to modify the class in the future, and prevent people from breaking all of your class's invariants.
Hope this helps!
Never publicly inherit from a std container, unless the code is meant to be throw away code. An honestly it's terrifying how often throw away code becomes production code when push comes to shove.
I understand you don't want to reproduce the whole std::vector interface. That is tedious write, a pain to maintain, and honestly could create bugs.
Try this instead
class Page: private std::vector
{
public:
using std::vector::push_back;
using std::vector::size;
// ...
};
Ignoring the std::vector issue this should work for the concurrency part of the problem.
class Page
{
~Page( void )
{
m_thread.join();
}
void start( void );
private:
// note this is private, it must be to maintain the s_running invariant
void play( void )
{
assert( s_current == this );
// Only one Page at a time will execute this code.
std::lock_guard<std::mutex> _{ s_mutex };
s_running = nullptr;
}
std::thread m_thread;
static Page* s_running;
static std::mutex s_mutex;
};
Page* Page::s_running = nullptr;
std::mutex Page::s_mutex;
std::condition Page::s_condition;
void Page::start( void )
{
std::lock_guard<std::mutex> _{ s_mutex };
if( s_running == nullptr )
{
s_running = this;
m_thread = std::thread{ [this](){ this->play(); } };
}
}
This solution is may have initialization order issues if Page is instantiate before main()

C++ Critical Section not working

My critical section code does not work!!!
Backgrounder.run IS able to modify MESSAGE_QUEUE g_msgQueue and LockSections destructor hadn't been called yet !!!
Extra code :
typedef std::vector<int> MESSAGE_LIST; // SHARED OBJECT .. MUST LOCK!
class MESSAGE_QUEUE : MESSAGE_LIST{
public:
MESSAGE_LIST * m_pList;
MESSAGE_QUEUE(MESSAGE_LIST* pList){ m_pList = pList; }
~MESSAGE_QUEUE(){ }
/* This class will be shared between threads that means any
* attempt to access it MUST be inside a critical section.
*/
void Add( int messageCode ){ if(m_pList) m_pList->push_back(messageCode); }
int getLast()
{
if(m_pList){
if(m_pList->size() == 1){
Add(0x0);
}
m_pList->pop_back();
return m_pList->back();
}
}
void removeLast()
{
if(m_pList){
m_pList->erase(m_pList->end()-1,m_pList->end());
}
}
};
class Backgrounder{
public:
MESSAGE_QUEUE* m_pMsgQueue;
static void __cdecl Run( void* args){
MESSAGE_QUEUE* s_pMsgQueue = (MESSAGE_QUEUE*)args;
if(s_pMsgQueue->getLast() == 0x45)printf("It's a success!");
else printf("It's a trap!");
}
Backgrounder(MESSAGE_QUEUE* pMsgQueue)
{
m_pMsgQueue = pMsgQueue;
_beginthread(Run,0,(void*)m_pMsgQueue);
}
~Backgrounder(){ }
};
int main(){
MESSAGE_LIST g_List;
CriticalSection crt;
ErrorHandler err;
LockSection lc(&crt,&err); // Does not work , see question #2
MESSAGE_QUEUE g_msgQueue(&g_List);
g_msgQueue.Add(0x45);
printf("%d",g_msgQueue.getLast());
Backgrounder back_thread(&g_msgQueue);
while(!kbhit());
return 0;
}
#ifndef CRITICALSECTION_H
#define CRITICALSECTION_H
#include <windows.h>
#include "ErrorHandler.h"
class CriticalSection{
long m_nLockCount;
long m_nThreadId;
typedef CRITICAL_SECTION cs;
cs m_tCS;
public:
CriticalSection(){
::InitializeCriticalSection(&m_tCS);
m_nLockCount = 0;
m_nThreadId = 0;
}
~CriticalSection(){ ::DeleteCriticalSection(&m_tCS); }
void Enter(){ ::EnterCriticalSection(&m_tCS); }
void Leave(){ ::LeaveCriticalSection(&m_tCS); }
void Try();
};
class LockSection{
CriticalSection* m_pCS;
ErrorHandler * m_pErrorHandler;
bool m_bIsClosed;
public:
LockSection(CriticalSection* pCS,ErrorHandler* pErrorHandler){
m_bIsClosed = false;
m_pCS = pCS;
m_pErrorHandler = pErrorHandler;
// 0x1AE is code prefix for critical section header
if(!m_pCS)m_pErrorHandler->Add(0x1AE1);
if(m_pCS)m_pCS->Enter();
}
~LockSection(){
if(!m_pCS)m_pErrorHandler->Add(0x1AE2);
if(m_pCS && m_bIsClosed == false)m_pCS->Leave();
}
void ForceCSectionClose(){
if(!m_pCS)m_pErrorHandler->Add(0x1AE3);
if(m_pCS){m_pCS->Leave();m_bIsClosed = true;}
}
};
/*
Safe class basic structure;
class SafeObj
{
CriticalSection m_cs;
public:
void SafeMethod()
{
LockSection myLock(&m_cs);
//add code to implement the method ...
}
};
*/
#endif
Two questions in one. I don't know about the first, but the critical section part is easy to explain. The background thread isn't trying to claim the lock and so, of course, is not blocked. You need to make the critical section object crt visible to the thread so that it can lock it.
The way to use this lock class is that each section of code that you want serialised must create a LockSection object and hold on to it until the end of the serialised block:
Thread 1:
{
LockSection lc(&crt,&err);
//operate on shared object from thread 1
}
Thread 2:
{
LockSection lc(&crt,&err);
//operate on shared object from thread 2
}
Note that it has to be the same critical section instance crt that is used in each block of code that is to be serialised.
This code has a number of problems.
First of all, deriving from the standard containers is almost always a poor idea. In this case you're using private inheritance, which reduces the problems, but doesn't eliminate them entirely. In any case, you don't seem to put the inheritance to much (any?) use anyway. Even though you've derived your MESSAGE_QUEUE from MESSAGE_LIST (which is actually std::vector<int>), you embed a pointer to an instance of a MESSAGE_LIST into MESSAGE_QUEUE anyway.
Second, if you're going to use a queue to communicate between threads (which I think is generally a good idea) you should make the locking inherent in the queue operations rather than requiring each thread to manage the locking correctly on its own.
Third, a vector isn't a particularly suitable data structure for representing a queue anyway, unless you're going to make it fixed size, and use it roughly like a ring buffer. That's not a bad idea either, but it's quite a bit different from what you've done. If you're going to make the size dynamic, you'd probably be better off starting with a deque instead.
Fourth, the magic numbers in your error handling (0x1AE1, 0x1AE2, etc.) is quite opaque. At the very least, you need to give these meaningful names. The one comment you have does not make the use anywhere close to clear.
Finally, if you're going to go to all the trouble of writing code for a thread-safe queue, you might as well make it generic so it can hold essentially any kind of data you want, instead of dedicating it to one specific type.
Ultimately, your code doesn't seem to save the client much work or trouble over using the Windows functions directly. For the most part, you've just provided the same capabilities under slightly different names.
IMO, a thread-safe queue should handle almost all the work internally, so that client code can use it about like it would any other queue.
// Warning: untested code.
// Assumes: `T::T(T const &) throw()`
//
template <class T>
class queue {
std::deque<T> data;
CRITICAL_SECTION cs;
HANDLE semaphore;
public:
queue() {
InitializeCriticalSection(&cs);
semaphore = CreateSemaphore(NULL, 0, 2048, NULL);
}
~queue() {
DeleteCriticalSection(&cs);
CloseHandle(semaphore);
}
void push(T const &item) {
EnterCriticalSection(&cs);
data.push_back(item);
LeaveCriticalSection(&cs);
ReleaseSemaphore(semaphore, 1, NULL);
}
T pop() {
WaitForSingleObject(semaphore, INFINITE);
EnterCriticalSection(&cs);
T item = data.front();
data.pop_front();
LeaveCriticalSection(&cs);
return item;
}
};
HANDLE done;
typedef queue<int> msgQ;
enum commands { quit, print };
void backgrounder(void *qq) {
// I haven't quite puzzled out what your background thread
// was supposed to do, so I've kept it really simple, executing only
// the two commands listed above.
msgQ *q = (msgQ *)qq;
int command;
while (quit != (command = q->pop()))
printf("Print\n");
SetEvent(done);
}
int main() {
msgQ q;
done = CreateEvent(NULL, false, false, NULL);
_beginthread(backgrounder, 0, (void*)&q);
for (int i=0; i<20; i++)
q.push(print);
q.push(quit);
WaitForSingleObject(done, INFINITE);
return 0;
}
Your background thread needs access to the same CriticalSection object and it needs to create LockSection objects to lock it -- the locking is collaborative.
You are trying to return the last element after popping it.

How to schedule member function for execution in boost::threadpoool

I found a threadpool which doesn't seem to be in boost yet, but I may be able to use it for now (unless there is a better solution).
I have several million small tasks that I want to execute concurrently and I wanted to use a threadpool to schedule the execution of the tasks. The documentation of the threadpool provides (roughly) this example:
#include "threadpool.hpp"
using namespace boost::threadpool;
// A short task
void task()
{
// do some work
}
void execute_with_threadpool(int poolSize, int numTasks)
{
// Create a thread pool.
pool tp(poolSize);
for(int i = 0; i++; i < numTasks)
{
// Add some tasks to the pool.
tp.schedule(&task);
}
// Leave this function and wait until all tasks are finished.
}
However, the example only allows me to schedule non-member functions (or tasks). Is there a way that I can schedule a member function for execution?
Update:
OK, supposedly the library allows you to schedule a Runnable for execution, but I can't figure out where is the Runnable class that I'm supposed to inherit from.
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj);
Update2:
I think I found out what I need to do: I have to make a runnable which will take any parameters that would be necessary (including a reference to the object that has a function which will be called), then I use the static schedule function to schedule the runnable on the given threadpool:
class Runnable
{
private:
MyClass* _target;
Data* _data;
public:
Runnable(MyClass* target, Data* data)
{
_target = target;
_data = data;
}
~Runnable(){}
void run()
{
_target->doWork(_data);
}
};
Here is how I schedule it within MyClass:
void MyClass::doWork(Data* data)
{
// do the work
}
void MyClass::produce()
{
boost::threadpool::schedule(myThreadPool, boost::shared_ptr<Runnable>(new Runnable(myTarget, new Data())));
}
However, the adaptor from the library has a bug in it:
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj)
{
return pool->schedule(bind(&Runnable::run, obj));
}
Note that it takes a reference to a Pool but it tries to call it as if it was a pointer to a Pool, so I had to fix that too (just changing the -> to a .).
To schedule any function or member function - use Boost.Bind or Boost.Lambda (in this order). Also you can consider special libraries for your situation. I can recommend Inter Threading Building Blocks or, in case you use VC2010 - Microsoft Parallel Patterns Library.
EDIT:
I've never used this library or heard anything bad about it, but it's old enough and still is not included into Boost. I would check why.
EDIT 2:
Another option - Boost.Asio. It's primarily a networking library, but it has a scheduler that you can use. I would use this multithreading approach. Just instead of using asynchronous network operations schedule your tasks by boost::asio::io_service::post().
I think I found out what I need to do: I have to make a runnable which will take any parameters that would be necessary (including a reference to the object that has a function which will be called), then I use the static schedule function to schedule the runnable on the given threadpool:
class Runnable
{
private:
MyClass* _target;
Data* _data;
public:
Runnable(MyClass* target, Data* data)
{
_target = target;
_data = data;
}
~Runnable(){}
void run()
{
_target->doWork(_data);
}
};
Here is how I schedule it within MyClass:
void MyClass::doWork(Data* data)
{
// do the work
}
void MyClass::produce()
{
boost::threadpool::schedule(myThreadPool, boost::shared_ptr<Runnable>(new Runnable(myTarget, new Data())));
}
However, the adaptor from the library has a bug in it:
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj)
{
return pool->schedule(bind(&Runnable::run, obj));
}
Note that it takes a reference to a Pool but it tries to call it as if it was a pointer to a Pool, so I had to fix that too (just changing the -> to a .).
However, as it turns out, I can't use that boost thread pool because I am mixing native C++ (dll), C++/CLI (dll) and .NET code: I have a C++/CLI library that wraps a native C++ library which in tern uses boost::thread. Unfortunately, that results in a BadImageFormatException at runtime (which has previously been discussed by other people):
The problem is that the static boost thread library tries to hook the
native win32 PE TLS callbacks in order to ensure that the thread-local
data used by boost thread is cleaned up correctly. This is not
compatible with a C++/CLI executable.
This solution is what I was able to implement using the information: http://think-async.com/Asio/Recipes. I tried implementing this recipe and found that the code worked in Windows but not in Linux. I was unable to figure out the problem but searching the internet found the key which was make the work object an auto pointer within the code block. I've include the void task() that the user wanted for my example I was able to create a convenience function and pass pointers into my function does the work. For my case, I create a thread pool that uses the function : boost::thread::hardware_concurrency() to get the possible number of threads. I've used the recipe below with as many as 80 tasks with 15 threads.
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/scoped_ptr.hpp>
// A short task
void task()
{
// do some work
}
void execute_with_threadpool( int numTasks,
int poolSize = boost::thread::hardware_concurrency() )
{
boost::asio::io_service io_service;
boost::thread_group threads;
{
boost::scoped_ptr< boost::asio::io_service::work > work( new boost::asio::io_service::work(io_service) );
for(int t = 0; t < poolSize; t++)
{
threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
}
for( size_t t = 0; t < numTasks; t++ )
{
++_number_of_jobs;
io_service.post(boost::bind(task) );
}
}
threads.join_all();
}
Figured it out, you must have run() method defined, this is the easiest way:
class Command
{
public:
Command() {}
~Command() {}
void run() {}
};
In main(), tp is your threadpool:
shared_ptr<Command> pc(new Command());
tp.schedule(bind(&Command::run, pc));
Done.