Callback pattern with a Functor - c++11

I'm trying to wrap an HttpRequest object (from Cocos2d-x) in my own functor. Everything's working fine except calling the callback passed to my functor. Can you spot the error in the classes below? (I only pasted the relevant parts of the code).
Cloud.hpp:
#ifndef Cloud_hpp
#define Cloud_hpp
#include "external/json/document.h"
#include "network/HttpClient.h"
using namespace cocos2d::network;
typedef std::function<void()> CloudCallback;
class Cloud
{
private:
std::string url { "http://localhost:3000/1.0/" };
std::string end_point;
CloudCallback callback;
std::string getPath();
void onHttpRequestCompleted(HttpClient *sender, HttpResponse *response);
public:
Cloud (std::string end_point) : end_point(end_point) {}
void operator() (CloudCallback callback);
};
#endif /* Cloud_hpp */
This is the class that stores the callback passed in the constructor. Here's the implementation:
#include "Cloud.hpp"
#include <iostream>
std::string Cloud::getPath()
{
return url + end_point;
}
void Cloud::operator()(CloudCallback callback)
{
this->callback = callback;
std::vector<std::string> headers;
HttpRequest* request = new (std::nothrow) HttpRequest();
request->setUrl(this->getPath().c_str());
request->setRequestType(HttpRequest::Type::GET);
request->setHeaders(headers);
request->setResponseCallback(CC_CALLBACK_2(Cloud::onHttpRequestCompleted, this));
HttpClient::getInstance()->send(request);
request->release();
}
void Cloud::onHttpRequestCompleted(HttpClient *sender, HttpResponse *response)
{
this->callback();
}
What I'm trying to do is, make a simple Http request with the help of a functor, calling like this:
Cloud cloud("decks");
cloud([&]() {
CCLOG("Got the decks");
});
I'm getting EXC_BAD_ACCESS(Code=EXC_I386_GPFLT) as soon as the line
this->callback();
is called.
What is it that I am doing wrong here?
EDIT: Now I guess it's something to do with threads. If I remove the HttpRequest and call the callback method passed to the operator() immediately, this works without any problems. Begging for help :-)

It looks like the problem could be a lifetime issue. Since the http response callback is called asynchronously, some objects may have been destroyed in the meantime. There are two possibilities:
The Cloud object itself is destroyed before the callback is called.
One or more objects referenced by the lambda (since you're capturing by reference), may have also gone out of scope and been destroyed.

Try this:
void Cloud::operator()(const CloudCallback &callback)

Related

C++11 Call virtual member function

I`m trying to implement something like this using C++11.
class Proto{
public:
virtual void fu() = 0;
};
class Impl: public Proto{
public:
void fu();
};
void Impl::fu(){
LOG_INFO("im fu");
}
class Inv{
public:
void useFu(void (Proto::*)());
};
void Inv::useFu(void (Proto::*fu)()){
//fu();
};
void main(){
Impl impl;
Inv inv;
//inv.useFu(impl.fu);
}
useFu(void (Proto::*)()) must be declared in this way because, fu() uses some specific to Proto functionality's
I have two places were things going wrong.
First is fu() call itself and second how to pass fu as parameter inv.useFu(impl.fu).
Edit after bipll answer
The suggested usage of inv.useFu() solves the second problem of my question.
inv.useFu(static_cast<void (Proto::*)(void)>(&Impl::fu));
But I still need to call fu as a pointer to member function;
The way your useFu is declared now, it should be called as
inv.useFu(static_cast<void (Proto::*)(void)>(&Impl::fu));
But I guess that's not what you wanted. It should rather be
template<class F> void useFu(F &&f) { std::invoke(std::forward<F>(f)); }
or simply
void useFu(std::function<void()> f) { std::invoke(std::move(f)); }
and called as
useFu([&]{ impl.fu(); });
(Rather than using a lambda you can bind the method to the object with std::bind in the latter call but almost nobody ever does that.)

wxTimer not calling overriden Notify()

I'm running into an issue where I implemented a derived wxTimer class to override the Notify() call since I'm not using an owner implementation as described in the documentation.
When I debug the run, I can see
the timer is being instantiated
my_timer_instance->IsRunning() returns true
MyTimer::Notify() is never called
This leads me to believe that the timer is being set and running, but when it expires it's calling the base class Notify() procedure and not my override it's not calling notify() but I'm not sure why.
EDIT: I added frame->getTimer()->Notify(); to my app and the correct procedure was called. Therefore, the timer just isn't calling Notify when it expires.
EDIT2: Added this minimal working example, and the timer works as expected. I'll try to compare the two and see what the problem is.
MyApp.hpp
#pragma once
#ifndef __NONAME_H__
#define __NONAME_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/statusbr.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/frame.h>
#include <wx/timer.h>
///////////////////////////////////////////////////////////////////////////
class MyTimerClass : public wxTimer
{
wxFrame* MyFrame;
public:
MyTimerClass(wxFrame* frame): MyFrame(frame) {};
void Notify() override;
};
///////////////////////////////////////////////////////////////////////////////
/// Class MyFrame1
///////////////////////////////////////////////////////////////////////////////
class MyFrame1 : public wxFrame
{
private:
protected:
wxStatusBar* m_statusBar1;
MyTimerClass* MyTimer;
public:
void StartTimer(int TimeInSeconds);
MyFrame1(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(500, 300), long style = wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL);
~MyFrame1();
};
#endif //__NONAME_H__
MyApp.cpp
#include "MyApp.hpp"
#include "wx/wxprec.h"
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
///////////////////////////////////////////////////////////////////////////
void MyTimerClass::Notify()
{
MyFrame->SetStatusText("Timer popped", 0);
}
MyFrame1::MyFrame1(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxFrame(parent, id, title, pos, size, style)
{
MyTimer = new MyTimerClass(this);
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
m_statusBar1 = this->CreateStatusBar(1, wxSTB_SIZEGRIP, wxID_ANY);
this->Centre(wxBOTH);
this->StartTimer(5);
}
void MyFrame1::StartTimer(int TimeInSeconds)
{
SetStatusText("Timer started with " + std::to_string(TimeInSeconds) + " seconds.");
MyTimer->Start(TimeInSeconds * 1000);
}
MyFrame1::~MyFrame1()
{
}
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
// the application icon (under Windows it is in resources and even
// though we could still include the XPM here it would be unused)
#ifndef wxHAS_IMAGES_IN_RESOURCES
#include "../sample.xpm"
#endif
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
class MyApp : public wxApp
{
public:
virtual bool OnInit() wxOVERRIDE;
};
enum
{
// menu items
Minimal_Quit = wxID_EXIT,
Minimal_About = wxID_ABOUT
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
// call the base class initialization method, currently it only parses a
// few common command-line options but it could be do more in the future
if (!wxApp::OnInit())
return false;
// create the main application window
MyFrame1 *frame = new MyFrame1(NULL, -1, "Test Frame");
frame->Show(true);
return true;
}
#BobbyTables,
From the documentation:
This member should be overridden by the user if the default
constructor was used and SetOwner() wasn't called.
Is it the case?
Nothing seems to be wrong in the code you show (although I'd change a few things, such as using raw pointer for my_timer_instance), so the problem must be elsewhere. As usual, the best would be to come up with a SSCCE, without it I can only offer some guesses as to what the problem actually is.
Are you running the event loop? The timers will only fire when it's running, so if you block doing some computation, this wouldn't happen.
Also, what is frame in Notify()? Is this a global (I'd rather pass it as parameter to MyTimer ctor)?
So after mimicking the code provided in the question, the following changes were made:
Instead of using a getter and setter to access the private timer member, I instead use
void refreshTimer(int time_in_seconds) in my parent frame class and create the timer in the parent frame's constructor rather than letting the app create it and pass it in.
I don't see why either of those two things would change the behavior of the timer but the timer now works as expected. I apologize for not being able to identify a concrete bug as the source of the problem.
NOTE: This behavior was caused by the timer being invoked outside the wxwindow's thread. Be careful when creating multithreaded programs using wxwidgets as a GUI. To circumvent this issue since I needed the timer to be invoked in a different thread, I created my own timer class that works correctly.

std::bind and CC_CALLBACK_(0~3)

#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)
Please forgive my poor English~~~!
The header file "ccMacros.h" inCocos2d-x 3.x,CC_CALLBACK Technology use the the new ISO C++ standard std::bind, for instance:
class HelloWorldScene : cocos2d::Layer
{
public :
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(HelloWorldScene);
// overload this function
void ontouchmoved(cocos2d::Touch*, cocos2d::Event*);
};
// HelloWorld.cpp
bool HelloWorldScene::init()
{
auto listener = cocos2d::EventListenerTouchOneByOne::create();
listener->onTouchBegan = [](cocos2d::Touch* _touch, cocos2d::Event* _event){ CCLOG("onTouchBegan..."); return true;};
// using the CC_CALLBACK
listener->onTouchMoved = CC_CALLBACK_2(HelloWorldScene::ontouchmoved, this);
listener->onTouchEnded = [](cocos2d::Touch* _touch, cocos2d::Event* _event){ CCLOG("onTouchEnded...");};
cocos2d::Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
return true;
}
void HelloWorldScene::ontouchmoved(cocos2d::Touch* touch, cocos2d::Event* event)
{
CCLOG("onTouchMoved...");
}
I send this function "HelloWorld::ontouchmoved" and pointer "this", `"HelloWorld::ontouchmoved" is selector in CC_CALLBACK_2, "this" is target in CC_CALLBACK_2。
but why? I send no more parameter to CC_CALLBACK_2, but the definition of CC_CALLBACK_2 is :
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
The placeholders_1 and placehoders_2 bind no parameters, What's the use of them? I guess them bind the parameters of HelloWorld::ontouchmoved, but i don't kown the way to bind parameters of HelloWorld::ontouchmoved。
Help me!Thanks a lot!
I don't exactly understand your question, but why not use lambda functions?:
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = [&](Touch* touch, Event* event){
};
listener->onTouchMoved = [&](Touch* touch, Event* event){
};
listener->onTouchEnded = [&](Touch* touch, Event* event){
};
listener->onTouchCancelled = [&](Touch* touch, Event* event){
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
Please read more detail in addEventListenerWithSceneGraphPriority function. Touch and Event added at this point.
The purpose of std::placeholders::_N is to allow std::bind to create a function with parameters matching the Nth parameter of the original function.
You can attach values instead of placeholder if you want to create a function that takes fewer parameters (wrap around the original function) or reorders or duplicates the original parameters. You can also bind any variables passed in by value or by reference.
You'll want to read up a little more on std::bind if you want to learn more about all the crazy things you can do.
http://en.cppreference.com/w/cpp/utility/functional/bind

asio socket, inside a class declaration, scope issue

I want to have a class inside which I initialize and open a tcp socket, but I want to repeatedly write to the socket only by calling a method of that class, without having to re-establish connection everytime.
My code is below. I get the compile time errors as pasted here below the code block.
The method is unable to see the socket that was initialized in the constructor. Seems to be a simple C++ "scope" issue, but beats me!
#include <ctime>
#include <iostream>
#include <string>
#include <asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using asio::ip::udp;
using asio::ip::tcp;
class rpcClass {
char sendBuffer[16];
asio::ip::tcp::endpoint epdPt;
asio::io_service io_service;
asio::ip::tcp::endpoint endPt;
public:
rpcClass () { // constructor
asio::ip::tcp::socket socketTCP(io_service);
strcpy (sendBuffer, "*Constructor*\n");
endPt = asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"),\
boost::lexical_cast<int>(5004));
socketTCP.connect(endPt);
socketTCP.write_some (asio::buffer(sendBuffer));
};
void sendRPCData (void) { //send data when called from main()
strcpy (sendBuffer, "rpcData\n");
socketTCP.write_some (asio::buffer(sendBuffer));
};
};
int main(void) {
rpcClass rpc; // I WANT THE rpc OBJECT TO SEND DATA
rpc.sendRPCData (); // ONLY WHEN THIS METHOD IS CALLED
return (0);
}
Here is the error output (Eclipse)
rpc-class.cpp: In member function ‘void rpcClass::sendRPCData()’:
rpc-class.cpp: error: ‘socketTCP’ was not declared in this scope
Thanks a lot for helping!
-pn
You've declared socketTCP as a local variable in the constructor, not a member variable of the class.
That means you can't use it in other functions.
Presumably you meant to declare a member variable, and initialize that in the constructor instead of a local variable.

how do we access the socket handle inside a boost asio completion handler?

Is there any possible way to access the socket handle inside a boost asio async completion handler ? i looked at the boost asio placeholders but there is no variable which stores the socket handle.
You can just arrange for it, anyway you would outside boost or asio.
To bind a function that takes e.g. a socket to expose a void() function you can use bind:
int foo(std::string const& s, int);
std::function<void()> adapted = std::bind(foo, "hello world", 42);
So, usually you'd have code similar to this:
boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
boost::bind(&client::handle_connect, this, boost::asio::placeholders::error));
Note, by using bind and this, we've bound a member function to the completion handler:
struct client
{
// ....
void handle_connect(boost::system::error_code err)
{
// you can just use `this->socket_` here
// ...
}
};
This implies that in handle_connect we can just use the socket_ member variable.
However, if you want to make things complicated you can use free functions as well
boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
boost::bind(&free_handle_connect, boost::ref(socket_), boost::asio::placeholders::error));
Now the implied handler function looks like
static void free_handle_connect(
boost::asio::ip::tcp::socket& socket_,
boost::system::error_code err)
{
// using `socket_` as it was passed in
int fd = _socket.native_handle_type();
}

Resources