#include <iostream>
#include <mutex>
using namespace std;
class A;
class B {
public:
B(A *_parent = nullptr) {
parent = _parent;
}
A *parent;
};
class A {
public:
std::mutex m;
B *b;
A() {
b = new B(this);
}
};
int main() {
A a_obj;
B *b = new B(&a_obj);
//b->parent->m.lock();
return 0;
}
I believe the composed objects above function as expected and I've been using a similar design (my A creates B's and adds them to a data structure. The B's are constructed with references to their parent.)
When I tried to add threadsafe message-passing between A's and B's, the program crashed whenever a B tried to use a threadsafe container in A.
The code above recreates the problem. Why can B not acquire A's mutex?
Related
Am trying to pass data structure to QT thread and but no success.
here is what am doing and have done.
i prepare data for the thread, like this and then tried to pass prepared data to thread before starting.
void mytable::prepare_data(){
// get table row count
int rowCount = ui->my_table_view->rowCount();
// create structure array based on rowCount
pnp_com_info pnp_data[rowCount];
/* pnp_com_info structure defined it top of file below includes to make it global
struct pnp_com_info{
QString com_name = "";
int x = 0;
int y = 0;
int angle = 0;
bool status = false;
};
*/
// loop on table rows columns and load pnp_data with data of columns
// PROBLEM : how to pass pnp_data structure to thread side ?
// can pass basic vars like
RunJobThread->mynum = 10;
// start QT thread
RunJobThread->start();
// std:: thread experiment
// std::stdthreadtest(pnp_data,rowCount);
}
run_job_thread.h source code
#ifndef RUN_JOB_THREAD_H
#define RUN_JOB_THREAD_H
#include <QObject>
#include <QThread>
class run_job_thread : public QThread
{
Q_OBJECT
public:
run_job_thread();
void run();
int mynum;
struct pnp_com_info_thread{
QString com_name = "";
int x = 0;
int y = 0;
int angle = 0;
bool status = false;
};
bool Stop; // bool to stop the job
signals:
void select_row_of_table_signal(int);
public slots:
};
#endif // RUN_JOB_THREAD_H
run_job_thread.cpp source code
#include "run_job_thread.h"
#include <QtCore>
run_job_thread::run_job_thread()
{
}
// run the thread
void run_job_thread::run(){
qDebug() << "my num passed value is : "<<this->mynum; // output : 10
// Goal : loop on pnp_data structure and emit signal to table rows
emit select_row_of_table_signal(5);
}
things i tried
instead of struct i tried to use other data containers like map, multimap, vectors but they give error , as am initializing pnp_com_info struct inside mytable::prepare_data() function based on rowCount which make it local and limited to prepare_data() function but with map,multimap,vector my plan was that they will be global and i will be able to access it from thread, however it not worked.
std::map<std::string, int,int,int> pnp_com_info; // error: too many template arguments for class template 'map'
std::multimap<std::string, int,int,int,bool> pnp_com_info; // error: too many template arguments for class template 'multimap'
std::vector<std::string, int,int,int,bool> pnp_com_info; // error: too many template arguments for class template 'vector'
i also tried std::thread which was partial success , i mean it was working ok but looks like std::thread not works with QT GUI thread as upon running app GUI will go freez although std::thread was doing its job
I would suggest to do the following, because the declaration of the
pnp_com_info pnp_data[rowCount];
is inside a context i think their lifecycle will be lost once you leave it, other problem is that it would be really "unsafe" to create this kind of arrays and then pass it from one side to another. Therefore I would create a QList and then pass either a copy or the reference to the worker thread. So
1) Create a QList pnp_data, in the public part of mytable
2) Fill all data using a for loop as follows.
3) Create another QList pnp_data or a QList *pnp_data (if you want to use a copy or a pointer)
4) Then just pass either a copy or a reference to the worker thread.
Then it should look like this:
mytable.h source code
public: QList<pnp_com_info> pnp_data;
mytable.cpp source code
void mytable::prepare_data(){
// get table row count
int rowCount = ui->my_table_view->rowCount();
// HERE YOU LOAD ALL THE VALUES TO THE LIST
for(int i = 0; i<rowCount; i++){
pnp_com_info itemToInsert;
//FILL HERE THE itemToInsert
//Insert the item inside the list.
pnp_data.append(itemToInsert);
}
// PROBLEM : how to pass pnp_data structure to thread side ?
// Either pass it as a copy
RunJobThread->pnp_data = pnp_data;
//or as a reference
QList<pnp_com_info> *pnpDataPointer = &pnp_data;
RunJobThread->pnp_data_reference = pnpDataPointer;
// start QT thread
RunJobThread->start();
// std:: thread experiment
// std::stdthreadtest(pnp_data,rowCount);
}
run_job_thread.h source code
#ifndef RUN_JOB_THREAD_H
#define RUN_JOB_THREAD_H
#include <QObject>
#include <QThread>
class run_job_thread : public QThread
{
Q_OBJECT
public:
run_job_thread();
void run();
struct pnp_com_info_thread{
QString com_name = "";
int x = 0;
int y = 0;
int angle = 0;
bool status = false;
};
QList<pnp_com_info> pnp_data; //This one if you create a copy
QList<pnp_com_info> *pnp_data_reference; //This if you want a pointer
bool Stop; // bool to stop the job
signals:
void select_row_of_table_signal(int);
public slots:
};
#endif // RUN_JOB_THREAD_H
I hope this helps.
First, don't subclass QThread to create a worker - re-read How To Really, Truly Use QThreads; The Full Explanation by Maya Posch. You will find it much more manageable to create a worker object and connect the threads started() to your worker's main method, and the worker's signals to the thread's quit() and deleteLater().
Then, it should be much more straightforward to pass your data to the worker before it's moved to the thread, or to use a signal connection if it needs to be passed when the worker is running (remember to register your structure with the meta-object system for that).
I am writing a base class to manage threads. The idea is to allow the thread function to be overridden in child class while the base class manages thread life cycle. I ran into a strange behavior which I don't understand - it seems that the virtual function mechanism does not work when the call is made from a thread. To illustrate my problem, I reduced my code to the following:
#include <iostream>
#include <thread>
using namespace std;
struct B
{
thread t;
void thread_func_non_virt()
{
thread_func();
}
virtual void thread_func()
{
cout << "B::thread_func\n";
}
B(): t(thread(&B::thread_func_non_virt, this)) { }
void join() { t.join(); }
};
struct C : B
{
virtual void thread_func() override
{
cout << "C::thread_func\n";
}
};
int main()
{
C c; // output is "B::thread_func" but "C::thread_func" is expected
c.join();
c.thread_func_non_virt(); // output "C::thread_func" as expected
}
I tried with both Visual studio 2017 and g++ 5.4 (Ubuntu 16) and found the behavior is consistent. Can someone point out where I got wrong?
== UPDATE ==
Based on Igor's answer, I moved the thread creation out of the constructor into a separate method and calling that method after the constructor and got the desired behavior.
Your program exhibits undefined behavior. There's a race on *this between thread_func and C's (implicitly defined) constructor.
#include <iostream>
#include <thread>
using namespace std;
struct B
{
thread t;
void thread_func_non_virt()
{
thread_func();
}
virtual void thread_func()
{
cout << "B::thread_func\n";
}
B(B*ptr): t(thread(&B::thread_func_non_virt, ptr))
{
}
void join() { t.join(); }
};
struct C:public B
{
C():B(this){}
virtual void thread_func() override
{
cout << "C::thread_func\n";
}
};
int main()
{
C c; // "C::thread_func" is expected as expected
c.join();
c.thread_func_non_virt(); // output "C::thread_func" as expected
}
I am using Rcpp to create a package in R that leverages C++ code. I have read all of the Rcpp vignettes, but I haven't been able to find a solution to the following problem.
One of the C++ classes I'm trying to use contains a pointer. I am exposing the class using a module. When I try to install the package in R, I get the following error.
error: expected unqualified-id before '*' token.field("*w", &ffm_model::*w)
What am I doing wrong?
Code for Class Containing Pointer
typedef float ffm_float;
typedef int ffm_int;
class ffm_model {
public:
ffm_int n; // number of features
ffm_int m; // number of fields
ffm_int k; // number of latent factors
ffm_float *w = nullptr;
bool normalization;
~ffm_model();
};
Code for Corresponding RCPP Module
RCPP_MODULE(ffmModelMod){
using namespace Rcpp;
//Expose class as ffm_model on the r side
class_<ffm_model>( "ffm_model")
.field("n", &ffm_model::n)
.field("m", &ffm_model::m)
.field("k", &ffm_model::k)
.field("*w", &ffm_model::*w)
.field("normalization", &ffm_model::normalization)
.method("~ffm_model",&ffm_model::~ffm_model)
;
}
I had a similar problem, and as Dirk mentions, it is due to types that cannot be mapped automatically, such as float*.
The following workaround works for me:
Do not expose the fields with problematic types to R.
Instead, expose get() and set() functions to the fields above.
Here is an example, in which both the (unproblematic) value field and the (problematic) child field (a pointer to an object of the same class) are hidden:
Class
#include <Rcpp.h>
using namespace Rcpp;
class node
{
public:
double value; // Voluntarily hidden from R
node* child; // Must be hidden from R
// Exposed functions
void setVal(double value);
double getVal();
node* createNode(double value); // return pointer to a node
node* createChild(double value); // set child
node* getChild();
};
Methods
void node::setVal(double value){
this->value = value;
}
double node::getVal(){
return this->value;
}
node* node::createNode(double value){
node* n = new node;
n->value = value;
return n;
}
node* node::createChild(double value){
this->child = createNode(value);
return child;
}
node* node::getChild(){
return this->child;
}
RCPP Module
RCPP_MODULE(gbtree_module){
using namespace Rcpp;
class_<node>("node")
.constructor()
.method("setVal", &node::setVal)
.method("getVal", &node::getVal)
.method("createNode", &node::createNode)
.method("createChild", &node::createChild)
.method("getChild", &node::getChild)
;
}
Usage in R
n <- new(node)
n$setVal(2)
n$getVal()
n2 <- n$createNode(1) # unrelated node
n3 <- n$createChild(3) #child node
n$getChild() #pointer to child node
n3
In a single thread, I have this beautiful class that redirects all cout output to a QTextEdit
#include <iostream>
#include <streambuf>
#include <string>
#include <QScrollBar>
#include "QTextEdit"
#include "QDateTime"
class ThreadLogStream : public std::basic_streambuf<char>, QObject
{
Q_OBJECT
public:
ThreadLogStream(std::ostream &stream) : m_stream(stream)
{
m_old_buf = stream.rdbuf();
stream.rdbuf(this);
}
~ThreadLogStream()
{
// output anything that is left
if (!m_string.empty())
{
log_window->append(m_string.c_str());
}
m_stream.rdbuf(m_old_buf);
}
protected:
virtual int_type overflow(int_type v)
{
if (v == '\n')
{
log_window->append(m_string.c_str());
m_string.erase(m_string.begin(), m_string.end());
}
else
m_string += v;
return v;
}
virtual std::streamsize xsputn(const char *p, std::streamsize n)
{
m_string.append(p, p + n);
long pos = 0;
while (pos != static_cast<long>(std::string::npos))
{
pos = m_string.find('\n');
if (pos != static_cast<long>(std::string::npos))
{
std::string tmp(m_string.begin(), m_string.begin() + pos);
log_window->append(tmp.c_str());
m_string.erase(m_string.begin(), m_string.begin() + pos + 1);
}
}
return n;
}
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
std::string m_string;
QTextEdit* log_window;
};
However, this doesn't work if ANY thread (QThread) is initiated with a cout. This is because all pointers are messed up, and one has to use signals and slots for allowing transfer of data between the sub-thread and the main thread.
I would like to modify this class to emit a signal rather than write to a text file. This requires that this class becomes a Q_OBJECT and be inherited from one. I tried to inherit from QObject in addition to std::basic_streambuf<char> and added Q_OBJECT macro in the body but it didn't compile.
Could you please help me to achieve this? What should I do to get this class to emit signals that I can connect to and that are thread safe?
For those who need the full "working" answer, here it's. I just copied it because #GraemeRock asked for it.
#ifndef ThreadLogStream_H
#define ThreadLogStream_H
#include <iostream>
#include <streambuf>
#include <string>
#include <QScrollBar>
#include "QTextEdit"
#include "QDateTime"
class ThreadLogStream : public QObject, public std::basic_streambuf<char>
{
Q_OBJECT
public:
ThreadLogStream(std::ostream &stream) : m_stream(stream)
{
m_old_buf = stream.rdbuf();
stream.rdbuf(this);
}
~ThreadLogStream()
{
// output anything that is left
if (!m_string.empty())
{
emit sendLogString(QString::fromStdString(m_string));
}
m_stream.rdbuf(m_old_buf);
}
protected:
virtual int_type overflow(int_type v)
{
if (v == '\n')
{
emit sendLogString(QString::fromStdString(m_string));
m_string.erase(m_string.begin(), m_string.end());
}
else
m_string += v;
return v;
}
virtual std::streamsize xsputn(const char *p, std::streamsize n)
{
m_string.append(p, p + n);
long pos = 0;
while (pos != static_cast<long>(std::string::npos))
{
pos = static_cast<long>(m_string.find('\n'));
if (pos != static_cast<long>(std::string::npos))
{
std::string tmp(m_string.begin(), m_string.begin() + pos);
emit sendLogString(QString::fromStdString(tmp));
m_string.erase(m_string.begin(), m_string.begin() + pos + 1);
}
}
return n;
}
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
std::string m_string;
signals:
void sendLogString(const QString& str);
};
#endif // ThreadLogStream_H
The derivation needs to happen QObject-first:
class LogStream : public QObject, std::basic_streambuf<char> {
Q_OBJECT
...
};
...
If the goal was to minimally modify your code, there's a simpler way. You don't need to inherit QObject to emit signals iff you know exactly what slots the signals are going to. All you need to do is to invoke the slot in a thread safe way:
QMetaObject::invokeMethod(log_window, "append", Qt::QueuedConnection,
Q_ARG(QString, tmp.c_str()));
To speed things up, you can cache the method so that it doesn't have to be looked up every time:
class LogStream ... {
QPointer<QTextEdit> m_logWindow;
QMetaMethod m_append;
LogStream::LogStream(...) :
m_logWindow(...),
m_append(m_logWindow->metaObject()->method(
m_logWindow->metaObject()->indexOfSlot("append(QString)") )) {
...
}
};
You can then invoke it more efficiently:
m_append.invoke(m_logWindow, Qt::QueuedConnection, Q_ARG(QString, tmp.c_str()));
Finally, whenever you're holding pointers to objects whose lifetimes are not under your control, it's helpful to use QPointer since it never dangles. A QPointer resets itself to 0 when the pointed-to object gets destructed. It will at least prevent you from dereferencing a dangling pointer, since it never dangles.
# include "stdafx.h"
# include <iostream>
#include <ctype.h>
using namespace std;
class a
{
protected:
int d;
public:
virtual void assign(int A) = 0;
int get();
};
class b : a
{
char* n;
public:
b()
{
n=NULL;
}
virtual ~b()
{
delete n;
}
void assign(int A)
{
d=A;
}
void assignchar(char *c)
{
n=c;
}
int get()
{
return d;
}
char* getchart()
{
return n;
}
};
class c : b
{
b *pB;
int e;
public:
c()
{
pB=new b();
}
~c()
{
delete pB;
}
void assign(int A)
{
e=A;
pB->assign(A);
}
int get()
{
return e;
}
b* getp()
{
return pB;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
c *pC=new c();
pC->assign(10);
b *p=pC->getp();
p->assignchar("a");
char *abc=p->getchart();
delete pC;
cout<<*abc<<endl;
getchar();
}
i'm a noob at c++ and was experimenting when i got to this point. I don't understand why i keep getting a memory corruption message from VS2010. I am trying to replicate a problem which is at a higher level by breaking it down into smaller bits, any help would be appreciated.
From a cursory glance, you are passing a static char array to AssignChar that cannot be deleted (ie when you type "A" into your code, its a special block of memory the compiler allocates for you).
You need to understand what assignment of a char* does (or any pointer to type). When you call n=c you are just assigning the pointer, the memory that pointer points to remains where it is. So, unless this is exactly what you meant to do, you will have 2 pointers pointing to the same block of memory.. and you need to decide which to delete (you can't delete it twice, that'd be bad).
My advice here is to start using C++, so no more char* types, use std::string instead. Using char* is C programming. Note that if you did use a std::string, and passed one to assignChars, it would copy as you expected (and there is no need to free std::string objects in your destructor, they handle all that for you).
The problem occurs when you're trying to delete pC.
When ~c() destructor calls ~b() destructor - you're trying to delete n;.
The problem is that after assignchar(), n points to a string literal which was given to it as an argument ("a").
That string is not dynamically allocated, and should not be freed, meaning you should either remove the 'delete n;' line, or give a dynamically-allocated string to assignchar() as an argument.