wqking / eventpp Goto Github PK
View Code? Open in Web Editor NEWEvent Dispatcher and callback list for C++
License: Other
Event Dispatcher and callback list for C++
License: Other
Question is pretty straightforward.
What if I call process() and what if I call processOne()? Are there any race conditions or issues that may arise?
I roughly have the following setup with names changed:
// a.h
enum class UpdateType { MeasurementUpdate, HealthUpdate };
// wrapper for listener with argument adapter
template <typename Params>
eventpp::EventQueue<UpdateType, void(const Update&)>::Handle
RegisterEventListener(const UpdateType& event_type,
std::function<Params>& callback) {
return unified_event_queue_.appendListener(
event_type, eventpp::argumentAdapter<Params>(callback));
}
class Update {
public:
Update() {
}
virtual ~Update() {
}
};
class Status : public Update {
public:
explicit Status(const A a, const B b, const C c)
: a {a},
b {b},
c {c} {}
A GetA() const {
return a;
}
B GetB() const {
return b;
}
C GetC() const {
return c;
}
private:
A a;
B b;
C c;
}
eventpp::EventQueue<UpdateType, void(const Update&)> unified_event_queue_;
I'm enqueueing with
// a.cc
A a {/* data I know about */};
B b {/* data I know about */};
C c {/* data I know about */};
unified_event_queue_.enqueue(
UpdateType::MeasurementUpdate,
Status(a, b, c));
and i've registered listeners with
// b.cc in a method of a class
std::function<void(const Status&)> status_f {
[this](const auto& e) {
this->CheckABC(e);
}};
RegisterEventListener(UpdateType::MeasurementUpdate,
status_f);
void CheckABC(const Status& status) {
const auto a {status.GetA()};
const auto b {status.GetB()};
...
}
when I check the attributes of status
, I think that status
has been sliced because the data I knew about is now no longer there when I call GetA()
etc. My question is, where might this be happening? I've tried not to accidentally use anything but a reference, and I imagine that a dynamic cast is going on under the hood. I'm using unified_event_queue_.process()
to dispatch. Would prefer not to use a pointer if I don't have to
ubuntu 20.04
gcc 8.5
I updated catch.hpp like CelestiaProject/Celestia#1118 and then it worked.
Hello,
One question, is it appropriate to replace the first line with the second one as shown below?
static auto forEach(const Self * /self/, A && ...args)
//static auto forEach(const Self * /self/, A && ...)
It's line 271 of “eventpp/eventdispatcher.h”.
Seems that, this removes a warning “unused parameter 'args'“ emitted from clang if -Wunused-parameter is on.
Thank you.
struct MyClass: Class1, EventDispatcher<int, void()> {
etc....
}
generates compilation error
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2988: unrecognizable template declaration/definition (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(282): note: see reference to class template instantiation 'eventpp::internal_::EventDispatcherBase<EventType,ReturnType(Args...),PoliciesType,MixinRoot_>' being compiled (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2143: syntax error: missing ')' before 'this' (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2143: syntax error: missing ';' before 'this' (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2238: unexpected token(s) preceding ';' (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2059: syntax error: 'this' (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2059: syntax error: ')' (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(262): error C2334: unexpected token(s) preceding ':'; skipping apparent function body (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(30): fatal error C1075: the left brace '{' was unmatched at the end of the file (compiling source file sources\MonaTiny.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2988: unrecognizable template declaration/definition (compiling source file sources\main.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(282): note: see reference to class template instantiation 'eventpp::internal_::EventDispatcherBase<EventType,ReturnType(Args...),PoliciesType,MixinRoot_>' being compiled (compiling source file sources\main.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2143: syntax error: missing ')' before 'this' (compiling source file sources\main.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2143: syntax error: missing ';' before 'this' (compiling source file sources\main.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2238: unexpected token(s) preceding ';' (compiling source file sources\main.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2059: syntax error: 'this' (compiling source file sources\main.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(248): error C2059: syntax error: ')' (compiling source file sources\main.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(262): error C2334: unexpected token(s) preceding ':'; skipping apparent function body (compiling source file sources\main.cpp)
1>g:\programming\c++\monaserver2\eventdispatcher\eventpp\include\eventpp\eventdispatcher.h(30): fatal error C1075: the left brace '{' was unmatched at the end of the file (compiling source file sources\main.cpp)
If the Dispatcher is a member of a Class, and the callback function is a member function, and how should I use the appendListener? thanks.
The code below shows this class
Declaration:
class sysEvent_C
{
private:
// Define an Event to hold all parameters.
struct _sysEventStruct{
int type;
std::string message;
int param;
};
// Define policies to let the dispatcher knows how to
// extract the event type.
struct _sysEventPolicies{
static int getEvent(const _sysEventStruct & e, bool /*b*/) {
return e.type;
}
};
eventpp::EventDispatcher< int,
void (const _sysEventStruct& e, bool b),
_sysEventPolicies > Dispatcher;
private:
void _LED_cbHandler(const _sysEventStruct& e, bool b);
void _speaker_cbHandler(const _sysEventStruct& e, bool b);
public:
void init();
};
Definition:
void sysEvent_C::init()
{
/// led
Dispatcher.appendListener(EventType::LED, _LED_cbHandler);
/// speaker
Dispatcher.appendListener(EventType::Speaker, _speaker_cbHandler);
}
the IDE will report
error: invalid use of non-static member function ‘void sysEvent_C::_LED_cbHandler(const sysEvent_C::_sysEventStruct&, bool)’
How can it be improved??
Removed
Hey!
Thank you for this library.
I have a suggestion for a small improvement. In my use case it is quite common to want to remove all callbacks from the CallbackList. I know this can be acheived with the forEach
function, but since I see this as a common and simple operation I think it makes sense to provide it as a simple function.
The operator CallbackListBase & operator = (CallbackListBase && other)
only release head and tail.
I fixed the problem on my fork in a branch move-assignement-fix
Fix in callbacklist.h
CallbackListBase & operator = (CallbackListBase && other) noexcept {
if(this != &other) {
while(head) {
// Create copy because doFreeNode reset temp->counter
// after head reassignment.
auto temp = head;
doFreeNode(temp);
}
head = std::move(other.head);
tail = std::move(other.tail);
currentCounter = other.currentCounter.load();
}
}
And the unit test demonstrating the problem:
TEST_CASE("CallbackList, move assignement")
{
using CL = eventpp::CallbackList<void()>;
CL callbackList;
const auto h1 = callbackList.append([]() {});
const auto h2 = callbackList.append([]() {});
callbackList = {};
// Make sure nodes were destroyed
REQUIRE(h1.expired());
REQUIRE(h2.expired());
}
Would you consider a PR for this?
A event queue type like eventpp::EventQueue<int, std::function<void()>>
, can't compile success.
In file included ...
eventpp/include/eventpp/eventqueue.h: In instantiation of ‘class eventpp::EventQueue<int, std::function<void()> >’:
pipeline.cpp:24:53: required from here
eventpp/include/eventpp/eventqueue.h:482:7: error: invalid use of incomplete type ‘using Type = class eventpp::internal_::EventQueueBase<int, std::function<void()>, eventpp::DefaultPolicies> {aka class eventpp::internal_::EventQueueBase<int, std::function<void()>, eventpp::DefaultPolicies>}’
class EventQueue : public internal_::InheritMixins<
^~~~~~~~~~
In file included ...
eventpp/include/eventpp/eventqueue.h:36:7: note: declaration of ‘using Type = class eventpp::internal_::EventQueueBase<int, std::function<void()>, eventpp::DefaultPolicies> {aka class eventpp::internal_::EventQueueBase<int, std::function<void()>, eventpp::DefaultPolicies>}’
class EventQueueBase;
^~~~~~~~~~~~~~
In file included ...
eventpp/include/eventpp/eventqueue.h:494:15: error: type ‘eventpp::EventQueue<int, std::function<void()> >::super {aka eventpp::internal_::EventQueueBase<int, std::function<void()>, eventpp::DefaultPolicies>}’ is not a base type for type ‘eventpp::EventQueue<int, std::function<void()> >’
using super::super;
Hi, I just testing your great-looking library for events but receiving some warnings during compilation.
When I try to compile this minimal test-case:
eventpp::EventDispatcher<int, void(const std::string &, const bool)> dispatcher;
dispatcher.dispatch(3, "Hello", true);
dispatcher.dispatch(5, "World", false);
Visual Studio 2017 is reporting the following issues:
1>eventDispatcher.test.cpp
1>q:\applications\atomixdevelopment\atomixdevelopment\axcore\axevents\eventpp\internal/eventpolicies_i.h(163): warning C4100: '<args_2>': unreferenced formal parameter
1>q:\applications\atomixdevelopment\atomixdevelopment\axcore\axevents\eventpp/eventdispatcher.h(225): note: see reference to function template instantiation 'bool eventpp::internal_::ForEachMixins<eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>,eventpp::MixinList<>,eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>::DoMixinBeforeDispatch>::forEach<const eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>*const ,const std::string&,_Ty&>(const eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void> *const &&,const std::string &,_Ty &)' being compiled
1> with
1> [
1> Event_=int,
1> Prototype_=void (const std::string &,bool),
1> Policies_=eventpp::DefaultPolicies,
1> _Ty=bool
1> ]
1>q:\applications\atomixdevelopment\atomixdevelopment\axcore\axevents\eventpp/eventdispatcher.h(224): note: see reference to function template instantiation 'bool eventpp::internal_::ForEachMixins<eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>,eventpp::MixinList<>,eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>::DoMixinBeforeDispatch>::forEach<const eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>*const ,const std::string&,_Ty&>(const eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void> *const &&,const std::string &,_Ty &)' being compiled
1> with
1> [
1> Event_=int,
1> Prototype_=void (const std::string &,bool),
1> Policies_=eventpp::DefaultPolicies,
1> _Ty=bool
1> ]
1>q:\applications\atomixdevelopment\atomixdevelopment\axcore\axevents\eventpp/eventdispatcher.h(223): note: while compiling class template member function 'void eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>::doDispatch(const int &,const std::string &,bool) const'
1> with
1> [
1> Event_=int,
1> Prototype_=void (const std::string &,bool),
1> Policies_=eventpp::DefaultPolicies
1> ]
1>q:\applications\atomixdevelopment\atomixdevelopment\axcore\axevents\eventpp/eventdispatcher.h(215): note: see reference to function template instantiation 'void eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>::doDispatch(const int &,const std::string &,bool) const' being compiled
1> with
1> [
1> Event_=int,
1> Prototype_=void (const std::string &,bool),
1> Policies_=eventpp::DefaultPolicies
1> ]
1>q:\applications\atomixdevelopment\atomixdevelopment\axcore\axevents\eventpp/eventdispatcher.h(295): note: see reference to class template instantiation 'eventpp::internal_::EventDispatcherBase<Event_,Prototype_,Policies_,void>' being compiled
1> with
1> [
1> Event_=int,
1> Prototype_=void (const std::string &,bool),
1> Policies_=eventpp::DefaultPolicies
1> ]
1>axEvents\eventDispatcher.test.cpp(37): note: see reference to class template instantiation 'eventpp::EventDispatcher<int,void (const std::string &,bool),eventpp::DefaultPolicies>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(54): note: see reference to class template instantiation 'boost::arg<9>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(53): note: see reference to class template instantiation 'boost::arg<8>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(52): note: see reference to class template instantiation 'boost::arg<7>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(51): note: see reference to class template instantiation 'boost::arg<6>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(50): note: see reference to class template instantiation 'boost::arg<5>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(49): note: see reference to class template instantiation 'boost::arg<4>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(48): note: see reference to class template instantiation 'boost::arg<3>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(47): note: see reference to class template instantiation 'boost::arg<2>' being compiled
1>Q:\SharedLibraries2015\boost32\include\boost/bind/placeholders.hpp(46): note: see reference to class template instantiation 'boost::arg<1>' being compiled
1>q:\applications\atomixdevelopment\atomixdevelopment\axcore\axevents\eventpp\internal/eventpolicies_i.h(163): warning C4100: '<args_1>': unreferenced formal parameter
1>q:\applications\atomixdevelopment\atomixdevelopment\axcore\axevents\eventpp\internal/eventpolicies_i.h(163): warning C4100: '<args_0>': unreferenced formal parameter
Also I'm not sure why complaining about boost::args<> when there is no boost used in the compiled code.
Is there any way how to remove these warnings?
Thanks
Handle insertListener(const Event & event, const Callback & callback, const Handle & before)
if the "event" type is not equal to the "before" object's event type, seems to cause problems ?
appendListener(const Event & event, const Callback & callback) in the class EventDispatcherBase, the "callback " could be Class Member Function? How to use?
This is not an actual issue, more of a feature request.
I'm wondering if it would be possible to support an additional process
call on the eventqueue similar to boost SPSC: size_type pop(T * ret, size_type size)
The idea would be that for queue:
eventpp::EventQueue<
EventType,
void(Event&),
EventPolicies> {};
your listener could handle:
queue.appendListener(event_type, [](Event* data, size_t count) {
...
});
Producers would still be able to enqueue one at a time.
Dispatch would look something like:
queue.process_all(max_size)
where max_size is the largest number of elements possible supplied to the listener callback.
I went through eventdispatcher.h and I was trying to figure out if the event dispatching runs the cbs in a different thread, but it doesn't look like that.
Am I correct to assume that cbs are invoked on the main thread and are blocking? E.g, a cb, if it blocks, may prevent the event from being propagated to all the listeners?
eventpp如何能实现不定参数的回调
类似伪代码
Listen(1, [](int a, const std::string& b){...});
Listen(2, [](int a, int b){...});
Invoke(1, 3, "abc");
Invoke(2, 3, 4);
Just wondering if there's an easy way to do one shot subscriptions on an eventqueue object, any advice?
Would it be possible\make sense to make ScopedRemover movable?
看了下参考例子,有点不太理解,
eventpp::EventDispatcher<int, void ()> dispatcher;
就限定死了回调参数类型,那如果回调参数类型是int (int), 是不是还得声明
eventpp::EventDispatcher<int, int(int)> dispatcher;
Hello,
I'm sure it is a super simple question, but I cannot handle the syntax. Could you please point out how to pass the instance of member function into it so it just work?
class MySettings
{
public:
...
eventpp::CallbackList<void(void)> AnySettingsUpdated;
}
class cMain : public wxFrame
{
protected:
void OnAnySeetingsUpdate();
}
MySettings.AnySettingsUpdated.append(&cMain::OnAnySeetingsUpdate);
Which leaves me error:
1>c:\dev_pcn\ocr\code\ocrviaopencvwgui\ocrviaopencvwgui\cmain.cpp(52): error C2664: 'eventpp::internal_::CallbackListBase<Prototype_,Policies_>::Handle_ eventpp::internal_::CallbackListBase<Prototype_,Policies_>::append(const std::function<ReturnType (void)> &)': cannot convert argument 1 from 'void (cdecl cMain::* )(void)' to 'const std::function<ReturnType (void)> &'
1> with
1> [
1> Prototype=void (void),
1> Policies=eventpp::DefaultPolicies,
1> ReturnType=void
1> ]
1> and
1> [
1> ReturnType=void
1> ]
1>c:\dev_pcn\ocr\code\ocrviaopencvwgui\ocrviaopencvwgui\cmain.cpp(52): note: Reason: cannot convert from 'void (__cdecl cMain::* )(void)' to 'const std::function<ReturnType (void)>'
1> with
1> [
1> ReturnType=void
1> ]
1>c:\dev_pcn\ocr\code\ocrviaopencvwgui\ocrviaopencvwgui\cmain.cpp(52): note: No constructor could take the source type, or constructor overload resolution was ambiguous
Hi, firstly let me say that I really like your project 🫠!
I was looking for some event-dispatcher library for C++ and I found this. What I needed though was to be able to subscribe for different types of events and also dispatch different types of events. Your primary API provides only one event type per dispatcher. Of course I can use polymorphism and do the casting in every lambda I pass to the dispatcher but that's a little bit too much work for me 😅
So I was wondering... what was stopping you from making this library... well... more generic?
I made a short code sample that showcases the core functionality of your library but written in a more generic way:
#include <iostream>
#include <functional>
#include <list>
#include <typeindex>
#include <map>
struct Dispatcher
{
using Listeners = std::list<std::function<void(const void*)>>;
std::map<std::type_index, Listeners> listenersByType;
template<typename T>
void appendListener(const std::function<void(const T&)>& listener)
{
listenersByType[std::type_index(typeid(T))].push_back([listener](const auto& msg) {
const T* concreteMessage = static_cast<const T*>(msg);
listener(*concreteMessage);
});
}
template<typename T>
void dispatch(const T& msg)
{
const auto& listeners = listenersByType.find(std::type_index(typeid(T)));
if (listeners != listenersByType.end()) {
for (auto &listener: listeners->second) {
listener(&msg);
}
}
}
};
And here is the usage:
struct Message {};
struct MousePressedMsg
{
int x, y;
};
struct Chicken {};
int main() {
Dispatcher dispatcher;
dispatcher.appendListener<MousePressedMsg>([](const auto& msg) {
std::cout << "Mouse pressed: (" << msg.x << ", " << msg.y << ")" << std::endl;
});
dispatcher.appendListener<Message>([](const auto& msg) {
std::cout << "Some message" << std::endl;
});
dispatcher.dispatch(Message{}); // prints "Some message"
dispatcher.dispatch(MousePressedMsg{10, 20}); // prints "Mouse pressed: (10, 20)"
dispatcher.dispatch(Chicken{}); // no listener for this type, but no problem
return 0;
}
And as you can see, I don't need any strange EventPolicies. EventType is just a C++ type. It is a compile-time unique identifier. What's the benefit of having a long enum-list with event types separately?
Also, I can add listener for literally every type and dispatch every type of message.
You said yourself that you are a big fan of observer pattern. And as an author of this library you definitely have much greater knowledge than me in this matter. I am creating this issue to ask a simple, and maybe stupid question (sorry 😟): why isn't your library more generic, like in the example that I provided? Are there some limitations that I have not yet reached in my solution?
In the following code:
eventpp/include/eventpp/eventqueue.h
Lines 174 to 189 in 63497c6
Where
auto enqueue(T && first, A ...args)
Why does A...
not add universal references, likes A&&...
.
In my tests, there is extra move and destruct overhead (local variables) if the universal reference is not added. Is there any particular reason for this?
Dear eventpp developers,
I really love this library, and have used it before in a PC project. Lately I started to work on embedded ARM Linux project where the gcc cross-compiler is set to C++11 standard. No way to upgrade to C++17. To my disappointment, when using eventpp, I am facing compilation problems. I believe they are due to use of fold expressions that only appear in C++17. They do resemble parameter packs (C++11) but not quite the same. Could you please confirm that the problem I am seeing is due to my compiler not supporting C++17? If yes, could you please provide some advice on how I can rewrite the expressions to fit the C++11 standard.
My compiler: arm-none-linux-gnueabi-g++ (Sourcery CodeBench Lite 2014.05-29) 4.8.3 20140320 (prerelease)
My compile errors:
host/bin/arm-none-linux-gnueabi-g++ -g -DDEBUG=1 -O0 -std=c++11 -D__cplusplus=201103L -fmessage-length=0 -DISO_DATE=
date -u +'"%Y-%m-%dT%H:%M:%S"'
-DGIT_BRANCH="git name-rev --name-only HEAD
" -DGIT_REV="git log -1 --pretty=%h
" -I../CommandHandlers/src -I../DataLinkCommunicators/src -I../ElvisDataModel/sr
c -I../DriverCommunicators/src -I../ScpiServerCmdsCommunicator/src -I../ClientBaseServerCmdsCommunicators/src -I../../Common/src -I../BAL/src -I/home/maxim/workspace/elvis/3.Implementation/Software/FirmwareBuilder
/build/buildroot-2019.02.3/achilles2-dev/build/scpi-server-0.1/ControlLink/ScpiServer/CommandHandlers/src -I/home/maxim/workspace/elvis/3.Implementation/Software/FirmwareBuilder/build/buildroot-2019.02.3/achille
s2-dev/build/scpi-server-0.1/ControlLink/ScpiServer/DataLinkCommunicators/src -I/home/maxim/workspace/elvis/3.Implementation/Software/FirmwareBuilder/build/buildroot-2019.02.3/achilles2-dev/build/scpi-server-0.1/
ControlLink/ScpiServer/ElvisDataModel/src -I/home/maxim/workspace/elvis/3.Implementation/Software/FirmwareBuilder/build/buildroot-2019.02.3/achilles2-dev/build/scpi-server-0.1/ControlLink/ScpiServer/DriverCommunicators/src -I/home/maxim/workspace/elvis/3.Implementation/Software/FirmwareBuilder/build/buildroot-2019.02.3/achilles2-dev/build/scpi-server-0.1/ControlLink/ScpiServer/ScpiServerCmdsCommunicator/src -I/home/maxim
/workspace/elvis/3.Implementation/Software/FirmwareBuilder/build/buildroot-2019.02.3/achilles2-dev/build/scpi-server-0.1/ControlLink/ScpiServer/ClientBaseServerCmdsCommunicators/src -I/home/maxim/workspace/elvis/
3.Implementation/Software/FirmwareBuilder/build/buildroot-2019.02.3/achilles2-dev/build/scpi-server-0.1/ControlLink/ScpiServer/../Common/src -I/home/maxim/workspace/elvis/3.Implementation/Software/FirmwareBuilder
/build/buildroot-2019.02.3/achilles2-dev/build/scpi-server-0.1/ControlLink/ScpiServer/BAL/src -I../../IdqCppSdk/logger/src -I../../IdqCppSdk/Util/src -I../../../IdqCppSdk/logger/src -I../../../IdqCppSdk/Util/src
-I../../../IdqCppSdk/eventpp/include -c src/EvtQueue.cpp -o Debug/EvtQueue.o
In file included from ../../../IdqCppSdk/eventpp/include/eventpp/eventdispatcher.h:17:0,
from ../../../IdqCppSdk/eventpp/include/eventpp/eventqueue.h:17,
from src/EvtQueue.h:20,
from src/EvtQueue.cpp:1:
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h: In member function 'void eventpp::internal::CallbackListBase<ReturnType(Args ...), PoliciesType>::operator()(Args ...) const':
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h:260:19: error: expected ',' before '...' token
forEachIf([&args...](Callback & callback) -> bool {
^
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h:260:19: error: expected identifier before '...' token
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h:260:22: error: parameter packs not expanded with '...':
forEachIf([&args...](Callback & callback) -> bool {
^
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h:260:22: note: 'args'
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h: In lambda function:
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h:261:17: error: expansion pattern 'args' contains no argument packs
callback(args...);
^
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h:262:56: error: expansion pattern 'args' contains no argument packs
return CanContinueInvoking::canContinueInvoking(args...);
^
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h: In instantiation of 'struct eventpp::internal::CallbackListBase<ReturnType(Args ...), PoliciesType>::operator()(Args ...) const [with PoliciesType = even
tpp::DefaultPolicies; ReturnType = void; Args = {bal::EventType, const std::basic_string<char, std::char_traits, std::allocator >&, std::shared_ptrbal::GeneralArgs}]::lambda2':
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h:263:4: required from 'void eventpp::internal::CallbackListBase<ReturnType(Args ...), PoliciesType>::operator()(Args ...) const [with PoliciesType = even
tpp::DefaultPolicies; ReturnType = void; Args = {bal::EventType, const std::basic_string<char, std::char_traits, std::allocator >&, std::shared_ptrbal::GeneralArgs}]'
../../../IdqCppSdk/eventpp/include/eventpp/eventdispatcher.h:228:47: required from 'void eventpp::internal::EventDispatcherBase<EventType, ReturnType(Args ...), Policies, MixinRoot>::directDispatch(const Eve
nt&, Args ...) const [with EventType = bal::EventType; Policies = eventpp::DefaultPolicies; MixinRoot = eventpp::internal_::EventQueueBase<bal::EventType, void(bal::EventType, const std::basic_string&, st
d::shared_ptrbal::GeneralArgs), eventpp::DefaultPolicies>; ReturnType = void; Args = {bal::EventType, const std::basic_string<char, std::char_traits, std::allocator >&, std::shared_ptr<bal::GeneralAr
gs>}; eventpp::internal_::EventDispatcherBase<EventType_, ReturnType(Args ...), Policies_, MixinRoot_>::Event = bal::EventType]'
../../../IdqCppSdk/eventpp/include/eventpp/eventqueue.h:411:3: required from 'void eventpp::internal_::EventQueueBase<EventType_, ReturnType(Args ...), Policies_>::doDispatchQueuedEvent(T&&, eventpp::internal_::
IndexSequence<Indexes ...>) [with T = eventpp::internal_::EventQueueBase<bal::EventType, void(bal::EventType, const std::basic_string&, std::shared_ptrbal::GeneralArgs), eventpp::DefaultPolicies>::QueuedEv
ent_&; unsigned int ...Indexes = {0u, 1u, 2u}; EventType_ = bal::EventType; Policies_ = eventpp::DefaultPolicies; ReturnType = void; Args = {bal::EventType, const std::basic_string<char, std::char_traits, st
d::allocator >&, std::shared_ptrbal::GeneralArgs}]'
../../../IdqCppSdk/eventpp/include/eventpp/eventqueue.h:259:5: required from 'bool eventpp::internal_::EventQueueBase<EventType_, ReturnType(Args ...), Policies_>::processOne() [with EventType_ = bal::EventType;
Policies_ = eventpp::DefaultPolicies; ReturnType = void; Args = {bal::EventType, const std::basic_string<char, std::char_traits, std::allocator >&, std::shared_ptrbal::GeneralArgs}]'
src/EvtQueue.cpp:54:27: required from here
../../../IdqCppSdk/eventpp/include/eventpp/callbacklist.h:260:15: error: using invalid field 'eventpp::internal_::CallbackListBase<ReturnType(Args ...), PoliciesType>::operator()(Args ...) const::__lambda2::__args
'
forEachIf([&args...](Callback & callback) -> bool {
^
make[3]: *** [/home/maxim/workspace/elvis/3.Implementation/Software/FirmwareBuilder/_build/buildroot-2019.02.3/achilles2-dev/build/scpi-server-0.1/ControlLink/ScpiServer/../mk/common.mk:104: Debug/EvtQueue.o] Erro
r 1
make[2]: *** [Makefile:9: all] Error 2
Check this at eventdispatcher.h:121
EventDispatcherBase & operator = (const EventDispatcherBase & other)
{
eventCallbackListMap = other;
}
EventDispatcherBase & operator = (EventDispatcherBase && other) noexcept
{
eventCallbackListMap = std::move(other);
}
and hetereventdispatcher have same error
Hi, the document:
eventpp/tutorial_eventdispatcher.md at master · wqking/eventpp
Looks good!
But at the last statement:
Remarks A common situation is an Event class is defined as the base class, all other events derive from Event, and the actual event type is a data member of Event (think QEvent in Qt). To let EventDispatcher knows how to get the event type from class Event, policies (the third template parameter) is used.
So my suggestion is that can you add another example about using the policies?
I see a similar example in this page: eventpp/argumentadapter.md at master · wqking/eventpp
But argument adapter is the second argument of the function appendListener()
, while the policy is the third argument.
Thanks.
BTW: I'm not sure, I see your library is the only library which support such policy feature. I mean that for many applications, when signal(event) can have different types, and we have different kinds of callback functions, such as:
void callback1(EventA &e);
void callback2(EventB &e);
The need here is both the above two functions can be added to the single signal/slot dispatcher object, and once a EventA signal happens, the callback1 function will be called, and not callback2. Once a EventB signal happens ,the callback2 function will be called, but not callbak1 function.
Generally, people don't need to use two different dispatcher objects for different event/signal classes, which make the library more flexible!
At first, I would like to say you Thank you 🙏 because it's a convenient, stable yet lightweight library that's very helpful.
I use the library for an application written for ESP32 platform, it has 32 bit architecture and the linker produces an error, because there is a Node Counter declared and it's typed as uint_64t
. After changing its type to uint_32t
the linker works fine.
Is there a possibility to choose the type of Node Counter depends on architecture? May be with flags?
Thank you.
The docs for eventmaker point to the header #include <eventpp/eventmaker.h>
when it is actually at #include <eventpp/utilities/eventmaker.h>
I had two questions regarding use of handles to remove a callback from the callbacklist type.
int l = 0;
eventpp::CallbackList<void()>::Handle two_shot_handle;
two_shot_handle = CB_list.append(
[&l, &two_shot_handle, &CB_list]() {
static int ctr = 0;
EXPECT_LT(ctr, 2); // should not run more than twice
ctr++;
l++;
if (ctr == 2) {
// unsubscribe with your own handle when a certain condition is met
// Is there a way to do this without CB_list, or atleast without capturing
// the handle? like CB_list.remove_self()
CB_list.remove(two_shot_handle);
}
});
int i;
auto handle = CB_list.append([&i](){++i;})
// remove the handle's callback
handle.self_destruct()
Thanks!
if append a method of a class,compile said can't link not static member.
For example, internal implementation mechanism, application scenario and design intention
I tried to compile the following code in the tutorial but failed.
`using CL = eventpp::CallbackList<void ()>;
CL callbackList;
// Add some callbacks.
callbackList.append( {
std::cout << "Got callback 1." << std::endl;
});
callbackList.append( {
std::cout << "Got callback 2." << std::endl;
});
callbackList.append( {
std::cout << "Got callback 3." << std::endl;
});
// Now call forEach to remove the second callback
// The forEach callback prototype is void(const CallbackList::Handle & handle, const CallbackList::Callback & callback)
int index = 0;
callbackList.forEach([&callbackList, &index](const CL::Handle & handle, const CL::Callback & callback) {
std::cout << "forEach(Handle, Callback), invoked " << index << std::endl;
if(index == 1) {
callbackList.remove(handle);
std::cout << "forEach(Handle, Callback), removed second callback" << std::endl;
}
++index;
});
// The forEach callback prototype can also be void(const CallbackList::Handle & handle)
callbackList.forEach([&callbackList, &index](const CL::Handle & handle) {
std::cout << "forEach(Handle), invoked" << std::endl;
});
// The forEach callback prototype can also be void(const CallbackList::Callback & callback)
callbackList.forEach([&callbackList, &index](const CL::Callback & callback) {
std::cout << "forEach(Callback), invoked" << std::endl;
});
// Invoke the callback list
// The "Got callback 2" callback should not be triggered.
callbackList();
Errors may happen at
// The forEach callback prototype can also be void(const CallbackList::Handle & handle)
callbackList.forEach([&callbackList, &index](const CL::Handle & handle) {
std::cout << "forEach(Handle), invoked" << std::endl;
});`
As below:
eventpp/include/eventpp/eventqueue.h:85:15: error: dependent using declaration resolved to type without 'typename'
[build] using super::Handle;
[build] ^
eventpp/include/eventpp/eventqueue.h:86:15: error: dependent using declaration resolved to type without 'typename'
[build] using super::Callback;
[build] ^
clang version 6.0.0
I'm adding ci with GH actions with lots of my small project because it's so easy to do.
I tried to add it to eventpp on a branch on my repo. https://github.com/OlivierLDff/eventpp/actions
As you can see tests are not compiling on macOs.
Would you be interested in such a PR? I can also fix compilation error on mac when i will have time.
I think it can be cool to have at least CI for windows/ubuntu in Release
我在我的代码中使用了eventpp的EventQueue接收来自其他线程的一系列事件:
我的理解是当调用EventQueue的enqueue方法以后,其他线程就可以继续添加新的事件了
但是从现象来看,一旦某一个任务没有处理完成,线程似乎就会阻塞
请问是我的用法有问题吗?
I'm using eventpp's EventQueue in my code to receive a series of events from other threads:
My understanding is that after calling the enqueue method of EventQueue, other threads can continue to add new events
But from the phenomenon, once a certain task is not processed, the thread seems to be blocked
Is there a problem with my usage?
The project I'm working on currently uses flags -Wall -Wextra -Werror -Wpedantic for compiling. I get unused parameters errors like so:
/home/lemagicien/Development/winter/pawlib/pawlib-source/../../libdeps/libs/include/eventpp/eventpolicies.h:95:43: error: unused parameter 'order' [-Werror,-Wunused-parameter] void store(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept ^
/home/lemagicien/Development/winter/pawlib/pawlib-source/../../libdeps/libs/include/eventpp/eventpolicies.h:125:43: error: unused parameter 'lock' [-Werror,-Wunused-parameter] void wait(std::unique_lock<std::mutex>& lock, Predicate pred)
Are these intentional or an issue with eventpp? Compiling with Clang 7.0
Replacing process() with processOne() in the sample code that you provided for OrderedQueueList, will cause a compilation error.
The code:
#include <iostream>
#include "eventpp/eventqueue.h"
#include "eventpp/utilities/orderedqueuelist.h"
struct MyEvent
{
int e;
int priority;
};
// The comparison function object used by eventpp::OrderedQueueList.
// The function compares the event by priority.
struct MyCompare
{
template <typename T>
bool operator() (const T & a, const T & b) const {
return std::get<0>(a.arguments).priority > std::get<0>(b.arguments).priority;
}
};
// Define the EventQueue policy
struct MyPolicy
{
template <typename Item>
using QueueList = eventpp::OrderedQueueList<Item, MyCompare >;
static int getEvent(const MyEvent & event) {
return event.e;
}
};
int main()
{
using EQ = eventpp::EventQueue<int, void(const MyEvent &), MyPolicy>;
EQ queue;
queue.appendListener(3, [](const MyEvent & event) {
std::cout << "Get event " << event.e << "(should be 3)." << " priority: " << event.priority << std::endl;
});
queue.appendListener(5, [](const MyEvent & event) {
std::cout << "Get event " << event.e << "(should be 5)." << " priority: " << event.priority << std::endl;
});
queue.appendListener(7, [](const MyEvent & event) {
std::cout << "Get event " << event.e << "(should be 7)." << " priority: " << event.priority << std::endl;
});
// Add an event, the first number 5 is the event type, the second number 100 is the priority.
// After the queue processes, the events will be processed from higher priority to lower priority.
queue.enqueue(MyEvent{ 5, 100 });
queue.enqueue(MyEvent{ 5, 200 });
queue.enqueue(MyEvent{ 7, 300 });
queue.enqueue(MyEvent{ 7, 400 });
queue.enqueue(MyEvent{ 3, 500 });
queue.enqueue(MyEvent{ 3, 600 });
queue.processOne();
}
Error message:
Compilation flags:
"-std=c++11 -O0"
Steps to reproduce:
compile this code
class Event {
public:
int type;
};
class DerivedEvent : public Event {
public:
int data;
};
struct EventPolicies
{
static int getEvent(const Event& e) {
return e.type;
}
};
void app_main() {
eventpp::EventDispatcher<int, void (const Event&), EventPolicies> dispatcher;
dispatcher.appendListener(3, [](const DerivedEvent& e) {
std::cout
<< std::boolalpha
<< "Event::type is " << e.type << std::endl
;
});
DerivedEvent event;
event.type = 3;
event.data = 5;
dispatcher.dispatch(event);
}
Expected behaviour:
Code to be compiled
Actual behaviour:
Got an error
src/main.cpp: In function 'void app_main()':
src/main.cpp:94:6: error: no matching function for call to 'eventpp::EventDispatcher<int, void(const Event&), EventPolicies>::appendListener(int, app_main()::<lambda(const DerivedEvent&)>)'
When I changed in the listener callback prototype [](const DerivedEvent& e)
to [](const Event& e)
it compiles perfectly. I could create instances of EventDispatcher for each event type, but not sure if it's a good idea.
Is there a possibility to use derived classes in prototype?
I have some problems with using a method (class function) as a callback. I don't know which kind of signature is necessary when using std::bind, which I assume I have to use for this use case. Could you provide a little example?
each event type has its own event class, such as a mouseDown event has MouseDown event class.
I think the word should be:
each event type has its own event class, such as a mouseDown event type has MouseDown event class.
Am I correct?
Thanks.
Is it possible to append priority to event queues? I couldn't find anything in the docs
Hi, I stumbled across this library while researching for my own signal/slots implementation.
Unless I missread something the callbacklist class is supposed to support concurrent removal and iteration both from multiple threads and recursively (i.e. the callback removes itself). I might be wrong, but I don't think the current implementation actually does.
The issue I see is actually (kinda) documented in doFreeNode, where it says:
// don't modify node->previous or node->next
// because node may be still used in a loop.
right after modifying the previous/next value of the node before/after the removed one. So while keeping the values in the removed node works in practice I am fairly sure this is a data race if another node is removed concurrently. Consider the following flow of events:
Thread A starts iterating the list
Thread A starts reading nodeX->next and gets interupted after getting part of nodeX->next
Thread B removes the node after nodeX (which in turn updates nodeX->next)
Thread A is resumed and continues reading the rest of nodeX->next which now contains different data.
The result is that ThreadA now has a invalid pointer that might or might not lead to a crash. The root of the problem is that assigning/reading a shared_ptr is neither atomic nor threadsafe (thats why the free standing overloads of std::atomic_load
for shared_ptr exist).
Please correct me if I am missing something, but I don't think the algorithm in the current form is actually thread safe (even if it might not manifest in practice).
大佬 研究你的代码 但是在
template
struct HasTypeCallback {
template
static std::true_type test(typename C::Callback*);
template<typename C>
static std::false_type test(...);
enum {
value = !!decltype(test<T>(0))()
};
};
块看不懂了 尤其是 value = !!decltype(test(0))() 真的很迷
Hi!
Any plans for a new release soon? It seems like there has been significant development (fixes etc) since version 0.1.2 (June 2022).
We manage our dependencies via vcpkg so cloning the master branch is not a preferred alternative.
Thank you!
I'd like to be able to handle the scenario where there are no listeners for an event. In my specific case, I want to provide a default handler if there is not one. Is there already a mechanism to determine if dispatch()
did nothing?
Perhaps dispatch()
could return the listener count?
Hi, maybe I am missing something here, but should't there be queue instead of dispatcher?
dispatcher.appendListener(3, [](const std::string s, bool b) {
std::cout << std::boolalpha << "Got event 3, s is " << s << " b is " << b << std::endl;
});
dispatcher.appendListener(5, [](const std::string s, bool b) {
std::cout << std::boolalpha << "Got event 5, s is " << s << " b is " << b << std::endl;
});
// The listeners are not triggered during enqueue.
queue.enqueue(3, "Hello", true);
queue.enqueue(5, "World", false);
// Process the event queue, dispatch all queued events.
queue.process();
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.