I am currently trying to run a class member function in a separate thread which results in a call to implicitly deleted copy constructor , there are already multiple Questions to this answered here on StackOverflow but honestly a lot of this is 5+ years old or feels hacky thats why I am asking myself what would be the best practice to do this with modern c++?
So currently I have the following :
A ZMQWorker which should run in separate threads ( sock is not Thread save)
zmqwoker.cpp
#include "zmqworker.h"
#include <QDebug>
#include <iostream>
ZMQWorker::ZMQWorker()
: sock(ctx, zmq::socket_type::dealer)
{
qDebug() << "Dealer Socket created";
}
void ZMQWorker::connectSocket()
{
std::string origin="CPP_ZMQ";
sock.connect("tcp://127.0.0.1:5555");
qDebug() << "Dealer Socket connected";
}
void ZMQWorker::receiveMessage()
{
while (1){
std::vector<zmq::message_t> recv_msg;
auto res = zmq::recv_multipart(sock,
std::back_inserter(recv_msg));
for (auto&& msg : recv_msg) {
std::cout << msg.to_string_view() << std::endl;
}
}
}
zmq::socket_t &ZMQWorker::getSock()
{
return sock;
}
zmqworker.h
#ifndef ZMQWORKER_H
#define ZMQWORKER_H
#include <zmq_addon.hpp>
#include <thread>
class ZMQWorker
{
public:
ZMQWorker();
void connectSocket();
zmq::context_t ctx;
zmq::socket_t sock;
void receiveMessage();
zmq::socket_t &getSock();
};
#endif // ZMQWORKER_H
and a ZMQBridge which should act as Bridge between QT and the ZMQ socket , since receive and send both are blocking function these should work in different Threads.
zmqbridge.h
#ifndef ZMQBRIDGE_H
#define ZMQBRIDGE_H
#include <QObject>
#include <iostream>
#include "zmqworker.h"
class ZMQBridge : public QObject
{
Q_OBJECT
public:
explicit ZMQBridge(QObject *parent = nullptr);
void createMessageSocket();
ZMQWorker sendSocket;
Q_INVOKABLE void callCoro(QString msg);
signals:
private:
void spawnWorker();
};
#endif // ZMQBRIDGE_H
zmqbridge.cpp
#include "zmqbridge.h"
#include <stdio.h>
#include <QDebug>
#include "zmq_dealer.h"
#include <iostream>
#include <msgpack.hpp>
#include <thread>
#include <chrono>
#include <iostream>
#include <string>
#include <random>
#include <nlohmann/json.hpp>
ZMQBridge::ZMQBridge(QObject *parent)
: QObject{parent},
sendSocket()
{
sendSocket.connectSocket();
}
void ZMQBridge::createMessageSocket(){}
void ZMQBridge::spawnWorker(){}
void ZMQBridge::callCoro(QString msg)
{
std::cout << "Hello from c++";
ZMQWorker receiveSocket = ZMQWorker();
std::thread (&ZMQWorker::receiveMessage, receiveSocket).detach();
qDebug() << "Hello";
nlohmann::json jmsg;
jmsg["randvar"] = "Hello";
zmq::message_t z_out(jmsg.dump());
sendSocket.getSock().send(z_out, zmq::send_flags::none);
}
Error Message:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/usr/include/c++/v1/type_traits:2596: error: call to implicitly-deleted copy constructor of 'typename decay<ZMQWorker &>::type' (aka 'ZMQWorker')
In file included from /Users/ahoehne/repos/ondoki-desktop/zmqbridge.cpp:1:
In file included from /Users/ahoehne/repos/ondoki-desktop/zmqbridge.h:4:
In file included from /Users/ahoehne/Qt/6.2.2/macos/lib/QtCore.framework/Headers/QObject:1:
In file included from /Users/ahoehne/Qt/6.2.2/macos/lib/QtCore.framework/Headers/qobject.h:46:
In file included from /Users/ahoehne/Qt/6.2.2/macos/lib/QtCore.framework/Headers/qobjectdefs.h:48:
In file included from /Users/ahoehne/Qt/6.2.2/macos/lib/QtCore.framework/Headers/qnamespace.h:44:
In file included from /Users/ahoehne/Qt/6.2.2/macos/lib/QtCore.framework/Headers/qglobal.h:45:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/usr/include/c++/v1/type_traits:2596:12: error: call to implicitly-deleted copy constructor of 'typename decay<ZMQWorker &>::type' (aka 'ZMQWorker')
return _VSTD::forward<_Tp>(__t);
^~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/usr/include/c++/v1/__config:856:15: note: expanded from macro '_VSTD'
#define _VSTD std::_LIBCPP_ABI_NAMESPACE
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/usr/include/c++/v1/thread:312:28: note: in instantiation of function template specialization 'std::__decay_copy<ZMQWorker &>' requested here
_VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...));
^
/Users/ahoehne/repos/ondoki-desktop/zmqbridge.cpp:31:1: note: in instantiation of function template specialization 'std::thread::thread<void (ZMQWorker::*)(), ZMQWorker &, void>' requested here
std::thread (&ZMQWorker::receiveMessage, receiveSocket).detach();
^
/Users/ahoehne/repos/ondoki-desktop/zmqworker.h:14:20: note: copy constructor of 'ZMQWorker' is implicitly deleted because field 'ctx' has a deleted copy constructor
zmq::context_t ctx;
^
/Users/ahoehne/repos/vcpkg/installed/arm64-osx/include/zmq.hpp:903:5: note: 'context_t' has been explicitly marked deleted here
context_t(const context_t &) ZMQ_DELETED_FUNCTION;
^
In other languages like Java or Python which I am used to , I would just inherit from Thread and overwrite the run method and maybe depending on how dynamic and many I need use this with a ThreadPool combined with async/await ...How would I do this in C++ .The informations seems to be mixed and it feels like following a rabbit into it's hole to a new magic land.
Thank you for your help ....
You're passing receiveSocket by value trying to call the deleted copy constructor.
You have to either pass a pointer to your ZMQWorker:
std::thread (&ZMQWorker::receiveMessage, &receiveSocket)
or a reference:
std::thread (&ZMQWorker::receiveMessage, std::ref(receiveSocket))
But then you have to solve another problem:
ZMQWorker receiveSocket;
goes out of scope at the end of this method and will be destroyed while your other thread might still be using it.
What I did now is this :
zmqbridge.cpp
#include "zmqbridge.h"
#include <stdio.h>
#include <QDebug>
#include "zmq_dealer.h"
#include <iostream>
#include <msgpack.hpp>
#include <thread>
#include <chrono>
#include <iostream>
#include <string>
#include <random>
#include <nlohmann/json.hpp>
ZMQBridge::ZMQBridge(QObject *parent)
: QObject{parent},
sendSocket("CPP_SEND"),
receiveSocket("CPP_RECV")
{
this->sendSocket.connectSocket();
this->receiveSocket.connectSocket();
std::thread (&ZMQWorker::receiveMessage, &receiveSocket).detach();
}
void ZMQBridge::createMessageSocket(){}
void ZMQBridge::spawnWorker(){}
void ZMQBridge::callCoro(QString msg)
{
std::cout << "Hello from c++";
qDebug() << "Hello";
nlohmann::json jmsg;
jmsg["name"] = "hello";
jmsg["dispatch_to"] = "caller";
zmq::message_t z_out(jmsg.dump());
sendSocket.getSock().send(z_out, zmq::send_flags::none);
}
zmqbridge.h
#ifndef ZMQBRIDGE_H
#define ZMQBRIDGE_H
#include <QObject>
#include <iostream>
#include "zmqworker.h"
class ZMQBridge : public QObject
{
Q_OBJECT
public:
explicit ZMQBridge(QObject *parent = nullptr);
void createMessageSocket();
ZMQWorker sendSocket;
ZMQWorker receiveSocket;
Q_INVOKABLE void callCoro(QString msg);
signals:
private:
void spawnWorker();
};
#endif // ZMQBRIDGE_H
This works but it does not feel like a ideal grade solution , if so I will accept the answer provided by Stefan Riedel
I am having two classes one main class and another server class. I am calling run method in server class as a seperate thread from main class. I need to pass values from main class to server class periodically.
I tried using std::atomic but the value in the thread is not getting changed.
Am I doing something wrong below? Any help or advice is highly appreciated. THanks.
#include <iostream>
#include "server.h"
#include "atomic"
using namespace std;
std::atomic<int> clientSignal(-1);
void foo();
int main()
{
cout << "Hello World!" << endl;
server* board;
board = new server();
thread serverThread(&server::run,*board,std::ref(clientSignal));
serverThread.join();
foo(); // the value of clientSignal is changed from within main class //based on input from sensors.
return 0;
}
void foo(){
clientSignal = 8;
}
server.h
#ifndef SERVER_H
#define SERVER_H
class server
{
public:
server();
~server();
void run(std::atomic<int> &clientSignal);
private:
std::atomic<int> *clientFlag;
};
#endif // SERVER_H
server.cpp
#include "server.h"
server::server()
{
}
server::~server()
{
}
void server::run(std::atomic<int> &clientSignal) {
clientFlag = &clientSignal;
cout << *clientFlag;
...
}
I'm using Gtkmm and multithreading.
I have a class "NetworkWorker" doig stuffs with the network in a secondary thread.
In this class i want to make many signals which will be handled by my class "MainWindow".
The methods which handle these signals, will edit append text in a TextView.
I have the following code:
NetworkWorker.h
#ifndef NETWORKWORKER_H_
# define NETWORKWORKER_H_
# include <sigc++/sigc++.h>
# include <glibmm/threads.h>
# include <string>
class NetworkWorker
{
public:
NetworkWorker();
~NetworkWorker();
void start();
void stop();
sigc::signal<void, std::string&>& signal_data_received();
private:
void run();
sigc::signal<void, std::string&> m_signal_data_received;
Glib::Threads::Thread* m_thread;
Glib::Threads::Mutex m_mutex;
bool m_stop;
};
#endif
NetworkWorker.c
#include <cstdlib>
#include <glibmm/timer.h>
#include <glibmm/threads.h>
#include <iostream>
#include <sigc++/sigc++.h>
#include "NetworkWorker.h"
NetworkWorker::NetworkWorker() :
m_thread(NULL), m_stop(false)
{
}
NetworkWorker::~NetworkWorker()
{
stop();
}
void NetworkWorker::start()
{
if (!m_thread)
m_thread = Glib::Threads::Thread::create(sigc::mem_fun(*this, &NetworkWorker::run));
}
void NetworkWorker::stop()
{
{
Glib::Threads::Mutex::Lock lock(m_mutex);
m_stop = true;
}
if (m_thread)
m_thread->join();
}
sigc::signal<void, std::string&>& NetworkWorker::signal_data_received()
{
return m_signal_data_received;
}
void NetworkWorker::run()
{
while (true)
{
{
Glib::Threads::Mutex::Lock lock(m_mutex);
if (m_stop)
break;
}
Glib::usleep(5000);
std::cout << "Thread" << std::endl;
std::string* str = new std::string("MyData");
m_signal_data_received.emit(*str);
}
}
MainWindow.h
#ifndef MAIN_WINDOW_H_
# define MAIN_WINDOW_H_
# include <gtkmm/textview.h>
# include <gtkmm/window.h>
# include <string>
class MainWindow : public Gtk::Window
{
public:
MainWindow();
~MainWindow();
void appendText(const std::string& str);
private:
Gtk::TextView m_text_view;
};
#endif
MainWindow.c
#include <gtkmm/notebook.h>
#include <gtkmm/widget.h>
#include <iostream>
#include <string>
#include "MainWindow.h"
MainWindow::MainWindow()
{
set_title("My App");
set_default_size(800, 600);
add(m_text_view);
}
MainWindow::~MainWindow()
{
}
void MainWindow::appendText(const std::string& str)
{
std::string final_text = str + "\n";
Glib::RefPtr<Gtk::TextBuffer> buffer = m_text_view.get_buffer();
Gtk::TextBuffer::iterator it = buffer->end();
buffer->insert(it, final_text);
Glib::RefPtr<Gtk::Adjustment> adj = m_text_view.get_vadjustment();
adj->set_value(adj->get_upper() - adj->get_page_size());
}
and my main.cpp
#include <cstdlib>
#include <gtkmm/main.h>
#include <iostream>
#include <string>
#include "MainWindow.h"
#include "NetworkWorker.h"
void recv(const std::string& str)
{
std::cout << str << std::endl;
}
int main(int argc, char **argv)
{
Gtk::Main app(Gtk::Main(argc, argv));
MainWindow main_window;
NetworkWorker network_worker;
main_window.show_all();
network_worker.signal_data_received().connect(sigc::ptr_fun(&recv));
network_worker.signal_data_received().connect(sigc::mem_fun(main_window, &MainWindow::appendText));
network_worker.start();
Gtk::Main::run(main_window);
return (EXIT_SUCCESS);
}
These snippetes have been a re-adapted for this question, so maybe some change is incoherent.
When I execute this code, I have the following output:
$> ./client
Thread
MyData
Thread
MyData
[...]
Thread
MyData
Thread
MyData
(client:5596): Gtk-CRITICAL **: gtk_text_layout_real_invalidate: assertion 'layout->wrap_loop_count == 0' failed
Thread
MyData
Thread
MyData
[...]
Thread
MyData
Thread
MyData
[1] 5596 segmentation fault (core dumped) ./client
Can some one help me to resolve this issue ? :)
The issue is you are calling non threadsafe function call (signal callbacks are not threadsafe).
So you need to use something like Glib::signal_idle().connect( sigc::mem_fun(*this, &IdleExample::on_idle) );(or whatever is equivalent to C API call g_idle_add(GCallback func)) from your thread. This function is threadsafe (at least the one from the C API).
See this tutorial for a simplified example.
Never call or signal from different threads when using UI libraries. Usually the APIs are designed to be called from a single thread. This is the single most often made mistake when using UI toolkits.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I post all the files of my project, It seems to be done correct, but this error is incomprensible for me...
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <activemq/library/ActiveMQCPP.h>
#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <decaf/lang/Integer.h>
#include <decaf/lang/Long.h>
#include <decaf/lang/System.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include "IfacomAmqSender.h"
using namespace activemq::core;
using namespace decaf::util::concurrent;
using namespace decaf::util;
using namespace decaf::lang;
using namespace cms;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow,public MessageListener
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void onMessage(const Message*);
void connetionSender();
IfacomAmqSender m_IfacomMessageBroker;
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "IfacomAmqSender.h"
#include "IfacomAmqReceiver.h"
#include <activemq/library/ActiveMQCPP.h>
#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <decaf/lang/Integer.h>
#include <decaf/lang/Long.h>
#include <decaf/lang/System.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <memory>
#include <qstring.h>
#include <QTextStream>
#include <QMessageBox>
using namespace activemq::core;
using namespace decaf::util::concurrent;
using namespace decaf::util;
using namespace decaf::lang;
using namespace cms;
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::connetionSender()
{
activemq::library::ActiveMQCPP::initializeLibrary();
std::string brokerURI = "failover://(tcp://localhost:61613?wireFormat=stomp)"; // localhost;
// brokerURI = "failover://(tcp://localhost:61616)"; // localhost
// Queue name
std::string destName = "IFACOM-CMS";
// Queue or Topic
bool useTopics = false; // true=Topic, false=Queue
// SESSION_TRANSACTED or AUTO_ACKNOWLEDGE
bool sessionTransacted = false; // if true, commit all messages
// ***** Initialisation **************************************************************
IfacomAmqSender m_IfacomMessageBroker(brokerURI, useTopics, sessionTransacted, destName);
m_IfacomMessageBroker.initConnection();
IfacomAmqReceiver IfacomAmqReceiverBroker(brokerURI,10, useTopics, sessionTransacted, destName,2000);
IfacomAmqReceiverBroker.initConnection();
IfacomAmqReceiverBroker.getConsumer()->setMessageListener(this);
}
void MainWindow::on_pushButton_clicked()
{
//****** Send message ******************************************************
//IfacomAmqSender IfacomAmqReceiverBroker;
std::string text = "My IFaCOM message";
// Customized message
try{
std::auto_ptr<TextMessage> message(m_IfacomMessageBroker.getSession()->createTextMessage(text));
message->setCMSTimestamp(System::currentTimeMillis());
message->setStringProperty("MyProperty", "test");
m_IfacomMessageBroker.sendMessage(message);
} catch (CMSException& e) {
e.printStackTrace();
}
// Simple text message
m_IfacomMessageBroker.sendMessage(text);
long long startTime = System::currentTimeMillis();
long long endTime = System::currentTimeMillis();
double totalTime = (double)(endTime - startTime) / 1000.0;
// Close the connection
m_IfacomMessageBroker.close();
//ui->label->setText(QString::fromStdString(text));
// To Do at the end
//activemq::library::ActiveMQCPP::shutdownLibrary();
}
//***************** Receive Message *****************************************************
void MainWindow::onMessage(const Message* message) {
try {
const TextMessage* textMessage = dynamic_cast<const TextMessage*> (message);
string text = "";
if (textMessage != NULL) {
text = textMessage->getText();
} else {
text = "NOT A TEXTMESSAGE!";
}
//printf("Message received: %s\n", text.c_str());
//WM get param.
std::string msgId = message->getCMSMessageID();
int prio = message->getCMSPriority();
long long timestamp = message->getCMSTimestamp();
ui->label->setText(QString::fromStdString(text));
} catch (CMSException& e) {
e.printStackTrace();
}
// Commit all messages.
/*if (this->m_sessionTransacted) {
m_session->commit();
}
// No matter what, tag the count down latch until done.
m_doneLatch.countDown();*/
}
IfacomAmqReceiver.h
#ifndef _IfacomAmqReceiver_h
#define _IfacomAmqReceiver_h
#include <activemq/library/ActiveMQCPP.h>
#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <decaf/lang/Integer.h>
#include <decaf/lang/Long.h>
#include <decaf/lang/System.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <memory>
using namespace activemq::core;
using namespace decaf::util::concurrent;
using namespace decaf::util;
using namespace decaf::lang;
using namespace cms;
class IfacomAmqReceiver : public ExceptionListener, public MessageListener{
private:
CountDownLatch m_latch;
CountDownLatch m_doneLatch;
Connection* m_connection;
Session* m_session;
Destination* m_destination;
MessageConsumer* m_consumer;
MessageProducer* m_producer;
std::auto_ptr<TextMessage> m_message;
long m_waitMillis;
bool m_useTopic;
bool m_sessionTransacted;
std::string m_brokerURI;
std::string m_destName;
DeliveryMode m_message_delivery_mode;
int m_message_priority;
//IfacomAmqReceiver(const IfacomAmqReceiver&);
//IfacomAmqReceiver& operator=(const IfacomAmqReceiver&);
public:
IfacomAmqReceiver(const std::string&, int, bool, bool, const std::string&, int);
virtual ~IfacomAmqReceiver();
void close();
void waitUntilReady() ;
void cleanup();
// MM
void createConnection();
void createSession();
void createDestination();
void createConsumer();
void initConnection();
void onMessage(const Message*);
MessageConsumer* getConsumer();
// If something bad happens you see it here as this class is also been
// registered as an ExceptionListener with the connection.
void onException(const CMSException&);
};
#endif
IfacomAmqReceiver.cpp
#include <activemq/library/ActiveMQCPP.h>
#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <decaf/lang/Integer.h>
#include <decaf/lang/Long.h>
#include <decaf/lang/System.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <memory>
#include "IfacomAmqReceiver.h"
using namespace activemq::core;
using namespace decaf::util::concurrent;
using namespace decaf::util;
using namespace decaf::lang;
using namespace cms;
using namespace std;
IfacomAmqReceiver::IfacomAmqReceiver(const std::string& brokerURI, int numMessages, bool useTopic = false, bool sessionTransacted = false, const std::string& destName = "IFACOM-CMS", int waitMillis = 1000) :
m_latch(1),
m_doneLatch(numMessages),
m_connection(NULL),
m_session(NULL),
m_destination(NULL),
m_consumer(NULL),
m_waitMillis(waitMillis),
m_useTopic(useTopic),
m_sessionTransacted(sessionTransacted),
m_destName(destName),
m_brokerURI(brokerURI) {
}
IfacomAmqReceiver::~IfacomAmqReceiver() {
cleanup();
}
void IfacomAmqReceiver::close() {
this->cleanup();
}
void IfacomAmqReceiver::waitUntilReady() {
m_latch.await();
}
//------ Init connexion ---------------
void IfacomAmqReceiver::createConnection()
{
// Create a ConnectionFactory
auto_ptr<ConnectionFactory> connectionFactory(ConnectionFactory::createCMSConnectionFactory(m_brokerURI));
// Create a Connection
m_connection = connectionFactory->createConnection();
m_connection->start();
m_connection->setExceptionListener(this);
}
void IfacomAmqReceiver::createSession()
{
// Create a Session
if (this->m_sessionTransacted == true) {
m_session = m_connection->createSession(Session::SESSION_TRANSACTED);
} else {
m_session = m_connection->createSession(Session::AUTO_ACKNOWLEDGE);
}
}
void IfacomAmqReceiver::createDestination()
{
// Create the destination (Topic or Queue)
if (m_useTopic) {
m_destination = m_session->createTopic(m_destName);
} else {
m_destination = m_session->createQueue(m_destName);
}
}
void IfacomAmqReceiver::createConsumer()
{
m_consumer = m_session->createConsumer(m_destination);
//m_consumer->setMessageListener(this);
}
void IfacomAmqReceiver::initConnection() {
try {
createConnection();
// Create the session
createSession();
// Create the destination (Topic or Queue)
createDestination();
// Create a MessageConsumer from the Session to the Topic or Queue
createConsumer();
// Indicate we are ready for messages.
m_latch.countDown();
// Wait while asynchronous messages come in.
m_doneLatch.await(m_waitMillis);
} catch (CMSException& e) {
// Indicate we are ready for messages.
//latch.countDown();
e.printStackTrace();
}
}
//------ Get the message ---------------
// Called from the consumer since this class is a registered MessageListener.
void IfacomAmqReceiver::onMessage(const Message* message) {}
//--------------------------------------------------
// If something bad happens you see it here as this class is also been
// registered as an ExceptionListener with the connection.
void IfacomAmqReceiver::onException(const CMSException& ex AMQCPP_UNUSED) {
printf("CMS Exception occurred. Shutting down client.\n");
ex.printStackTrace();
exit(1);
}
void IfacomAmqReceiver::cleanup() {
if (m_connection != NULL) {
try {
m_connection->close();
} catch (cms::CMSException& ex) {
ex.printStackTrace();
}
}
// Destroy resources.
try {
delete m_destination;
m_destination = NULL;
delete m_consumer;
m_consumer = NULL;
delete m_session;
m_session = NULL;
delete m_connection;
m_connection = NULL;
} catch (CMSException& e) {
e.printStackTrace();
}
}
MessageConsumer* IfacomAmqReceiver::getConsumer()
{
return m_consumer;
}
IfacomAmqSender.h
#ifndef _IfacomAmqSender_h
#define _IfacomAmqSender_h
#include <activemq/library/ActiveMQCPP.h>
#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <decaf/lang/Integer.h>
#include <decaf/lang/Long.h>
#include <decaf/lang/System.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <memory>
using namespace activemq::core;
using namespace decaf::util::concurrent;
using namespace decaf::util;
using namespace decaf::lang;
using namespace cms;
class IfacomAmqSender : public ExceptionListener{
private:
CountDownLatch m_latch;
CountDownLatch m_doneLatch;
Connection* m_connection;
Session* m_session;
Destination* m_destination;
MessageConsumer* m_consumer;
MessageProducer* m_producer;
std::auto_ptr<TextMessage> m_message;
long m_waitMillis;
bool m_useTopic;
bool m_sessionTransacted;
std::string m_brokerURI;
std::string m_destName;
DeliveryMode m_message_delivery_mode;
int m_message_priority;
IfacomAmqSender(const IfacomAmqSender&);
IfacomAmqSender& operator=(const IfacomAmqSender&);
public:
IfacomAmqSender(const std::string&, int, bool, bool, const std::string&, int);
IfacomAmqSender(const std::string&, bool, bool, const std::string&);
virtual ~IfacomAmqSender();
void close();
void waitUntilReady();
void cleanup();
// KH
void createConnection();
void createSession();
void createDestination();
void createProducer();
void initConnection();
virtual void sendMessage(std::string);
// Send a ActiveMQ Message
virtual void sendMessage(std::auto_ptr<TextMessage>);
//--------------------------------------------------
// If something bad happens you see it here as this class is also been
// registered as an ExceptionListener with the connection.
virtual void onException(const CMSException&) ;
// Message Priority (0:Lowest - 9:Highest)
void setPriority(int);
int getPriority();
// Message Delivery Mode
void setDeliveryMode(DeliveryMode);
DeliveryMode getDeliveryMode();
Session* getSession();
};
#endif
IfacomAmqSender.cpp
#include <activemq/library/ActiveMQCPP.h>
#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <decaf/lang/Integer.h>
#include <decaf/lang/Long.h>
#include <decaf/lang/System.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <memory>
#include "IfacomAmqSender.h"
using namespace activemq::core;
using namespace decaf::util::concurrent;
using namespace decaf::util;
using namespace decaf::lang;
using namespace cms;
using namespace std;
IfacomAmqSender::IfacomAmqSender(const std::string& brokerURI, int numMessages, bool useTopic = false, bool sessionTransacted = false, const std::string& destName = "IFACOM-CMS", int waitMillis = 1000) :
m_latch(1),
m_doneLatch(numMessages),
m_connection(NULL),
m_session(NULL),
m_destination(NULL),
m_consumer(NULL),
m_waitMillis(waitMillis),
m_useTopic(useTopic),
m_sessionTransacted(sessionTransacted),
m_destName(destName),
m_brokerURI(brokerURI) {
}
IfacomAmqSender::IfacomAmqSender(const std::string& brokerURI, bool useTopic = false, bool sessionTransacted = false, const std::string& destName = "IFACOM-CMS") :
m_latch(1),
m_doneLatch(1),
m_connection(NULL),
m_session(NULL),
m_destination(NULL),
m_consumer(NULL),
m_waitMillis(1000),
m_useTopic(useTopic),
m_sessionTransacted(sessionTransacted),
m_destName(destName),
m_brokerURI(brokerURI) {
}
IfacomAmqSender::~IfacomAmqSender() {
cleanup();
}
void IfacomAmqSender::close() {
this->cleanup();
}
void IfacomAmqSender::waitUntilReady() {
m_latch.await();
}
//------ Init connexion ---------------
void IfacomAmqSender::createConnection()
{
// Create a ConnectionFactory
auto_ptr<ConnectionFactory> connectionFactory(ConnectionFactory::createCMSConnectionFactory(m_brokerURI));
// Create a Connection
m_connection = connectionFactory->createConnection();
m_connection->start();
m_connection->setExceptionListener(this);
}
void IfacomAmqSender::createSession()
{
// Create a Session
if (this->m_sessionTransacted == true) {
m_session = m_connection->createSession(Session::SESSION_TRANSACTED);
} else {
m_session = m_connection->createSession(Session::AUTO_ACKNOWLEDGE);
}
}
void IfacomAmqSender::createDestination()
{
// Create the destination (Topic or Queue)
if (m_useTopic) {
m_destination = m_session->createTopic(m_destName);
} else {
m_destination = m_session->createQueue(m_destName);
}
}
void IfacomAmqSender::createProducer()
{
m_producer = m_session->createProducer(m_destination);
m_producer->setDeliveryMode(DeliveryMode::NON_PERSISTENT);
}
void IfacomAmqSender::initConnection() {
try {
createConnection();
// Create the session
createSession();
// Create the destination (Topic or Queue)
createDestination();
// Create a MessageProducer from the Session to the Topic or Queue
createProducer();
m_producer->setDeliveryMode(DeliveryMode::NON_PERSISTENT);
// Indicate we are ready for messages.
m_latch.countDown();
// Wait while asynchronous messages come in.
m_doneLatch.await(m_waitMillis);
} catch (CMSException& e) {
// Indicate we are ready for messages.
//latch.countDown();
e.printStackTrace();
}
}
void IfacomAmqSender::sendMessage(string text) {
try {
std::auto_ptr<TextMessage> message(m_session->createTextMessage(text));
// to set a property
////message->setIntProperty("Integer", ix);
m_producer->send(message.get());
message->setCMSTimestamp(System::currentTimeMillis());
} catch (CMSException& e) {
e.printStackTrace();
}
}
// Send a ActiveMQ Message
void IfacomAmqSender::sendMessage(std::auto_ptr<TextMessage> amq_message) {
try {
amq_message->setCMSTimestamp(System::currentTimeMillis());
m_producer->send(amq_message.get());
} catch (CMSException& e) {
e.printStackTrace();
}
}
//--------------------------------------------------
// If something bad happens you see it here as this class is also been
// registered as an ExceptionListener with the connection.
void IfacomAmqSender::onException(const CMSException& ex AMQCPP_UNUSED) {
printf("CMS Exception occurred. Shutting down client.\n");
ex.printStackTrace();
exit(1);
}
// Message Priority (0:Lowest - 9:Highest)
void IfacomAmqSender::setPriority(int priority){m_message_priority = priority;}
int IfacomAmqSender::getPriority(){return m_message_priority;}
// Message Delivery Mode
void IfacomAmqSender::setDeliveryMode(DeliveryMode delivery_mode){m_message_delivery_mode = delivery_mode;}
DeliveryMode IfacomAmqSender::getDeliveryMode(){return m_message_delivery_mode;}
Session* IfacomAmqSender::getSession()
{
return m_session;
}
void IfacomAmqSender::cleanup() {
if (m_connection != NULL) {
try {
m_connection->close();
} catch (cms::CMSException& ex) {
ex.printStackTrace();
}
}
// Destroy resources.
try {
delete m_destination;
m_destination = NULL;
delete m_consumer;
m_consumer = NULL;
delete m_session;
m_session = NULL;
delete m_connection;
m_connection = NULL;
} catch (CMSException& e) {
e.printStackTrace();
}
}
main.cpp
#include "ifacomamqsender.h"
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
and the error is:
Error 29 error C2512: 'IfacomAmqSender' : no appropriate default constructor available 42 1 GUI-CMS
In MainWindow you have a member variable called m_IfacomMessageBroker which is a IfacomAmqSender. This class doesn't have a default constructor, so you must call one of its constructors in the initialization list for MainWindow.
You're not doing this, so the compiler assumes you want to call the default construtor, and it notices that there isn't one, so you get the error. The reason there isn't a default constructor if because you've created your own constructors, so the compiler generated default doesn't exist. Therefore if you want a default constructor you need to manually create it.
I don't see a default constructor in the definition of the IfacomAmqSender object, but you have an instance of it in your MainWindow.
You have this line.
IfacomAmqSender m_IfacomMessageBroker;
This is trying to call a no arg constructor, and you don't have one.
You have:
IfacomAmqSender(const std::string&, int, bool, bool, const std::string&, int);
IfacomAmqSender(const std::string&, bool, bool, const std::string&);
... and need:
IfacomAmqSender();
... or you need to assign default values.
If I know right and I do, the default constructor is not available if the programmer is defining a constructor. You have done it, so there is no default constructor, only the ones that you have declared.
No default constructor is available for the specified class, structure, or union. The compiler supplies a default constructor if user-defined constructors are not provided.
If you provide a constructor that takes a non-void parameter, and you want to allow your class to be created with no parameters, you must also provide a default constructor. The default constructor can be a constructor with default values for all parameters.
For More Information refer :
http://msdn.microsoft.com/en-us/library/9zkz8dx6.aspx
Hi I am trying to send an HTTP GET request and receive the result with a function. But I am getting this error:
no matching function for call to 'HttpNetworkRequest::connect(QNetworkAccessManager*&, const char*, RequestFinishFunction&, const
char*)'
the connect function is in this HttpNetworkRequest.cpp file
#include "HttpNetworkRequest.hpp"
#include <QObject>
#include <QIODevice>
#include <QDir>
#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/XmlDataModel>
#include <RequestFinishFunction.hpp>
using namespace bb::cascades;
HttpNetworkRequest::HttpNetworkRequest(bb::cascades::Application *app)
: QObject(app)
{
QNetworkRequest networkRequest = QNetworkRequest();
networkRequest.setUrl(QUrl("http://www.blackberry.com"));
RequestFinishFunction req;
QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager;
bool res = connect(networkAccessManager,SIGNAL(finished(QNetworkReply*)),
req,SLOT(requestFinished()));
Q_ASSERT(res);
Q_UNUSED(res);
networkAccessManager->get(networkRequest);
}
The included RequestFinishFunction.hpp
#ifndef REQUESTFINISHFUNCTION_HPP_
#define REQUESTFINISHFUNCTION_HPP_
#include <bb/cascades/ActivityIndicator>
#include <QObject>
#include <QObject>
class RequestFinishFunction : QObject
{
public slots:
void requestFinished(QNetworkReply* reply);
};
#endif /* REQUESTFINISHFUNCTION_HPP_ */
The RequestFinishFunction.cpp file is
#include <bb/cascades/ActivityIndicator>
#include <QObject>
#include <QObject>
#include <RequestFinishFunction.hpp>
void RequestFinishFunction::requestFinished(QNetworkReply* reply)
{
reply->deleteLater();
}
Syntax of connect method
bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoConnection )
We have to pass references of both sender & receiver.
You didn't send reference of receiver. You have two options to do so.
1) Send reference of req using & operator in connect method call
Replace
connect(networkAccessManager,SIGNAL(finished(QNetworkReply*)), req,SLOT(requestFinished()));
with
connect(networkAccessManager,SIGNAL(finished(QNetworkReply*)), &req,SLOT(requestFinished()));
OR
2) Declare req as pointer
Replace
RequestFinishFunction req;
with
RequestFinishFunction *req;