c++multithreadingboostsignalsboost-signals2

Boost signals2 giving noncopyable errors


I'm currently working on a C++ application where I need to create a module that sends boost signals to another class. I'm using the Document-View example as a basis for my application (http://www.boost.org/doc/libs/1_55_0/doc/html/signals2/tutorial.html#signals2.tutorial.document-view) , but I keep getting an error :

Error   1   error C2280: boost::noncopyable_::noncopyable::noncopyable(const   boost::noncopyable_::noncopyable &)' : attempting to reference a deleted function

This has me completely stumped - where does the error actually occur?

Build log is as follows :

1>------ Build started: Project: 32BitTrial, Configuration: Debug Win32 ------
1>  InboundLogicAdaptor.cpp
1>  main.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xlocmon(232): error C2280: 'boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable &)' : attempting to reference a deleted function
1>          C:\boost_1_58_0\boost/core/noncopyable.hpp(34) : see declaration of 'boost::noncopyable_::noncopyable::noncopyable'
1>          This diagnostic occurred in the compiler generated function 'boost::signals2::signal_base::signal_base(const boost::signals2::signal_base &)'
1>  OutboundLogicAdaptor.cpp
1>  TrialLogic.cpp
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

My main function is rather simple - I construct a GUI, a model for communicating with the GUI (TrialModel), a simple Logic that counts +1 every 500msec and an outbound logic adaptor, that is accessed via boost signals2 library from the Logic.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    TrialModel m;

    Trial w(0, &m);
    w.show();


    TrialLogic logic;

    OutboundLogicAdaptor adaptor(&m, logic);

    boost::thread t(logic);

    a.exec();

    t.join();

    return 1;

}

The logic class defines a signal that has one argument (integer) and an operator() for acting as a thread.

TrialLogic.h :

#pragma once

#include <boost\thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost\signals2.hpp>



class TrialLogic
{
public:
    typedef boost::signals2::signal<void(int x)> signal_t;

    void operator()();
    TrialLogic();
    ~TrialLogic();

    boost::signals2::connection connect(const signal_t::slot_type &subscriber);

    void doubleIncrementSlot();

private:

    void emitSignal();

    signal_t signal;

    int testNum;

};

and the code itself :

#include "TrialLogic.h"

TrialLogic::TrialLogic()
{   
    testNum = 0;
}


TrialLogic::~TrialLogic()
{
}

boost::signals2::connection TrialLogic::connect(const signal_t::slot_type &subscriber){
    return signal.connect(subscriber);
}

void TrialLogic::operator()(){
    boost::this_thread::sleep(boost::posix_time::milliseconds(500));
    testNum++;
    emitSignal();

}

void TrialLogic::emitSignal(){
    signal_t(testNum);
}

And finally, the adaptor that receives the signal -

#include "OutboundLogicAdaptor.h"


OutboundLogicAdaptor::OutboundLogicAdaptor(TrialModel *modelHook, TrialLogic &logicHook) : logic(logicHook)
{
    this->hook = modelHook;

    signalConnection = logic.connect(boost::bind(&OutboundLogicAdaptor::transmitAngle, this, _1));
}



OutboundLogicAdaptor::~OutboundLogicAdaptor()
{
    signalConnection.disconnect();
}

void OutboundLogicAdaptor::transmitAngle(int angle){
    hook->postAngle(angle);
}

From my first inspection I cannot find anything that I've done wrong, but obviously there is a critical fault with my code. I'm pretty sure that the problem is not in the GUI side either, as I don't actually use any boost functions there and it worked fine before I tried to bind the system together.

Any suggestions?


Solution

  • Here is the reason for the failure:

    Your TrialLogic class has a member of type boost.signal in it, and this type is not copiable (it is inherited from signal_base, which is inherited from nocopyable). This makes the class TrialLogic itself non-copyable. Yet you are trying to copy it here:

    TrialLogic logic;
    boost::thread t(logic);
    

    Boost.thread accepts argument by value, so you are trying to copy something which is not copyable and the compiler is upset.

    As for the solution, the easiest seems to be following: instead of defining operator() on your TrialLogic, define a function, than pass that function as well as a pointer or reference to the logic class. Something like that:

    class TrialLogic
    {
    ...
    void launch() {
        boost::this_thread::sleep(boost::posix_time::milliseconds(500));
        testNum++;
        emitSignal();
    }
    };
    ...
    // in main
    boost::thread(&TrialLogic::launch, &logic);
    

    Last, but not the least, I do not advise on using boost::thread. C++11 thread support is fully operational, and boost::thread doesn't really add any benefits.