Monitor and ReaderWriterLockSlim aren't working - visual-studio

I tried to implement a typical threading application where one thread asks a device is data is available, copies the data to its own memory and sends an event to the main thread that the data is available. The main thread copies the data to its own memory and displays it on the GUI.
For this I used Visual Studio 2012 and C++/CLI with Winforms.
There is a class “Work” which holds the thread method “checkDataIsAvailable”. The “Work” class implements an interface (rather an abstract class) with a delegate “OnRetrievedData” which works as event and calls “BeginInvoke” in “Form1” to have an asynchronous behavior. And there is a method “getData” where the main thread can get the data from the “checkDataIsAvailable” thread. Furthermore the “Work” class tries to get the data from the class “ValueGenerator” which could represents any real device. I identifies a critical section for the “data” in the “Work” class called “array^ m_Data;”. The problem is that neither the “Monitor” nor the “ReaderWriterLockSlim” work approach is working.
With “Monitor” the GUI has a delayed responding and many updates are missing.
With “ReaderWriterLockSlim” the application crashes.
And without saving the critical section the application works. But I don’t know the reason because I’m sure that the data must be saved.
I would like to simplify the source code and emphasize the important things.
Most important is the thread method:
System::Void Work::checkDataIsAvailable()
{
while ( ( Thread::CurrentThread->ThreadState & Threading::ThreadState::Running) == Threading::ThreadState::Running )
{
m_WaitForDoCheckDataIsAvailableHandle->WaitOne();
//Monitor::Enter(m_LockData);
m_rwlock->EnterWriteLock();
m_Data = m_ValueGenerator->getData();
m_rwlock->ExitWriteLock();
//Monitor::Exit(m_LockData);
if ( nullptr != OnRetrievedData)
{
OnRetrievedData();
}
}
}
Here you see the copy process from the "ValueGenerator" to the variable m_Data. In my eyes this is a critical section. Then the event "OnRetrievedData" will be send that the data is available.
This event will get the Form1:
System::Void Form1::OnAcquisitionUpdate()
{
if(this->InvokeRequired == true)
{
OnAcquisitionUpdateDelegate^ onAcquisitionUpdateDelegate = gcnew OnAcquisitionUpdateDelegate(this, &Form1::OnAcquisitionUpdate);
this->BeginInvoke(onAcquisitionUpdateDelegate);
//this->Invoke(onAcquisitionUpdateDelegate);
}
else
{
if ( nullptr != m_Work )
{
//Thread::Sleep(5000);
array<System::Int32>^ data;
m_Work->getData(data);
dataResult_label->Text = data->Length.ToString();
}
}
}
"Form1::OnAcquisitionUpdate" changes it to the main thread via "BeginInvoke" and calls again the "Form1::OnAcquisitionUpdate" but now "InvokeRequired" is false so the "Work" class be called to get the data from the main thread.
System::Void Work::getData(array<System::Int32>^% data)
{
//Monitor::Enter(m_LockData);
m_rwlock->EnterReadLock();
Console::WriteLine(" getData() -> Data length = {0}", m_Data->Length);
data = m_Data;
m_rwlock->EnterReadLock();
//Monitor::Exit(m_LockData);
}
Here I see the next critical section where the data will be copied for the caller Form1.
It would be nice if anybody could help in this case.

I found a solution with a bool flag. Th flag is called "System::Boolean m_bCanWriteData;" and will be used in "Work::checkDataIsAvailable()" and "Work::getData(...)" in this way.
System::Void Work::checkDataIsAvailable()
{
while ( ( Thread::CurrentThread->ThreadState & Threading::ThreadState::Running) == Threading::ThreadState::Running )
{
m_WaitForDoCheckDataIsAvailableHandle->WaitOne();
#ifdef Use_Monitor
Monitor::Enter(m_LockData);
#endif
#ifdef Use_RW_Lock
m_rwlock->EnterWriteLock();
#endif
if ( m_bCanWriteData )
{
m_bCanWriteData = false;
m_Data = m_ValueGenerator->getData();
debugOutput("Work::checkDataIsAvailable() -> Data length = " + m_Data->Length);
if ( nullptr != OnRetrievedData)
{
OnRetrievedData();
}
}
#ifdef Use_RW_Lock
m_rwlock->ExitWriteLock();
#endif
#ifdef Use_Monitor
Monitor::Exit(m_LockData);
#endif
}
}
System::Void Work::getData(array<System::Int32>^% data)
{
debugOutput("Work::getData() START");
#ifdef Use_Monitor
Monitor::Enter(m_LockData);
debugOutput("Work::getData() + Monitor::Enter");
#endif
#ifdef Use_RW_Lock
m_rwlock->EnterReadLock();
#endif
m_WaitForDoCheckDataIsAvailableHandle->Reset(); // Block the thread method.
debugOutput("Work::getData() -> Data length = " + m_Data->Length);
data = m_Data;
m_bCanWriteData = true;
if ( m_bIsRunning )
{
m_WaitForDoCheckDataIsAvailableHandle->Set(); // Start the thread method.
}
#ifdef Use_RW_Lock
m_rwlock->EnterReadLock();
#endif
#ifdef Use_Monitor
Monitor::Exit(m_LockData);
#endif
debugOutput("Work::getData() END");
}
As you see the writting into and reading out is controlled and it works for the Monitor.

Related

Why does only some of my objects get created using std::async

I have a loop that pushes back calls of std::async that are used to create objects in the pointed function and emplace them back to another vector. All the calls are pushed to the futures function and the results are ready when i used the VS debugger. However of the 507 calls, only 30 objects are actually created and i cant seem to pin point why.I have tried setting the launch policy to both async and defered but get the same result.
void load_sec_p(vector<Security>* secs, map<string, map<string, vector<daySec>>> *psa_timeline,security sec) {
Security tmp = Security(psa_timeline, &sec.tsymb, &sec.gicsInd);
std::lock_guard<std::mutex> lock(s_SecsMutex);
secs->emplace_back(tmp);
}
Above is the function being executed in the async call
below is the loop that pushes back the futures
for (auto& sec : security_list) {
m_SecFutures.emplace_back(std::async(load_sec_p,&async_secs, &psa_timeline, sec));
}
The following pictures show the watch of both variables after the above loop is completed and the entire future vectors is checked for completion.
I have tried creating the objects by just using a regular for loop and appending them synchronously but it simply just takes too long(2 hours and 11 minutes long). If anyone has any advice on alternatives or how to fix my vector problem it would be greatly appreciated.
The code that checks if all the futures is shown below:
bool done = false;
cout << "Waiting...";
do {
done = futures_ready(m_SecFutures);
} while (!done);
The function is
template<class T>
bool futures_ready(std::vector<std::future<T>>& futures) {
std::chrono::milliseconds span(5);
bool finished = false;
int pends = 0;
while (!finished) {
//allowing thread to sleep so futures can process a bit more and also
//so thread doesnt reach max cpu usage
std::this_thread::sleep_for(std::chrono::milliseconds(100));
for (auto& x : futures) {
if (x.wait_for(span) == std::future_status::timeout) {
++pends;
}
}
if (pends == 0) {
finished = true;
}
else {
pends = 0;
}
}
return finished;
}

Crashes after parsing the equation

The application want to parse a string equation to mathematics and return the data to user. for this purpose the library is used is exprtk
for easy analysis I have shared minimum working code
minimum working code
when application parses the string to code back to back [multithreaded but locked]
void reset()
{
// Why? because msvc doesn't support swap properly.
//stack_ = std::stack<std::pair<char,std::size_t> >();
/**
it was crashing on destructor on ~deque()
stating memory reallocation
so I change it to pop so for now this has been resolved
*/
while(stack_.size()) stack_.pop();
state_ = true;
error_token_.clear();
}
now the code always crashes on
static inline void destroy(control_block*& cntrl_blck)
{
if (cntrl_blck)
{
/**now crashes on this condition check*/
if ( (0 != cntrl_blck->ref_count) && (0 == --cntrl_blck->ref_count) )
{
delete cntrl_blck;
}
cntrl_blck = 0;
}
}
UPDATE
pastebin code updated new code with main has been added with main and minimum working code.
all the shared_ptr has been removed. now they are normal objects.
as for exprtk reset function has been changed to original one
void reset()
{
// Why? because msvc doesn't support swap properly.
stack_ = std::stack<std::pair<char,std::size_t> >();
state_ = true;
error_token_.clear();
}
and backtrace of gdb has been added backtrace

Instant Veins 4.7-i1 Localization Time of Arrival

I am a masters student working on localization, using ranging (time of arrival between vehicle and RSU) and relative location (Using emulated Inertial Navigation System).
I have done an implementation of my kalman filter based localization logic on Matlab, now I would like to implement this on veins. I want only the RSU to send out a message comprising of its location and ID
1) I know that i can use
double Coord = mobility->getCurrentPosition().x;
double Coord = mobility->getCurrentPosition().y;
to the location of RSU(and my vehicle as well), I do not understand how I should assign these coordinates to the message. I cannot use sstream since I understand that the message are supposed to be of type const char *
Thanks for any input
Edit 1: So this is what my new code on RSU looks like:
#include "RsuScOne.h"
#include <sstream>
Define_Module(RsuScOne);
void RsuScOne::initialize(int stage) {
BaseWaveApplLayer::initialize(stage);
if (stage == 0) {
//Initializing members and pointers of your application goes here
//WaveShortMessage* wsm = new WaveShortMessage();
EV << "Initializing " << std::endl;
}
else if (stage == 1) {
//Initializing members that require initialized other modules goes here
}
}
void RsuScOne::finish() {
BaseWaveApplLayer::finish();
//statistics recording goes here
cancelEvent(sendWSAEvt);
}
void RsuScOne::onWSM(WaveShortMessage* wsm) {
//Your application has received a data message from another car or RSU
//code for handling the message goes here, see TraciDemo11p.cc for examples
populateWSM(wsm);
std::stringstream ss;
ss<<mobility->getCurrentPosition().x<<mobility->getCurrentPosition().y;
wsm->setWsmData(ss.str().c_str());
scheduleAt(simTime()+par("beaconInterval").doubleValue(), sendWSAEvt);
EV<<wsm;
}
void RsuScOne::handleSelfMsg(cMessage* msg) {
BaseWaveApplLayer::handleSelfMsg(msg);
}
But I realize that all that being done now is my RSU constantly sending a generic BSM, Why is this so?

Safari plugin crashes on NPN_GetValue

My plugin code crashes when I call the NPN_GetValue. Basically I created a scriptable object which has a 'getDevice' method that can return a device array to JavaScript. Below is the code snippet.
static bool mainNPObjectInvoke(NPObject *obj, NPIdentifier identifier, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
printf("create main object");
MainNPObject *mainObject = (MainNPObject *)obj;
if (identifier == methodIdentifiers[METHOD_ID_GET_DEVICES])
{
NPObject *windowObj = NULL;
browser->getvalue(mainObject->npp, NPNVWindowNPObject, &windowObj);
// it crashed here
....
}
}
I created the MainNPObject instance with below method.
NPObject *createMainNPObject(NPP npp)
{
MainNPObject *object = (MainNPObject *)browser->createobject(npp, &mainNPClass);
object->npp = npp;
theMainObject = object;
return (NPObject *)object;
}
The createMainNPObject is called in the plugin function I provided to browser.
NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{
PluginObject *obj = instance->pdata;
switch (variable) {
case NPPVpluginCoreAnimationLayer:
if (!obj->rootLayer)
setupLayerHierarchy(obj);
*(CALayer **)value = obj->rootLayer;
return NPERR_NO_ERROR;
case NPPVpluginScriptableNPObject:
if (!obj->mainObject)
{
obj->mainObject = createMainNPObject(instance);
}
....
}
And the allocate function is as below.
static NPObject *mainNPObjectAllocate(NPP npp, NPClass *class)
{
initializeIdentifiers();
MainNPObject *mainObject = malloc(sizeof(MainNPObject));
mainObject->deviceManager = [[DeviceManager alloc] init];
return (NPObject *)mainObject;
}
Definition of MainNPObject:
typedef struct
{
NPObject *npobject;
NPP npp;
DeviceManager *deviceManager;
} MainNPObject;
By debugging the code, I found that the system raised an EXC_BAD_ACCESS when calling the browser->getValue and it looks like the npp pointer is invalid.
0x00007fff83f82dab <+0019> je 0x7fff83f82db9 <_ZN6WebKit14NetscapePlugin7fromNPPEP4_NPP+33>
0x00007fff83f82dad <+0021> incl 0x8(%rax)
Can someone help me out?
Thanks!
Hmm; not seeing anything obvious. Try adding another parameter (an int?) to your structure and set it during allocate or immediately afterwords, then later on check to see if it's still the value you set before you call getvalue. See if your struct is somehow getting corrupt. That happened to me once when I was casting the NPObject funny in a non-obvious way.

Determining object types in Qt

I have a series of QTextEdits and QLineEdits connected to a slot through a QSignalMapper(which emits a textChanged(QWidget*) signal). When the connected slot is called (pasted below), I need to be able to differentiate between the two so I know whether to call the text() or toPlainText() function. What's the easiest way to determine the subclass type of a QWidget?
void MainWindow::changed(QWidget *sender)
{
QTextEdit *temp = qobject_cast<QTextEdit *>(sender);
QString currentText = temp->toPlainText(); // or temp->text() if its
// a QLineEdit...
if(currentText.compare(""))
{
...
}
else
{
...
}
}
I was considering using try-catch but Qt doesn't seem to have very extensive support for Exceptions... Any ideas?
Actually, your solution is already almost there. In fact, qobject_cast will return NULL if it can't perform the cast. So try it on one of the classes, if it's NULL, try it on the other:
QString text;
QTextEdit *textEdit = qobject_cast<QTextEdit*>(sender);
QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender);
if (textEdit) {
text = textEdit->toPlainText();
} else if (lineEdit) {
text = lineEdit->text();
} else {
// Return an error
}
You can also use sender->metaObject()->className() so you won't make unnecesary casts. Specially if you have a lot of classes to test. The code will be like this:
QString text;
QString senderClass = sender->metaObject()->className();
if (senderClass == "QTextEdit") {
QTextEdit *textEdit = qobject_cast<QTextEdit*>(sender);
text = textEdit->toPlainText();
} else if (senderClass == "QLineEdit") {
QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender);
text = lineEdit->text();
} else {
// Return an error
}
I know is an old question but I leave this answer just in case it would be useful for somebody...

Resources