Boost Signals2 tracking - c++

I am using Boost Signals2 in one of our project.In this I want automatic connection management,for this I am testing Boost Signals2 tracking but I am not getting slot invoked.
After I run following code , slots are not called .
Environment:
VS 2010,windows 7,boost 1.54
#include <stdio.h>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/shared_ptr.hpp>
typedef boost::signals2::signal<void ()> signal_test;
using namespace boost;
class SubjectTest
{
public:
void Connect(const signal_test::slot_type &subscriber)
{
m_Signal.connect(subscriber);
std::cout << "No of connections : " << m_Signal.num_slots() << std::endl;
}
void Notify()
{
m_Signal();
}
private:
signal_test m_Signal;
};
class Listner
{
public:
Listner(){}
~Listner(){}
Listner(std::string name)
:m_name(name)
{
}
void GotSignal()
{
std::cout << m_name << std::endl;
}
void ConnectWithTracking(SubjectTest *s)
{
shared_ptr<Listner> l = new Listner();
s->Connect(signal_test::slot_type(&Listner::GotSignal,l.get()).track(l));
}
void ConnectNormal(SubjectTest *s)
{
s->Connect(bind(&Listner::GotSignal,this));
}
private:
std::string m_name;
shared_ptr<Listner> l;
};
void main()
{
Listner l2("First");
SubjectTest sub;
try
{
l2.ConnectWithTracking(&sub);
//l2.ConnectNormal(&sub);
sub.Notify();
{
Listner l3("Second");
l3.ConnectWithTracking(&sub);
//l3.ConnectNormal(&sub);
sub.Notify();
}
sub.Notify();
}
catch(std::exception ex)
{
std::cout << ex.what() << std::endl;
}
std::cout << "Finish" <<std::endl;
}
Updated :
*Working now*
#include <stdio.h>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/shared_ptr.hpp>
typedef boost::signals2::signal<void ()> signal_test;
using namespace boost;
class SubjectTest
{
public:
void Connect(const signal_test::slot_type &subscriber)
{
m_Signal.connect(subscriber);
std::cout << "No of connections : " << m_Signal.num_slots() << std::endl;
}
void Notify()
{
m_Signal();
}
private:
signal_test m_Signal;
};
class Listner : public boost::enable_shared_from_this<Listner>
{
public:
Listner(){}
~Listner(){}
Listner(std::string name)
:m_name(name)
{
}
void GotSignal()
{
std::cout << m_name << std::endl;
}
void ConnectWithTracking(SubjectTest *s)
{
s->Connect(signal_test::slot_type(&Listner::GotSignal,shared_from_this().get()).track(shared_from_this()));
}
void ConnectNormal(SubjectTest *s)
{
s->Connect(bind(&Listner::GotSignal,this));
}
private:
std::string m_name;
};
void main()
{
shared_ptr<Listner> l2(new Listner("First"));
SubjectTest sub;
try
{
l2->ConnectWithTracking(&sub);
sub.Notify();
{
shared_ptr<Listner> l3(new Listner("Second"));
l3->ConnectWithTracking(&sub);
//l3.ConnectNormal(&sub);
sub.Notify();
}
sub.Notify();
}
catch(std::exception ex)
{
std::cout << ex.what() << std::endl;
}
std::cout << "Finish" <<std::endl;
}
Now this is complete example of Signal2 Automatic Connection Management

{
shared_ptr<Listner> l(new Listner());
s->Connect(signal_test::slot_type(&Listner::GotSignal,l.get()).track(l));
}
In the above lines l pointee gets destroyed at the closing } - meaning that the slot you just connected got expired.
The whole point of tracking is to pass to track() a shared_ptr (or weak_ptr), which is bound (or tightly related) to the slot itself. It doesn't make sense to pass a shared_ptr whose lifespan is unrelated to that of the slot itself.

Related

unique_ptr is not deleted after calling reset

This is my minimal, reproducible example
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
void do_func() {
while(true) {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
I was expecting the object to be deleted after reset is called. Even the code cannot exit because the while loop is blocking, which is understandable. I need to delete the object after a particular event, and cannot wait till the unique_ptr goes out of scope. If I change the do_func to
void do_func() {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(20));
}
then it is the expected behaviour.
Edit:
Based on your comments I have updated my code to
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
BaseClass() : x(1) {
dummy = std::make_shared<SomeClass>();
}
void do_func() {
while(true) {
std::cout << "doing stuff " << dummy->do_stuff(x) << std::endl;
x++;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
private:
int x;
class SomeClass {
public:
int do_stuff(int x) {
return x * x;
}
};
std::shared_ptr<SomeClass> dummy;
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
And now the function does print garbage values. Does that mean I need to explicitly delete dummy in the destructor?
The simplest way to synchronize these two threads would be to use std::atomic_bool
#include <atomic>
class BaseClass {
public:
std::atomic_bool shouldContinueWork = true;
void do_func() {
while(shouldContinueWork) {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
obj->shouldContinueWork = false; //the thread will not do anything more after this, but the sleep will need to end on it's own
std::cout << "stopping work!" << std::endl;
// do not remove the object before join is called - you don't know if it will be still accessed from the other thread or not
// obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
// here it is safe to remove the `obj`, main thread is surely the only thread that accesses it
// (but it goes out of scope anyway)
return 0;
}
This solution doesn't take into account stopping the work midway (i.e. whole loop iteration must always be performed) and is generally prone to having a few more or less iterations of work - it should be precise enough when you have sleep of 1s, but with smaller sleep it won't guarantee any exact number of iterations, take that into account. std::condition_variable can be used for more precise control of thread synchronization.
Thanks for all your quick responses! Let me know if this is a good solution
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
BaseClass() : x(1) {
dummy = std::make_shared<SomeClass>();
}
virtual ~BaseClass() {
dummy.reset();
}
void do_func() {
while(dummy) {
std::cout << "doing stuff " << dummy->do_stuff(x) << std::endl;
x++;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
private:
int x;
class SomeClass {
public:
int do_stuff(int x) {
return x * x;
}
};
std::shared_ptr<SomeClass> dummy;
};
class DerivedClass : public BaseClass {
};
int main() {
auto obj = std::make_unique<DerivedClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
The behaviour is now as expected.

How can I run miltiple ServerApplications with POCO C++?

I've started learning POCO C++ library and I'm stuck while trying to run 2 servers in the same application (so that they can use some common runtime variables). These are 2 different servers, one of them is TCP TimeServer and the other one is simple UDP EchoServer. The code:
#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/TCPServerParams.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Exception.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>
using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;
using Poco::Net::TCPServer;
using Poco::Timestamp;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
class TimeServerConnection : public TCPServerConnection
{
public:
TimeServerConnection(const StreamSocket& s, const std::string& format) :
TCPServerConnection(s),
_format(format)
{
}
void run()
{
Application& app = Application::instance();
bool isOpen = true;
Poco::Timespan timeOut(10, 0);
unsigned char incommingBuffer[1000];
app.logger().information("SYSLOG from " + this->socket().peerAddress().toString());
while (isOpen) {
if (socket().poll(timeOut, Poco::Net::Socket::SELECT_READ) == false) {
std::cout << "TIMEOUT!" << std::endl << std::flush;
} else {
int nBytes = -1;
try {
nBytes = socket().receiveBytes(incommingBuffer, sizeof(incommingBuffer));
std::cout << incommingBuffer << std::endl;
} catch (Poco::Exception& exc) {
std::cerr << "Network error: " << exc.displayText() << std::endl;
isOpen = false;
}
if (nBytes == 0) {
std::cout << "Client closes connection!" << std::endl << std::flush;
isOpen = false;
} else {
std::cout << "Receiving nBytes: " << nBytes << std::endl << std::flush;
}
}
}
try
{
Timestamp now;
std::string dt(DateTimeFormatter::format(now, _format));
dt.append("\r\n");
socket().sendBytes(dt.data(), (int)dt.length());
}
catch (Poco::Exception& exc)
{ app.logger().log(exc); }
}
private:
std::string _format;
};
class TimeServerConnectionFactory : public TCPServerConnectionFactory
{
public:
TimeServerConnectionFactory(const std::string& format) :
_format(format)
{
}
TCPServerConnection* createConnection(const StreamSocket& socket)
{ return new TimeServerConnection(socket, _format); }
private:
std::string _format;
};
class UDPServer : public Poco::Util::ServerApplication
{
public:
UDPServer(){}
~UDPServer(){}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void uninitialize() { ServerApplication::uninitialize(); }
int main(const std::vector<std::string>& args)
{
unsigned short port = (unsigned short)config().getInt("udpport", 9002);
std::cout << "[UDP] Using port " << port << std::endl;
std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT));
Poco::Net::SocketAddress socketaddress(Poco::Net::IPAddress(), 9001);
Poco::Net::DatagramSocket datagramsocket(socketaddress);
char buffer[1024]; // 1K byte
while (1) {
Poco::Net::SocketAddress sender;
int n = datagramsocket.receiveFrom(buffer, sizeof(buffer) - 1, sender);
buffer[n] = '\0';
std::cout << sender.toString() << ":" << buffer << std::endl;
}
return 0;
}
};
class TimeServer : public Poco::Util::ServerApplication
{
public:
TimeServer() : _helpRequested(false)
{
}
~TimeServer()
{
}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void uninitialize()
{
ServerApplication::uninitialize();
}
void defineOptions(OptionSet& options)
{
ServerApplication::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));
}
void handleOption(const std::string& name, const std::string& value)
{
ServerApplication::handleOption(name, value);
if (name == "help")
_helpRequested = true;
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A server application that serves the current date and time.");
helpFormatter.format(std::cout);
}
int main(const std::vector<std::string>& args)
{
if (_helpRequested)
{
displayHelp();
}
else
{
unsigned short port = (unsigned short)config().getInt("tcpport", 9911);
std::cout << "Using port " << port << std::endl;
std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT));
ServerSocket svs(port);
TCPServer srv(new TimeServerConnectionFactory(format), svs);
srv.start();
std::cout << "Server started!\n";
waitForTerminationRequest();
srv.stop();
std::cout << "Server stopped!\n";
}
return Application::EXIT_OK;
}
private:
bool _helpRequested;
};
int main(int argc, char** argv)
{
TimeServer app;
UDPServer app2;
app.run(argc, argv);
app2.run(argc, argv);
}
In the end of code I have int main() method where I'm trying to run 2 servers. However I get assertion violation here. There is a similar question on StackOverflow, however boost is used there while I'm using plain C++, so that solution is not relevant to me.
How can I run simultaneously these 2 servers?
ServerApplication was not designed for multiple instances. What you should do is run one ServerApplication and launch TCPServer and UDPServer in that application.
Actually if you want to made like this (as you question), seperated both
tcp (a) class and
udp (b) class.
Call both in other class (c) and
define which one
(c) -> (a)
(c) -> (b)
u need to call first and when. So u need make condition and decision.
Note: give them space time before run to made poco breath. 😂

cpprestsdk handler class crashes when using STL container as member

I wrote a simple code using cpprestsdk. I use a map (records) as a member of CommandHandler class, and manipulate it in a public method (has_record()).
it works before handler.open().wait() runs, but when I call it in a request, it crashes!
Here is my code:
#define BOOST_DATE_TIME_NO_LIB
#include <string>
#include <vector>
#include <cpprest/uri.h>
#include <cpprest/http_listener.h>
#include <cpprest/asyncrt_utils.h>
using namespace std;
using namespace web;
using namespace http;
using namespace utility;
using namespace http::experimental::listener;
class CommandHandler
{
public:
CommandHandler(utility::string_t url);
pplx::task<void> open() { return m_listener.open(); }
pplx::task<void> close() { return m_listener.close(); }
bool has_record();
private:
std::map< std::string, unsigned int > records;
void handle_get_or_post(http_request message);
http_listener m_listener;
};
bool CommandHandler::has_record()
{
return records.size() > 0 && records.find("1") != records.end();
}
CommandHandler::CommandHandler(utility::string_t url) : m_listener(url)
{
m_listener.support(methods::GET, std::bind(&CommandHandler::handle_get_or_post, this, std::placeholders::_1));
m_listener.support(methods::POST, std::bind(&CommandHandler::handle_get_or_post, this, std::placeholders::_1));
}
void CommandHandler::handle_get_or_post(http_request request)
{
if(this->has_record())
request.reply(status_codes::OK, 1);
else
request.reply(status_codes::OK, 0);
};
int main(int argc, char** argv)
{
try
{
utility::string_t address = U("http://127.0.0.1:9595");
uri_builder uri(address);
auto addr = uri.to_uri().to_string();
CommandHandler handler(addr);
if(handler.has_record())
std::cout<<"work!";
handler.open().wait();
ucout << utility::string_t(U("Listening for requests at: ")) << addr << std::endl;
ucout << U("Press ENTER key to quit...") << std::endl;
std::string line;
std::getline(std::cin, line);
handler.close().wait();
}
catch (std::exception& ex)
{
ucout << U("Exception: ") << ex.what() << std::endl;
ucout << U("Press ENTER key to quit...") << std::endl;
std::string line;
std::getline(std::cin, line);
}
return 0;
}
I found the problem but I don't understand why it throws. The problem is in this line of code:
request.reply(status_codes::OK, 0);
That 0 throws an exception

Interruptible thread implementation with Boost::thread

I'm using Boost::thread to implement an InterruptibleThread class, while getting segmentation fault during execution. Any idea?
The source and the output are under below.
interruptiblethread.h
#ifndef INTERRUPTIBLETHREAD_H
#define INTERRUPTIBLETHREAD_H
#include <boost/thread.hpp>
#include <boost/thread/future.hpp>
#include <boost/thread/tss.hpp>
class InterruptFlag
{
public:
inline void set()
{
boost::lock_guard<boost::mutex> guard(_mtx);
_set = true;
}
inline bool is_set()
{
std::cout << "is_set()" << std::endl;
boost::lock_guard<boost::mutex> guard(_mtx);
std::cout << "is_set() end" << std::endl;
return _set;
}
private:
boost::mutex _mtx;
bool _set;
};
extern boost::thread_specific_ptr<InterruptFlag> this_thread_interrupt_flag;
class InterruptibleThread
{
public:
template<typename FunctionType>
InterruptibleThread(FunctionType f)
{
boost::promise<InterruptFlag*> p;
_internal_thread = boost::thread([f, &p]()
{
p.set_value(this_thread_interrupt_flag.get());
f();
});
_interrupt_flag = p.get_future().get();
}
inline void interrupt()
{
if (_interrupt_flag != nullptr)
{
_interrupt_flag->set();
}
}
private:
boost::thread _internal_thread;
InterruptFlag* _interrupt_flag;
};
#endif // INTERRUPTIBLETHREAD_H
interruptiblethread.cpp
#include <iostream>
#include <functional>
#include "interruptiblethread.h"
using std::cout; using std::endl;
using std::function;
boost::thread_specific_ptr<InterruptFlag> this_thread_interrupt_flag;
struct thread_interrupted {};
void interruption_point()
{
cout << "interruption_point()" << endl;
if (this_thread_interrupt_flag->is_set())
{
cout << "is_set" << endl;
throw thread_interrupted();
}
}
void foo()
{
while (true)
{
cout << "iterate" << endl;
try
{
interruption_point();
} catch (const thread_interrupted& interrupt)
{
cout << "catch thread_interrupted" << endl;
break;
}
}
}
int main()
{
InterruptibleThread int_thread(foo);
int_thread.interrupt();
while (true) {}
}
Output:
➜ build ./main
iterate
interruption_point()
is_set()
[1] 44435 segmentation fault ./main
this_thread_interrupt_flag is not initialized. Please initialize it correctly as described here
Your call to is_set is UB.

how printing exception by a class function that contains the string to print?

I have this:
catch (Except& e) {
std::cout << e.print() << std::endl;
}
I want this to print: OK you won!
so I have the class:
class Except{
public:
std::string print() {
std::string error("OK you won!\n");
return error;
}
};
I have this error in the Except class: "'string' in namespace 'std' does not name a type"
You have to include the header for std::string : #include <string>
You're probably not throwing it right - works for me:
#include <iostream>
#include <string>
class Except{
public:
std::string stack() {
std::string error("OK you won!\n");
return error;
}
};
int main() {
try {
throw Except();
} catch (Except& e) {
std::cout << e.stack() << std::endl;
}
return 0;
};
Output:
OK you won!
Check the code below:
#include <iostream>
#include <string>
class Except{
public:
std::string stack() {
std::string error("OK you won!\n");
return error;
}
};
int main() {
try {
throw Except();
} catch (Except &e) {
std::cout << e.stack() << std::endl;
}
return 0;
}
The output is:
./a.out
OK you won!