I have an application that makes a number of calls to an external library. One of these calls is not thread-safe so everything will crash if I don't guard it somehow.
I tried to use the following pattern, i.e. wrapping a mutex inside a shared_ptr. Note that this class may be instantiated at many different places in the application from different threads.
class MyClass
{
public:
MyClass(const std::shared_ptr<std::mutex>& mutex) :
_mutex(mutex)
{
}
MyClass(MyClass&& other) :
_mutex(other._mutex)
{
}
void run()
{
std::lock_guard<std::mutex> lock(*_mutex);
ExtLib::runNonThreadSafeFunction();
}
private:
std::shared_ptr<std::mutex> _mutex;
};
Are there any risks using this approach? I'm suspecting that it causes dead-locks but I'm not sure.
If this is not a good approach, how would you implement it?
Note: I am also considering using a static mutex inside the run-function, but I believe Visual Studio 2013 doesn't support it: https://connect.microsoft.com/VisualStudio/feedback/details/808030/runtime-crash-with-static-std-mutex).
I am new to c++ programming. I am trying few things
I tried using directive in following way as shown in below program just for trail it is throwing error
IDE used:VS 2015
language :VC++
Project type: library
Error occured is Error: Expected an identifier
This is in Stdafx.h
#define MANAGED_PUBLIC public ref
This is in trail.h
using namespace System;
namespace trail {
MANAGED_PUBLIC class Class1
{
// TODO: Add your methods for this class here.
};
}
I wanted to use MANAGED_PUBLIC instead of using public ref each and every time in whole project
You cannot do that. public ref is a context sensitive keyword. You cannot bury it down under a macro. C++/CLI compiler would process it differently than a regular compiler hence the macro outcome won't be public ref. You must type it everywhere.
You can use two macros:
#define MANAGED_PUB public
#define MANAGED_REF ref
MANAGED_PUB MANAGED_REF class Class1
{
// TODO: Add your methods for this class here.
};
You might try a compiler flag: -DMANAGED_PUBLIC="public ref" for your legacy code (quotes are stripped according to msdn).
I have two constructors: normal ctor which initialises the object properly and a second default ctor for Hibernate which generates initialize fields warnings. What's the preferred way to get rid of the warnings?
package test;
public class Example {
String x;
public Example(String x) {
this.x = x;
}
Example() {
// Ctor for Hibernate, warnings generated here.
}
}
You didn't mention looking in the documentation, so I'm not sure whether you have done so. The Checker Framework manual contains a chapter titled "Suppressing warnings", which might contain all the information you need.
The most common approach is to write a #SuppressingWarnings annotation, which is the standard way to suppress warnings from the Java compiler.
You should write it on the smallest program element possible (such as a local variable declaration rather than the whole constructor or class), and you should supply the most specific key possible. The reason is to avoid accidentally suppressing more warnings than you intended.
(Pseudo-)Code
Here is a non-compilable code-sketch of the concepts I am having trouble with:
struct Data {};
struct A {};
struct B {};
struct C {};
/* and many many more...*/
template<typename T>
class Listener {
public:
Listener(MyObject* worker):worker(worker)
{ /* do some magic to register with RTI DDS */ };
public:
// This function is used ass a callback from RTI DDS, i.e. it will be
// called from other threads when new Data is available
void callBackFunction(Data d)
{
T t = extractFromData(d);
// Option 1: direct function call
// works somewhat, but shows "QObject::startTimer: timers cannot be started
// from another thread" at the console...
worker->doSomeWorkWithData(t); //
// Option 2: Use invokeMethod:
// seems to fail, as the macro expands including '"T"' and that type isn't
// registered with the QMetaType system...
// QMetaObject::invokeMethod(worker,"doSomeGraphicsWork",Qt::AutoConnection,
// Q_ARG(T, t)
// );
// Option 3: use signals slots
// fails as I can't make Listener, a template class, a QObject...
// emit workNeedsToBeDone(t);
}
private:
MyObject* worker;
T extractFromData(Data d){ return T(d);};
};
class MyObject : public QObject {
Q_OBJECT
public Q_SLOTS:
void doSomeWorkWithData(A a); // This one affects some QGraphicsItems.
void doSomeWorkWithData(B b){};
void doSomeWorkWithData(C c){};
public:
MyObject():QObject(nullptr){};
void init()
{
// listeners are not created in the constructor, but they should have the
// same thread affinity as the MyObject instance that creates them...
// (which in this example--and in my actual code--would be the main GUI
// thread...)
new Listener<A>(this);
new Listener<B>(this);
new Listener<C>(this);
};
};
main()
{
QApplication app;
/* plenty of stuff to set up RTI DDS and other things... */
auto myObject = new MyObject();
/* stuff resulting in the need to separate "construction" and "initialization" */
myObject.init();
return app.exec();
};
Some more details from the actual code:
The Listener in the example is a RTI DataReaderListener, the callback
function is onDataAvailable()
What I would like to accomplish
I am trying to write a little distributed program that uses RTI's Connext DDS for communication and Qt5 for the GUI stuff--however, I don't believe those details do matter much as the problem, as far as I understood it, boils down to the following:
I have a QObject-derived object myObject whose thread affinity might or might not be with the main GUI thread (but for simplicity, let's assume that is the case.)
I want that object to react to event's which happen in another, non-Qt 3rd-party library (in my example code above represented by the functions doSomeWorkWithData().
What I understand so far as to why this is problematic
Disclaimer: As usual, there is always more than one new thing one learns when starting a new project. For me, the new things here are/were RTI's Connext and (apparently) my first time where I myself have to deal with threads.
From reading about threading in Qt (1,2,3,4, and 5 ) it seems to me that
QObjects in general are not thread safe, i.e. I have to be a little careful about things
Using the right way of "communicating" with QObjects should allow me to avoid having to deal with mutexes etc myself, i.e. somebody else (Qt?) can take care of serializing access for me.
As a result from that, I can't simply have (random) calls to MyClass::doSomeWorkWithData() but I need to serialize that. One, presumably easy, way to do so is to post an event to the event queue myObject lives in which--when time is available--will trigger the execution of the desired method, MyClass::doSomeWorkWithData() in my case.
What I have tried to make things work
I have confirmed that myObject, when instantiated similarly as in the sample code above, is affiliated with the main GUI thread, i.e. myObject.thread() == QApplication::instance()->thread().
With that given, I have tried three options so far:
Option 1: Directly calling the function
This approach is based upon the fact that
- myObject lives in the GUI thread
- All the created listeners are also affiliated with the GUI thread as they are
created by `myObject' and inherit its thread that way
This actually results in the fact that doSomeWorkWithData() is executed. However,
some of those functions manipulate QGraphicsItems and whenever that is the case I get
error messages reading: "QObject::startTimer: timers cannot be started from another
thread".
Option 2: Posting an event via QMetaObject::invokeMethod()
Trying to circumvent this problem by properly posting an event for myObject, I
tried to mark MyObject::doSomeWorkWithData() with Q_INVOKABLE, but I failed at invoking the
method as I need to pass arguments with Q_ARG. I properly registered and declared my custom types
represented by struct A, etc. in the example), but I failed at the fact the
Q_ARG expanded to include a literal of the type of the argument, which in the
templated case didn't work ("T" isn't a registered or declared type).
Trying to use conventional signals and slots
This approach essentially directly failed at the fact that the QMeta system doesn't
work with templates, i.e. it seems to me that there simply can't be any templated QObjects.
What I would like help with
After spending about a week on attempting to fix this, reading up on threads (and uncovering some other issues in my code), I would really like to get this done right.
As such, I would really appreciate if :
somebody could show me a generic way of how a QObject's member function can be called via a callback function from another 3rd-party library (or anything else for that matter) from a different, non QThread-controlled, thread.
somebody could explain to me why Option 1 works if I simply don't create a GUI, i.e. do all the same work, just without a QGraphcisScene visualizing it (and the project's app being a QCoreApplication instead of a QApplication and all the graphics related work #defineed out).
Any, and I mean absolutely any, straw I could grasp on is truly appreciated.
Update
Based on the accepted answer I altered my code to deal with callbacks from other threads: I introduced a thread check at the beginning of my void doSomeWorkWithData() functions:
void doSomeWorkWithData(A a)
{
if( QThread::currentThread() != this->thread() )
{
QMetaObject::invokeMethod( this,"doSomeWorkWithData"
,Qt::QueuedConnection
,Q_ARG(A, a) );
return;
}
/* The actual work this function does would be below here... */
};
Some related thoughts:
I was contemplating to introduce a QMutexLocker before the if statement, but decided against it: the only part of the function that is potentially used in parallel (anything above the return; in the if statement) is--as far as I understand--thread safe.
Setting the connection type manually to Qt::QueuedConnection: technically, if I understand the documentation correctly, Qt should do the right thing and the default, Qt::AutoConnection, should end up becoming a Qt::QueuedConnection. But since would always be the case when that statement is reached, I decided to put explicitly in there to remind myself about why this is there.
putting the queuing code directly in the function and not hiding it in an interim function: I could have opted to put the call to invokeMethod in another interim function, say queueDoSomeWorkWithData()', which would be called by the callback in the listener and then usesinvokeMethodwith anQt::AutoConnection' on doSomeWorkWithData(). I decided against this as there seems no way for me to auto-code this interim function via templates (templates and the Meta system was part of the original problem), so "the user" of my code (i.e. the person who implements doSomeWorkWithData(XYZ xyz)) would have to hand type the interim function as well (as that is how the templated type names are correctly resolved). Including the check in the actual function seems to me to safe typing an extra function header, keeps the MyClass interface a little cleaner, and better reminds readers of doSomeWorkWithData() that there might be a threading issue lurking in the dark.
It is ok to call a public function on a subclass of QObject from another thread if you know for certain that the individual function will perform only thread-safe actions.
One nice thing about Qt is that it will handle foreign threads just as well as it handles QThreads. So, one option is to create a threadSafeDoSomeWorkWithData function for each doSomeWorkWithData that does nothing but QMetaMethod::invoke the non-threadsafe one.
public:
void threadSafeDoSomeWorkWithData(A a) {
QMetaMethod::invoke("doSomeWorkWithData", Q_ARG(A,a));
}
Q_INVOKABLE void doSomeWorkWithData(A a);
Alternatively, Sergey Tachenov suggests an interesting way of doing more or less the same thing in his answer here. He combines the two functions I suggested into one.
void Obj2::ping() {
if (QThread::currentThread() != this->thread()) {
// not sure how efficient it is
QMetaObject::invoke(this, "ping", Qt::QueuedConnection);
return;
}
// thread unsafe code goes here
}
As to why you see normal behaviour when not creating a GUI? Perhaps you're not doing anything else that is unsafe, aside from manipulating GUI objects. Or, perhaps they're the only place in which your thread-safety problems are obvious.
[EDIT: further digging revealed a different root issue. I'm rephrasing the question, but leaving the old version below, for consistency with the answer by #Leo]
It seems VC++ (both under VS2005 & VS2010) allows me to dllexport classes with missing implementations! The following code builds fine:
// missingimp.h :
class __declspec(dllexport) MissingImp
{
void DoStuff(); // no implementation anywhere
void DoMoreStuff(); // neither for this
}
// missingimp.cpp
#include "missingimp.h"
The code both compiles and links fine (in dll configuration) - and of course statically linking with the resulting dll fails.
Is this be a bug? is this behavior somehow by design??
[Old question:]
I'm trying to dllexport a class, that has a data member templated on a forward-declared type:
// Class2Export.h:
class ForwardDeclared ;
template<class T> class TemplatedClass
{
T *m_ptr;
public:
TemplatedClass() { m_ptr->DoSomething(); }
};
class __declspec(dllexport) ExportedClass
{
TemplatedClass<ForwardDeclared> TemplateForward;
};
// Class2Export.cpp:
#include "Class2Export.h"
(This is not a contrived example - in the real code TemplatedClass is a smart pointer, but that seems irrelevant to the issue at hand.)
This code fails to compile, with -
error C2027: use of undefined type
'ForwardDeclared'
That still makes some kind of sense, based on a reply from MS:
If TemplatedClass has a constructor
then a constructor will be
automatically generated for
ExportedClass. Since ExportedClass is
exported the compiler tries to export
the constructor but fails to generate
code for it because ForwardDeclared is
unknown.
But I suspect that is not the ultimate answer, as when I declare (without even implementing!) a ctor for ExportedClass:
...
class __declspec(dllexport) ExportedClass
{
ExportedClass();
TemplatedClass<ForwardDeclared> TemplateForward;
};
...
both compile and link succeed (with a due warning*). The issue over at MS-connect seems abandoned - perhaps anyone can shed some light over this strange behaviour?
Thanks!
*EDIT: the generated warning is C4251 :
class 'TemplatedClass ' needs to have dll-interface to be used by clients of class 'ExportedClass'
Unless I've got the wrong end of the stick, the issue is about when the ExportedClass constructor code is generated.
If the ExportedClass constructor code is generated before ForwardDeclared is declared (not forward-declared but properly declared) then you'll get an error, since the ExportedClass constructor implicitly calls the TemplatedClass constructor, and that calls a method on ForwardDeclared which is undefined.
Your final example, the one which compiles and links with a warning, works because the ExportedClass constructor is never defined. (Presumably the warning is that ExportedClass::ExportedClass does not exist. Since nothing actually tries to use it it's just a warning and not an error.) You've avoided the issue there. As it is, that code is not useful as nothing can create ExportedClass (it has no constructor) but if you define the constructor somewhere then everything should work fine, provided ForwardDeclared is declared/defined before then.
If you change your final example to this you should get the errors back again: (All that's added are two braces to give the ExportedClass constructor an empty body)
class __declspec(dllexport) ExportedClass
{
ExportedClass() { } // Error here
TemplatedClass<ForwardDeclared> TemplateForward;
};
And that code is what you are implicitly doing if you don't have a constructor for ExportedClass at all. In these cases the constructor's code is being generated there and then in the header file. On the other hand, when the constructor is declared without a body in the header you are leaving the code to be defined and generated somewhere else.
Eventually I found an answer in MS forums.
I'm linking to it here, in case it's useful to anyone some day.