Reputation: 5425
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);
Upvotes: 2
Views: 1483
Reputation: 3843
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.
Upvotes: 1
Reputation: 4626
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.
Upvotes: 1