From 6e5f6ee45d6e9b1aad8d6bb533cafd1333b2a8e6 Mon Sep 17 00:00:00 2001 From: wqking Date: Fri, 4 Feb 2022 09:00:50 +0800 Subject: [PATCH] tab->spaces in documents for easier read --- doc/anyid.md | 26 +- doc/argumentadapter.md | 198 ++++++++-------- doc/benchmark.md | 408 ++++++++++++++++---------------- doc/callbacklist.md | 4 +- doc/conditionalfunctor.md | 64 ++--- doc/conditionalremover.md | 60 ++--- doc/counterremover.md | 54 ++--- doc/eventdispatcher.md | 6 +- doc/eventmaker.md | 74 +++--- doc/eventqueue.md | 50 ++-- doc/eventutil.md | 26 +- doc/faq.md | 52 ++-- doc/hetercallbacklist.md | 4 +- doc/hetereventdispatcher.md | 6 +- doc/hetereventqueue.md | 28 +-- doc/heterogeneous.md | 32 +-- doc/introduction.md | 18 +- doc/mixins.md | 40 ++-- doc/orderedqueuelist.md | 74 +++--- doc/policies.md | 132 +++++------ doc/scopedremover.md | 118 ++++----- doc/tutorial_callbacklist.md | 36 +-- doc/tutorial_eventdispatcher.md | 48 ++-- doc/tutorial_eventqueue.md | 54 ++--- readme.md | 18 +- 25 files changed, 815 insertions(+), 815 deletions(-) diff --git a/doc/anyid.md b/doc/anyid.md index 1d461df..e2969c8 100644 --- a/doc/anyid.md +++ b/doc/anyid.md @@ -54,9 +54,9 @@ A typical implementation of `Digester`: template struct MyDigest { - TheDigestTypeSuchAsSizeT operator() (const T & value) const { - // compute the digest of value and return the digest. - } + TheDigestTypeSuchAsSizeT operator() (const T & value) const { + // compute the digest of value and return the digest. + } }; ``` Note: the return type of the function call operator (here is TheDigestTypeSuchAsSizeT) must be the same for all T, it can't be different type for different T. @@ -65,12 +65,12 @@ A typical implementation of `Storage`: ```c++ struct MyStorage { - template - MyStorage(const T & value) { - // store the value - } - - // any other member functions can be added, such as getting the underlying value. + template + MyStorage(const T & value) { + // store the value + } + + // any other member functions can be added, such as getting the underlying value. }; ``` Or none template version: @@ -78,10 +78,10 @@ Or none template version: // In this version, only value of `int` and `std::string` can be stored. struct MyStorage { - MyStorage(const int value) {} - MyStorage(const std::string & value) {} - - // any other member functions can be added, such as getting the underlying value. + MyStorage(const int value) {} + MyStorage(const std::string & value) {} + + // any other member functions can be added, such as getting the underlying value. }; ``` diff --git a/doc/argumentadapter.md b/doc/argumentadapter.md index c15bce8..4f7ac7a 100644 --- a/doc/argumentadapter.md +++ b/doc/argumentadapter.md @@ -70,74 +70,74 @@ Below is the example code to demonstrate how to use `argumentAdapter`. There are // Define the event types enum class EventType { - // for MouseEvent - mouse, + // for MouseEvent + mouse, - // for KeyEvent - key, + // for KeyEvent + key, - // for MessageEvent - message, + // for MessageEvent + message, - // For either MouseEvent or KeyEvent, we use this type to demonstrate - // how to use conditionalFunctor - input, + // For either MouseEvent or KeyEvent, we use this type to demonstrate + // how to use conditionalFunctor + input, }; class Event { public: - Event() { - } + Event() { + } - // Make the Event polymorphism so we can use dynamic_cast to detect - // if it's a MouseEvent or KeyEvent - virtual ~Event() { - } + // Make the Event polymorphism so we can use dynamic_cast to detect + // if it's a MouseEvent or KeyEvent + virtual ~Event() { + } }; class MouseEvent : public Event { public: - MouseEvent(const int x, const int y) - : x(x), y(y) - { - } + MouseEvent(const int x, const int y) + : x(x), y(y) + { + } - int getX() const { return x; } - int getY() const { return y; } + int getX() const { return x; } + int getY() const { return y; } private: - int x; - int y; + int x; + int y; }; class KeyEvent : public Event { public: - explicit KeyEvent(const int key) - : key(key) - { - } + explicit KeyEvent(const int key) + : key(key) + { + } - int getKey() const { return key; } + int getKey() const { return key; } private: - int key; + int key; }; class MessageEvent : public Event { public: - explicit MessageEvent(const std::string & message) - : message(message) { - } + explicit MessageEvent(const std::string & message) + : message(message) { + } - std::string getMessage() const { return message; } + std::string getMessage() const { return message; } private: - std::string message; + std::string message; }; // A free function that will be added as listener later. @@ -145,61 +145,61 @@ private: // lambda, functor object, std::function, free function, etc. void tutorialArgumentAdapterFreeFunction(const MouseEvent & e) { - std::cout << "Received MouseEvent in free function, x=" << e.getX() << " y=" << e.getY() << std::endl; + std::cout << "Received MouseEvent in free function, x=" << e.getX() << " y=" << e.getY() << std::endl; } void example1() { - eventpp::EventDispatcher eventDispatcher; + eventpp::EventDispatcher eventDispatcher; - // callback 1 -- lambda, or any functor object + // callback 1 -- lambda, or any functor object - // This can't compile because a 'const Event &' can be passed to 'const MouseEvent &' - //eventDispatcher.appendListener(mouseEventId, [](const MouseEvent & e) {}); + // This can't compile because a 'const Event &' can be passed to 'const MouseEvent &' + //eventDispatcher.appendListener(mouseEventId, [](const MouseEvent & e) {}); - // This compiles. eventpp::argumentAdapter creates a functor object that static_cast - // 'const Event &' to 'const MouseEvent &' automatically. - // Note we need to pass the function type to eventpp::argumentAdapter because the lambda - // doesn't have any function type information and eventpp::argumentAdapter can't deduce - // the type. This rule also applies to other functor object. - eventDispatcher.appendListener( - EventType::mouse, - eventpp::argumentAdapter([](const MouseEvent & e) { - std::cout << "Received MouseEvent in lambda, x=" << e.getX() << " y=" << e.getY() << std::endl; - }) - ); - eventDispatcher.appendListener( - EventType::message, - eventpp::argumentAdapter([](const MessageEvent & e) { - std::cout << "Received MessageEvent in lambda, message=" << e.getMessage() << std::endl; - }) - ); + // This compiles. eventpp::argumentAdapter creates a functor object that static_cast + // 'const Event &' to 'const MouseEvent &' automatically. + // Note we need to pass the function type to eventpp::argumentAdapter because the lambda + // doesn't have any function type information and eventpp::argumentAdapter can't deduce + // the type. This rule also applies to other functor object. + eventDispatcher.appendListener( + EventType::mouse, + eventpp::argumentAdapter([](const MouseEvent & e) { + std::cout << "Received MouseEvent in lambda, x=" << e.getX() << " y=" << e.getY() << std::endl; + }) + ); + eventDispatcher.appendListener( + EventType::message, + eventpp::argumentAdapter([](const MessageEvent & e) { + std::cout << "Received MessageEvent in lambda, message=" << e.getMessage() << std::endl; + }) + ); - // callback 2 -- std::function - // We don't need to pass the function type to eventpp::argumentAdapter because it can - // deduce the type from the std::function - eventDispatcher.appendListener( - EventType::key, - eventpp::argumentAdapter(std::function([](const KeyEvent & e) { - std::cout << "Received KeyEvent in std::function, key=" << e.getKey() << std::endl; - })) - ); + // callback 2 -- std::function + // We don't need to pass the function type to eventpp::argumentAdapter because it can + // deduce the type from the std::function + eventDispatcher.appendListener( + EventType::key, + eventpp::argumentAdapter(std::function([](const KeyEvent & e) { + std::cout << "Received KeyEvent in std::function, key=" << e.getKey() << std::endl; + })) + ); - // callback 3 -- free function - // We don't need to pass the function type to eventpp::argumentAdapter because it can - // deduce the type from the free function - eventDispatcher.appendListener( - EventType::mouse, - eventpp::argumentAdapter(tutorialArgumentAdapterFreeFunction) - ); + // callback 3 -- free function + // We don't need to pass the function type to eventpp::argumentAdapter because it can + // deduce the type from the free function + eventDispatcher.appendListener( + EventType::mouse, + eventpp::argumentAdapter(tutorialArgumentAdapterFreeFunction) + ); - eventDispatcher.dispatch(EventType::mouse, MouseEvent(3, 5)); - eventDispatcher.dispatch(EventType::key, KeyEvent(255)); - eventDispatcher.dispatch(EventType::message, MessageEvent("Hello, argumentAdapter")); - // In syntax we can dispatch KeyEvent under EventType::mouse, in our case, - // the EventType::mouse listener casts KeyEvent to MouseEvent, which is invalid object, - // and the listener will either use garbled data, or crash. - //eventDispatcher.dispatch(EventType::mouse, KeyEvent(255)); + eventDispatcher.dispatch(EventType::mouse, MouseEvent(3, 5)); + eventDispatcher.dispatch(EventType::key, KeyEvent(255)); + eventDispatcher.dispatch(EventType::message, MessageEvent("Hello, argumentAdapter")); + // In syntax we can dispatch KeyEvent under EventType::mouse, in our case, + // the EventType::mouse listener casts KeyEvent to MouseEvent, which is invalid object, + // and the listener will either use garbled data, or crash. + //eventDispatcher.dispatch(EventType::mouse, KeyEvent(255)); } void example2() @@ -212,25 +212,25 @@ eventpp::EventDispatcher eventDispatcher; // listener 1 eventDispatcher.appendListener( - EventType::input, - eventpp::conditionalFunctor( - eventpp::argumentAdapter([](const MouseEvent & e) { - std::cout << "Received MouseEvent in conditional tutorial, x=" << e.getX() << " y=" << e.getY() << std::endl; - }), - // This lambda is the condition. We use dynamic_cast to check if the event is desired. - // This is for demonstration purpose, in production you may use a better way than dynamic_cast. - [](const Event & e) { return dynamic_cast(&e) != nullptr; } - ) + EventType::input, + eventpp::conditionalFunctor( + eventpp::argumentAdapter([](const MouseEvent & e) { + std::cout << "Received MouseEvent in conditional tutorial, x=" << e.getX() << " y=" << e.getY() << std::endl; + }), + // This lambda is the condition. We use dynamic_cast to check if the event is desired. + // This is for demonstration purpose, in production you may use a better way than dynamic_cast. + [](const Event & e) { return dynamic_cast(&e) != nullptr; } + ) ); // listener 2 eventDispatcher.appendListener( - EventType::input, - eventpp::conditionalFunctor( - eventpp::argumentAdapter([](const KeyEvent & e) { - std::cout << "Received KeyEvent in conditional tutorial, key=" << e.getKey() << std::endl; - }), - [](const Event & e) { return dynamic_cast(&e) != nullptr; } - ) + EventType::input, + eventpp::conditionalFunctor( + eventpp::argumentAdapter([](const KeyEvent & e) { + std::cout << "Received KeyEvent in conditional tutorial, key=" << e.getKey() << std::endl; + }), + [](const Event & e) { return dynamic_cast(&e) != nullptr; } + ) ); // listener 1 will receive this event, listener 2 will not. @@ -255,10 +255,10 @@ eventpp::EventQueue)> eventQueue; // This compiles. eventpp::argumentAdapter creates a functor object that static_cast // 'std::shared_ptr' to 'std::shared_ptr' automatically. eventQueue.appendListener( - EventType::mouse, - eventpp::argumentAdapter)>([](std::shared_ptr e) { - std::cout << "Received MouseEvent as std::shared_ptr, x=" << e->getX() << " y=" << e->getY() << std::endl; - }) + EventType::mouse, + eventpp::argumentAdapter)>([](std::shared_ptr e) { + std::cout << "Received MouseEvent as std::shared_ptr, x=" << e->getX() << " y=" << e->getY() << std::endl; + }) ); eventQueue.enqueue(EventType::mouse, std::make_shared(3, 5)); diff --git a/doc/benchmark.md b/doc/benchmark.md index c4101b6..0f624c3 100644 --- a/doc/benchmark.md +++ b/doc/benchmark.md @@ -8,40 +8,40 @@ Time unit: milliseconds (unless explicitly specified) - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + +
IterationsQueue sizeEvent countEvent TypesListener countTime of single threadingTime of multi threadingIterationsQueue sizeEvent countEvent TypesListener countTime of single threadingTime of multi threading
100k10010M1001004011146100k10010M1001004011146
100k1000100M100100401211467100k1000100M100100401211467
100k1000100M10001000410211600100k1000100M10001000410211600
@@ -53,107 +53,107 @@ The EventQueue is processed in one thread. The Single/Multi threading in the tab
- - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + +
MutexEnqueue threadsProcess threadsEvent countEvent TypesListener countTimeMutexEnqueue threadsProcess threadsEvent countEvent TypesListener countTime
std::mutex1110M1001002283std::mutex1110M1001002283
SpinLock1110M1001001692SpinLock1110M1001001692
std::mutex1310M1001003446std::mutex1310M1001003446
SpinLock1310M1001003025SpinLock1310M1001003025
std::mutex2210M1001004000std::mutex2210M1001004000
SpinLock2210M1001003076SpinLock2210M1001003076
std::mutex4410M1001001971std::mutex4410M1001001971
SpinLock4410M1001001755SpinLock4410M1001001755
std::mutex161610M100100928std::mutex161610M100100928
SpinLock161610M1001002082SpinLock161610M1001002082
@@ -172,123 +172,123 @@ Iterations: 100,000,000 - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + +
FunctionCompilerNative invokingCallbackList single threadingCallbackList multi threadingFunctionCompilerNative invokingCallbackList single threadingCallbackList multi threading
Inline global functionMSVC 201721715016921Inline global functionMSVC 201721715016921
GCC 7.218714894463GCC 7.218714894463
Non-inline global functionMSVC 201724115266544Non-inline global functionMSVC 201724115266544
GCC 7.223314884787GCC 7.223314884787
Function objectMSVC 201719414986433Function objectMSVC 201719414986433
GCC 7.221214854951GCC 7.221214854951
Member virtual functionMSVC 201720715336558Member virtual functionMSVC 201720715336558
GCC 7.221214854489GCC 7.221214854489
Member non-virtual functionMSVC 201721415336390Member non-virtual functionMSVC 201721415336390
GCC 7.221114864872GCC 7.221114864872
Member non-inline virtual functionMSVC 201720615226578Member non-inline virtual functionMSVC 201720615226578
GCC 7.218216664593GCC 7.218216664593
Member non-inline non-virtual functionMSVC 201720614916992Member non-inline non-virtual functionMSVC 201720614916992
GCC 7.220514864490GCC 7.220514864490
All functionsMSVC 201713741095129973All functionsMSVC 201713741095129973
GCC 7.21223977022958GCC 7.21223977022958
@@ -306,40 +306,40 @@ volatile int globalValue = 0; void globalFunction(int a, const int b) { - globalValue += a + b; + globalValue += a + b; } NON_INLINE void nonInlineGlobalFunction(int a, const int b) { - globalValue += a + b; + globalValue += a + b; } struct FunctionObject { - void operator() (int a, const int b) - { - globalValue += a + b; - } + void operator() (int a, const int b) + { + globalValue += a + b; + } - virtual void virFunc(int a, const int b) - { - globalValue += a + b; - } + virtual void virFunc(int a, const int b) + { + globalValue += a + b; + } - void nonVirFunc(int a, const int b) - { - globalValue += a + b; - } + void nonVirFunc(int a, const int b) + { + globalValue += a + b; + } - NON_INLINE virtual void nonInlineVirFunc(int a, const int b) - { - globalValue += a + b; - } + NON_INLINE virtual void nonInlineVirFunc(int a, const int b) + { + globalValue += a + b; + } - NON_INLINE void nonInlineNonVirFunc(int a, const int b) - { - globalValue += a + b; - } + NON_INLINE void nonInlineNonVirFunc(int a, const int b) + { + globalValue += a + b; + } }; #undef NON_INLINE diff --git a/doc/callbacklist.md b/doc/callbacklist.md index ca6e3d4..a04c544 100644 --- a/doc/callbacklist.md +++ b/doc/callbacklist.md @@ -35,8 +35,8 @@ eventpp/callbacklist.h ```c++ template < - typename Prototype, - typename Policies = DefaultPolicies + typename Prototype, + typename Policies = DefaultPolicies > class CallbackList; ``` diff --git a/doc/conditionalfunctor.md b/doc/conditionalfunctor.md index ed54d0f..de15076 100644 --- a/doc/conditionalfunctor.md +++ b/doc/conditionalfunctor.md @@ -10,14 +10,14 @@ For example, eventpp::CallbackList callbackList; callbackList.append( - eventpp::conditionalFunctor( - [](const int value) { - std::cout << "We should get value 1." << here; - }, - [](const int value) { - return value == 1; - } - ) + eventpp::conditionalFunctor( + [](const int value) { + std::cout << "We should get value 1." << here; + }, + [](const int value) { + return value == 1; + } + ) ); callbackList(2); // not trigger the callback callbackList(1); // trigger the callback @@ -44,34 +44,34 @@ eventpp::CallbackList callbackList; std::vector dataList(3); callbackList.append( - eventpp::conditionalFunctor( - [&dataList](const int index) { - ++dataList[index]; - }, - [](const int index) { - return index == 0; - } - ) + eventpp::conditionalFunctor( + [&dataList](const int index) { + ++dataList[index]; + }, + [](const int index) { + return index == 0; + } + ) ); callbackList.append( - eventpp::conditionalFunctor( - [&dataList](const int index) { - ++dataList[index]; - }, - [](const int index) { - return index == 1; - } - ) + eventpp::conditionalFunctor( + [&dataList](const int index) { + ++dataList[index]; + }, + [](const int index) { + return index == 1; + } + ) ); callbackList.append( - eventpp::conditionalFunctor( - [&dataList](const int index) { - ++dataList[index]; - }, - [](const int index) { - return index == 2; - } - ) + eventpp::conditionalFunctor( + [&dataList](const int index) { + ++dataList[index]; + }, + [](const int index) { + return index == 2; + } + ) ); REQUIRE(dataList == std::vector{ 0, 0, 0 }); diff --git a/doc/conditionalremover.md b/doc/conditionalremover.md index cdb25c7..c01f6a0 100644 --- a/doc/conditionalremover.md +++ b/doc/conditionalremover.md @@ -49,47 +49,47 @@ Constructs an instance of ConditionalRemover. ```c++ template typename DispatcherType::Handle appendListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener, - const Condition & condition - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener, + const Condition & condition + ); template typename DispatcherType::Handle prependListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener, - const Condition & condition - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener, + const Condition & condition + ); template typename DispatcherType::Handle insertListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener, - const typename DispatcherType::Handle & before, - const Condition & condition - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener, + const typename DispatcherType::Handle & before, + const Condition & condition + ); ``` **Member functions for CallbackList** ```c++ template typename CallbackListType::Handle append( - const typename CallbackListType::Callback & listener, - const Condition & condition - ); + const typename CallbackListType::Callback & listener, + const Condition & condition + ); template typename CallbackListType::Handle prepend( - const typename CallbackListType::Callback & listener, - const Condition & condition - ); + const typename CallbackListType::Callback & listener, + const Condition & condition + ); template typename CallbackListType::Handle insert( - const typename CallbackListType::Callback & listener, - const typename CallbackListType::Handle & before, - const Condition & condition - ); + const typename CallbackListType::Callback & listener, + const typename CallbackListType::Handle & before, + const Condition & condition + ); ``` The member functions have the same names with the corresponding underlying class (CallbackList, EventDispatcher, or EventQueue), and also have the same parameters except there is one more parameter, `condition`. `condition` is a predicate function that returns a bool value. It's invoked after each trigger, if it returns true, the listener will be removed. @@ -126,26 +126,26 @@ eventpp::EventDispatcher dispatcher; constexpr int event = 3; dispatcher.appendListener(event, []() { - // listener A + // listener A }); // Note the ConditionalRemover instance returned by conditionalRemover is invoked // prependListener and destroyed immediately. std::string removeWho; eventpp::conditionalRemover(dispatcher).prependListener(event, [&dataList]() { - // listener B + // listener B }, [&removeWho]() -> bool { - return removeWho == "removeB"; + return removeWho == "removeB"; }); auto handle = eventpp::conditionalRemover(dispatcher).appendListener(event, [&dataList]() { - // listener C + // listener C }, [&removeWho]() -> bool { - return removeWho == "removeC"; + return removeWho == "removeC"; }); eventpp::conditionalRemover(dispatcher).insertListener(event, [&dataList]() { - // listener D + // listener D }, handle, [&removeWho]() -> bool { - return removeWho == "removeD"; + return removeWho == "removeD"; }); dispatcher.dispatch(event); diff --git a/doc/counterremover.md b/doc/counterremover.md index f070fb4..d9e7743 100644 --- a/doc/counterremover.md +++ b/doc/counterremover.md @@ -48,42 +48,42 @@ Constructs an instance of CounterRemover. **Member functions for EventDispatcher and EventQueue** ```c++ typename DispatcherType::Handle appendListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener, - const int triggerCount = 1 - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener, + const int triggerCount = 1 + ); typename DispatcherType::Handle prependListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener, - const int triggerCount = 1 - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener, + const int triggerCount = 1 + ); typename DispatcherType::Handle insertListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener, - const typename DispatcherType::Handle & before, - const int triggerCount = 1 - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener, + const typename DispatcherType::Handle & before, + const int triggerCount = 1 + ); ``` **Member functions for CallbackList** ```c++ typename CallbackListType::Handle append( - const typename CallbackListType::Callback & listener, - const int triggerCount = 1 - ); + const typename CallbackListType::Callback & listener, + const int triggerCount = 1 + ); typename CallbackListType::Handle prepend( - const typename CallbackListType::Callback & listener, - const int triggerCount = 1 - ); + const typename CallbackListType::Callback & listener, + const int triggerCount = 1 + ); typename CallbackListType::Handle insert( - const typename CallbackListType::Callback & listener, - const typename CallbackListType::Handle & before, - const int triggerCount = 1 - ); + const typename CallbackListType::Callback & listener, + const typename CallbackListType::Handle & before, + const int triggerCount = 1 + ); ``` The member functions have the same names with the corresponding underlying class (CallbackList, EventDispatcher, or EventQueue), and also have the same parameters except there is one more parameter, `triggerCount`. `triggerCount` is decreased by one on each trigger, and when `triggerCount` is zero or negative, the listener will be removed. @@ -110,19 +110,19 @@ eventpp::EventDispatcher dispatcher; constexpr int event = 3; dispatcher.appendListener(event, []() { - // listener A + // listener A }); // Note the CounterRemover instance returned by counterRemover is invoked // prependListener and destroyed immediately. eventpp::counterRemover(dispatcher).prependListener(event, []() { - // listener B + // listener B }); auto handle = eventpp::counterRemover(dispatcher).appendListener(event, []() { - // listener C + // listener C }, 2); eventpp::counterRemover(dispatcher).insertListener(event, []() { - // listener D + // listener D }, handle, 3); dispatcher.dispatch(event); diff --git a/doc/eventdispatcher.md b/doc/eventdispatcher.md index 67f5773..61e9e85 100644 --- a/doc/eventdispatcher.md +++ b/doc/eventdispatcher.md @@ -34,9 +34,9 @@ eventpp/eventdispatcher.h ```c++ template < - typename Event, - typename Prototype, - typename Policies = DefaultPolicies + typename Event, + typename Prototype, + typename Policies = DefaultPolicies > class EventDispatcher; ``` diff --git a/doc/eventmaker.md b/doc/eventmaker.md index c6df094..5cbe945 100644 --- a/doc/eventmaker.md +++ b/doc/eventmaker.md @@ -15,23 +15,23 @@ class Event class EventMouseDown : public Event { public: - int getX() const; - int getY() const; - int getButton() const; - + int getX() const; + int getY() const; + int getButton() const; + private: - int x; - int y; - int button; + int x; + int y; + int button; }; class EventKeyDown : public Event { public: - int getKey() const; - + int getKey() const; + private: - int key; + int key; }; ``` @@ -62,8 +62,8 @@ The macro always generates a default constructor and a constructor that takes al Code examples: ```c++ EVENTPP_MAKE_EVENT( - EventDraw, Event, EventType::draw, - (std::string, getText, setText), (int, getX), (double, getSize) + EventDraw, Event, EventType::draw, + (std::string, getText, setText), (int, getX), (double, getSize) ); ``` Generates class like (in pseudo code), @@ -71,45 +71,45 @@ Generates class like (in pseudo code), class EventDraw : public Event { public: - EventDraw(const std::string & text, const int x, const double size) - : Event(EventType::draw), text(text), x(x), size(size) - { - } - - const std::string & getText() const { - return text; - } - - void setText(const std::string & value) { - text = value; - } - - const int getX() const { - return x; - } - - const double getSize() const { - return size; - } + EventDraw(const std::string & text, const int x, const double size) + : Event(EventType::draw), text(text), x(x), size(size) + { + } + + const std::string & getText() const { + return text; + } + + void setText(const std::string & value) { + text = value; + } + + const int getX() const { + return x; + } + + const double getSize() const { + return size; + } private: - std::string text; - int x; - double size; + std::string text; + int x; + double size; }; ``` ```c++ EVENTPP_MAKE_EVENT(EventDraw, (Event), EventType::draw, - (std::string, getText, setText), (int, getX), (double, getSize) + (std::string, getText, setText), (int, getX), (double, getSize) ); ``` Similar to above example, except the base class is `Event`. ```c++ EVENTPP_MAKE_EVENT(EventDraw, (Event), (EventType::draw, 5), - (std::string, getText, setText), (int, getX), (double, getSize) + (std::string, getText, setText), (int, getX), (double, getSize) ); ``` Similar to above example, except the base class is constructed with `(EventType::draw, 5)` instead of `(EventType::draw)`. diff --git a/doc/eventqueue.md b/doc/eventqueue.md index 7180ae2..a0b711b 100644 --- a/doc/eventqueue.md +++ b/doc/eventqueue.md @@ -33,9 +33,9 @@ eventpp/eventqueue.h ```c++ template < - typename Event, - typename Prototype, - typename Policies = DefaultPolicies + typename Event, + typename Prototype, + typename Policies = DefaultPolicies > class EventQueue; ``` @@ -49,16 +49,16 @@ EventQueue has the exactly same template parameters with EventDispatcher. Please ```c++ struct EventQueue::QueuedEvent { - EventType event; - std::tuple arguments; - - // get the event - EventType getEvent() const; + EventType event; + std::tuple arguments; + + // get the event + EventType getEvent() const; - // get the argument of index N - // same as std::get(queuedEvent.arguments) - template - NthArgType getArgument() const; + // get the argument of index N + // same as std::get(queuedEvent.arguments) + template + NthArgType getArgument() const; }; ``` `event` is the EventQueue::Event, `arguments` are the arguments passed in `enqueue`. @@ -170,8 +170,8 @@ Note: though `wait` has work around with spurious wakeup internally, the queue i `wait` is useful when a thread processes the event queue. A sampel usage is, ```c++ for(;;) { - eventQueue.wait(); - eventQueue.process(); + eventQueue.wait(); + eventQueue.process(); } ``` The code works even if it doesn't `wait`, but doing that will waste CPU power resource. @@ -188,12 +188,12 @@ Return true if the queue is not empty, false if the return is caused by time out ```c++ std::atomic shouldStop(false); for(;;) { - while(! eventQueue.waitFor(std::chrono::milliseconds(10)) && ! shouldStop.load()) ; - if(shouldStop.load()) { - break; - } + while(! eventQueue.waitFor(std::chrono::milliseconds(10)) && ! shouldStop.load()) ; + if(shouldStop.load()) { + break; + } - eventQueue.process(); + eventQueue.process(); } ``` @@ -206,8 +206,8 @@ Retrieve an event from the queue. The event is returned in `queuedEvent`. ```c++ struct EventQueue::QueuedEvent { - TheEventType event; - std::tuple arguments; + TheEventType event; + std::tuple arguments; }; ``` `queuedEvent` is a EventQueue::QueuedEvent struct. `event` is the EventQueue::Event, `arguments` are the arguments passed in `enqueue`. @@ -245,10 +245,10 @@ Sample code using EQ = eventpp::EventQueue; EQ queue; { - EQ::DisableQueueNotify disableNotify(&queue); - // any blocking threads will not be waken up by the below two lines. - queue.enqueue(1); - queue.enqueue(2); + EQ::DisableQueueNotify disableNotify(&queue); + // any blocking threads will not be waken up by the below two lines. + queue.enqueue(1); + queue.enqueue(2); } // any blocking threads are waken up here immediately. diff --git a/doc/eventutil.md b/doc/eventutil.md index ddbf66a..338932c 100644 --- a/doc/eventutil.md +++ b/doc/eventutil.md @@ -9,9 +9,9 @@ eventpp/utilities/eventutil.h ```c++ template bool removeListener( - DispatcherType & dispatcher, - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener + DispatcherType & dispatcher, + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener ); ``` The function finds `listener` of `event` in `dispatcher`, if it finds one, removes the listener and returns true, otherwise returns false. @@ -21,8 +21,8 @@ This function requires the listener be able to be compared with equal operator ( ```c++ template bool removeListener( - CallbackListType & callbackList, - const typename CallbackListType::Callback & callback + CallbackListType & callbackList, + const typename CallbackListType::Callback & callback ); ``` The function finds `callback` in `callbackList`, if it finds one, removes the callback and returns true, otherwise returns false. @@ -32,9 +32,9 @@ This function requires the callback be able to be compared with equal operator ( ```c++ template bool hasListener( - DispatcherType & dispatcher, - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener + DispatcherType & dispatcher, + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener ); ``` The function finds `listener` of `event` in `dispatcher`, returns true if it finds any one, otherwise returns false. @@ -43,8 +43,8 @@ This function requires the listener be able to be compared with equal operator ( ```c++ template bool hasAnyListener( - DispatcherType & dispatcher, - const typename DispatcherType::Event & event + DispatcherType & dispatcher, + const typename DispatcherType::Event & event ); ``` The function finds any listener of `event` in `dispatcher`, returns true if it finds any one, otherwise returns false. @@ -52,8 +52,8 @@ The function finds any listener of `event` in `dispatcher`, returns true if it f ```c++ template bool hasListener( - CallbackListType & callbackList, - const typename CallbackListType::Callback & callback + CallbackListType & callbackList, + const typename CallbackListType::Callback & callback ); ``` The function finds `callback` in `callbackList`, returns true if it finds one, otherwise returns false. @@ -62,7 +62,7 @@ This function requires the callback be able to be compared with equal operator ( ```c++ template bool hasAnyListener( - CallbackListType & callbackList + CallbackListType & callbackList ); ``` The function finds any callback in `callbackList`, returns true if it finds any one, otherwise returns false. diff --git a/doc/faq.md b/doc/faq.md index 7d0afa2..be9a408 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -58,7 +58,7 @@ For example, class MyEventDispatcher : public EventDispatcher { public: - virtual ~MyEventDispatcher(); + virtual ~MyEventDispatcher(); }; class MyClass : public MyEventDispatcher @@ -86,22 +86,22 @@ eventpp::CallbackList mainLoopTasks; void mainLoop() { - for(;;) { - // Do any stuff in the loop - - mainLoopTasks(); - } + for(;;) { + // Do any stuff in the loop + + mainLoopTasks(); + } } class MyEventQueue : public eventpp::EventQueue { public: - MyEventQueue() - { - mainLoopTasks.append([this]() { - process(); - }); - } + MyEventQueue() + { + mainLoopTasks.append([this]() { + process(); + }); + } }; ``` @@ -118,25 +118,25 @@ eventpp::CallbackList mainLoopTasks; void threadMain() { - while(! stopped) { - ioService.poll(); - mainLoopTasks(); - sleepSomeTime(); - } - - ioService.run(); - mainLoopTasks(); + while(! stopped) { + ioService.poll(); + mainLoopTasks(); + sleepSomeTime(); + } + + ioService.run(); + mainLoopTasks(); } class MyEventQueue : public eventpp::EventQueue { public: - MyEventQueue() - { - mainLoopTasks.append([this]() { - process(); - }); - } + MyEventQueue() + { + mainLoopTasks.append([this]() { + process(); + }); + } }; ``` diff --git a/doc/hetercallbacklist.md b/doc/hetercallbacklist.md index d50ddae..b488ff1 100644 --- a/doc/hetercallbacklist.md +++ b/doc/hetercallbacklist.md @@ -32,8 +32,8 @@ eventpp/hetercallbacklist.h ```c++ template < - typename PrototypeList, - typename Policies = DefaultPolicies + typename PrototypeList, + typename Policies = DefaultPolicies > class HeterCallbackList; ``` diff --git a/doc/hetereventdispatcher.md b/doc/hetereventdispatcher.md index 394e606..81ab062 100644 --- a/doc/hetereventdispatcher.md +++ b/doc/hetereventdispatcher.md @@ -31,9 +31,9 @@ eventpp/hetereventdispatcher.h ```c++ template < - typename Event, - typename PrototypeList, - typename Policies = DefaultPolicies + typename Event, + typename PrototypeList, + typename Policies = DefaultPolicies > class HeterEventDispatcher; ``` diff --git a/doc/hetereventqueue.md b/doc/hetereventqueue.md index 8d9c538..32f34c4 100644 --- a/doc/hetereventqueue.md +++ b/doc/hetereventqueue.md @@ -31,9 +31,9 @@ eventpp/eventqueue.h ```c++ template < - typename Event, - typename PrototypeList, - typename Policies = DefaultPolicies + typename Event, + typename PrototypeList, + typename Policies = DefaultPolicies > class HeterEventQueue; ``` @@ -137,8 +137,8 @@ Note: though `wait` has work around with spurious wakeup internally, the queue i `wait` is useful when a thread processes the event queue. A sampel usage is, ```c++ for(;;) { - eventQueue.wait(); - eventQueue.process(); + eventQueue.wait(); + eventQueue.process(); } ``` The code works event if it doesn't `wait`, but doing that will waste CPU power resource. @@ -155,12 +155,12 @@ Return true if the queue is not empty, false if the return is caused by time out ```c++ std::atomic shouldStop(false); for(;;) { - while(! eventQueue.waitFor(std::chrono::milliseconds(10)) && ! shouldStop.load()) ; - if(shouldStop.load()) { - break; - } + while(! eventQueue.waitFor(std::chrono::milliseconds(10)) && ! shouldStop.load()) ; + if(shouldStop.load()) { + break; + } - eventQueue.process(); + eventQueue.process(); } ``` @@ -177,10 +177,10 @@ Sample code using EQ = eventpp::HeterEventQueue; EQ queue; { - EQ::DisableQueueNotify disableNotify(&queue); - // any blocking threads will not be waken up by the below two lines. - queue.enqueue(1); - queue.enqueue(2); + EQ::DisableQueueNotify disableNotify(&queue); + // any blocking threads will not be waken up by the below two lines. + queue.enqueue(1); + queue.enqueue(2); } // any blocking threads are waken up here immediately. diff --git a/doc/heterogeneous.md b/doc/heterogeneous.md index 41f05ff..09884ea 100644 --- a/doc/heterogeneous.md +++ b/doc/heterogeneous.md @@ -30,22 +30,22 @@ eventpp/hetereventqueue.h ```c++ template < - typename PrototypeList, - typename Policies = DefaultPolicies + typename PrototypeList, + typename Policies = DefaultPolicies > class HeterCallbackList; template < - typename Event, - typename PrototypeList, - typename Policies = DefaultPolicies + typename Event, + typename PrototypeList, + typename Policies = DefaultPolicies > class HeterEventDispatcher; template < - typename Event, - typename PrototypeList, - typename Policies = DefaultPolicies + typename Event, + typename PrototypeList, + typename Policies = DefaultPolicies > class HeterEventQueue; ``` @@ -54,22 +54,22 @@ For comparison, below are the template parameters for the homogeneous counterpar ```c++ template < - typename Prototype, - typename Policies = DefaultPolicies + typename Prototype, + typename Policies = DefaultPolicies > class CallbackList; template < - typename Event, - typename Prototype, - typename Policies = DefaultPolicies + typename Event, + typename Prototype, + typename Policies = DefaultPolicies > class EventDispatcher; template < - typename Event, - typename Prototype, - typename Policies = DefaultPolicies + typename Event, + typename Prototype, + typename Policies = DefaultPolicies > class EventQueue; ``` diff --git a/doc/introduction.md b/doc/introduction.md index 31b7f0d..a73be62 100644 --- a/doc/introduction.md +++ b/doc/introduction.md @@ -28,22 +28,22 @@ EventDispatcher is ideal when there are many kinds of events, or the number of e ```c++ enum class MyEventType { - redraw, - mouseDown, - mouseUp, - //... maybe 200 other events here + redraw, + mouseDown, + mouseUp, + //... maybe 200 other events here }; struct MyEvent { - MyEventType type; - // data that all events may need + MyEventType type; + // data that all events may need }; struct MyEventPolicies { - static MyEventType getEvent(const MyEvent & e) { - return e.type; - } + static MyEventType getEvent(const MyEvent & e) { + return e.type; + } }; eventpp::EventDispatcher dispatcher; diff --git a/doc/mixins.md b/doc/mixins.md index 84d7ccb..2b5fb0c 100644 --- a/doc/mixins.md +++ b/doc/mixins.md @@ -47,7 +47,7 @@ class MyMixin : public Base To enable mixins, add them to the `Mixins` type in the policies class. For example, to enable `MixinFilter`, define the dispatcher as, ```c++ struct MyPolicies { - using Mixins = eventpp::MixinList; + using Mixins = eventpp::MixinList; }; eventpp::EventDispatcher dispatcher; ``` @@ -121,19 +121,19 @@ Return true if the filter is removed successfully. **Code** ```c++ struct MyPolicies { - using Mixins = eventpp::MixinList; + using Mixins = eventpp::MixinList; }; eventpp::EventDispatcher dispatcher; dispatcher.appendListener(3, [](const int e, const int i, const std::string & s) { - std::cout - << "Got event 3, i was 1 but actural is " << i - << " s was Hello but actural is " << s - << std::endl - ; + std::cout + << "Got event 3, i was 1 but actural is " << i + << " s was Hello but actural is " << s + << std::endl + ; }); dispatcher.appendListener(5, [](const int e, const int i, const std::string & s) { - std::cout << "Shout not got event 5" << std::endl; + std::cout << "Shout not got event 5" << std::endl; }); // Add three event filters. @@ -141,27 +141,27 @@ dispatcher.appendListener(5, [](const int e, const int i, const std::string & s) // The first filter modifies the input arguments to other values, then the subsequence filters // and listeners will see the modified values. dispatcher.appendFilter([](const int e, int & i, std::string & s) -> bool { - std::cout << "Filter 1, e is " << e << " passed in i is " << i << " s is " << s << std::endl; - i = 38; - s = "Hi"; - std::cout << "Filter 1, changed i is " << i << " s is " << s << std::endl; - return true; + std::cout << "Filter 1, e is " << e << " passed in i is " << i << " s is " << s << std::endl; + i = 38; + s = "Hi"; + std::cout << "Filter 1, changed i is " << i << " s is " << s << std::endl; + return true; }); // The second filter filters out all event of 5. So no listeners on event 5 can be triggered. // The third filter is not invoked on event 5 also. dispatcher.appendFilter([](const int e, int & i, std::string & s) -> bool { - std::cout << "Filter 2, e is " << e << " passed in i is " << i << " s is " << s << std::endl; - if(e == 5) { - return false; - } - return true; + std::cout << "Filter 2, e is " << e << " passed in i is " << i << " s is " << s << std::endl; + if(e == 5) { + return false; + } + return true; }); // The third filter just prints the input arguments. dispatcher.appendFilter([](const int e, int & i, std::string & s) -> bool { - std::cout << "Filter 3, e is " << e << " passed in i is " << i << " s is " << s << std::endl; - return true; + std::cout << "Filter 3, e is " << e << " passed in i is " << i << " s is " << s << std::endl; + return true; }); // Dispatch the events, the first argument is always the event type. diff --git a/doc/orderedqueuelist.md b/doc/orderedqueuelist.md index 89a1782..666a068 100644 --- a/doc/orderedqueuelist.md +++ b/doc/orderedqueuelist.md @@ -43,10 +43,10 @@ Its default implementation `OrderedQueueListCompare` looks like, ```c++ struct OrderedQueueListCompare { - template - bool operator() (const T & a, const T & b) const { - return a.event < b.event; - } + template + bool operator() (const T & a, const T & b) const { + return a.event < b.event; + } }; ``` The typename T is actually the `EventQueue::QueuedEvent`. But since `OrderedQueueList` is used in the policies that are used to construct the EventQueue, it's not possible to specify the actual type in `OrderedQueueListCompare`, so here we use a template operator. @@ -56,8 +56,8 @@ The typename T is actually the `EventQueue::QueuedEvent`. But since `OrderedQueu ```c++ struct QueuedEvent { - EventType event; - std::tuple arguments; + EventType event; + std::tuple arguments; }; ``` `event` is the event sent to the queue. @@ -70,56 +70,56 @@ struct QueuedEvent // First let's define the event struct. e is the event type, priority determines the priority. struct MyEvent { - int e; - int priority; + int e; + int priority; }; // The comparison function object used by eventpp::OrderedQueueList. // The function compares the event by priority. struct MyCompare { - template - bool operator() (const T & a, const T & b) const { - return std::get<0>(a.arguments).priority > std::get<0>(b.arguments).priority; - } + template + 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 - using QueueList = eventpp::OrderedQueueList; + template + using QueueList = eventpp::OrderedQueueList; - static int getEvent(const MyEvent & event) { - return event.e; - } + static int getEvent(const MyEvent & event) { + return event.e; + } }; void main() { - using EQ = eventpp::EventQueue; - EQ queue; + using EQ = eventpp::EventQueue; + 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; - }); + 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 }); + // 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.process(); + queue.process(); } ``` diff --git a/doc/policies.md b/doc/policies.md index 19f827c..b0a0a19 100644 --- a/doc/policies.md +++ b/doc/policies.md @@ -42,39 +42,39 @@ Sample code ```c++ // Define an Event to hold all parameters. struct MyEvent { - int type; - std::string message; - int param; + int type; + std::string message; + int param; }; // Define policies to let the dispatcher knows how to // extract the event type. struct MyEventPolicies { - static int getEvent(const MyEvent & e, bool /*b*/) { - return e.type; - } + static int getEvent(const MyEvent & e, bool /*b*/) { + return e.type; + } }; // Pass MyEventPolicies as the third template argument of EventDispatcher. // Note: the first template argument is the event type type int, not MyEvent. eventpp::EventDispatcher< - int, - void (const MyEvent &, bool), - MyEventPolicies + int, + void (const MyEvent &, bool), + MyEventPolicies > dispatcher; // Add a listener. // Note: the first argument is the event type of type int, not MyEvent. dispatcher.appendListener(3, [](const MyEvent & e, bool b) { - std::cout - << std::boolalpha - << "Got event 3" << std::endl - << "Event::type is " << e.type << std::endl - << "Event::message is " << e.message << std::endl - << "Event::param is " << e.param << std::endl - << "b is " << b << std::endl - ; + std::cout + << std::boolalpha + << "Got event 3" << std::endl + << "Event::type is " << e.type << std::endl + << "Event::message is " << e.message << std::endl + << "Event::param is " << e.param << std::endl + << "b is " << b << std::endl + ; }); // Dispatch the event. @@ -93,35 +93,35 @@ Sample code ```c++ struct MyEvent { - MyEvent() : type(0), canceled(false) { - } - explicit MyEvent(const int type) - : type(type), canceled(false) { - } + MyEvent() : type(0), canceled(false) { + } + explicit MyEvent(const int type) + : type(type), canceled(false) { + } - int type; - mutable bool canceled; + int type; + mutable bool canceled; }; struct MyEventPolicies { - static int getEvent(const MyEvent & e) { - return e.type; - } + static int getEvent(const MyEvent & e) { + return e.type; + } - static bool canContinueInvoking(const MyEvent & e) { - return ! e.canceled; - } + static bool canContinueInvoking(const MyEvent & e) { + return ! e.canceled; + } }; eventpp::EventDispatcher dispatcher; dispatcher.appendListener(3, [](const MyEvent & e) { - std::cout << "Got event 3" << std::endl; - e.canceled = true; + std::cout << "Got event 3" << std::endl; + e.canceled = true; }); dispatcher.appendListener(3, [](const MyEvent & e) { - std::cout << "Should not get this event 3" << std::endl; + std::cout << "Should not get this event 3" << std::endl; }); dispatcher.dispatch(MyEvent(3)); @@ -158,12 +158,12 @@ A typical `Threading` type looks like ```c++ struct MultipleThreading { - using Mutex = std::mutex; + using Mutex = std::mutex; - template - using Atomic = std::atomic; + template + using Atomic = std::atomic; - using ConditionVariable = std::condition_variable; + using ConditionVariable = std::condition_variable; }; ``` For `SingleThreading`, all the types `Mutex`, `Atomic`, and `ConditionVariable` are dummy types that don't do anything. @@ -177,15 +177,15 @@ Below is the sample code for how to use `SpinLock` ```c++ struct MultipleThreadingSpinLock { - using Mutex = eventpp::SpinLock; + using Mutex = eventpp::SpinLock; - template - using Atomic = std::atomic; + template + using Atomic = std::atomic; - using ConditionVariable = std::condition_variable; + using ConditionVariable = std::condition_variable; }; struct MyEventPolicies { - using Threading = MultipleThreadingSpinLock; + using Threading = MultipleThreadingSpinLock; }; eventpp::EventDispatcher dispatcher; eventpp::CallbackList callbackList; @@ -194,18 +194,18 @@ eventpp::CallbackList callbackList; `eventpp` provides a shortcut template class to customize the threading. ```c++ template < - typename Mutex_, - template class Atomic_ = std::atomic, - typename ConditionVariable_ = std::condition_variable + typename Mutex_, + template class Atomic_ = std::atomic, + typename ConditionVariable_ = std::condition_variable > struct GeneralThreading { - using Mutex = Mutex_; + using Mutex = Mutex_; - template - using Atomic = Atomic_; + template + using Atomic = Atomic_; - using ConditionVariable = ConditionVariable_; + using ConditionVariable = ConditionVariable_; }; ``` @@ -213,7 +213,7 @@ So the previous sample code for spinlock can be rewritten as ```c++ struct MyEventPolicies { - using Threading = eventpp::GeneralThreading; + using Threading = eventpp::GeneralThreading; }; eventpp::EventDispatcher dispatcher; eventpp::CallbackList callbackList; @@ -270,12 +270,12 @@ Examples to demonstrate argument passing mode ```c++ struct MyPolicies { - using ArgumentPassingMode = ArgumentPassingAutoDetect; + using ArgumentPassingMode = ArgumentPassingAutoDetect; }; eventpp::EventDispatcher< - int, - void(int, const std::string &), - MyPolicies + int, + void(int, const std::string &), + MyPolicies > dispatcher; // or just //eventpp::EventDispatcher dispatcher; @@ -286,12 +286,12 @@ dispatcher.dispatch(3, 8, "hello"); // Compile OK ```c++ struct MyPolicies { - using ArgumentPassingMode = ArgumentPassingIncludeEvent; + using ArgumentPassingMode = ArgumentPassingIncludeEvent; }; eventpp::EventDispatcher< - int, - void(int, const std::string &), - MyPolicies + int, + void(int, const std::string &), + MyPolicies > dispatcher; dispatcher.dispatch(3, "hello"); // Compile OK //dispatcher.dispatch(3, 8, "hello"); // Compile failure @@ -300,12 +300,12 @@ dispatcher.dispatch(3, "hello"); // Compile OK ```c++ struct MyPolicies { - using ArgumentPassingMode = ArgumentPassingExcludeEvent; + using ArgumentPassingMode = ArgumentPassingExcludeEvent; }; eventpp::EventDispatcher< - int, - void(int, const std::string &), - MyPolicies + int, + void(int, const std::string &), + MyPolicies > dispatcher; //dispatcher.dispatch(3, "hello"); // Compile failure dispatcher.dispatch(3, 8, "hello"); // Compile OK @@ -367,10 +367,10 @@ To use policies, declare a struct, define the policies in it, and pass the struc ```c++ struct MyPolicies //the struct name doesn't matter { - template - static int getEvent(const MyEvent & e, const Args &...) { - return e.type; - } + template + static int getEvent(const MyEvent & e, const Args &...) { + return e.type; + } }; EventDispatcher dispatcher; ``` diff --git a/doc/scopedremover.md b/doc/scopedremover.md index de3177b..0f6ccb3 100644 --- a/doc/scopedremover.md +++ b/doc/scopedremover.md @@ -58,24 +58,24 @@ void reset(); void setDispatcher(DispatcherType & dispatcher); typename DispatcherType::Handle appendListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener + ); typename DispatcherType::Handle prependListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener + ); typename DispatcherType::Handle insertListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Callback & listener, - const typename DispatcherType::Handle & before - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Callback & listener, + const typename DispatcherType::Handle & before + ); bool removeListener( - const typename DispatcherType::Event & event, - const typename DispatcherType::Handle handle - ); + const typename DispatcherType::Event & event, + const typename DispatcherType::Handle handle + ); ``` **Member functions for CallbackList** @@ -85,17 +85,17 @@ void reset(); void setCallbackList(CallbackListType & callbackList); typename CallbackListType::Handle append( - const typename CallbackListType::Callback & callback - ); + const typename CallbackListType::Callback & callback + ); typename CallbackListType::Handle prepend( - const typename CallbackListType::Callback & callback - ); + const typename CallbackListType::Callback & callback + ); typename CallbackListType::Handle insert( - const typename CallbackListType::Callback & callback, - const typename CallbackListType::Handle & before - ); + const typename CallbackListType::Callback & callback, + const typename CallbackListType::Handle & before + ); bool remove(const typename CallbackListType::Handle handle); ``` @@ -119,39 +119,39 @@ using Remover = eventpp::ScopedRemover >; constexpr int event = 3; dispatcher.appendListener(event, [&dataList]() { - // listener A + // listener A }); { - Remover r1(dispatcher); - r1.prependListener(event, [&dataList]() { - // listener B - }); - { - Remover r2(dispatcher); - auto handle = r2.appendListener(event, [&dataList]() { - // listener C - }); - { - Remover r3(dispatcher); - r3.insertListener(event, [&dataList]() { - // listener D - }, handle); + Remover r1(dispatcher); + r1.prependListener(event, [&dataList]() { + // listener B + }); + { + Remover r2(dispatcher); + auto handle = r2.appendListener(event, [&dataList]() { + // listener C + }); + { + Remover r3(dispatcher); + r3.insertListener(event, [&dataList]() { + // listener D + }, handle); - dispatcher.dispatch(event); - // All listeners were triggered. - } - - // listener D was removed + dispatcher.dispatch(event); + // All listeners were triggered. + } + + // listener D was removed - dispatcher.dispatch(event); - // Listeners A, B, C were triggered. - } + dispatcher.dispatch(event); + // Listeners A, B, C were triggered. + } - // listener C was removed + // listener C was removed - dispatcher.dispatch(event); - // Listeners A, B were triggered. + dispatcher.dispatch(event); + // Listeners A, B were triggered. } // listener B was removed @@ -173,12 +173,12 @@ SomeDispatcher someDispatcher; class MyClass { - MyClass() - { - someDispatcher.appendListener(SomeEvent, callback of myListener); - } - - void myListener() {} + MyClass() + { + someDispatcher.appendListener(SomeEvent, callback of myListener); + } + + void myListener() {} }; ``` @@ -191,14 +191,14 @@ SomeDispatcher someDispatcher; class MyClass { - MyClass() : scopedRemover(someDispatcher) - { - scopedRemover.appendListener(SomeEvent, callback of myListener); - } - - void myListener() {} + MyClass() : scopedRemover(someDispatcher) + { + scopedRemover.appendListener(SomeEvent, callback of myListener); + } + + void myListener() {} - eventpp::ScopedRemover scopedRemover; + eventpp::ScopedRemover scopedRemover; }; ``` diff --git a/doc/tutorial_callbacklist.md b/doc/tutorial_callbacklist.md index cc503dc..e4a0ccf 100644 --- a/doc/tutorial_callbacklist.md +++ b/doc/tutorial_callbacklist.md @@ -19,10 +19,10 @@ eventpp::CallbackList callbackList; // Lambda is not required, any function or std::function // or whatever function object with the required prototype is fine. callbackList.append([]() { - std::cout << "Got callback 1." << std::endl; + std::cout << "Got callback 1." << std::endl; }); callbackList.append([]() { - std::cout << "Got callback 2." << std::endl; + std::cout << "Got callback 2." << std::endl; }); // Invoke the callback list @@ -44,7 +44,7 @@ The *prototype* is C++ function type, such as `void (int)`, `void (const std::st Now let's add a callback. ```c++ callbackList.append([]() { - std::cout << "Got callback 1." << std::endl; + std::cout << "Got callback 1." << std::endl; }); ``` Function `append` takes one arguments, the *callback*. @@ -65,12 +65,12 @@ During the invoking, all callbacks will be invoked one by one in the order of th eventpp::CallbackList callbackList; callbackList.append([](const std::string & s, const bool b) { - std::cout << std::boolalpha << "Got callback 1, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got callback 1, s is " << s << " b is " << b << std::endl; }); // The callback prototype doesn't need to be exactly same as the callback list. // It would be fine as long as the arguments are compatible with the callbacklist. callbackList.append([](std::string s, int b) { - std::cout << std::boolalpha << "Got callback 2, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got callback 2, s is " << s << " b is " << b << std::endl; }); // Invoke the callback list @@ -96,13 +96,13 @@ CL::Handle handle2; // Add some callbacks. callbackList.append([]() { - std::cout << "Got callback 1." << std::endl; + std::cout << "Got callback 1." << std::endl; }); handle2 = callbackList.append([]() { - std::cout << "Got callback 2." << std::endl; + std::cout << "Got callback 2." << std::endl; }); callbackList.append([]() { - std::cout << "Got callback 3." << std::endl; + std::cout << "Got callback 3." << std::endl; }); callbackList.remove(handle2); @@ -127,30 +127,30 @@ CL callbackList; // Add some callbacks. callbackList.append([]() { - std::cout << "Got callback 1." << std::endl; + std::cout << "Got callback 1." << std::endl; }); callbackList.append([]() { - std::cout << "Got callback 2." << std::endl; + std::cout << "Got callback 2." << std::endl; }); callbackList.append([]() { - std::cout << "Got callback 3." << std::endl; + 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; + 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::Callback & callback) callbackList.forEach([&callbackList, &index](const CL::Callback & callback) { - std::cout << "forEach(Callback), invoked" << std::endl; + std::cout << "forEach(Callback), invoked" << std::endl; }); // Invoke the callback list diff --git a/doc/tutorial_eventdispatcher.md b/doc/tutorial_eventdispatcher.md index 296c4d0..72bf90b 100644 --- a/doc/tutorial_eventdispatcher.md +++ b/doc/tutorial_eventdispatcher.md @@ -22,13 +22,13 @@ eventpp::EventDispatcher dispatcher; // Lambda is not required, any function or std::function // or whatever function object with the required prototype is fine. dispatcher.appendListener(3, []() { - std::cout << "Got event 3." << std::endl; + std::cout << "Got event 3." << std::endl; }); dispatcher.appendListener(5, []() { - std::cout << "Got event 5." << std::endl; + std::cout << "Got event 5." << std::endl; }); dispatcher.appendListener(5, []() { - std::cout << "Got another event 5." << std::endl; + std::cout << "Got another event 5." << std::endl; }); // Dispatch the events, the first argument is always the event type. @@ -53,7 +53,7 @@ The *prototype* is C++ function type, such as `void (int)`, `void (const std::st Now let's add a listener. ```c++ dispatcher.appendListener(3, []() { - std::cout << "Got event 3." << std::endl; + std::cout << "Got event 3." << std::endl; }); ``` Function `appendListener` takes at least two arguments. The first argument is the *event* of type *event type*, here is `int`. The second is the *callback*. @@ -76,15 +76,15 @@ During the dispatching, all listeners of that event will be invoked one by one i eventpp::EventDispatcher dispatcher; dispatcher.appendListener(3, [](const std::string & s, const bool b) { - std::cout << std::boolalpha << "Got event 3, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got event 3, s is " << s << " b is " << b << std::endl; }); // The listener prototype doesn't need to be exactly same as the dispatcher. // It would be find as long as the arguments is compatible with the dispatcher. dispatcher.appendListener(5, [](std::string s, int b) { - std::cout << std::boolalpha << "Got event 5, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got event 5, s is " << s << " b is " << b << std::endl; }); dispatcher.appendListener(5, [](const std::string & s, const bool b) { - std::cout << std::boolalpha << "Got another event 5, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got another event 5, s is " << s << " b is " << b << std::endl; }); // Dispatch the events, the first argument is always the event type. @@ -107,39 +107,39 @@ The listener's prototype is not required to be same as the dispatcher, it's fine ```c++ // Define an Event to hold all parameters. struct MyEvent { - int type; - std::string message; - int param; + int type; + std::string message; + int param; }; // Define policies to let the dispatcher knows how to // extract the event type. struct MyEventPolicies { - static int getEvent(const MyEvent & e, bool /*b*/) { - return e.type; - } + static int getEvent(const MyEvent & e, bool /*b*/) { + return e.type; + } }; // Pass MyEventPolicies as the third template argument of EventDispatcher. // Note: the first template argument is the event type type int, not MyEvent. eventpp::EventDispatcher< - int, - void (const MyEvent &, bool), - MyEventPolicies + int, + void (const MyEvent &, bool), + MyEventPolicies > dispatcher; // Add a listener. // Note: the first argument is the event type of type int, not MyEvent. dispatcher.appendListener(3, [](const MyEvent & e, bool b) { - std::cout - << std::boolalpha - << "Got event 3" << std::endl - << "Event::type is " << e.type << std::endl - << "Event::message is " << e.message << std::endl - << "Event::param is " << e.param << std::endl - << "b is " << b << std::endl - ; + std::cout + << std::boolalpha + << "Got event 3" << std::endl + << "Event::type is " << e.type << std::endl + << "Event::message is " << e.message << std::endl + << "Event::param is " << e.param << std::endl + << "b is " << b << std::endl + ; }); // Dispatch the event. diff --git a/doc/tutorial_eventqueue.md b/doc/tutorial_eventqueue.md index 8139ae3..d6e8d5b 100644 --- a/doc/tutorial_eventqueue.md +++ b/doc/tutorial_eventqueue.md @@ -13,15 +13,15 @@ Note if you are going to try the tutorial code, you'd better test the code under eventpp::EventQueue &)> queue; queue.appendListener(3, [](const std::string & s, std::unique_ptr & n) { - std::cout << "Got event 3, s is " << s << " n is " << *n << std::endl; + std::cout << "Got event 3, s is " << s << " n is " << *n << std::endl; }); // The listener prototype doesn't need to be exactly same as the dispatcher. // It would be find as long as the arguments is compatible with the dispatcher. queue.appendListener(5, [](std::string s, const std::unique_ptr & n) { - std::cout << "Got event 5, s is " << s << " n is " << *n << std::endl; + std::cout << "Got event 5, s is " << s << " n is " << *n << std::endl; }); queue.appendListener(5, [](const std::string & s, std::unique_ptr & n) { - std::cout << "Got another event 5, s is " << s << " n is " << *n << std::endl; + std::cout << "Got another event 5, s is " << s << " n is " << *n << std::endl; }); // Enqueue the events, the first argument is always the event type. @@ -59,19 +59,19 @@ constexpr int otherEvent = 2; // Start a thread to process the event queue. // All listeners are invoked in that thread. std::thread thread([stopEvent, otherEvent, &queue]() { - volatile bool shouldStop = false; - queue.appendListener(stopEvent, [&shouldStop](int) { - shouldStop = true; - }); - queue.appendListener(otherEvent, [](const int index) { - std::cout << "Got event, index is " << index << std::endl; - }); + volatile bool shouldStop = false; + queue.appendListener(stopEvent, [&shouldStop](int) { + shouldStop = true; + }); + queue.appendListener(otherEvent, [](const int index) { + std::cout << "Got event, index is " << index << std::endl; + }); - while(! shouldStop) { - queue.wait(); + while(! shouldStop) { + queue.wait(); - queue.process(); - } + queue.process(); + } }); // Enqueue an event from the main thread. After sleeping for 10 milliseconds, @@ -85,20 +85,20 @@ std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::cout << "Should have triggered event with index = 2" << std::endl; { - // EventQueue::DisableQueueNotify is a RAII class that - // disables waking up any waiting threads. - // So no events should be triggered in this code block. - // DisableQueueNotify is useful when adding lots of events at the same time - // and only want to wake up the waiting threads after all events are added. - EQ::DisableQueueNotify disableNotify(&queue); + // EventQueue::DisableQueueNotify is a RAII class that + // disables waking up any waiting threads. + // So no events should be triggered in this code block. + // DisableQueueNotify is useful when adding lots of events at the same time + // and only want to wake up the waiting threads after all events are added. + EQ::DisableQueueNotify disableNotify(&queue); - queue.enqueue(otherEvent, 10); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - std::cout << "Should NOT trigger event with index = 10" << std::endl; - - queue.enqueue(otherEvent, 11); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - std::cout << "Should NOT trigger event with index = 11" << std::endl; + queue.enqueue(otherEvent, 10); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::cout << "Should NOT trigger event with index = 10" << std::endl; + + queue.enqueue(otherEvent, 11); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::cout << "Should NOT trigger event with index = 11" << std::endl; } // The DisableQueueNotify object is destroyed here, and has resumed // waking up waiting threads. So the events should be triggered. diff --git a/readme.md b/readme.md index fcdfe6d..299aad6 100644 --- a/readme.md +++ b/readme.md @@ -52,8 +52,8 @@ In brief, MSVC, GCC, Clang that has well support for C++11, or released after 20 * The library: C++11. * To develop the library * Unit tests: C++17. - * Tutorials: C++11. - * Benchmakrs: C++11. + * Tutorials: C++11. + * Benchmakrs: C++11. ## Quick start @@ -101,10 +101,10 @@ Note: the method 2 doesn't work well with MingW on Windows. It works well on Lin #include "eventpp/callbacklist.h" eventpp::CallbackList callbackList; callbackList.append([](const std::string & s, const bool b) { - std::cout << std::boolalpha << "Got callback 1, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got callback 1, s is " << s << " b is " << b << std::endl; }); callbackList.append([](std::string s, int b) { - std::cout << std::boolalpha << "Got callback 2, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got callback 2, s is " << s << " b is " << b << std::endl; }); callbackList("Hello world", true); ``` @@ -114,13 +114,13 @@ callbackList("Hello world", true); #include "eventpp/eventdispatcher.h" eventpp::EventDispatcher dispatcher; dispatcher.appendListener(3, []() { - std::cout << "Got event 3." << std::endl; + std::cout << "Got event 3." << std::endl; }); dispatcher.appendListener(5, []() { - std::cout << "Got event 5." << std::endl; + std::cout << "Got event 5." << std::endl; }); dispatcher.appendListener(5, []() { - std::cout << "Got another event 5." << std::endl; + std::cout << "Got another event 5." << std::endl; }); // dispatch event 3 dispatcher.dispatch(3); @@ -133,10 +133,10 @@ dispatcher.dispatch(5); eventpp::EventQueue queue; queue.appendListener(3, [](const std::string s, bool b) { - std::cout << std::boolalpha << "Got event 3, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got event 3, s is " << s << " b is " << b << std::endl; }); queue.appendListener(5, [](const std::string s, bool b) { - std::cout << std::boolalpha << "Got event 5, s is " << s << " b is " << b << std::endl; + std::cout << std::boolalpha << "Got event 5, s is " << s << " b is " << b << std::endl; }); // The listeners are not triggered during enqueue.