C++11 Observers Pass parameters on Notify - c++11

I'm coming from C# and trying to implement a simple Events/EventHandler pattern in c++11 which i believe the common name is Observers and signals, i know there are boost library and others but i dont want to use any external libs.
While searching online I found a simple implementation for what I need, so I took and modified the code and it works ok.
My problem is that the parameters are passed when registering events/observers, and not when raising/signaling/notifying which I find a bit awkward.
class EventManager
{
private:
static std::map<EventType, std::vector<std::function<void()>>> _eventHandlers;
public:
EventManager() = default;
template <typename EventHandler>
static void RegisterEventHandler(EventType&& eventType, EventHandler&& eventHandler)
{
EventManager::_eventHandlers[std::move(eventType)].push_back(std::forward<EventHandler>(eventHandler));
}
static void Raise(const EventType& event)
{
for (const auto& eventHandler : EventManager::_eventHandlers.at(event))
{
eventHandler();
}
}
// disallow copying and assigning
EventManager(const EventManager&) = delete;
EventManager& operator=(const EventManager&) = delete;
};
Can anyone help me to extend the following code by adding the functionality to accept parameters when raising the event as well ?

I believe this solves your question:
// g++ -std=c++11 -o /tmp/events /tmp/events.cpp && /tmp/events
// handler=1 arg=1
// handler=2 arg=1
// handler=1 arg=2
// handler=2 arg=2
#include <functional>
#include <map>
#include <vector>
template<class EventType, class... HandlerArgs>
class EventManager
{
public:
using EventHandler = std::function< void(HandlerArgs...) >;
void register_event(EventType&& event, EventHandler&& handler)
{
_handlers[std::move(event)].push_back(std::forward<EventHandler>(handler));
}
void raise_event(const EventType& event, HandlerArgs&&... args)
{
for (const auto& handler: EventManager::_handlers.at(event)) {
handler(std::forward<HandlerArgs>(args)...);
}
}
private:
std::map<EventType, std::vector<EventHandler>> _handlers;
};
int main(int argc, char **argv)
{
EventManager<int, int> m;
m.register_event(1, [](int arg) { printf("handler=%d arg=%d\n", 1, arg); });
m.register_event(1, [](int arg) { printf("handler=%d arg=%d\n", 2, arg); });
m.raise_event(1, 1);
m.raise_event(1, 2);
}
PS: I removed all the code regarding non-copiability and such, since it is not relevant to this question.

Since i havent got any answers on this, i figured a way to do so but i dont like it since i wanted a better way but well creating a static class that has static variables for each event, before raising the event , the caller will set those variables and the handler will read then reset them . this is dangerous approach especially with multi-threading since one or more threads might change the values while raising same event by mutli threads, so i had to implement some locking features to ensure thread safety.
Yes i know its not the best approach but as i'm not an expert in C++ and this question didnt get any comments nor answers, so this is the approach im following.

Related

std::function and friend function

In this example, I have a pointer of function (std::function) as an attribute of my class. So I can associate any function of the form void myFunction(void) to my class.
#include <iostream>
#include <functional>
class Example{
private:
int variable=4;
public:
std::function<void(void)> myNonMemberFunction;
Example(void){
}
Example(std::function<void(void)> MyNonMemberFunction){
myNonMemberFunction=MyNonMemberFunction;
}
};
void PrintPlop(){
std::cout<<"plop"<<std::endl;
}
int main() {
Example example(PrintPlop);
example.myNonMemberFunction();
}
Now, I want to do the same but with a function which has accessed to the class attribute like a friend function or a class-member function. How can I do this?
So you want any function you pass to the constructor become a friend?
In the strict sense it is impossible, because the access level (friend or not) is a compile-time issue, and which value is passed to the constructor, generally speaking, is determined only in run-time.
So you either declare all the relevant functions as friends (why not just make them methods in this case?) or pass the private members to them as additional parameters. Like this:
class Example{
private:
int variable=4;
std::function<void(int)> myNonMemberFunction;
public:
Example(void){
}
Example(std::function<void(int)> MyNonMemberFunction){
myNonMemberFunction=MyNonMemberFunction;
}
void callMyNonMemberFunction() {
myNonMemberFunction(variable);
}
};
void PrintPlop(int v){
std::cout<<"plop"<< v << std::endl;
}
int main() {
Example example(PrintPlop);
example.callMyNonMemberFunction();
}

c++11 template metaprogramming construct a std::unorderer_map at compile time

i trying to develop a Finite State Machine with template meta programming techniques, but i getting stuck with a map that it has to be fill at compile time, this the code(gcc 4.8 c++11):
#include <functional>
#include <type_traits>
#include <iostream>
#include <unordered_map>
namespace NSStateMachine {
//Definicion de estado unidad
template<class FSM, class From, class Event, class TO, bool(FSM::* transicion_fn)(const Event &)>
struct Transition
{
using FSM_TYPE=FSM;
using FROM_STATE= From;
using EVENT_TYPE= Event;
using TO_STATE_TYPE=TO;
using EVENT_BASE_TYPE = typename Event::BASE_TYPE;
static bool do_transition(FSM_TYPE& currenState, EVENT_BASE_TYPE const& aEvent)
{
return (currenState.*transicion_fn)(static_cast<EVENT_TYPE const&>(aEvent));
}
};
//States
template<class Transition, const Transition * const TransitionPtr, class ... Args>
class StateMachine
{
public:
StateMachine():transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
{}
template<class Event>
bool evalEvent(const Event & aEvent)
{
std::cout<<"evento recibido"<<std::endl;
}
std::unordered_map<typename Transition::TransitionID, const Transition * const > transitionMap ;
};
}
int main()
{
//it doesnt compile, i canoot create the state machine
return 0;
}
The compile error:
error: 'TransitionPtr' is not a class, namespace, or enumeration
StateMachine():transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
^
The problem seem to be in the line
transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
i will try to init the unorderer_map with the automatic constructor.
i have defined this Transition::TransitionID as a class variable defined in the class represented by the template argument
I will really appreciate any help.
Thx!!!!
i have already test with default types , it compile and work this
The error message is pretty clear. TransitionPtr is a pointer, not a type, so you can't use it to the left of :: in TransitionPtr::TransitionID_Value.
Also, I don't think you'll find a way to initialize an unordered_set at compile time, since it doesn't have constexpr constructors and in general almost certainly uses heap allocations.

Getting type_info from variadic template breaks the compiler... why?

So I am essentially trying to shove the rtti of a parameter pack into a list of type_info*. But for some reason, it doesn't seem to compile (or rather the compiler gives up half way through). Either way I can't seem to figure it out. Does anyone have a method to fix this, or better yet, know why it's breaking? Anywho, here's the code:
#pragma once
#include <typeinfo>
#include <vector>
class ParamChecker
{
public:
typedef std::vector<const type_info*> Types;
template <typename T> void PushType()
{
types.push_back(&typeid(T));
}
template <typename Head, typename... Tail> void PushTypes()
{
PushType<Head>();
PushTypes<Tail...>();
}
void PushTypes() {}
private:
Types types;
};
Thanks in advance!
I don't have Visual Studio to test, but I see the problem in your code so I'll tell you about that, and you can test on Visual Studio.
The problem is that, when you recurse into PushTypes<Tail...>(); and Tail... is empty, you're calling, PushTypes<>();. Notice that your base case, void PushTypes() {} is not a template function, i.e. you can't call it via PushTypes<>();.
Also note that you'll need a class template as a helper because we don't have partial specializations for function templates yet (hopefully it'll be coming soon).
But here's what you can do.
#include <typeinfo>
#include <vector>
class ParamChecker {
public:
/* Our type info structure. */
using Types = std::vector<const std::type_info *>;
/* Delegate work to PushTypesImpl<>. */
template <typename... Types>
void PushTypes() {
PushTypesImpl<Types...>()(types_);
}
private:
/* Forward declaration. */
template <typename... Types>
class PushTypesImpl;
/* Collection of type information. */
Types types_;
}; // ParamChecker
/* Base case. */
template <>
class ParamChecker::PushTypesImpl<> {
public:
void operator()(Types &) const { /* Do nothing. */ }
};
/* Recursive case. */
template <typename Head, typename... Tail>
class ParamChecker::PushTypesImpl<Head, Tail...> {
public:
void operator()(Types &types) const {
types.push_back(&typeid(Head));
PushTypesImpl<Tail...>()(types);
}
};
int main() {
ParamChecker x;
x.PushTypes<>(); // push nothing.
x.PushTypes<int>(); // push int.
x.PushTypes<int, double>(); // push int and double.
}
EDIT:
The following is an alternative approach using type_list and passing it as an argument.
NOTE: The use of type_list<> here instead of tuple<> is because constructing an empty tuple requires that all of the types be default-constructable, and even if they were all default-constructable, we don't want to default-construct them for no reason.
template <typename... Types>
class type_list {};
class ParamChecker {
public:
/* Our type info structure. */
using Types = std::vector<const std::type_info *>;
/* Base case. Do nothing. */
void PushTypes(type_list<> &&) {}
/* Recursive case. */
template <typename Head, typename... Tail>
void PushTypes(type_list<Head, Tail...> &&) {
types_.push_back(&typeid(Head));
PushTypes(type_list<Tail...>());
}
private:
/* Collection of type information. */
Types types_;
}; // ParamChecker
int main() {
ParamChecker x;
x.PushTypes(type_list<>()); // push nothing.
x.PushTypes(type_list<int>()); // push int.
x.PushTypes(type_list<int, double>()); // push int and double.
}

Concurrent blocking queue in C++11

For message passing in between threads, I'm looking for a concurrent queue with following properties:
bounded size
pop method that blocks/waits until an element is available.
abort method to cancel the wait
Optional: priority
Multiple producers, one consumer.
The concurrent_bounded_queue of TBB would provide that, but I'm looking for alternatives to avoid the additional dependency of TBB.
The application uses C++11 and boost. I couldn't find anything suitable in boost. What are the options?
Naive implementation using Boost library(circular_buffer) and C++11 standard library.
#include <mutex>
#include <condition_variable>
#include <boost/circular_buffer.hpp>
struct operation_aborted {};
template <class T, std::size_t N>
class bound_queue {
public:
typedef T value_type;
bound_queue() : q_(N), aborted_(false) {}
void push(value_type data)
{
std::unique_lock<std::mutex> lk(mtx_);
cv_pop_.wait(lk, [=]{ return !q_.full() || aborted_; });
if (aborted_) throw operation_aborted();
q_.push_back(data);
cv_push_.notify_one();
}
value_type pop()
{
std::unique_lock<std::mutex> lk(mtx_);
cv_push_.wait(lk, [=]{ return !q_.empty() || aborted_; });
if (aborted_) throw operation_aborted();
value_type result = q_.front();
q_.pop_front();
cv_pop_.notify_one();
return result;
}
void abort()
{
std::lock_guard<std::mutex> lk(mtx_);
aborted_ = true;
cv_pop_.notify_all();
cv_push_.notify_all();
}
private:
boost::circular_buffer<value_type> q_;
bool aborted_;
std::mutex mtx_;
std::condition_variable cv_push_;
std::condition_variable cv_pop_;
};

Passing non static delegate property function as parameter in C++ / CLI

I make a interface class in C++ for voice recognition, i´m using the Julius API. http://julius.sourceforge.jp/en_index.php?q=index-en.html.
Well, my class has some events, these events will be triggered by the Julius API.
The Julius API has the function call callback_add with this signature:
int callback_add (Recog *recog, int code, void(*func)(Recog *recog, void *data), void data)
I using some 'proxy' functions to Invoke the events and passing this functions to callback_add.
If the property event is static, it works fine, but if is a non static, inside the proxy function the property not be recognized.
The difficult is because I have to use the callback_add function and can't modify this.
Here is a summary of the class with 2 events (static and non-static)
Header
#ifndef FALAENGINE_H_
#define FALAENGINE_H_
#pragma once
extern "C"{
#include <julius/julius.h>
}
namespace FalaAPI {
public ref class FalaEngine
{
public:
FalaEngine();
~FalaEngine();
// Events
delegate void OnRecognizedDele(FalaAPI::RecoResult^ result);
static property OnRecognizedDele^ OnRecognized;
delegate void OnEngineStartDele();
property OnEngineStartDele^ OnEngineStart;
private:
Recog *recog;
Jconf *jconf;
};
}
#endif /* FALAENGINE_H_*/
Source
#include "stdafx.h"
using System::String;
using System::Console;
#include "FalaEngine.h"
#include <windows.h>
namespace FalaAPI{
void StartOnEngineStart()(Recog *recog, void * dummy){
if(FalaEngine::OnEngineStart->GetInvocationList()->Length > 0)
FalaEngine::OnEngineStart->Invoke();
}
void StartOnRecognized()(Recog *recog, void * dummy){
if(FalaEngine::OnRecognized->GetInvocationList()->Length > 0)
FalaEngine::OnRecognized->Invoke();
}
FalaEngine::FalaEngine(){
recog = j_recog_new();
jconf = j_jconf_new();
//Julius callback Functions
callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, StartOnEngineStart, NULL);
callback_add(recog, CALLBACK_RESULT, StartOnRecognized, NULL);
}
}
The problem occurs inside StartOnEngineStart function:
error C2227: left of '->GetInvocationList' must point to class/struct/union/generic type
A non-static member exists separately in each instance. You haven't specified which instance contains the delegate you want to inspect, you've only specified a class (and there may be many instances).
Try using the dummy parameter to pass your instance. But be careful, because the garbage collector will move objects around unless you have pinned them, so simply passing the address will not work. You need to create and pass a GCHandle instead. (Be careful not to leak the GCHandle, or your object will never be released)
Something like this should be effective:
ref class FalaEngine;
struct EngineHandle
{
gcroot<FalaEngine^> handle;
EngineHandle(FalaEngine^ engine) : handle(engine) {}
};
public ref class FalaEngine
{
clr_scoped_ptr<EngineHandle> callback_ptr;
public:
FalaEngine();
~FalaEngine();
// Events
delegate void OnRecognizedDele(FalaAPI::RecoResult^ result);
property OnRecognizedDele^ OnRecognized;
delegate void OnEngineStartDele();
property OnEngineStartDele^ OnEngineStart;
private:
Recog *recog;
Jconf *jconf;
};
void StartOnEngineStart(Recog *recog, void * dummy)
{
FalaEngine^ that = static_cast<EngineHandle*>(dummy)->handle;
that->OnEngineStart(); // C++/CLI already checks if the invocation list is empty
}
void StartOnRecognized(Recog *recog, void * dummy)
{
FalaEngine^ that = static_cast<EngineHandle*>(dummy)->handle;
that->OnRecognized(recog->get_result());
}
FalaEngine::FalaEngine()
: callback_ptr(new EngineHandle(this))
{
recog = j_recog_new();
jconf = j_jconf_new();
//Julius callback Functions
callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, StartOnEngineStart, callback_ptr.get());
callback_add(recog, CALLBACK_RESULT, StartOnRecognized, callback_ptr.get());
}
The clr_scoped_ptr class is here. There are not many license requirements, make sure you follow them though if you use it.

Resources