boost signal-slot generalisation - c++

I am searching for a way to implement something like this, using boost
class GenBoost{
boost::signal<void(void)> m_signal;
std::function<void (bool)> m_function
public:
void setSignal(boost::signal<void(void)> sigArg)
{
m_signal = sigArg;
}
void setFunction(std::function<void (bool)> &functionArg)
{
m_function = functionArg;
m_signal.connect(boost::bind(&GebBoost::onSignal,this,_1));
}
void onSignal(){
//do something
}
};
How can this be achieved. signal copying is not possible!?

I am not 100% sure of your intent, but assuming that onSignal() will not need to interact with m_signal (and that you only need one connection to m_signal), it appears that you can decouple m_signal from your class entirely. For example, if you really do not want the body of 'onSignal()' to be called until a 'm_function' has been set, you could do something like:
class GenBoost{
std::function<void (bool)> m_function;
boost::signals::scoped_conection m_connection;
public:
void setSignal(boost::signal<void(void)>& sigArg)
{
m_connection = sigArg.connect(boost::bind(&GebBoost::onSignal,this));
}
void setFunction(std::function<void (bool)> &functionArg)
{
m_function = functionArg;
}
void onSignal()
{
if ( m_function )
do_work();
}
void do_work()
{
//do something
}
};
Note that I stripped the last _1 from m_signal.connect(boost::bind(&GebBoost::onSignal,this,_1)); because the signal is declared as type void(void) so should be connected to a void callback. I also added the scoped_connection so that if the object of type GenBoost is destroyed before the signal it is connected to, it will automatically disconnect rather than allow the signal to retain an invalid pointer.
Alternatively, if you needed to retain a reference to the original signal, you could add back your original signal member, but as a pointer boost::signal<void(void)>* m_signal;. Then setSignal becomes:
void setSignal(boost::signal<void(void)>& sigArg)
{
m_signal = &sigArg;
m_connection = m_signal->connect(boost::bind(&GebBoost::onSignal,this));
}
I still recommend using the scoped connection and connecting in setSignal so that you ensure you only have one connection to one signal (If setSignal is called twice, the connection to the first signal is automatically disconnected). If you go the pointer route, you must externally ensure that the passed-in signal has a lifetime longer than the GenBoost object.

Related

shared_from_this() causes std::bad_weak_ptr even when correctly using make_shared

I am creating a C++ server application using standalone Asio and C++11 and am getting an error, which is why I am asking for help.
The error
In the class worker_thread, during the call to shared_from_this(), a bad_weak_ptr exception is raised, which causes the program to crash.
The layout
The class connection_manager creates and stores objects of type std::shared_ptr<worker_thread> inside a std::vector container
The class worker_thread inherits from std::enable_shared_from_this<worker_thread>.
The class worker_thread creates objects of type std::shared_ptr<connection>.
The class connection requires a pointer (which is a shared pointer) to the class worker_thread, so that in can call the void handle_finish(std::shared_ptr<connection>)
Program flow
The class worker_thread is created via its constructor, from the class connection_manager using std::make_shared<worker_thread> with two shared pointers as parameters.
void init() is called from worker_thread by connection_manager
Later in the program, connection_manager calls std::shared_ptr<connection> get_available_connection() from worker_thread
During this method's execution, a new connection is created via std::make_shared<connection>, and one of the arguments is the shared pointer to the current worker_thread obtained via shared_from_this()
During the shared_from_this() call, the program crashes with a bad_weak_ptr exception.
Research
From my research, the most common causes of this error are:
When shared_from_this() is called within a constructor (or a function which is called by the constructor)
When there is no existing std::shared_ptr pointing to the object.
In my program:
The call to the constructor and the get_available_connection() are separate, and through outputing lines in the terminal, it seems that the worker_thread is constructed and initialised by the time the call to get_available_connection() occurs
The connection_manager class holds a shared pointer to every worker_thread object.
Code
All something_ptr are std::shared_ptr<something>
Header files
connection_manager.hpp
typedef asio::executor_work_guard<asio::io_context::executor_type>
io_context_work;
std::vector<worker_thread_ptr> workers;
std::vector<io_context_ptr> io_contexts;
std::vector<io_context_work> work;
worker_thread.hpp
class worker_thread : std::enable_shared_from_this<worker_thread> {
public:
/// Create a worker thread.
explicit worker_thread(io_context_ptr io, config_ptr vars_global);
void init();
void join();
connection_ptr get_available_connection();
//...
connection.hpp
explicit connection(std::shared_ptr<worker_thread> worker,
std::shared_ptr<asio::io_context> io,
config_ptr vars_parent);
Source files
connection_manager.cpp
connection_manager::connection_manager(config_ptr vars) {
std::size_t number_of_threads = vars->worker_threads;
while(number_of_threads > 0) {
io_context_ptr io_context(new asio::io_context);
io_contexts.push_back(io_context);
work.push_back(asio::make_work_guard(*io_context));
worker_thread_ptr worker =
std::make_shared<worker_thread>(io_context, vars);
workers.push_back(worker);
worker->init();
--number_of_threads;
}
}
connection_ptr connection_manager::get_available_connection() {
std::size_t index_of_min_thread = 0;
std::size_t worker_count = workers.size();
for(std::size_t i = 1; i < worker_count; ++i) {
if(workers[i]->active_connection_count() <
workers[index_of_min_thread]->active_connection_count())
index_of_min_thread = i;
}
return workers[index_of_min_thread]->get_available_connection();
}
worker_thread.cpp
worker_thread::worker_thread(io_context_ptr io,
config_ptr vars_global)
:io_context(io), active_conn_count(0), vars(vars_global),
worker(
[this]() {
if(io_context)
io_context->run();
}
) {}
void worker_thread::init() {
//Additional initialisation, this is called by connection_manager
//after this thread's construction
}
connection_ptr worker_thread::get_available_connection() {
connection_ptr conn;
if(!available_connections.empty()) {
conn = available_connections.front();
available_connections.pop();
active_connections.insert(conn);
return conn;
} else {
conn = std::make_shared<connection>(shared_from_this(), io_context, vars);
active_connections.insert(conn);
return conn;
}
}
I am sorry if this question has been answered before, but I tried to resolve this, and after trying for some time, I decided it would be better to ask for help.
EDIT
Here is a minimum test, which fails. It requires CMake, and you might have to change the minimum required version.
Google Drive link
I think your problem might be that you use default private inheritance.
here is a simple example of a program that crashes:
class GoodUsage : public std::enable_shared_from_this<GoodUsage>
{
public:
void DoSomething()
{
auto good = shared_from_this();
}
};
class BadUsage : std::enable_shared_from_this<BadUsage> // private inheritance
{
public:
void DoSomething()
{
auto bad = shared_from_this();
}
};
int main()
{
auto good = std::make_shared<GoodUsage>();
auto bad = std::make_shared<BadUsage>();
good->DoSomething(); // ok
bad->DoSomething(); // throws std::bad_weak_ptr
}

Accessing member variables within a boost::asio::spawned coroutine

I'm trying to add some async operations deep within an existing codebase, which is being called within a web server implemented using pion (which itself uses boost::asio).
The current code needs to continue operating in contexts where there is no io_service available, so I did the following, where Foo::bar is the main entry point of the existing codebase, and handleRequest is the pion request handler:
class Foo
{
public:
void bar(std::string input, boost::asio::io_service* io = NULL)
{
ioService = io;
if ( io == NULL )
{
barCommon(input);
}
else
{
boost::asio::spawn(*io, boost::bind(&Foo::barAsync, this, input, _1));
}
}
void barAsync(std::string input, boost::asio::yield_context yc)
{
barCommon(input, &yc);
}
void barCommon(std::string input, boost::asio::yield_context* yieldContext = NULL)
{
// Existing code here, with some operations performed async
// using ioService and yieldContext if they are not NULL.
}
private:
boost::asio::io_service* ioService;
// Other member variables, which cause a crash when accessed
}
void handleRequest(pion::http::request_ptr request, pion::tcp::connection_ptr connection)
{
Foo* foo = acquireFooPointer();
foo->bar(std::string(request->get_content()), &connection->get_io_service());
}
This seems to work insofar as it ends up running Foo::barCommon inside a coroutine, but the existing code crashes as soon as it tries to access Foo member variables. What am I missing here?
EDIT: Just to be clear, the pointer acquired in handleRequest is to a heap-allocated Foo object whose lifetime matches that of the server process.

How should I restructure this event-handling code?

I've been reading some C++ books (Sutters, Meyers) lately which motivated me to start using smart pointers (and object destruction in general) more effectively. But now I'm not sure how to fix what I have.
Specifically, I now have a IntroScene class which inherits from both Scene and InputListener.
Scene isn't really relevant, but the InputListener subscribes to an InputManager on construction,
and unsubs again on destruction.
class IntroScene : public sfg::Scene, public sfg::InputListener {
/*structors, inherited methods*/
virtual bool OnEvent(sf::Event&) override; //inputlistener
}
But now, if the inputmanager sends events over to a scene, and the scene decided to replace itself
because of it, I have function running on an object that no longer exists.
bool IntroScene::OnEvent(sf::Event& a_Event) {
if (a_Event.type == sf::Event::MouseButtonPressed) {
sfg::Game::Get()->SceneMgr()->Replace(ScenePtr(new IntroScene()));
} //here the returned smartpointer kills the scene/listener
}
Side-question: Does that matter? I googled it but did not find a definite yes or no. I do know 100%
no methods are invoked on the destroyed object after it is destroyed.
I can store the Replace() return value until the end of the OnEvent() method if I have to.
The real problem is InputListener
InputListener::InputListener() {
Game::Get()->InputMgr()->Subscribe(this);
}
InputListener::~InputListener() {
if (m_Manager) m_Manager->Unsubscribe(this);
}
since it is called during OnEvent(), which is called by InputManager during HandleEvents()
void InputManager::HandleEvents(EventQueue& a_Events) const {
while (!a_Events.empty()) {
sf::Event& e = a_Events.front();
for (auto& listener : m_Listeners) {
if (listener->OnEvent(e)) //swallow event
break;
}
a_Events.pop();
}
void InputManager::Subscribe(InputListener* a_Listener) {
m_Listeners.insert(a_Listener);
a_Listener->m_Manager = this;
}
void InputManager::Unsubscribe(InputListener* a_Listener) {
m_Listeners.erase(a_Listener);
a_Listener->m_Manager = nullptr;
}
So when the new Scene+Listener is created, and when the old one is destroyed, the list m_Listeners is modified during the loop. So the thing breaks.
I've thought about setting a flag when starting and stopping the loop, and storing (un)subscriptions that happen while it is set in a separate list, and handle that after. But it feels a bit hacky.
So, how can I actually redesign this properly to prevent these kind of situations? Thanks in advance.
EDIT, Solution:
I ended up going with the loop flags and deferred entry list (inetknight's answer below)
for subscription only, since that can be safely done later.
Unsubscriptions have to be dealt with immediately, so instead of storing raw pointers I store a (pointer-mutable bool) pair (mutable since a set only returns a const_iterator). I set the bool to false when that happens and check for it in the event loop (see dave's comment below).
Not sure it's cleanest possible solution, but it works like a charm. Thanks a lot guys
Side-question: Does that matter? I googled it but did not find a definite yes or no. I do know 100% no methods are invoked on the destroyed object after it is destroyed. I can store the Replace() return value until the end of the OnEvent() method if I have to.
If you know 100% no methods are invoked ont he destroyed object and none of its member variables are accessed, then it's safe. Whether or not it's intended is up to you.
You could have another list of objects which have requested to be un/subscribed. Then after you've told everyone in the list of events, you would then process the list of un/subscription requests before continuing on to the next event.
/* this should be a member of InputManager however you did not provide a class definition */
typedef std::pair<InputListener *, bool> SubscriptionRequest;
bool handleEventsActive = false;
std::vector<SubscriptionRequest> deferredSubscriptionRequests;
void InputManager::HandleEvents(EventQueue& a_Events) const {
// process events
handleEventsActive = true;
while (!a_Events.empty()) {
sf::Event& e = a_Events.front();
for (auto& listener : m_Listeners)
{
//swallow event
if (listener->OnEvent(e)) {
break;
}
}
a_Events.pop();
// process deferred subscription requests occurred during event
while ( not deferredSubscriptionRequests.empty() ) {
SubscriptionRequest request = deferredSubscriptionRequests.back();
deferredSubscriptionRequests.pop_back();
DoSubscriptionRequest(request);
}
}
handleEventsActive = false;
}
void InputManager::DoSubscriptionRequest(SubscriptionRequest &request) {
if ( request.second ) {
m_Listeners.insert(request.first);
request.first->m_Manager = this;
} else {
m_Listeners.erase(request.first);
request.first->m_Manager = nullptr;
}
}
void InputManager::Subscribe(InputListener* a_Listener)
{
SubscriptionRequest request{a_Listener, true};
if ( handleEventsActive ) {
deferredSubscriptionRequests.push_back(request);
} else {
DoSubscriptionRequest(request);
}
}
void InputManager::Unsubscribe(InputListener* a_Listener)
{
SubscriptionRequest request{a_Listener, false};
if ( handleEventsActive ) {
deferredSubscriptionRequests.push_back(request);
} else {
DoSubscriptionRequest(request);
}
}

Unable to receive a message using message_queue in Boost thread

I have a requirement for creating a Event based Multi-thread application for which i am trying to use boost::thread and boost/interprocess/ipc/message_queue for sending messages between threads.
What i am doing currently is making the thread wait in its workerfunction to wait for a message.
Actually this is just for basic start where the sender and receiver both is a same thread, on later stage i have thought to store a list of message_queue corresponding for each thread and then fetch it accordingly or something like that.
But now, as per the code below i am using
//in a common class
typedef struct s_Request{
int id;
}st_Request;
//in thread(XYZ) class
st_Request dataone;
message_queue *mq;
void XYZ::threadfunc(void *ptr)
{
XYZ*obj = (XYZ*) ptr;
obj->RecieveMsg();
}
void XYZ::RecieveMsg()
{
message_queue mq1(open_only,"message_queue");
if(!(mq1.try_receive(&dataone, sizeof(st_Request), recvd_size, priority)))
printf("msg not received");
printf("id = %d",dataone.id);
}
void XYZ::Create()
{
mq= new message_queue(open_or_create,"message_queue",100,sizeof(st_Request));
boost:thread workerthread(threadfunc,this);
workerthread.join();
}
void XYZ::Send(st_Request *data)
{
if (!(mq->try_send(data, sizeof(st_Request), 0)))
printf("message sending failed");
}
//I am calling it like
class ABC: public XYZ
{
..some functions to do stuff... };
void ABC::createMSGQ()
{
create();
st_Request *data;
data->id =10;
send(data);
}
My thread is waiting in RecieveMsg but i am not getting any msg and the prints are coming till Send function entry and than the code crash.
Please Guide me for what i am doing wrong, if the approach is entirely wrong, i am open to move to new approach.
P.s. this is my first question on stack overflow i tried follow the guidelines still if i strayed away anywhere please do correct.
st_Request *data;
data->id =10;
data is uninitialized, you cannot dereference it. Pointers should point to something before you dereference them.
I don't understand the point of this function:
void XYZ::Create()
{
mq= new message_queue(open_or_create,"message_queue",100,sizeof(st_Request));
boost:thread workerthread(threadfunc,this);
workerthread.join();
}
You create a new thread, then block and wait for it to finish so you can join it. Why not just do the work here, instead of creating a new thread and waiting for it to finish?
What is threadfunc? Do you mean ThreadFunc?
This function is written strangely:
void XYZ::ThreadFunc(void *ptr)
{
XYZ*obj = (XYZ*) ptr;
obj->RecieveMsg();
}
Why not pass the argument as XYZ* instead of void*? Boost.Thread doesn't require everything to be passed as void*. Is that function static? It doesn't need to be:
struct XYZ {
void threadFunc();
void create();
void recv();
};
void XYZ::threadFunc()
{
recv();
}
void XYZ::create()
{
boost::thread thr(&XYZ::threadFunc, this);
thr.join();
}

Any way to cancel signal propagation in boost signals2 without exceptions?

I'd like to use boost::signals2 to handle event notification in my C++ app. I'm hoping to implement something with similar functionality to browser DOM events, specifically the ability to stop the propagation of an event so that the current receiver is the last one to know about a signal and subsequent receivers are not called. (see http://www.w3.org/TR/DOM-Level-3-Events/#events-event-type-stopImmediatePropagation for more on how this works in browsers)
I have a hypothetical App class with a signal called thingHappened. It's likely there'll only be one App instance, with several other Widget classes of varying types that will connect to thingHappened to receive ThingEvent notifications. Sometimes the widget would like to consume (stop) the ThingEvent so that no other Widgets are notified.
At first I wondered if I could achieve this with a shared_connection_block but now I understand that this only suppresses one connection at a time. Initially I passed a shared_ptr<ThingEvent> to my signal but once the signal was called there was no way to intervene with its propagation. If I pass a shared_ptr I could have signal receivers check a value on the event and return if it's set, but I don't want to push that detail off to users of my library.
The solution I've found is to pass a ThingEvent on the stack so that it is copied for each receiver. If I set mStopPropagation on the event then when it is destroyed I can throw an exception and the signal calls terminate. The downside to this is that I need my own try/catch at the point where the signal is called, and stylistically it means I'm using an exception for an unexceptional purpose. Is there a better way?
Here's my hypothetical App class, with a signal thingHappened:
class App
{
public:
boost::signals2::signal<void (class ThingEvent)> thingHappened;
};
My ThingEvent class, with some data about the event (e.g. type) and an mStopPropagation property that will cause an exception to be thrown if it is set in the destructor:
class ThingEvent
{
public:
ThingEvent(string type): mType(type), mStopPropagation(false) { }
~ThingEvent()
{
if (mStopPropagation) {
throw exception();
}
}
void stopPropagation() { mStopPropagation = true; }
string getType() { return mType; }
private:
string mType;
bool mStopPropagation;
};
Here's a sample signal consumer, a Widget, that will call stopPropagation() on an event if the type is "goat":
class Widget
{
public:
Widget(string name): mName(name) {}
~Widget() {}
void thingHappened(ThingEvent thing)
{
cout << thing.getType() << " thingHappened in widget " << mName << endl;
if (thing.getType() == "goat") {
thing.stopPropagation();
}
}
string getName()
{
return mName;
}
private:
string mName;
};
Finally, here's a quick main() function that uses these classes:
int main()
{
App app;
Widget w1("1");
Widget w2("2");
Widget w3("3");
boost::signals2::connection c1 = app.thingHappened.connect(boost::bind(&Widget::thingHappened, &w1, _1));
boost::signals2::connection c2 = app.thingHappened.connect(boost::bind(&Widget::thingHappened, &w2, _1));
boost::signals2::connection c3 = app.thingHappened.connect(boost::bind(&Widget::thingHappened, &w3, _1));
// all three widgets will receive this
app.thingHappened(ThingEvent("otter"));
{
// suppress calls to c2
boost::signals2::shared_connection_block block(c2,true);
// only w1 and w3 will receive this
app.thingHappened(ThingEvent("badger"));
}
// Widgets call ThingEvent::stopPropagation() if the type is "goat"
try {
// only w1 will receive this
app.thingHappened(ThingEvent("goat"));
} catch (exception &e) {
// ThingEvent's destructor throws if mStopPropagation is true
std::cout << "exception thrown by thingHappened(goat)" << std::endl;
}
return 0;
}
If you have boost to hand (I'm using 1.44) and you want to compile it, the full code and Makefile are at https://gist.github.com/1445230
You can do this with a custom signal combiner. These are explained in the "Signal Return Values (Advanced)" section of the boost.signals tutorial: http://www.boost.org/doc/libs/1_48_0/doc/html/signals/tutorial.html#id3070223
Here's the gist of it:
struct MyCombiner {
typedef bool result_type;
template <typename InputIterator> result_type operator()(InputIterator aFirstObserver, InputIterator aLastObserver) const {
result_type val = false;
for (; aFirstObserver != aLastObserver && !val; ++aFirstObserver) {
val = *aFirstObserver;
}
return val;
}
};
The input iterators to operator() refer to the collection of slots for the signal. Each time you dereference one of the iterators, it calls the slot. So you can let one of the slots return a value to indicate that it doesn't want any further slots to be called.
Then you just pass it in to the second template arg of your signal:
boost::signals2::signal<bool(ThingEvent), MyCombiner> sig;
Now you can implement thingHappened to return a bool value indicating whether or not you want the signal to be stopped.