How to call callback in member function thread? - c++

I'am writing small class for RS232 port. It can sync write and async read. So, for async read I'm using second thread, that waiting input data. When data received, I want to call user callback (that I get as constructor argument) with input data. It's look like:
typedef int (*ReceivedCallback)(string data);
class RS232
{
RS232(string portName, ReceivedCallback dataReceived);
~RS232();
private:
ReceivedCallback dataReceivedCallback;
private:
static unsigned ReaderThread(void* data);
public:
SendData(string data);
}
My problem is: ReaderThread MUST be static to pass pointer to it to _beginthreadex() function. And in ReaderThread I want to call "dataReceivedCallback", obtained from the user in constructor. But I can't, cause I can't call non-static functions in static ReaderThread. Also, I can't make "dataReceivedCallback" static, cause I may have many instances of my class (for COM1, COM2, COM3) and every instance should have it's own callback, obtained by user.
Where is my architecture mistake? How would you implement it?
Thanks in advance!
P.S. Using Visual Studio 2005.

You need to pass a pointer to the instance of RS232 to ReaderThread, which will, in turn, either pass that pointer to a static callback, or directly call non-static methods on the RS232 object.
I would also use [CreateThread][1] rather than beginthreadex. My code samples will use CreateThread, but you can adapt the technique to beginthreadex if you so desire.
Simply, when kicking off the ReaderThread, pass it a pointer to the instance:
RS232* myObj = new RS232;
CreateThread (..., myObj);
...use reinterpret_cast to cast it back:
unsigned RS232::ReaderThread (void* data)
{
RS232* that = reinterpret_cast <RS232*> (data);
}
Change your callback function so that it can pass the instance as well:
typedef int (*ReceivedCallback)(string data, RS232* that);
And now in the callback you can call member functions:
that->DoSomethingCool (data);

You will need to pass an extra argument to the thread function (which you already have a void *data available for).
Now, add this as a private element in your class RS232:
class RS232
{
RS232(string portName, ReceivedCallback dataReceived);
~RS232();
private:
ReceivedCallback dataReceivedCallback;
private:
static unsigned ReaderThread(void* data);
public:
SendData(string data);
}
and in the constructor:
RS232::RS232(string portName, ReceivedCallback dataReceived)
{
... various stuff to initialize the serial port ...
_beginthreadex(securityarg, stacksize, ReaderThread, this, ...)
}
And in the ReaderThread function:
unsigned RS232::ReaderThread(void *data)
{
RS232 *self = static_cast<RS232*>(data);
.... stuff to read from serial port ...
... Now call the callback:
self->dataReceivedCallback(str);
....
}

To access the non-static object data in the static thread function you could use this extremely hacky and untested solution. But be warned --- it is for educational purposes only because it is extremely hacky. You should learn about locks and mutexes and probably boost threads. Note, this is a pthread style solution. I've no experience with the function _beginthreadex() but you can see that createThread does the job of creating your thread. Adapt as needed.
typedef int (*ReceivedCallback)(string data);
class RS232
{
public:
RS232(string portName, ReceivedCallback dataReceived);
~RS232();
SendData(string data);
createThread();
private:
ReceivedCallback dataReceivedCallback;
static unsigned ReaderThread(void* data);
thread m_someThread;
struct accessHelper
{
RS232* This;
void *actual_arg;
accessHelper(RS232 *t, void *p)
: This(t),
actual_arg(p)
{}
};
};
RS232::createThreaad()
{
int someData;
accessHelper ah(this, someData);
m_someThread.create(RS232::ReaderThread, &ah);
}
RS232::ReaderThread(void *data)
{
accessHelper *ah = static_cast<accessHelper*>(data);
RS232 *This = ah->This;
This->dataReceivedCallback......
}

Related

std::thread helper class to add thread name and stack size

I would like to make a helper class (or subclass of std::thread) to allow stack size to be set and also thread name.
If the thread is running on a platform, which does not support e.g. stack size, the number should just be ignored.
I was thinking of a "ThreadHelper", which has the extended constructor interface, and just returns a std::thread.
To be honest, I have very little experience when it comes to all the template stuff, which std::thread contains.
Right now the thread class is instantiated like:
m_thread = new std::thread(&Button::Process, this);
I would like something like:
m_thread = new ThreadHelper.Create(&Button::Process, this, stackSize, name);
Any advices are appreciated.
Thanks
Martin
Here is what you could do:
You need a wrapper around your thread start function so that you can call the appropriate functions before (and possibly after) your thread function is running. It might also be a good idea to include a try-catch block and do some error processing.
template <typename ThreadStartFnc>
struct ThreadWrapper
{
ThreadStartFnc fnc;
const char *name; // (1) Note: careful, just a pointer here, not a string. See below.
size_t priority;
size_t stack_size;
ThreadWrapper(...) // constructor here...
void operator()()
{
SetThreadName(name); // Whatever that is on your system
SetThreadPriority(priority); // dito
SetStackSize(stack_size); // not all systems allow this
try {
fnc();
}
catch(...) {
cerr << "Exception caught"; // Do exception processing here.
}
}
};
And you need a simple way to instantiate an std::thread with the wrapper "inserted", like this:
template <typename Fnc>
std::thread make_thread(const Fnc& f, const char *name, size_t priority=0, size_t stack_size=0)
{
return std::thread(ThreadWrapper<Fnc>(f, name, priority, stack_size));
}
And that is basically it. std::thread accepts a Functor object, which is what ThreadWrapper is. It calls Functor() to start the thread, which is void operator()(). This function uses the additional parameters name, priority, stack_size to set everything up and then call your function.
Enhance this with the C++11/14/17 goodies like variadic template parameters and/or lambda functions as you like.
Below is the actual wrapper function that we use (although we do not use a Functor, we use boost::bind and a static template function instead).
template <typename Fnc>
static inline void run_cstr(const Fnc &f, const char *name, DWORD priority)
{
int rc=_configthreadlocale(0);
/*
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
setlocale(LC_ALL, "C");
*/
SetThreadName(name);
watchdog::set_thread_info(name);
::SetThreadPriority(::GetCurrentThread(), priority);
_set_se_translator(&_se_translator);
_set_invalid_parameter_handler(&my_invalid_parameter_handler);
__try {
f();
}
__except (global_seh_handler(GetExceptionCode(), GetExceptionInformation()) ) {
}
}
It sets the ThreadName for Visual Studio (SetThreadName), sets the locale, sets the thread priority, connects our software watchdog to the thread and also sets up a global Windows try/catch handler for all exceptions including access violations etc....
The global_seh_handler will be executed if any uncaught exceptions (including invalid std lib parameters) end up here. It will write a crash dump file which we use for post mortem debugging.
(1) Note: I've used a const char *name for the thread name, because I am assuming that the thread will run immediately, while the string for the thread name is still available. That is actually unsafe, if you are storing objects of type ThreadWrapper for a longer period. You'd need to change const char* to std::string then.

How to deal with multiple parameters of different types in C++98?

In order to implement a thread class(In C++98 and Windows.h). I have something like this:
Thread::Thread(_beginthreadex_proc_type fn)
{
m_raw = fn;
m_args = 0;
m_handle = 0;
m_id = 0;
}
The code above works fine it takes a function that not receive parameters, and with the next code it function is called by a new thread:
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, m_raw, (m_args ? m_args : 0), 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
This code also works fine with functions that don't take any parameter.
Now my question is about how can i in C++98 receive variadic parameters in my constructor and save them.
And NO i can't use modern c++ if that was the case I din't need help. So plz don't give me solutions implemented with c++11 or higher.
Update
Now I'm trying a Java style solution in that every Thread is a IRunnable that have a pure virtual function named Run. And thread is almost the that this implementetation with the diff that is an abstract class. In this way can i avoid parameters because I don't pass the function instead of that I write another class that inherits from Thread and implements Run.
The code look like:
The interface
struct IRunnable
{
virtual void Run() = 0;
};
Thread class
class Thread : public IRunnable
{
HANDLE m_handle;
DWORD m_id;
typedef unsigned (__stdcall *Function)(void*);
_beginthreadex_proc_type m_raw;
void* m_args;
public:
Thread();
~Thread();
Thread(_beginthreadex_proc_type, void*);
Thread(_beginthreadex_proc_type);
unsigned GetId();
virtual void Run() = 0;
void Join();
unsigned int __stdcall call(void*);
};
Call only is a wrapper to call Run function member
unsigned int __stdcall Thread::call(void* data)
{
Run();
return 0;
}
My problem is here:
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, &this->call, 0, 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
When i compiling in vs2019 the code above produce the next error:
error C2276: '&': illegal operation on bound member function expression
error C2660: '_beginthreadex': function does not take 5 arguments
For your edited question, the reason you're getting a compile error is because you're trying to send the address to a member function of your Thread object. You can't take pointers to member functions and use them without also keeping the object pointer around. Instead, you should make a global function that takes a Thread* as its argument, send a pointer to that function, and let it call your runnable.
unsigned thread_entry(void* thread_ptr)
{
Thread* thread = (Thread*) thread_ptr;
return thread->call();
}
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, thread_entry, this, 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
P.S. It's usually best to ask new questions instead of editing old ones if the question is significantly different, which yours is.
If you look at pretty much any thread library, they very rarely support sending multiple arguments; you usually send a pointer to something, and if you want many things, you make a struct containing many things and send a pointer to it.
However, if you really want this, you could use the C varargs functions to iterate over all variadic arguments, and allocate a linked list with them, or allocate an array of them, or whatever other data structure you want. Then, send a pointer to that to your thread entry function. Your function would still be taking just one pointer, though.
In C, there is no easy way to construct a va_list, which is how variadic arguments are sent around. You can't just send the va_list you have on your main thread, because that memory won't be alive by the time it reaches your new thread. There is also no good way to expand a va_list to fill function arguments.
Btw, I realize you're using C++, but as far as C++98 goes, its varargs support is basically the same as in C, which is why I'm mentioning C in my answer.

Two pcap_compile() on one device at same time?

I have two threads and each one has packet capture from the same deviсe at the same time but the program crashes when the second thread reaches the pcap_compile() function. Also each thread has their own variables and don't use global. It seems that they get the same handle of the device, therefore the program crashes. Why do I need two threads? Because I want to seperate packets on the sent and on the recived by specified pcap filter. So how do I solve this? Or is it better to use one thread and sort manually the sent and the received packets by using the address from tcp header?
pcap_compile is not thread safe. You must surround all calls to it that may be encountered by separate threads with a critical section/mutex to prevent errors because of non thread-safe state within the parser that compiles the expression (for the gory details, it uses YACC to create code for parsing the expression and the code generated for that is eminently not thread safe).
You need to explicitly open the device once per thread that you're planning on using for the capture, if you reuse the same device handle across multiple threads then it will simply not do what you're asking for. You should open the pcap handle within the thread that you're planning on using it, so each thread that's planning on doing capture should do it's own pcap_open.
to guard the call to pcap_compile with a Critical Section, you could create a simple wrapper (C++ wrapper of windows critical section):
class lock_interface {
public:
virtual void lock() = 0;
virtual void unlock() = 0;
};
class cs : public lock_interface {
CRITICAL_SECTION crit;
public:
cs() { InitializeCriticalSection(&crit); }
~cs() { DeleteCriticalSection(&crit); }
virtual void lock() {
EnterCriticalSection(&crit);
}
virtual void unlock() {
LeaveCriticalSection(&crit);
}
private:
cs(const locker &);
cs &operator=(const cs &);
};
class locker {
lock_interface &m_ref;
public:
locker(lock_interface &ref) : m_ref(ref) { m_ref.lock(); }
~locker() { m_ref.unlock(); }
private:
locker(const locker &);
locker &operator=(const locker &);
};
static cs section;
int
wrapped_pcap_compile(pcap_t *p, struct bpf_program *fp, const char *str, int optimize, bpf_u_int32 netmask)
{
locker locked(section);
pcap_compile(p, fp, str, optimize, netmask);
}
If you are using C++11, you can have something like:
int thread_safe_pcap_compile_nopcap(int snap_len, int link_type,
struct bpf_program *fp, char const *str,
int optimize, bpf_u_int32 netmask) {
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
return pcap_compile_nopcap(snap_len, link_type, fp, str, optimize, netmask);
}
It is similar for pcap_compile function.

Static Callbacks in Abstract Base class C++

I’ve got an OOP / design problem that I have run into and am desperately hoping that someone can steer me in a direction that doesn’t require a complete re-write.
The system is essential a Windows Service that have ~9 secondary threads that are responsible for specific tasks. All the threads share some common functionality (for example, the ability to send and receive messages internally etc). Because of this, I defined an abstract base class from which all the threads inherit from.
However, four of the threads also make use of an Inter-Process communication system based on a 3rd-party IPC system (madshi’s CreateIpcQueue ). To save replicating all the same code in these four threads, I defined an additional class to support this:
TThread <-TBaseThread<-TIPCBaseThread<- Four IPC threads
^- All other threads.
The mechanics of the IPC system is that you define a Callback function and then call the CreateIpcQueue passing it this Callback. In my TIPCBaseThread I loosely did something like this:
// TIPCBaseThread.h
class TIPCBaseThread : public TBaseThread
{
private:
static TIPCBaseThrd *pThis;
// defines the callback to use with the IPC queue
static void CALLBACK IPCQueue(char *cName, void *pMsgBuf, unsigned int iMsgLen,
void *pRtnBuf, unsigned int iRtnLen);
protected:
// virtual method, to be defined in derived classes, to handle IPC message
virtual void ProcessIPCMsg(char *cName, void *pMsgBuf, unsigned int iMsgLen, void *pRtnBuf,
unsigned int iRtnLen) = 0;
public:
CRITICAL_SECTION csIPCCritSect;
…
// TIPCBaseThread.cpp
TIPCBaseThrd* TIPCBaseThrd::pThis = 0;
__fastcall TIPCBaseThread::TIPCBaseThread(…) : TBaseThread(…)
{
pThis = this;
InitializeCriticalSectionAndSpinCount(&csIPCCritSect, 1000);
CreateIpcQueueEx(“SomeQueueName”, IPCQueue, 1, 0x1000);
//^Callback Queue
…
}
void CALLBACK TIPCBaseThread::IPCQueue(char *cName, void *pMsgBuf, unsigned int iMsgLen,
void *pRtnBuf, unsigned int iRtnLen)
{
EnterCriticalSection(&pThis->csIPCCritSect);
pThis->ProcessIPCMsg(cName, pMsgBuf, iMsgLen, pRtnBuf, iRtnLen);
LeaveCriticalSection(&pThis->csIPCCritSect);
}
My general thinking was that the TIPCBaseThread would effectively take care of creating and managing the IPC channel and then call the ProcessIPCMsg() in the various derived classes.
Now, when I test the system and send a message to any of the IPC channels, the message is received in the TIPCBaseThread callback but is passed up to the last derived class (to be created), not the class that should receive it. I’m assuming it is something to do with the
[static TIPCBaseThrd *pThis]
property being overwritten when each derived class is instantiated (but I confess I’m not 100% sure)?
Could anyone steer me in the right direction here? Obviously I would like to know exactly what is causing the problem but ideally I would like to know if there is a work around that would avoid having to completely re-write the whole object inheritance – there is obviously a bit more going on under the hood than I have shown and I’m going to have serious problems if I have to abandon this design completely.
Many thanks in advance,
Mike Collins
I think you should change the callback to take the instance as an argument
static void CALLBACK IPCQueue(TIPCBaseThread *instance,
char *cName, void *pMsgBuf, unsigned int iMsgLen,
void *pRtnBuf, unsigned int iRtnLen);
...
void CALLBACK TIPCBaseThread::IPCQueue(char *cName, void *pMsgBuf, unsigned int iMsgLen,
void *pRtnBuf, unsigned int iRtnLen)
{
...
instance->ProcessIPCMsg(cName, pMsgBuf, iMsgLen, pRtnBuf, iRtnLen);
...
}
There is one very strange thing: pThis = this; with static TIPCBaseThrd *pThis;
It means that at any point in time only the latest instance of TIPCBaseThrd is accessible via pThis (all previous instances having been overwritten); and of course there is the issue that this global value is not protected by any kind of synchronisation (mutex, atomics, ...)
It's unfortunate, but this static TIPCBaseThrd *pThis; is just an horrible idea that cannot possibly work.

Cannot lock Qt mutex (QReadWriteLock) Access violation writing

Some background for this question is my previous question:
non-member function pointer as a callback in API to member function (it may well be irrelevant).
The callback launches a thread that writes some data. There is another thread that reads the same data, and that results in some crashes.
I just took a crash course in multi-threading (thanks SO), and here is my attempt to guarantee that the data isn't accessed by the writer and the reader at the same time. I'm using some mutex mechanism from Qt (QReadWriteLock).
#include <QSharedPointer>
#include <QReadWriteLock>
Class MyClass
{
public:
MyClass();
bool open();
float getData();
void streamCB(void* userdata);
protected:
float private_data_;
QSharedPointer<QReadWriteLock> lock_;
};
// callback wrapper from non-member C API to member function void
__stdcall streamCBWrapper(void* userdata)
{
static_cast<MyClass*>(userdata)->streamCB(userdata);
}
// constructor
MyClass::MyClass()
{
lock_ = QSharedPointer<QReadWriteLock>(new QReadWriteLock());
lock_->lockForWrite();
private_data_ = getData();
lock_->unlock();
}
// member callback
void MyClass:streamCB(void* userdata)
{
float a = getData();
lock_->lockForWrite(); //*** fails here
private_data_ = a;
lock_->unlock();
}
I have a segmentation fault while running the program. The VS debugger says Access violation writing location 0x00fedbed. on the line that I marked //*** fails here.
The lock worked in the constructor, but not in the callback.
Any idea what goes wrong? What should I look at? (and how can I refine my question)
Thanks!
Other relevant thread
Cannot access private member declared in class 'QReadWriteLock'Error 1 error C2248: 'QReadWriteLock::QReadWriteLock' (I used the QSharedPointer suggestion)
Edit 1:
The callback is set up
bool MyClass::open()
{
// stuffs
int mid = 0;
set_stream_callback(&streamCBWrapper, &mid);
// more stuffs
return true;
}
Edit 2:
Thank you for all the suggestions.
So my mistake(s) may not be due at all to the mutex, but to my lack of understanding of the API? I'm quite confused.. Here is the API doc for the set_stream_callback.
typedef void (__stdcall *STREAM_CALLBACK)(void *userdata);
/*! #brief Register a callback to be invoked when all subscribed fields have been updated
*
* #param streamCB pointer to callback function
* #param userdata pointer to private data to be passed back as argument to callback
* #return 0 if successful, error code otherwise
*/
__declspec(dllimport) int __stdcall set_stream_callback(
STREAM_CALLBACK streamCB, void *userdata);
Good example why sufficient code example is required.
If I interpret your callback syntax correctly,
set_stream_callback(&streamCBWrapper, &mid);
sets streamCBWrapper as callback function, while &mid is the pointer to userdata.
In the callback, you are actually now casting a pointer to int to MyClass, then try to access a member variable of a non-existant object.
Make sure to pass an instance of MyClass to your callback. I assume this would be this in your case.
Sounds fundamentally like a threading issue to me. Since you're using the Qt mutexing anyway, you might consider using Qt's threading mechanisms and sending signals and slots between the threads. They're pretty well documented and easy to use as long as you follow the suggestions here and here.