mirror of
https://github.com/wqking/eventpp.git
synced 2024-12-27 00:17:02 +08:00
tab->spaces in documents for easier read
This commit is contained in:
parent
05f3dc8249
commit
6e5f6ee45d
22
doc/anyid.md
22
doc/anyid.md
@ -54,9 +54,9 @@ A typical implementation of `Digester`:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct MyDigest
|
struct MyDigest
|
||||||
{
|
{
|
||||||
TheDigestTypeSuchAsSizeT operator() (const T & value) const {
|
TheDigestTypeSuchAsSizeT operator() (const T & value) const {
|
||||||
// compute the digest of value and return the digest.
|
// 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.
|
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++
|
```c++
|
||||||
struct MyStorage
|
struct MyStorage
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MyStorage(const T & value) {
|
MyStorage(const T & value) {
|
||||||
// store the value
|
// store the value
|
||||||
}
|
}
|
||||||
|
|
||||||
// any other member functions can be added, such as getting the underlying value.
|
// any other member functions can be added, such as getting the underlying value.
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
Or none template version:
|
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.
|
// In this version, only value of `int` and `std::string` can be stored.
|
||||||
struct MyStorage
|
struct MyStorage
|
||||||
{
|
{
|
||||||
MyStorage(const int value) {}
|
MyStorage(const int value) {}
|
||||||
MyStorage(const std::string & value) {}
|
MyStorage(const std::string & value) {}
|
||||||
|
|
||||||
// any other member functions can be added, such as getting the underlying value.
|
// any other member functions can be added, such as getting the underlying value.
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -70,74 +70,74 @@ Below is the example code to demonstrate how to use `argumentAdapter`. There are
|
|||||||
// Define the event types
|
// Define the event types
|
||||||
enum class EventType
|
enum class EventType
|
||||||
{
|
{
|
||||||
// for MouseEvent
|
// for MouseEvent
|
||||||
mouse,
|
mouse,
|
||||||
|
|
||||||
// for KeyEvent
|
// for KeyEvent
|
||||||
key,
|
key,
|
||||||
|
|
||||||
// for MessageEvent
|
// for MessageEvent
|
||||||
message,
|
message,
|
||||||
|
|
||||||
// For either MouseEvent or KeyEvent, we use this type to demonstrate
|
// For either MouseEvent or KeyEvent, we use this type to demonstrate
|
||||||
// how to use conditionalFunctor
|
// how to use conditionalFunctor
|
||||||
input,
|
input,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Event
|
class Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Event() {
|
Event() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the Event polymorphism so we can use dynamic_cast to detect
|
// Make the Event polymorphism so we can use dynamic_cast to detect
|
||||||
// if it's a MouseEvent or KeyEvent
|
// if it's a MouseEvent or KeyEvent
|
||||||
virtual ~Event() {
|
virtual ~Event() {
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MouseEvent : public Event
|
class MouseEvent : public Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MouseEvent(const int x, const int y)
|
MouseEvent(const int x, const int y)
|
||||||
: x(x), y(y)
|
: x(x), y(y)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int getX() const { return x; }
|
int getX() const { return x; }
|
||||||
int getY() const { return y; }
|
int getY() const { return y; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeyEvent : public Event
|
class KeyEvent : public Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit KeyEvent(const int key)
|
explicit KeyEvent(const int key)
|
||||||
: key(key)
|
: key(key)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int getKey() const { return key; }
|
int getKey() const { return key; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int key;
|
int key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MessageEvent : public Event
|
class MessageEvent : public Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit MessageEvent(const std::string & message)
|
explicit MessageEvent(const std::string & message)
|
||||||
: message(message) {
|
: message(message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getMessage() const { return message; }
|
std::string getMessage() const { return message; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string message;
|
std::string message;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A free function that will be added as listener later.
|
// A free function that will be added as listener later.
|
||||||
@ -145,61 +145,61 @@ private:
|
|||||||
// lambda, functor object, std::function, free function, etc.
|
// lambda, functor object, std::function, free function, etc.
|
||||||
void tutorialArgumentAdapterFreeFunction(const MouseEvent & e)
|
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()
|
void example1()
|
||||||
{
|
{
|
||||||
eventpp::EventDispatcher<EventType, void (const Event &)> eventDispatcher;
|
eventpp::EventDispatcher<EventType, void (const Event &)> 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 &'
|
// This can't compile because a 'const Event &' can be passed to 'const MouseEvent &'
|
||||||
//eventDispatcher.appendListener(mouseEventId, [](const MouseEvent & e) {});
|
//eventDispatcher.appendListener(mouseEventId, [](const MouseEvent & e) {});
|
||||||
|
|
||||||
// This compiles. eventpp::argumentAdapter creates a functor object that static_cast
|
// This compiles. eventpp::argumentAdapter creates a functor object that static_cast
|
||||||
// 'const Event &' to 'const MouseEvent &' automatically.
|
// 'const Event &' to 'const MouseEvent &' automatically.
|
||||||
// Note we need to pass the function type to eventpp::argumentAdapter because the lambda
|
// 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
|
// doesn't have any function type information and eventpp::argumentAdapter can't deduce
|
||||||
// the type. This rule also applies to other functor object.
|
// the type. This rule also applies to other functor object.
|
||||||
eventDispatcher.appendListener(
|
eventDispatcher.appendListener(
|
||||||
EventType::mouse,
|
EventType::mouse,
|
||||||
eventpp::argumentAdapter<void(const MouseEvent &)>([](const MouseEvent & e) {
|
eventpp::argumentAdapter<void(const MouseEvent &)>([](const MouseEvent & e) {
|
||||||
std::cout << "Received MouseEvent in lambda, x=" << e.getX() << " y=" << e.getY() << std::endl;
|
std::cout << "Received MouseEvent in lambda, x=" << e.getX() << " y=" << e.getY() << std::endl;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
eventDispatcher.appendListener(
|
eventDispatcher.appendListener(
|
||||||
EventType::message,
|
EventType::message,
|
||||||
eventpp::argumentAdapter<void(const MessageEvent &)>([](const MessageEvent & e) {
|
eventpp::argumentAdapter<void(const MessageEvent &)>([](const MessageEvent & e) {
|
||||||
std::cout << "Received MessageEvent in lambda, message=" << e.getMessage() << std::endl;
|
std::cout << "Received MessageEvent in lambda, message=" << e.getMessage() << std::endl;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// callback 2 -- std::function
|
// callback 2 -- std::function
|
||||||
// We don't need to pass the function type to eventpp::argumentAdapter because it can
|
// We don't need to pass the function type to eventpp::argumentAdapter because it can
|
||||||
// deduce the type from the std::function
|
// deduce the type from the std::function
|
||||||
eventDispatcher.appendListener(
|
eventDispatcher.appendListener(
|
||||||
EventType::key,
|
EventType::key,
|
||||||
eventpp::argumentAdapter(std::function<void(const KeyEvent &)>([](const KeyEvent & e) {
|
eventpp::argumentAdapter(std::function<void(const KeyEvent &)>([](const KeyEvent & e) {
|
||||||
std::cout << "Received KeyEvent in std::function, key=" << e.getKey() << std::endl;
|
std::cout << "Received KeyEvent in std::function, key=" << e.getKey() << std::endl;
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
// callback 3 -- free function
|
// callback 3 -- free function
|
||||||
// We don't need to pass the function type to eventpp::argumentAdapter because it can
|
// We don't need to pass the function type to eventpp::argumentAdapter because it can
|
||||||
// deduce the type from the free function
|
// deduce the type from the free function
|
||||||
eventDispatcher.appendListener(
|
eventDispatcher.appendListener(
|
||||||
EventType::mouse,
|
EventType::mouse,
|
||||||
eventpp::argumentAdapter(tutorialArgumentAdapterFreeFunction)
|
eventpp::argumentAdapter(tutorialArgumentAdapterFreeFunction)
|
||||||
);
|
);
|
||||||
|
|
||||||
eventDispatcher.dispatch(EventType::mouse, MouseEvent(3, 5));
|
eventDispatcher.dispatch(EventType::mouse, MouseEvent(3, 5));
|
||||||
eventDispatcher.dispatch(EventType::key, KeyEvent(255));
|
eventDispatcher.dispatch(EventType::key, KeyEvent(255));
|
||||||
eventDispatcher.dispatch(EventType::message, MessageEvent("Hello, argumentAdapter"));
|
eventDispatcher.dispatch(EventType::message, MessageEvent("Hello, argumentAdapter"));
|
||||||
// In syntax we can dispatch KeyEvent under EventType::mouse, in our case,
|
// In syntax we can dispatch KeyEvent under EventType::mouse, in our case,
|
||||||
// the EventType::mouse listener casts KeyEvent to MouseEvent, which is invalid object,
|
// the EventType::mouse listener casts KeyEvent to MouseEvent, which is invalid object,
|
||||||
// and the listener will either use garbled data, or crash.
|
// and the listener will either use garbled data, or crash.
|
||||||
//eventDispatcher.dispatch(EventType::mouse, KeyEvent(255));
|
//eventDispatcher.dispatch(EventType::mouse, KeyEvent(255));
|
||||||
}
|
}
|
||||||
|
|
||||||
void example2()
|
void example2()
|
||||||
@ -212,25 +212,25 @@ eventpp::EventDispatcher<EventType, void(const Event &)> eventDispatcher;
|
|||||||
|
|
||||||
// listener 1
|
// listener 1
|
||||||
eventDispatcher.appendListener(
|
eventDispatcher.appendListener(
|
||||||
EventType::input,
|
EventType::input,
|
||||||
eventpp::conditionalFunctor(
|
eventpp::conditionalFunctor(
|
||||||
eventpp::argumentAdapter<void(const MouseEvent &)>([](const MouseEvent & e) {
|
eventpp::argumentAdapter<void(const MouseEvent &)>([](const MouseEvent & e) {
|
||||||
std::cout << "Received MouseEvent in conditional tutorial, x=" << e.getX() << " y=" << e.getY() << std::endl;
|
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 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.
|
// This is for demonstration purpose, in production you may use a better way than dynamic_cast.
|
||||||
[](const Event & e) { return dynamic_cast<const MouseEvent *>(&e) != nullptr; }
|
[](const Event & e) { return dynamic_cast<const MouseEvent *>(&e) != nullptr; }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
// listener 2
|
// listener 2
|
||||||
eventDispatcher.appendListener(
|
eventDispatcher.appendListener(
|
||||||
EventType::input,
|
EventType::input,
|
||||||
eventpp::conditionalFunctor(
|
eventpp::conditionalFunctor(
|
||||||
eventpp::argumentAdapter<void(const KeyEvent &)>([](const KeyEvent & e) {
|
eventpp::argumentAdapter<void(const KeyEvent &)>([](const KeyEvent & e) {
|
||||||
std::cout << "Received KeyEvent in conditional tutorial, key=" << e.getKey() << std::endl;
|
std::cout << "Received KeyEvent in conditional tutorial, key=" << e.getKey() << std::endl;
|
||||||
}),
|
}),
|
||||||
[](const Event & e) { return dynamic_cast<const KeyEvent *>(&e) != nullptr; }
|
[](const Event & e) { return dynamic_cast<const KeyEvent *>(&e) != nullptr; }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// listener 1 will receive this event, listener 2 will not.
|
// listener 1 will receive this event, listener 2 will not.
|
||||||
@ -255,10 +255,10 @@ eventpp::EventQueue<EventType, void(std::shared_ptr<Event>)> eventQueue;
|
|||||||
// This compiles. eventpp::argumentAdapter creates a functor object that static_cast
|
// This compiles. eventpp::argumentAdapter creates a functor object that static_cast
|
||||||
// 'std::shared_ptr<Event>' to 'std::shared_ptr<MouseEvent>' automatically.
|
// 'std::shared_ptr<Event>' to 'std::shared_ptr<MouseEvent>' automatically.
|
||||||
eventQueue.appendListener(
|
eventQueue.appendListener(
|
||||||
EventType::mouse,
|
EventType::mouse,
|
||||||
eventpp::argumentAdapter<void(std::shared_ptr<MouseEvent>)>([](std::shared_ptr<MouseEvent> e) {
|
eventpp::argumentAdapter<void(std::shared_ptr<MouseEvent>)>([](std::shared_ptr<MouseEvent> e) {
|
||||||
std::cout << "Received MouseEvent as std::shared_ptr, x=" << e->getX() << " y=" << e->getY() << std::endl;
|
std::cout << "Received MouseEvent as std::shared_ptr, x=" << e->getX() << " y=" << e->getY() << std::endl;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
eventQueue.enqueue(EventType::mouse, std::make_shared<MouseEvent>(3, 5));
|
eventQueue.enqueue(EventType::mouse, std::make_shared<MouseEvent>(3, 5));
|
||||||
|
408
doc/benchmark.md
408
doc/benchmark.md
@ -8,40 +8,40 @@ Time unit: milliseconds (unless explicitly specified)
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Iterations</th>
|
<th>Iterations</th>
|
||||||
<th>Queue size</th>
|
<th>Queue size</th>
|
||||||
<th>Event count</th>
|
<th>Event count</th>
|
||||||
<th>Event Types</th>
|
<th>Event Types</th>
|
||||||
<th>Listener count</th>
|
<th>Listener count</th>
|
||||||
<th>Time of single threading</th>
|
<th>Time of single threading</th>
|
||||||
<th>Time of multi threading</th>
|
<th>Time of multi threading</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>100k</td>
|
<td>100k</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>401</td>
|
<td>401</td>
|
||||||
<td>1146</td>
|
<td>1146</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>100k</td>
|
<td>100k</td>
|
||||||
<td>1000</td>
|
<td>1000</td>
|
||||||
<td>100M</td>
|
<td>100M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>4012</td>
|
<td>4012</td>
|
||||||
<td>11467</td>
|
<td>11467</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>100k</td>
|
<td>100k</td>
|
||||||
<td>1000</td>
|
<td>1000</td>
|
||||||
<td>100M</td>
|
<td>100M</td>
|
||||||
<td>1000</td>
|
<td>1000</td>
|
||||||
<td>1000</td>
|
<td>1000</td>
|
||||||
<td>4102</td>
|
<td>4102</td>
|
||||||
<td>11600</td>
|
<td>11600</td>
|
||||||
</tr>
|
</tr>
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
@ -53,107 +53,107 @@ The EventQueue is processed in one thread. The Single/Multi threading in the tab
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Mutex</th>
|
<th>Mutex</th>
|
||||||
<th>Enqueue threads</th>
|
<th>Enqueue threads</th>
|
||||||
<th>Process threads</th>
|
<th>Process threads</th>
|
||||||
<th>Event count</th>
|
<th>Event count</th>
|
||||||
<th>Event Types</th>
|
<th>Event Types</th>
|
||||||
<th>Listener count</th>
|
<th>Listener count</th>
|
||||||
<th>Time</th>
|
<th>Time</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>std::mutex</td>
|
<td>std::mutex</td>
|
||||||
<td>1</td>
|
<td>1</td>
|
||||||
<td>1</td>
|
<td>1</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>2283</td>
|
<td>2283</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>SpinLock</td>
|
<td>SpinLock</td>
|
||||||
<td>1</td>
|
<td>1</td>
|
||||||
<td>1</td>
|
<td>1</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>1692</td>
|
<td>1692</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>std::mutex</td>
|
<td>std::mutex</td>
|
||||||
<td>1</td>
|
<td>1</td>
|
||||||
<td>3</td>
|
<td>3</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>3446</td>
|
<td>3446</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>SpinLock</td>
|
<td>SpinLock</td>
|
||||||
<td>1</td>
|
<td>1</td>
|
||||||
<td>3</td>
|
<td>3</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>3025</td>
|
<td>3025</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>std::mutex</td>
|
<td>std::mutex</td>
|
||||||
<td>2</td>
|
<td>2</td>
|
||||||
<td>2</td>
|
<td>2</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>4000</td>
|
<td>4000</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>SpinLock</td>
|
<td>SpinLock</td>
|
||||||
<td>2</td>
|
<td>2</td>
|
||||||
<td>2</td>
|
<td>2</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>3076</td>
|
<td>3076</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>std::mutex</td>
|
<td>std::mutex</td>
|
||||||
<td>4</td>
|
<td>4</td>
|
||||||
<td>4</td>
|
<td>4</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>1971</td>
|
<td>1971</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>SpinLock</td>
|
<td>SpinLock</td>
|
||||||
<td>4</td>
|
<td>4</td>
|
||||||
<td>4</td>
|
<td>4</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>1755</td>
|
<td>1755</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>std::mutex</td>
|
<td>std::mutex</td>
|
||||||
<td>16</td>
|
<td>16</td>
|
||||||
<td>16</td>
|
<td>16</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>928</td>
|
<td>928</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>SpinLock</td>
|
<td>SpinLock</td>
|
||||||
<td>16</td>
|
<td>16</td>
|
||||||
<td>16</td>
|
<td>16</td>
|
||||||
<td>10M</td>
|
<td>10M</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>100</td>
|
<td>100</td>
|
||||||
<td>2082</td>
|
<td>2082</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -172,123 +172,123 @@ Iterations: 100,000,000
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Function</th>
|
<th>Function</th>
|
||||||
<th>Compiler</th>
|
<th>Compiler</th>
|
||||||
<th>Native invoking</th>
|
<th>Native invoking</th>
|
||||||
<th>CallbackList single threading</th>
|
<th>CallbackList single threading</th>
|
||||||
<th>CallbackList multi threading</th>
|
<th>CallbackList multi threading</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">Inline global function</td>
|
<td rowspan="2">Inline global function</td>
|
||||||
<td>MSVC 2017</td>
|
<td>MSVC 2017</td>
|
||||||
<td>217</td>
|
<td>217</td>
|
||||||
<td>1501</td>
|
<td>1501</td>
|
||||||
<td>6921</td>
|
<td>6921</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>GCC 7.2</td>
|
<td>GCC 7.2</td>
|
||||||
<td>187</td>
|
<td>187</td>
|
||||||
<td>1489</td>
|
<td>1489</td>
|
||||||
<td>4463</td>
|
<td>4463</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">Non-inline global function</td>
|
<td rowspan="2">Non-inline global function</td>
|
||||||
<td>MSVC 2017</td>
|
<td>MSVC 2017</td>
|
||||||
<td>241</td>
|
<td>241</td>
|
||||||
<td>1526</td>
|
<td>1526</td>
|
||||||
<td>6544</td>
|
<td>6544</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>GCC 7.2</td>
|
<td>GCC 7.2</td>
|
||||||
<td>233</td>
|
<td>233</td>
|
||||||
<td>1488</td>
|
<td>1488</td>
|
||||||
<td>4787</td>
|
<td>4787</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">Function object</td>
|
<td rowspan="2">Function object</td>
|
||||||
<td>MSVC 2017</td>
|
<td>MSVC 2017</td>
|
||||||
<td>194</td>
|
<td>194</td>
|
||||||
<td>1498</td>
|
<td>1498</td>
|
||||||
<td>6433</td>
|
<td>6433</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>GCC 7.2</td>
|
<td>GCC 7.2</td>
|
||||||
<td>212</td>
|
<td>212</td>
|
||||||
<td>1485</td>
|
<td>1485</td>
|
||||||
<td>4951</td>
|
<td>4951</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">Member virtual function</td>
|
<td rowspan="2">Member virtual function</td>
|
||||||
<td>MSVC 2017</td>
|
<td>MSVC 2017</td>
|
||||||
<td>207</td>
|
<td>207</td>
|
||||||
<td>1533</td>
|
<td>1533</td>
|
||||||
<td>6558</td>
|
<td>6558</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>GCC 7.2</td>
|
<td>GCC 7.2</td>
|
||||||
<td>212</td>
|
<td>212</td>
|
||||||
<td>1485</td>
|
<td>1485</td>
|
||||||
<td>4489</td>
|
<td>4489</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">Member non-virtual function</td>
|
<td rowspan="2">Member non-virtual function</td>
|
||||||
<td>MSVC 2017</td>
|
<td>MSVC 2017</td>
|
||||||
<td>214</td>
|
<td>214</td>
|
||||||
<td>1533</td>
|
<td>1533</td>
|
||||||
<td>6390</td>
|
<td>6390</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>GCC 7.2</td>
|
<td>GCC 7.2</td>
|
||||||
<td>211</td>
|
<td>211</td>
|
||||||
<td>1486</td>
|
<td>1486</td>
|
||||||
<td>4872</td>
|
<td>4872</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">Member non-inline virtual function</td>
|
<td rowspan="2">Member non-inline virtual function</td>
|
||||||
<td>MSVC 2017</td>
|
<td>MSVC 2017</td>
|
||||||
<td>206</td>
|
<td>206</td>
|
||||||
<td>1522</td>
|
<td>1522</td>
|
||||||
<td>6578</td>
|
<td>6578</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>GCC 7.2</td>
|
<td>GCC 7.2</td>
|
||||||
<td>182</td>
|
<td>182</td>
|
||||||
<td>1666</td>
|
<td>1666</td>
|
||||||
<td>4593</td>
|
<td>4593</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">Member non-inline non-virtual function</td>
|
<td rowspan="2">Member non-inline non-virtual function</td>
|
||||||
<td>MSVC 2017</td>
|
<td>MSVC 2017</td>
|
||||||
<td>206</td>
|
<td>206</td>
|
||||||
<td>1491</td>
|
<td>1491</td>
|
||||||
<td>6992</td>
|
<td>6992</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>GCC 7.2</td>
|
<td>GCC 7.2</td>
|
||||||
<td>205</td>
|
<td>205</td>
|
||||||
<td>1486</td>
|
<td>1486</td>
|
||||||
<td>4490</td>
|
<td>4490</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2">All functions</td>
|
<td rowspan="2">All functions</td>
|
||||||
<td>MSVC 2017</td>
|
<td>MSVC 2017</td>
|
||||||
<td>1374</td>
|
<td>1374</td>
|
||||||
<td>10951</td>
|
<td>10951</td>
|
||||||
<td>29973</td>
|
<td>29973</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>GCC 7.2</td>
|
<td>GCC 7.2</td>
|
||||||
<td>1223</td>
|
<td>1223</td>
|
||||||
<td>9770</td>
|
<td>9770</td>
|
||||||
<td>22958</td>
|
<td>22958</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
@ -306,40 +306,40 @@ volatile int globalValue = 0;
|
|||||||
|
|
||||||
void globalFunction(int a, const int b)
|
void globalFunction(int a, const int b)
|
||||||
{
|
{
|
||||||
globalValue += a + b;
|
globalValue += a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
NON_INLINE void nonInlineGlobalFunction(int a, const int b)
|
NON_INLINE void nonInlineGlobalFunction(int a, const int b)
|
||||||
{
|
{
|
||||||
globalValue += a + b;
|
globalValue += a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FunctionObject
|
struct FunctionObject
|
||||||
{
|
{
|
||||||
void operator() (int a, const int b)
|
void operator() (int a, const int b)
|
||||||
{
|
{
|
||||||
globalValue += a + b;
|
globalValue += a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void virFunc(int a, const int b)
|
virtual void virFunc(int a, const int b)
|
||||||
{
|
{
|
||||||
globalValue += a + b;
|
globalValue += a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nonVirFunc(int a, const int b)
|
void nonVirFunc(int a, const int b)
|
||||||
{
|
{
|
||||||
globalValue += a + b;
|
globalValue += a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
NON_INLINE virtual void nonInlineVirFunc(int a, const int b)
|
NON_INLINE virtual void nonInlineVirFunc(int a, const int b)
|
||||||
{
|
{
|
||||||
globalValue += a + b;
|
globalValue += a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
NON_INLINE void nonInlineNonVirFunc(int a, const int b)
|
NON_INLINE void nonInlineNonVirFunc(int a, const int b)
|
||||||
{
|
{
|
||||||
globalValue += a + b;
|
globalValue += a + b;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef NON_INLINE
|
#undef NON_INLINE
|
||||||
|
@ -35,8 +35,8 @@ eventpp/callbacklist.h
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename Prototype,
|
typename Prototype,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class CallbackList;
|
class CallbackList;
|
||||||
```
|
```
|
||||||
|
@ -10,14 +10,14 @@ For example,
|
|||||||
eventpp::CallbackList<void(int)> callbackList;
|
eventpp::CallbackList<void(int)> callbackList;
|
||||||
|
|
||||||
callbackList.append(
|
callbackList.append(
|
||||||
eventpp::conditionalFunctor(
|
eventpp::conditionalFunctor(
|
||||||
[](const int value) {
|
[](const int value) {
|
||||||
std::cout << "We should get value 1." << here;
|
std::cout << "We should get value 1." << here;
|
||||||
},
|
},
|
||||||
[](const int value) {
|
[](const int value) {
|
||||||
return value == 1;
|
return value == 1;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
callbackList(2); // not trigger the callback
|
callbackList(2); // not trigger the callback
|
||||||
callbackList(1); // trigger the callback
|
callbackList(1); // trigger the callback
|
||||||
@ -44,34 +44,34 @@ eventpp::CallbackList<void(int)> callbackList;
|
|||||||
|
|
||||||
std::vector<int> dataList(3);
|
std::vector<int> dataList(3);
|
||||||
callbackList.append(
|
callbackList.append(
|
||||||
eventpp::conditionalFunctor(
|
eventpp::conditionalFunctor(
|
||||||
[&dataList](const int index) {
|
[&dataList](const int index) {
|
||||||
++dataList[index];
|
++dataList[index];
|
||||||
},
|
},
|
||||||
[](const int index) {
|
[](const int index) {
|
||||||
return index == 0;
|
return index == 0;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
callbackList.append(
|
callbackList.append(
|
||||||
eventpp::conditionalFunctor(
|
eventpp::conditionalFunctor(
|
||||||
[&dataList](const int index) {
|
[&dataList](const int index) {
|
||||||
++dataList[index];
|
++dataList[index];
|
||||||
},
|
},
|
||||||
[](const int index) {
|
[](const int index) {
|
||||||
return index == 1;
|
return index == 1;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
callbackList.append(
|
callbackList.append(
|
||||||
eventpp::conditionalFunctor(
|
eventpp::conditionalFunctor(
|
||||||
[&dataList](const int index) {
|
[&dataList](const int index) {
|
||||||
++dataList[index];
|
++dataList[index];
|
||||||
},
|
},
|
||||||
[](const int index) {
|
[](const int index) {
|
||||||
return index == 2;
|
return index == 2;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
REQUIRE(dataList == std::vector<int>{ 0, 0, 0 });
|
REQUIRE(dataList == std::vector<int>{ 0, 0, 0 });
|
||||||
|
@ -49,47 +49,47 @@ Constructs an instance of ConditionalRemover.
|
|||||||
```c++
|
```c++
|
||||||
template <typename Condition>
|
template <typename Condition>
|
||||||
typename DispatcherType::Handle appendListener(
|
typename DispatcherType::Handle appendListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener,
|
const typename DispatcherType::Callback & listener,
|
||||||
const Condition & condition
|
const Condition & condition
|
||||||
);
|
);
|
||||||
|
|
||||||
template <typename Condition>
|
template <typename Condition>
|
||||||
typename DispatcherType::Handle prependListener(
|
typename DispatcherType::Handle prependListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener,
|
const typename DispatcherType::Callback & listener,
|
||||||
const Condition & condition
|
const Condition & condition
|
||||||
);
|
);
|
||||||
|
|
||||||
template <typename Condition>
|
template <typename Condition>
|
||||||
typename DispatcherType::Handle insertListener(
|
typename DispatcherType::Handle insertListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener,
|
const typename DispatcherType::Callback & listener,
|
||||||
const typename DispatcherType::Handle & before,
|
const typename DispatcherType::Handle & before,
|
||||||
const Condition & condition
|
const Condition & condition
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Member functions for CallbackList**
|
**Member functions for CallbackList**
|
||||||
```c++
|
```c++
|
||||||
template <typename Condition>
|
template <typename Condition>
|
||||||
typename CallbackListType::Handle append(
|
typename CallbackListType::Handle append(
|
||||||
const typename CallbackListType::Callback & listener,
|
const typename CallbackListType::Callback & listener,
|
||||||
const Condition & condition
|
const Condition & condition
|
||||||
);
|
);
|
||||||
|
|
||||||
template <typename Condition>
|
template <typename Condition>
|
||||||
typename CallbackListType::Handle prepend(
|
typename CallbackListType::Handle prepend(
|
||||||
const typename CallbackListType::Callback & listener,
|
const typename CallbackListType::Callback & listener,
|
||||||
const Condition & condition
|
const Condition & condition
|
||||||
);
|
);
|
||||||
|
|
||||||
template <typename Condition>
|
template <typename Condition>
|
||||||
typename CallbackListType::Handle insert(
|
typename CallbackListType::Handle insert(
|
||||||
const typename CallbackListType::Callback & listener,
|
const typename CallbackListType::Callback & listener,
|
||||||
const typename CallbackListType::Handle & before,
|
const typename CallbackListType::Handle & before,
|
||||||
const Condition & condition
|
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.
|
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<int, void ()> dispatcher;
|
|||||||
constexpr int event = 3;
|
constexpr int event = 3;
|
||||||
|
|
||||||
dispatcher.appendListener(event, []() {
|
dispatcher.appendListener(event, []() {
|
||||||
// listener A
|
// listener A
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note the ConditionalRemover instance returned by conditionalRemover is invoked
|
// Note the ConditionalRemover instance returned by conditionalRemover is invoked
|
||||||
// prependListener and destroyed immediately.
|
// prependListener and destroyed immediately.
|
||||||
std::string removeWho;
|
std::string removeWho;
|
||||||
eventpp::conditionalRemover(dispatcher).prependListener(event, [&dataList]() {
|
eventpp::conditionalRemover(dispatcher).prependListener(event, [&dataList]() {
|
||||||
// listener B
|
// listener B
|
||||||
}, [&removeWho]() -> bool {
|
}, [&removeWho]() -> bool {
|
||||||
return removeWho == "removeB";
|
return removeWho == "removeB";
|
||||||
});
|
});
|
||||||
auto handle = eventpp::conditionalRemover(dispatcher).appendListener(event, [&dataList]() {
|
auto handle = eventpp::conditionalRemover(dispatcher).appendListener(event, [&dataList]() {
|
||||||
// listener C
|
// listener C
|
||||||
}, [&removeWho]() -> bool {
|
}, [&removeWho]() -> bool {
|
||||||
return removeWho == "removeC";
|
return removeWho == "removeC";
|
||||||
});
|
});
|
||||||
eventpp::conditionalRemover(dispatcher).insertListener(event, [&dataList]() {
|
eventpp::conditionalRemover(dispatcher).insertListener(event, [&dataList]() {
|
||||||
// listener D
|
// listener D
|
||||||
}, handle, [&removeWho]() -> bool {
|
}, handle, [&removeWho]() -> bool {
|
||||||
return removeWho == "removeD";
|
return removeWho == "removeD";
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatcher.dispatch(event);
|
dispatcher.dispatch(event);
|
||||||
|
@ -48,42 +48,42 @@ Constructs an instance of CounterRemover.
|
|||||||
**Member functions for EventDispatcher and EventQueue**
|
**Member functions for EventDispatcher and EventQueue**
|
||||||
```c++
|
```c++
|
||||||
typename DispatcherType::Handle appendListener(
|
typename DispatcherType::Handle appendListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener,
|
const typename DispatcherType::Callback & listener,
|
||||||
const int triggerCount = 1
|
const int triggerCount = 1
|
||||||
);
|
);
|
||||||
|
|
||||||
typename DispatcherType::Handle prependListener(
|
typename DispatcherType::Handle prependListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener,
|
const typename DispatcherType::Callback & listener,
|
||||||
const int triggerCount = 1
|
const int triggerCount = 1
|
||||||
);
|
);
|
||||||
|
|
||||||
typename DispatcherType::Handle insertListener(
|
typename DispatcherType::Handle insertListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener,
|
const typename DispatcherType::Callback & listener,
|
||||||
const typename DispatcherType::Handle & before,
|
const typename DispatcherType::Handle & before,
|
||||||
const int triggerCount = 1
|
const int triggerCount = 1
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Member functions for CallbackList**
|
**Member functions for CallbackList**
|
||||||
```c++
|
```c++
|
||||||
typename CallbackListType::Handle append(
|
typename CallbackListType::Handle append(
|
||||||
const typename CallbackListType::Callback & listener,
|
const typename CallbackListType::Callback & listener,
|
||||||
const int triggerCount = 1
|
const int triggerCount = 1
|
||||||
);
|
);
|
||||||
|
|
||||||
typename CallbackListType::Handle prepend(
|
typename CallbackListType::Handle prepend(
|
||||||
const typename CallbackListType::Callback & listener,
|
const typename CallbackListType::Callback & listener,
|
||||||
const int triggerCount = 1
|
const int triggerCount = 1
|
||||||
);
|
);
|
||||||
|
|
||||||
typename CallbackListType::Handle insert(
|
typename CallbackListType::Handle insert(
|
||||||
const typename CallbackListType::Callback & listener,
|
const typename CallbackListType::Callback & listener,
|
||||||
const typename CallbackListType::Handle & before,
|
const typename CallbackListType::Handle & before,
|
||||||
const int triggerCount = 1
|
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.
|
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<int, void ()> dispatcher;
|
|||||||
constexpr int event = 3;
|
constexpr int event = 3;
|
||||||
|
|
||||||
dispatcher.appendListener(event, []() {
|
dispatcher.appendListener(event, []() {
|
||||||
// listener A
|
// listener A
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note the CounterRemover instance returned by counterRemover is invoked
|
// Note the CounterRemover instance returned by counterRemover is invoked
|
||||||
// prependListener and destroyed immediately.
|
// prependListener and destroyed immediately.
|
||||||
eventpp::counterRemover(dispatcher).prependListener(event, []() {
|
eventpp::counterRemover(dispatcher).prependListener(event, []() {
|
||||||
// listener B
|
// listener B
|
||||||
});
|
});
|
||||||
auto handle = eventpp::counterRemover(dispatcher).appendListener(event, []() {
|
auto handle = eventpp::counterRemover(dispatcher).appendListener(event, []() {
|
||||||
// listener C
|
// listener C
|
||||||
}, 2);
|
}, 2);
|
||||||
eventpp::counterRemover(dispatcher).insertListener(event, []() {
|
eventpp::counterRemover(dispatcher).insertListener(event, []() {
|
||||||
// listener D
|
// listener D
|
||||||
}, handle, 3);
|
}, handle, 3);
|
||||||
|
|
||||||
dispatcher.dispatch(event);
|
dispatcher.dispatch(event);
|
||||||
|
@ -34,9 +34,9 @@ eventpp/eventdispatcher.h
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename Event,
|
typename Event,
|
||||||
typename Prototype,
|
typename Prototype,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class EventDispatcher;
|
class EventDispatcher;
|
||||||
```
|
```
|
||||||
|
@ -15,23 +15,23 @@ class Event
|
|||||||
class EventMouseDown : public Event
|
class EventMouseDown : public Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int getX() const;
|
int getX() const;
|
||||||
int getY() const;
|
int getY() const;
|
||||||
int getButton() const;
|
int getButton() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int button;
|
int button;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EventKeyDown : public Event
|
class EventKeyDown : public Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int getKey() const;
|
int getKey() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int key;
|
int key;
|
||||||
};
|
};
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -62,8 +62,8 @@ The macro always generates a default constructor and a constructor that takes al
|
|||||||
Code examples:
|
Code examples:
|
||||||
```c++
|
```c++
|
||||||
EVENTPP_MAKE_EVENT(
|
EVENTPP_MAKE_EVENT(
|
||||||
EventDraw, Event, EventType::draw,
|
EventDraw, Event, EventType::draw,
|
||||||
(std::string, getText, setText), (int, getX), (double, getSize)
|
(std::string, getText, setText), (int, getX), (double, getSize)
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
Generates class like (in pseudo code),
|
Generates class like (in pseudo code),
|
||||||
@ -71,45 +71,45 @@ Generates class like (in pseudo code),
|
|||||||
class EventDraw : public Event
|
class EventDraw : public Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EventDraw(const std::string & text, const int x, const double size)
|
EventDraw(const std::string & text, const int x, const double size)
|
||||||
: Event(EventType::draw), text(text), x(x), size(size)
|
: Event(EventType::draw), text(text), x(x), size(size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string & getText() const {
|
const std::string & getText() const {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setText(const std::string & value) {
|
void setText(const std::string & value) {
|
||||||
text = value;
|
text = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int getX() const {
|
const int getX() const {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
const double getSize() const {
|
const double getSize() const {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string text;
|
std::string text;
|
||||||
int x;
|
int x;
|
||||||
double size;
|
double size;
|
||||||
};
|
};
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
EVENTPP_MAKE_EVENT(EventDraw, (Event<int, char>), EventType::draw,
|
EVENTPP_MAKE_EVENT(EventDraw, (Event<int, char>), 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<int, char>`.
|
Similar to above example, except the base class is `Event<int, char>`.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
EVENTPP_MAKE_EVENT(EventDraw, (Event<int, char>), (EventType::draw, 5),
|
EVENTPP_MAKE_EVENT(EventDraw, (Event<int, char>), (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)`.
|
Similar to above example, except the base class is constructed with `(EventType::draw, 5)` instead of `(EventType::draw)`.
|
||||||
|
@ -33,9 +33,9 @@ eventpp/eventqueue.h
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename Event,
|
typename Event,
|
||||||
typename Prototype,
|
typename Prototype,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class EventQueue;
|
class EventQueue;
|
||||||
```
|
```
|
||||||
@ -49,16 +49,16 @@ EventQueue has the exactly same template parameters with EventDispatcher. Please
|
|||||||
```c++
|
```c++
|
||||||
struct EventQueue::QueuedEvent
|
struct EventQueue::QueuedEvent
|
||||||
{
|
{
|
||||||
EventType event;
|
EventType event;
|
||||||
std::tuple<ArgTypes...> arguments;
|
std::tuple<ArgTypes...> arguments;
|
||||||
|
|
||||||
// get the event
|
// get the event
|
||||||
EventType getEvent() const;
|
EventType getEvent() const;
|
||||||
|
|
||||||
// get the argument of index N
|
// get the argument of index N
|
||||||
// same as std::get<N>(queuedEvent.arguments)
|
// same as std::get<N>(queuedEvent.arguments)
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
NthArgType getArgument() const;
|
NthArgType getArgument() const;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
`event` is the EventQueue::Event, `arguments` are the arguments passed in `enqueue`.
|
`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,
|
`wait` is useful when a thread processes the event queue. A sampel usage is,
|
||||||
```c++
|
```c++
|
||||||
for(;;) {
|
for(;;) {
|
||||||
eventQueue.wait();
|
eventQueue.wait();
|
||||||
eventQueue.process();
|
eventQueue.process();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
The code works even if it doesn't `wait`, but doing that will waste CPU power resource.
|
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++
|
```c++
|
||||||
std::atomic<bool> shouldStop(false);
|
std::atomic<bool> shouldStop(false);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
while(! eventQueue.waitFor(std::chrono::milliseconds(10)) && ! shouldStop.load()) ;
|
while(! eventQueue.waitFor(std::chrono::milliseconds(10)) && ! shouldStop.load()) ;
|
||||||
if(shouldStop.load()) {
|
if(shouldStop.load()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventQueue.process();
|
eventQueue.process();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -206,8 +206,8 @@ Retrieve an event from the queue. The event is returned in `queuedEvent`.
|
|||||||
```c++
|
```c++
|
||||||
struct EventQueue::QueuedEvent
|
struct EventQueue::QueuedEvent
|
||||||
{
|
{
|
||||||
TheEventType event;
|
TheEventType event;
|
||||||
std::tuple<ArgumentTypes...> arguments;
|
std::tuple<ArgumentTypes...> arguments;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
`queuedEvent` is a EventQueue::QueuedEvent struct. `event` is the EventQueue::Event, `arguments` are the arguments passed in `enqueue`.
|
`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<int, void ()>;
|
using EQ = eventpp::EventQueue<int, void ()>;
|
||||||
EQ queue;
|
EQ queue;
|
||||||
{
|
{
|
||||||
EQ::DisableQueueNotify disableNotify(&queue);
|
EQ::DisableQueueNotify disableNotify(&queue);
|
||||||
// any blocking threads will not be waken up by the below two lines.
|
// any blocking threads will not be waken up by the below two lines.
|
||||||
queue.enqueue(1);
|
queue.enqueue(1);
|
||||||
queue.enqueue(2);
|
queue.enqueue(2);
|
||||||
}
|
}
|
||||||
// any blocking threads are waken up here immediately.
|
// any blocking threads are waken up here immediately.
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ eventpp/utilities/eventutil.h
|
|||||||
```c++
|
```c++
|
||||||
template <typename DispatcherType>
|
template <typename DispatcherType>
|
||||||
bool removeListener(
|
bool removeListener(
|
||||||
DispatcherType & dispatcher,
|
DispatcherType & dispatcher,
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener
|
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.
|
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++
|
```c++
|
||||||
template <typename CallbackListType>
|
template <typename CallbackListType>
|
||||||
bool removeListener(
|
bool removeListener(
|
||||||
CallbackListType & callbackList,
|
CallbackListType & callbackList,
|
||||||
const typename CallbackListType::Callback & callback
|
const typename CallbackListType::Callback & callback
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
The function finds `callback` in `callbackList`, if it finds one, removes the callback and returns true, otherwise returns false.
|
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++
|
```c++
|
||||||
template <typename DispatcherType>
|
template <typename DispatcherType>
|
||||||
bool hasListener(
|
bool hasListener(
|
||||||
DispatcherType & dispatcher,
|
DispatcherType & dispatcher,
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener
|
const typename DispatcherType::Callback & listener
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
The function finds `listener` of `event` in `dispatcher`, returns true if it finds any one, otherwise returns false.
|
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++
|
```c++
|
||||||
template <typename DispatcherType>
|
template <typename DispatcherType>
|
||||||
bool hasAnyListener(
|
bool hasAnyListener(
|
||||||
DispatcherType & dispatcher,
|
DispatcherType & dispatcher,
|
||||||
const typename DispatcherType::Event & event
|
const typename DispatcherType::Event & event
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
The function finds any listener of `event` in `dispatcher`, returns true if it finds any one, otherwise returns false.
|
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++
|
```c++
|
||||||
template <typename CallbackListType>
|
template <typename CallbackListType>
|
||||||
bool hasListener(
|
bool hasListener(
|
||||||
CallbackListType & callbackList,
|
CallbackListType & callbackList,
|
||||||
const typename CallbackListType::Callback & callback
|
const typename CallbackListType::Callback & callback
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
The function finds `callback` in `callbackList`, returns true if it finds one, otherwise returns false.
|
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++
|
```c++
|
||||||
template <typename CallbackListType>
|
template <typename CallbackListType>
|
||||||
bool hasAnyListener(
|
bool hasAnyListener(
|
||||||
CallbackListType & callbackList
|
CallbackListType & callbackList
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
The function finds any callback in `callbackList`, returns true if it finds any one, otherwise returns false.
|
The function finds any callback in `callbackList`, returns true if it finds any one, otherwise returns false.
|
||||||
|
48
doc/faq.md
48
doc/faq.md
@ -58,7 +58,7 @@ For example,
|
|||||||
class MyEventDispatcher : public EventDispatcher<blah blah>
|
class MyEventDispatcher : public EventDispatcher<blah blah>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~MyEventDispatcher();
|
virtual ~MyEventDispatcher();
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyClass : public MyEventDispatcher
|
class MyClass : public MyEventDispatcher
|
||||||
@ -86,22 +86,22 @@ eventpp::CallbackList<void ()> mainLoopTasks;
|
|||||||
|
|
||||||
void mainLoop()
|
void mainLoop()
|
||||||
{
|
{
|
||||||
for(;;) {
|
for(;;) {
|
||||||
// Do any stuff in the loop
|
// Do any stuff in the loop
|
||||||
|
|
||||||
mainLoopTasks();
|
mainLoopTasks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyEventQueue : public eventpp::EventQueue<blah blah>
|
class MyEventQueue : public eventpp::EventQueue<blah blah>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MyEventQueue()
|
MyEventQueue()
|
||||||
{
|
{
|
||||||
mainLoopTasks.append([this]() {
|
mainLoopTasks.append([this]() {
|
||||||
process();
|
process();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -118,25 +118,25 @@ eventpp::CallbackList<void ()> mainLoopTasks;
|
|||||||
|
|
||||||
void threadMain()
|
void threadMain()
|
||||||
{
|
{
|
||||||
while(! stopped) {
|
while(! stopped) {
|
||||||
ioService.poll();
|
ioService.poll();
|
||||||
mainLoopTasks();
|
mainLoopTasks();
|
||||||
sleepSomeTime();
|
sleepSomeTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
ioService.run();
|
ioService.run();
|
||||||
mainLoopTasks();
|
mainLoopTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyEventQueue : public eventpp::EventQueue<blah blah>
|
class MyEventQueue : public eventpp::EventQueue<blah blah>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MyEventQueue()
|
MyEventQueue()
|
||||||
{
|
{
|
||||||
mainLoopTasks.append([this]() {
|
mainLoopTasks.append([this]() {
|
||||||
process();
|
process();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ eventpp/hetercallbacklist.h
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename PrototypeList,
|
typename PrototypeList,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class HeterCallbackList;
|
class HeterCallbackList;
|
||||||
```
|
```
|
||||||
|
@ -31,9 +31,9 @@ eventpp/hetereventdispatcher.h
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename Event,
|
typename Event,
|
||||||
typename PrototypeList,
|
typename PrototypeList,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class HeterEventDispatcher;
|
class HeterEventDispatcher;
|
||||||
```
|
```
|
||||||
|
@ -31,9 +31,9 @@ eventpp/eventqueue.h
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename Event,
|
typename Event,
|
||||||
typename PrototypeList,
|
typename PrototypeList,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class HeterEventQueue;
|
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,
|
`wait` is useful when a thread processes the event queue. A sampel usage is,
|
||||||
```c++
|
```c++
|
||||||
for(;;) {
|
for(;;) {
|
||||||
eventQueue.wait();
|
eventQueue.wait();
|
||||||
eventQueue.process();
|
eventQueue.process();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
The code works event if it doesn't `wait`, but doing that will waste CPU power resource.
|
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++
|
```c++
|
||||||
std::atomic<bool> shouldStop(false);
|
std::atomic<bool> shouldStop(false);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
while(! eventQueue.waitFor(std::chrono::milliseconds(10)) && ! shouldStop.load()) ;
|
while(! eventQueue.waitFor(std::chrono::milliseconds(10)) && ! shouldStop.load()) ;
|
||||||
if(shouldStop.load()) {
|
if(shouldStop.load()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventQueue.process();
|
eventQueue.process();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -177,10 +177,10 @@ Sample code
|
|||||||
using EQ = eventpp::HeterEventQueue<int, void ()>;
|
using EQ = eventpp::HeterEventQueue<int, void ()>;
|
||||||
EQ queue;
|
EQ queue;
|
||||||
{
|
{
|
||||||
EQ::DisableQueueNotify disableNotify(&queue);
|
EQ::DisableQueueNotify disableNotify(&queue);
|
||||||
// any blocking threads will not be waken up by the below two lines.
|
// any blocking threads will not be waken up by the below two lines.
|
||||||
queue.enqueue(1);
|
queue.enqueue(1);
|
||||||
queue.enqueue(2);
|
queue.enqueue(2);
|
||||||
}
|
}
|
||||||
// any blocking threads are waken up here immediately.
|
// any blocking threads are waken up here immediately.
|
||||||
|
|
||||||
|
@ -30,22 +30,22 @@ eventpp/hetereventqueue.h
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename PrototypeList,
|
typename PrototypeList,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class HeterCallbackList;
|
class HeterCallbackList;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename Event,
|
typename Event,
|
||||||
typename PrototypeList,
|
typename PrototypeList,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class HeterEventDispatcher;
|
class HeterEventDispatcher;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename Event,
|
typename Event,
|
||||||
typename PrototypeList,
|
typename PrototypeList,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class HeterEventQueue;
|
class HeterEventQueue;
|
||||||
```
|
```
|
||||||
@ -54,22 +54,22 @@ For comparison, below are the template parameters for the homogeneous counterpar
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename Prototype,
|
typename Prototype,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class CallbackList;
|
class CallbackList;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename Event,
|
typename Event,
|
||||||
typename Prototype,
|
typename Prototype,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class EventDispatcher;
|
class EventDispatcher;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename Event,
|
typename Event,
|
||||||
typename Prototype,
|
typename Prototype,
|
||||||
typename Policies = DefaultPolicies
|
typename Policies = DefaultPolicies
|
||||||
>
|
>
|
||||||
class EventQueue;
|
class EventQueue;
|
||||||
```
|
```
|
||||||
|
@ -28,22 +28,22 @@ EventDispatcher is ideal when there are many kinds of events, or the number of e
|
|||||||
```c++
|
```c++
|
||||||
enum class MyEventType
|
enum class MyEventType
|
||||||
{
|
{
|
||||||
redraw,
|
redraw,
|
||||||
mouseDown,
|
mouseDown,
|
||||||
mouseUp,
|
mouseUp,
|
||||||
//... maybe 200 other events here
|
//... maybe 200 other events here
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MyEvent {
|
struct MyEvent {
|
||||||
MyEventType type;
|
MyEventType type;
|
||||||
// data that all events may need
|
// data that all events may need
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MyEventPolicies
|
struct MyEventPolicies
|
||||||
{
|
{
|
||||||
static MyEventType getEvent(const MyEvent & e) {
|
static MyEventType getEvent(const MyEvent & e) {
|
||||||
return e.type;
|
return e.type;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
eventpp::EventDispatcher<MyEventType, void(const MyEvent &), MyEventPolicies> dispatcher;
|
eventpp::EventDispatcher<MyEventType, void(const MyEvent &), MyEventPolicies> dispatcher;
|
||||||
|
@ -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,
|
To enable mixins, add them to the `Mixins` type in the policies class. For example, to enable `MixinFilter`, define the dispatcher as,
|
||||||
```c++
|
```c++
|
||||||
struct MyPolicies {
|
struct MyPolicies {
|
||||||
using Mixins = eventpp::MixinList<eventpp::MixinFilter>;
|
using Mixins = eventpp::MixinList<eventpp::MixinFilter>;
|
||||||
};
|
};
|
||||||
eventpp::EventDispatcher<int, void (), MyPolicies> dispatcher;
|
eventpp::EventDispatcher<int, void (), MyPolicies> dispatcher;
|
||||||
```
|
```
|
||||||
@ -121,19 +121,19 @@ Return true if the filter is removed successfully.
|
|||||||
**Code**
|
**Code**
|
||||||
```c++
|
```c++
|
||||||
struct MyPolicies {
|
struct MyPolicies {
|
||||||
using Mixins = eventpp::MixinList<eventpp::MixinFilter>;
|
using Mixins = eventpp::MixinList<eventpp::MixinFilter>;
|
||||||
};
|
};
|
||||||
eventpp::EventDispatcher<int, void (int e, int i, std::string), MyPolicies> dispatcher;
|
eventpp::EventDispatcher<int, void (int e, int i, std::string), MyPolicies> dispatcher;
|
||||||
|
|
||||||
dispatcher.appendListener(3, [](const int e, const int i, const std::string & s) {
|
dispatcher.appendListener(3, [](const int e, const int i, const std::string & s) {
|
||||||
std::cout
|
std::cout
|
||||||
<< "Got event 3, i was 1 but actural is " << i
|
<< "Got event 3, i was 1 but actural is " << i
|
||||||
<< " s was Hello but actural is " << s
|
<< " s was Hello but actural is " << s
|
||||||
<< std::endl
|
<< std::endl
|
||||||
;
|
;
|
||||||
});
|
});
|
||||||
dispatcher.appendListener(5, [](const int e, const int i, const std::string & s) {
|
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.
|
// 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
|
// The first filter modifies the input arguments to other values, then the subsequence filters
|
||||||
// and listeners will see the modified values.
|
// and listeners will see the modified values.
|
||||||
dispatcher.appendFilter([](const int e, int & i, std::string & s) -> bool {
|
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;
|
std::cout << "Filter 1, e is " << e << " passed in i is " << i << " s is " << s << std::endl;
|
||||||
i = 38;
|
i = 38;
|
||||||
s = "Hi";
|
s = "Hi";
|
||||||
std::cout << "Filter 1, changed i is " << i << " s is " << s << std::endl;
|
std::cout << "Filter 1, changed i is " << i << " s is " << s << std::endl;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// The second filter filters out all event of 5. So no listeners on event 5 can be triggered.
|
// 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.
|
// The third filter is not invoked on event 5 also.
|
||||||
dispatcher.appendFilter([](const int e, int & i, std::string & s) -> bool {
|
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;
|
std::cout << "Filter 2, e is " << e << " passed in i is " << i << " s is " << s << std::endl;
|
||||||
if(e == 5) {
|
if(e == 5) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// The third filter just prints the input arguments.
|
// The third filter just prints the input arguments.
|
||||||
dispatcher.appendFilter([](const int e, int & i, std::string & s) -> bool {
|
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;
|
std::cout << "Filter 3, e is " << e << " passed in i is " << i << " s is " << s << std::endl;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Dispatch the events, the first argument is always the event type.
|
// Dispatch the events, the first argument is always the event type.
|
||||||
|
@ -43,10 +43,10 @@ Its default implementation `OrderedQueueListCompare` looks like,
|
|||||||
```c++
|
```c++
|
||||||
struct OrderedQueueListCompare
|
struct OrderedQueueListCompare
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool operator() (const T & a, const T & b) const {
|
bool operator() (const T & a, const T & b) const {
|
||||||
return a.event < b.event;
|
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.
|
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++
|
```c++
|
||||||
struct QueuedEvent
|
struct QueuedEvent
|
||||||
{
|
{
|
||||||
EventType event;
|
EventType event;
|
||||||
std::tuple<Args> arguments;
|
std::tuple<Args> arguments;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
`event` is the event sent to the queue.
|
`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.
|
// First let's define the event struct. e is the event type, priority determines the priority.
|
||||||
struct MyEvent
|
struct MyEvent
|
||||||
{
|
{
|
||||||
int e;
|
int e;
|
||||||
int priority;
|
int priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The comparison function object used by eventpp::OrderedQueueList.
|
// The comparison function object used by eventpp::OrderedQueueList.
|
||||||
// The function compares the event by priority.
|
// The function compares the event by priority.
|
||||||
struct MyCompare
|
struct MyCompare
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool operator() (const T & a, const T & b) const {
|
bool operator() (const T & a, const T & b) const {
|
||||||
return std::get<0>(a.arguments).priority > std::get<0>(b.arguments).priority;
|
return std::get<0>(a.arguments).priority > std::get<0>(b.arguments).priority;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define the EventQueue policy
|
// Define the EventQueue policy
|
||||||
struct MyPolicy
|
struct MyPolicy
|
||||||
{
|
{
|
||||||
template <typename Item>
|
template <typename Item>
|
||||||
using QueueList = eventpp::OrderedQueueList<Item, MyCompare >;
|
using QueueList = eventpp::OrderedQueueList<Item, MyCompare >;
|
||||||
|
|
||||||
static int getEvent(const MyEvent & event) {
|
static int getEvent(const MyEvent & event) {
|
||||||
return event.e;
|
return event.e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
using EQ = eventpp::EventQueue<int, void(const MyEvent &), MyPolicy>;
|
using EQ = eventpp::EventQueue<int, void(const MyEvent &), MyPolicy>;
|
||||||
EQ queue;
|
EQ queue;
|
||||||
|
|
||||||
queue.appendListener(3, [](const MyEvent & event) {
|
queue.appendListener(3, [](const MyEvent & event) {
|
||||||
std::cout << "Get event " << event.e << "(should be 3)." << " priority: " << event.priority << std::endl;
|
std::cout << "Get event " << event.e << "(should be 3)." << " priority: " << event.priority << std::endl;
|
||||||
});
|
});
|
||||||
queue.appendListener(5, [](const MyEvent & event) {
|
queue.appendListener(5, [](const MyEvent & event) {
|
||||||
std::cout << "Get event " << event.e << "(should be 5)." << " priority: " << event.priority << std::endl;
|
std::cout << "Get event " << event.e << "(should be 5)." << " priority: " << event.priority << std::endl;
|
||||||
});
|
});
|
||||||
queue.appendListener(7, [](const MyEvent & event) {
|
queue.appendListener(7, [](const MyEvent & event) {
|
||||||
std::cout << "Get event " << event.e << "(should be 7)." << " priority: " << event.priority << std::endl;
|
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.
|
// 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.
|
// After the queue processes, the events will be processed from higher priority to lower priority.
|
||||||
queue.enqueue(MyEvent{ 5, 100 });
|
queue.enqueue(MyEvent{ 5, 100 });
|
||||||
queue.enqueue(MyEvent{ 5, 200 });
|
queue.enqueue(MyEvent{ 5, 200 });
|
||||||
queue.enqueue(MyEvent{ 7, 300 });
|
queue.enqueue(MyEvent{ 7, 300 });
|
||||||
queue.enqueue(MyEvent{ 7, 400 });
|
queue.enqueue(MyEvent{ 7, 400 });
|
||||||
queue.enqueue(MyEvent{ 3, 500 });
|
queue.enqueue(MyEvent{ 3, 500 });
|
||||||
queue.enqueue(MyEvent{ 3, 600 });
|
queue.enqueue(MyEvent{ 3, 600 });
|
||||||
|
|
||||||
queue.process();
|
queue.process();
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
132
doc/policies.md
132
doc/policies.md
@ -42,39 +42,39 @@ Sample code
|
|||||||
```c++
|
```c++
|
||||||
// Define an Event to hold all parameters.
|
// Define an Event to hold all parameters.
|
||||||
struct MyEvent {
|
struct MyEvent {
|
||||||
int type;
|
int type;
|
||||||
std::string message;
|
std::string message;
|
||||||
int param;
|
int param;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define policies to let the dispatcher knows how to
|
// Define policies to let the dispatcher knows how to
|
||||||
// extract the event type.
|
// extract the event type.
|
||||||
struct MyEventPolicies
|
struct MyEventPolicies
|
||||||
{
|
{
|
||||||
static int getEvent(const MyEvent & e, bool /*b*/) {
|
static int getEvent(const MyEvent & e, bool /*b*/) {
|
||||||
return e.type;
|
return e.type;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pass MyEventPolicies as the third template argument of EventDispatcher.
|
// Pass MyEventPolicies as the third template argument of EventDispatcher.
|
||||||
// Note: the first template argument is the event type type int, not MyEvent.
|
// Note: the first template argument is the event type type int, not MyEvent.
|
||||||
eventpp::EventDispatcher<
|
eventpp::EventDispatcher<
|
||||||
int,
|
int,
|
||||||
void (const MyEvent &, bool),
|
void (const MyEvent &, bool),
|
||||||
MyEventPolicies
|
MyEventPolicies
|
||||||
> dispatcher;
|
> dispatcher;
|
||||||
|
|
||||||
// Add a listener.
|
// Add a listener.
|
||||||
// Note: the first argument is the event type of type int, not MyEvent.
|
// Note: the first argument is the event type of type int, not MyEvent.
|
||||||
dispatcher.appendListener(3, [](const MyEvent & e, bool b) {
|
dispatcher.appendListener(3, [](const MyEvent & e, bool b) {
|
||||||
std::cout
|
std::cout
|
||||||
<< std::boolalpha
|
<< std::boolalpha
|
||||||
<< "Got event 3" << std::endl
|
<< "Got event 3" << std::endl
|
||||||
<< "Event::type is " << e.type << std::endl
|
<< "Event::type is " << e.type << std::endl
|
||||||
<< "Event::message is " << e.message << std::endl
|
<< "Event::message is " << e.message << std::endl
|
||||||
<< "Event::param is " << e.param << std::endl
|
<< "Event::param is " << e.param << std::endl
|
||||||
<< "b is " << b << std::endl
|
<< "b is " << b << std::endl
|
||||||
;
|
;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Dispatch the event.
|
// Dispatch the event.
|
||||||
@ -93,35 +93,35 @@ Sample code
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
struct MyEvent {
|
struct MyEvent {
|
||||||
MyEvent() : type(0), canceled(false) {
|
MyEvent() : type(0), canceled(false) {
|
||||||
}
|
}
|
||||||
explicit MyEvent(const int type)
|
explicit MyEvent(const int type)
|
||||||
: type(type), canceled(false) {
|
: type(type), canceled(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int type;
|
int type;
|
||||||
mutable bool canceled;
|
mutable bool canceled;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MyEventPolicies
|
struct MyEventPolicies
|
||||||
{
|
{
|
||||||
static int getEvent(const MyEvent & e) {
|
static int getEvent(const MyEvent & e) {
|
||||||
return e.type;
|
return e.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool canContinueInvoking(const MyEvent & e) {
|
static bool canContinueInvoking(const MyEvent & e) {
|
||||||
return ! e.canceled;
|
return ! e.canceled;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
eventpp::EventDispatcher<int, void (const MyEvent &), MyEventPolicies> dispatcher;
|
eventpp::EventDispatcher<int, void (const MyEvent &), MyEventPolicies> dispatcher;
|
||||||
|
|
||||||
dispatcher.appendListener(3, [](const MyEvent & e) {
|
dispatcher.appendListener(3, [](const MyEvent & e) {
|
||||||
std::cout << "Got event 3" << std::endl;
|
std::cout << "Got event 3" << std::endl;
|
||||||
e.canceled = true;
|
e.canceled = true;
|
||||||
});
|
});
|
||||||
dispatcher.appendListener(3, [](const MyEvent & e) {
|
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));
|
dispatcher.dispatch(MyEvent(3));
|
||||||
@ -158,12 +158,12 @@ A typical `Threading` type looks like
|
|||||||
```c++
|
```c++
|
||||||
struct MultipleThreading
|
struct MultipleThreading
|
||||||
{
|
{
|
||||||
using Mutex = std::mutex;
|
using Mutex = std::mutex;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Atomic = std::atomic<T>;
|
using Atomic = std::atomic<T>;
|
||||||
|
|
||||||
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.
|
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++
|
```c++
|
||||||
struct MultipleThreadingSpinLock
|
struct MultipleThreadingSpinLock
|
||||||
{
|
{
|
||||||
using Mutex = eventpp::SpinLock;
|
using Mutex = eventpp::SpinLock;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Atomic = std::atomic<T>;
|
using Atomic = std::atomic<T>;
|
||||||
|
|
||||||
using ConditionVariable = std::condition_variable;
|
using ConditionVariable = std::condition_variable;
|
||||||
};
|
};
|
||||||
struct MyEventPolicies {
|
struct MyEventPolicies {
|
||||||
using Threading = MultipleThreadingSpinLock;
|
using Threading = MultipleThreadingSpinLock;
|
||||||
};
|
};
|
||||||
eventpp::EventDispatcher<int, void (), MyEventPolicies> dispatcher;
|
eventpp::EventDispatcher<int, void (), MyEventPolicies> dispatcher;
|
||||||
eventpp::CallbackList<void (), MyEventPolicies> callbackList;
|
eventpp::CallbackList<void (), MyEventPolicies> callbackList;
|
||||||
@ -194,18 +194,18 @@ eventpp::CallbackList<void (), MyEventPolicies> callbackList;
|
|||||||
`eventpp` provides a shortcut template class to customize the threading.
|
`eventpp` provides a shortcut template class to customize the threading.
|
||||||
```c++
|
```c++
|
||||||
template <
|
template <
|
||||||
typename Mutex_,
|
typename Mutex_,
|
||||||
template <typename > class Atomic_ = std::atomic,
|
template <typename > class Atomic_ = std::atomic,
|
||||||
typename ConditionVariable_ = std::condition_variable
|
typename ConditionVariable_ = std::condition_variable
|
||||||
>
|
>
|
||||||
struct GeneralThreading
|
struct GeneralThreading
|
||||||
{
|
{
|
||||||
using Mutex = Mutex_;
|
using Mutex = Mutex_;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Atomic = Atomic_<T>;
|
using Atomic = Atomic_<T>;
|
||||||
|
|
||||||
using ConditionVariable = ConditionVariable_;
|
using ConditionVariable = ConditionVariable_;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ So the previous sample code for spinlock can be rewritten as
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
struct MyEventPolicies {
|
struct MyEventPolicies {
|
||||||
using Threading = eventpp::GeneralThreading<eventpp::SpinLock>;
|
using Threading = eventpp::GeneralThreading<eventpp::SpinLock>;
|
||||||
};
|
};
|
||||||
eventpp::EventDispatcher<int, void (), MyEventPolicies> dispatcher;
|
eventpp::EventDispatcher<int, void (), MyEventPolicies> dispatcher;
|
||||||
eventpp::CallbackList<void (), MyEventPolicies> callbackList;
|
eventpp::CallbackList<void (), MyEventPolicies> callbackList;
|
||||||
@ -270,12 +270,12 @@ Examples to demonstrate argument passing mode
|
|||||||
```c++
|
```c++
|
||||||
struct MyPolicies
|
struct MyPolicies
|
||||||
{
|
{
|
||||||
using ArgumentPassingMode = ArgumentPassingAutoDetect;
|
using ArgumentPassingMode = ArgumentPassingAutoDetect;
|
||||||
};
|
};
|
||||||
eventpp::EventDispatcher<
|
eventpp::EventDispatcher<
|
||||||
int,
|
int,
|
||||||
void(int, const std::string &),
|
void(int, const std::string &),
|
||||||
MyPolicies
|
MyPolicies
|
||||||
> dispatcher;
|
> dispatcher;
|
||||||
// or just
|
// or just
|
||||||
//eventpp::EventDispatcher<int, void(int, const std::string &)> dispatcher;
|
//eventpp::EventDispatcher<int, void(int, const std::string &)> dispatcher;
|
||||||
@ -286,12 +286,12 @@ dispatcher.dispatch(3, 8, "hello"); // Compile OK
|
|||||||
```c++
|
```c++
|
||||||
struct MyPolicies
|
struct MyPolicies
|
||||||
{
|
{
|
||||||
using ArgumentPassingMode = ArgumentPassingIncludeEvent;
|
using ArgumentPassingMode = ArgumentPassingIncludeEvent;
|
||||||
};
|
};
|
||||||
eventpp::EventDispatcher<
|
eventpp::EventDispatcher<
|
||||||
int,
|
int,
|
||||||
void(int, const std::string &),
|
void(int, const std::string &),
|
||||||
MyPolicies
|
MyPolicies
|
||||||
> dispatcher;
|
> dispatcher;
|
||||||
dispatcher.dispatch(3, "hello"); // Compile OK
|
dispatcher.dispatch(3, "hello"); // Compile OK
|
||||||
//dispatcher.dispatch(3, 8, "hello"); // Compile failure
|
//dispatcher.dispatch(3, 8, "hello"); // Compile failure
|
||||||
@ -300,12 +300,12 @@ dispatcher.dispatch(3, "hello"); // Compile OK
|
|||||||
```c++
|
```c++
|
||||||
struct MyPolicies
|
struct MyPolicies
|
||||||
{
|
{
|
||||||
using ArgumentPassingMode = ArgumentPassingExcludeEvent;
|
using ArgumentPassingMode = ArgumentPassingExcludeEvent;
|
||||||
};
|
};
|
||||||
eventpp::EventDispatcher<
|
eventpp::EventDispatcher<
|
||||||
int,
|
int,
|
||||||
void(int, const std::string &),
|
void(int, const std::string &),
|
||||||
MyPolicies
|
MyPolicies
|
||||||
> dispatcher;
|
> dispatcher;
|
||||||
//dispatcher.dispatch(3, "hello"); // Compile failure
|
//dispatcher.dispatch(3, "hello"); // Compile failure
|
||||||
dispatcher.dispatch(3, 8, "hello"); // Compile OK
|
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++
|
```c++
|
||||||
struct MyPolicies //the struct name doesn't matter
|
struct MyPolicies //the struct name doesn't matter
|
||||||
{
|
{
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
static int getEvent(const MyEvent & e, const Args &...) {
|
static int getEvent(const MyEvent & e, const Args &...) {
|
||||||
return e.type;
|
return e.type;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
EventDispatcher<int, void(const MyEvent &), MyPolicies> dispatcher;
|
EventDispatcher<int, void(const MyEvent &), MyPolicies> dispatcher;
|
||||||
```
|
```
|
||||||
|
@ -58,24 +58,24 @@ void reset();
|
|||||||
void setDispatcher(DispatcherType & dispatcher);
|
void setDispatcher(DispatcherType & dispatcher);
|
||||||
|
|
||||||
typename DispatcherType::Handle appendListener(
|
typename DispatcherType::Handle appendListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener
|
const typename DispatcherType::Callback & listener
|
||||||
);
|
);
|
||||||
|
|
||||||
typename DispatcherType::Handle prependListener(
|
typename DispatcherType::Handle prependListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener
|
const typename DispatcherType::Callback & listener
|
||||||
);
|
);
|
||||||
|
|
||||||
typename DispatcherType::Handle insertListener(
|
typename DispatcherType::Handle insertListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Callback & listener,
|
const typename DispatcherType::Callback & listener,
|
||||||
const typename DispatcherType::Handle & before
|
const typename DispatcherType::Handle & before
|
||||||
);
|
);
|
||||||
bool removeListener(
|
bool removeListener(
|
||||||
const typename DispatcherType::Event & event,
|
const typename DispatcherType::Event & event,
|
||||||
const typename DispatcherType::Handle handle
|
const typename DispatcherType::Handle handle
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Member functions for CallbackList**
|
**Member functions for CallbackList**
|
||||||
@ -85,17 +85,17 @@ void reset();
|
|||||||
void setCallbackList(CallbackListType & callbackList);
|
void setCallbackList(CallbackListType & callbackList);
|
||||||
|
|
||||||
typename CallbackListType::Handle append(
|
typename CallbackListType::Handle append(
|
||||||
const typename CallbackListType::Callback & callback
|
const typename CallbackListType::Callback & callback
|
||||||
);
|
);
|
||||||
|
|
||||||
typename CallbackListType::Handle prepend(
|
typename CallbackListType::Handle prepend(
|
||||||
const typename CallbackListType::Callback & callback
|
const typename CallbackListType::Callback & callback
|
||||||
);
|
);
|
||||||
|
|
||||||
typename CallbackListType::Handle insert(
|
typename CallbackListType::Handle insert(
|
||||||
const typename CallbackListType::Callback & callback,
|
const typename CallbackListType::Callback & callback,
|
||||||
const typename CallbackListType::Handle & before
|
const typename CallbackListType::Handle & before
|
||||||
);
|
);
|
||||||
bool remove(const typename CallbackListType::Handle handle);
|
bool remove(const typename CallbackListType::Handle handle);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -119,39 +119,39 @@ using Remover = eventpp::ScopedRemover<eventpp::EventDispatcher<int, void ()> >;
|
|||||||
constexpr int event = 3;
|
constexpr int event = 3;
|
||||||
|
|
||||||
dispatcher.appendListener(event, [&dataList]() {
|
dispatcher.appendListener(event, [&dataList]() {
|
||||||
// listener A
|
// listener A
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
Remover r1(dispatcher);
|
Remover r1(dispatcher);
|
||||||
r1.prependListener(event, [&dataList]() {
|
r1.prependListener(event, [&dataList]() {
|
||||||
// listener B
|
// listener B
|
||||||
});
|
});
|
||||||
{
|
{
|
||||||
Remover r2(dispatcher);
|
Remover r2(dispatcher);
|
||||||
auto handle = r2.appendListener(event, [&dataList]() {
|
auto handle = r2.appendListener(event, [&dataList]() {
|
||||||
// listener C
|
// listener C
|
||||||
});
|
});
|
||||||
{
|
{
|
||||||
Remover r3(dispatcher);
|
Remover r3(dispatcher);
|
||||||
r3.insertListener(event, [&dataList]() {
|
r3.insertListener(event, [&dataList]() {
|
||||||
// listener D
|
// listener D
|
||||||
}, handle);
|
}, handle);
|
||||||
|
|
||||||
dispatcher.dispatch(event);
|
dispatcher.dispatch(event);
|
||||||
// All listeners were triggered.
|
// All listeners were triggered.
|
||||||
}
|
}
|
||||||
|
|
||||||
// listener D was removed
|
// listener D was removed
|
||||||
|
|
||||||
dispatcher.dispatch(event);
|
dispatcher.dispatch(event);
|
||||||
// Listeners A, B, C were triggered.
|
// Listeners A, B, C were triggered.
|
||||||
}
|
}
|
||||||
|
|
||||||
// listener C was removed
|
// listener C was removed
|
||||||
|
|
||||||
dispatcher.dispatch(event);
|
dispatcher.dispatch(event);
|
||||||
// Listeners A, B were triggered.
|
// Listeners A, B were triggered.
|
||||||
}
|
}
|
||||||
|
|
||||||
// listener B was removed
|
// listener B was removed
|
||||||
@ -173,12 +173,12 @@ SomeDispatcher someDispatcher;
|
|||||||
|
|
||||||
class MyClass
|
class MyClass
|
||||||
{
|
{
|
||||||
MyClass()
|
MyClass()
|
||||||
{
|
{
|
||||||
someDispatcher.appendListener(SomeEvent, callback of myListener);
|
someDispatcher.appendListener(SomeEvent, callback of myListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void myListener() {}
|
void myListener() {}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -191,14 +191,14 @@ SomeDispatcher someDispatcher;
|
|||||||
|
|
||||||
class MyClass
|
class MyClass
|
||||||
{
|
{
|
||||||
MyClass() : scopedRemover(someDispatcher)
|
MyClass() : scopedRemover(someDispatcher)
|
||||||
{
|
{
|
||||||
scopedRemover.appendListener(SomeEvent, callback of myListener);
|
scopedRemover.appendListener(SomeEvent, callback of myListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void myListener() {}
|
void myListener() {}
|
||||||
|
|
||||||
eventpp::ScopedRemover<SomeDispatcher> scopedRemover;
|
eventpp::ScopedRemover<SomeDispatcher> scopedRemover;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -19,10 +19,10 @@ eventpp::CallbackList<void ()> callbackList;
|
|||||||
// Lambda is not required, any function or std::function
|
// Lambda is not required, any function or std::function
|
||||||
// or whatever function object with the required prototype is fine.
|
// or whatever function object with the required prototype is fine.
|
||||||
callbackList.append([]() {
|
callbackList.append([]() {
|
||||||
std::cout << "Got callback 1." << std::endl;
|
std::cout << "Got callback 1." << std::endl;
|
||||||
});
|
});
|
||||||
callbackList.append([]() {
|
callbackList.append([]() {
|
||||||
std::cout << "Got callback 2." << std::endl;
|
std::cout << "Got callback 2." << std::endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Invoke the callback list
|
// 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.
|
Now let's add a callback.
|
||||||
```c++
|
```c++
|
||||||
callbackList.append([]() {
|
callbackList.append([]() {
|
||||||
std::cout << "Got callback 1." << std::endl;
|
std::cout << "Got callback 1." << std::endl;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
Function `append` takes one arguments, the *callback*.
|
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<void (const std::string &, const bool)> callbackList;
|
eventpp::CallbackList<void (const std::string &, const bool)> callbackList;
|
||||||
|
|
||||||
callbackList.append([](const std::string & s, const bool b) {
|
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.
|
// 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.
|
// It would be fine as long as the arguments are compatible with the callbacklist.
|
||||||
callbackList.append([](std::string s, int b) {
|
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
|
// Invoke the callback list
|
||||||
@ -96,13 +96,13 @@ CL::Handle handle2;
|
|||||||
|
|
||||||
// Add some callbacks.
|
// Add some callbacks.
|
||||||
callbackList.append([]() {
|
callbackList.append([]() {
|
||||||
std::cout << "Got callback 1." << std::endl;
|
std::cout << "Got callback 1." << std::endl;
|
||||||
});
|
});
|
||||||
handle2 = callbackList.append([]() {
|
handle2 = callbackList.append([]() {
|
||||||
std::cout << "Got callback 2." << std::endl;
|
std::cout << "Got callback 2." << std::endl;
|
||||||
});
|
});
|
||||||
callbackList.append([]() {
|
callbackList.append([]() {
|
||||||
std::cout << "Got callback 3." << std::endl;
|
std::cout << "Got callback 3." << std::endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
callbackList.remove(handle2);
|
callbackList.remove(handle2);
|
||||||
@ -127,30 +127,30 @@ CL callbackList;
|
|||||||
|
|
||||||
// Add some callbacks.
|
// Add some callbacks.
|
||||||
callbackList.append([]() {
|
callbackList.append([]() {
|
||||||
std::cout << "Got callback 1." << std::endl;
|
std::cout << "Got callback 1." << std::endl;
|
||||||
});
|
});
|
||||||
callbackList.append([]() {
|
callbackList.append([]() {
|
||||||
std::cout << "Got callback 2." << std::endl;
|
std::cout << "Got callback 2." << std::endl;
|
||||||
});
|
});
|
||||||
callbackList.append([]() {
|
callbackList.append([]() {
|
||||||
std::cout << "Got callback 3." << std::endl;
|
std::cout << "Got callback 3." << std::endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now call forEach to remove the second callback
|
// Now call forEach to remove the second callback
|
||||||
// The forEach callback prototype is void(const CallbackList::Handle & handle, const CallbackList::Callback & callback)
|
// The forEach callback prototype is void(const CallbackList::Handle & handle, const CallbackList::Callback & callback)
|
||||||
int index = 0;
|
int index = 0;
|
||||||
callbackList.forEach([&callbackList, &index](const CL::Handle & handle, const CL::Callback & callback) {
|
callbackList.forEach([&callbackList, &index](const CL::Handle & handle, const CL::Callback & callback) {
|
||||||
std::cout << "forEach(Handle, Callback), invoked " << index << std::endl;
|
std::cout << "forEach(Handle, Callback), invoked " << index << std::endl;
|
||||||
if(index == 1) {
|
if(index == 1) {
|
||||||
callbackList.remove(handle);
|
callbackList.remove(handle);
|
||||||
std::cout << "forEach(Handle, Callback), removed second callback" << std::endl;
|
std::cout << "forEach(Handle, Callback), removed second callback" << std::endl;
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
});
|
});
|
||||||
|
|
||||||
// The forEach callback prototype can also be void(const CallbackList::Callback & callback)
|
// The forEach callback prototype can also be void(const CallbackList::Callback & callback)
|
||||||
callbackList.forEach([&callbackList, &index](const CL::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
|
// Invoke the callback list
|
||||||
|
@ -22,13 +22,13 @@ eventpp::EventDispatcher<int, void ()> dispatcher;
|
|||||||
// Lambda is not required, any function or std::function
|
// Lambda is not required, any function or std::function
|
||||||
// or whatever function object with the required prototype is fine.
|
// or whatever function object with the required prototype is fine.
|
||||||
dispatcher.appendListener(3, []() {
|
dispatcher.appendListener(3, []() {
|
||||||
std::cout << "Got event 3." << std::endl;
|
std::cout << "Got event 3." << std::endl;
|
||||||
});
|
});
|
||||||
dispatcher.appendListener(5, []() {
|
dispatcher.appendListener(5, []() {
|
||||||
std::cout << "Got event 5." << std::endl;
|
std::cout << "Got event 5." << std::endl;
|
||||||
});
|
});
|
||||||
dispatcher.appendListener(5, []() {
|
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.
|
// 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.
|
Now let's add a listener.
|
||||||
```c++
|
```c++
|
||||||
dispatcher.appendListener(3, []() {
|
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*.
|
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<int, void (const std::string &, const bool)> dispatcher;
|
eventpp::EventDispatcher<int, void (const std::string &, const bool)> dispatcher;
|
||||||
|
|
||||||
dispatcher.appendListener(3, [](const std::string & s, const bool b) {
|
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.
|
// 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.
|
// It would be find as long as the arguments is compatible with the dispatcher.
|
||||||
dispatcher.appendListener(5, [](std::string s, int b) {
|
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) {
|
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.
|
// 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++
|
```c++
|
||||||
// Define an Event to hold all parameters.
|
// Define an Event to hold all parameters.
|
||||||
struct MyEvent {
|
struct MyEvent {
|
||||||
int type;
|
int type;
|
||||||
std::string message;
|
std::string message;
|
||||||
int param;
|
int param;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define policies to let the dispatcher knows how to
|
// Define policies to let the dispatcher knows how to
|
||||||
// extract the event type.
|
// extract the event type.
|
||||||
struct MyEventPolicies
|
struct MyEventPolicies
|
||||||
{
|
{
|
||||||
static int getEvent(const MyEvent & e, bool /*b*/) {
|
static int getEvent(const MyEvent & e, bool /*b*/) {
|
||||||
return e.type;
|
return e.type;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pass MyEventPolicies as the third template argument of EventDispatcher.
|
// Pass MyEventPolicies as the third template argument of EventDispatcher.
|
||||||
// Note: the first template argument is the event type type int, not MyEvent.
|
// Note: the first template argument is the event type type int, not MyEvent.
|
||||||
eventpp::EventDispatcher<
|
eventpp::EventDispatcher<
|
||||||
int,
|
int,
|
||||||
void (const MyEvent &, bool),
|
void (const MyEvent &, bool),
|
||||||
MyEventPolicies
|
MyEventPolicies
|
||||||
> dispatcher;
|
> dispatcher;
|
||||||
|
|
||||||
// Add a listener.
|
// Add a listener.
|
||||||
// Note: the first argument is the event type of type int, not MyEvent.
|
// Note: the first argument is the event type of type int, not MyEvent.
|
||||||
dispatcher.appendListener(3, [](const MyEvent & e, bool b) {
|
dispatcher.appendListener(3, [](const MyEvent & e, bool b) {
|
||||||
std::cout
|
std::cout
|
||||||
<< std::boolalpha
|
<< std::boolalpha
|
||||||
<< "Got event 3" << std::endl
|
<< "Got event 3" << std::endl
|
||||||
<< "Event::type is " << e.type << std::endl
|
<< "Event::type is " << e.type << std::endl
|
||||||
<< "Event::message is " << e.message << std::endl
|
<< "Event::message is " << e.message << std::endl
|
||||||
<< "Event::param is " << e.param << std::endl
|
<< "Event::param is " << e.param << std::endl
|
||||||
<< "b is " << b << std::endl
|
<< "b is " << b << std::endl
|
||||||
;
|
;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Dispatch the event.
|
// Dispatch the event.
|
||||||
|
@ -13,15 +13,15 @@ Note if you are going to try the tutorial code, you'd better test the code under
|
|||||||
eventpp::EventQueue<int, void (const std::string &, std::unique_ptr<int> &)> queue;
|
eventpp::EventQueue<int, void (const std::string &, std::unique_ptr<int> &)> queue;
|
||||||
|
|
||||||
queue.appendListener(3, [](const std::string & s, std::unique_ptr<int> & n) {
|
queue.appendListener(3, [](const std::string & s, std::unique_ptr<int> & 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.
|
// 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.
|
// It would be find as long as the arguments is compatible with the dispatcher.
|
||||||
queue.appendListener(5, [](std::string s, const std::unique_ptr<int> & n) {
|
queue.appendListener(5, [](std::string s, const std::unique_ptr<int> & 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<int> & n) {
|
queue.appendListener(5, [](const std::string & s, std::unique_ptr<int> & 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.
|
// 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.
|
// Start a thread to process the event queue.
|
||||||
// All listeners are invoked in that thread.
|
// All listeners are invoked in that thread.
|
||||||
std::thread thread([stopEvent, otherEvent, &queue]() {
|
std::thread thread([stopEvent, otherEvent, &queue]() {
|
||||||
volatile bool shouldStop = false;
|
volatile bool shouldStop = false;
|
||||||
queue.appendListener(stopEvent, [&shouldStop](int) {
|
queue.appendListener(stopEvent, [&shouldStop](int) {
|
||||||
shouldStop = true;
|
shouldStop = true;
|
||||||
});
|
});
|
||||||
queue.appendListener(otherEvent, [](const int index) {
|
queue.appendListener(otherEvent, [](const int index) {
|
||||||
std::cout << "Got event, index is " << index << std::endl;
|
std::cout << "Got event, index is " << index << std::endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
while(! shouldStop) {
|
while(! shouldStop) {
|
||||||
queue.wait();
|
queue.wait();
|
||||||
|
|
||||||
queue.process();
|
queue.process();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Enqueue an event from the main thread. After sleeping for 10 milliseconds,
|
// 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;
|
std::cout << "Should have triggered event with index = 2" << std::endl;
|
||||||
|
|
||||||
{
|
{
|
||||||
// EventQueue::DisableQueueNotify is a RAII class that
|
// EventQueue::DisableQueueNotify is a RAII class that
|
||||||
// disables waking up any waiting threads.
|
// disables waking up any waiting threads.
|
||||||
// So no events should be triggered in this code block.
|
// So no events should be triggered in this code block.
|
||||||
// DisableQueueNotify is useful when adding lots of events at the same time
|
// 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.
|
// and only want to wake up the waiting threads after all events are added.
|
||||||
EQ::DisableQueueNotify disableNotify(&queue);
|
EQ::DisableQueueNotify disableNotify(&queue);
|
||||||
|
|
||||||
queue.enqueue(otherEvent, 10);
|
queue.enqueue(otherEvent, 10);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
std::cout << "Should NOT trigger event with index = 10" << std::endl;
|
std::cout << "Should NOT trigger event with index = 10" << std::endl;
|
||||||
|
|
||||||
queue.enqueue(otherEvent, 11);
|
queue.enqueue(otherEvent, 11);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
std::cout << "Should NOT trigger event with index = 11" << std::endl;
|
std::cout << "Should NOT trigger event with index = 11" << std::endl;
|
||||||
}
|
}
|
||||||
// The DisableQueueNotify object is destroyed here, and has resumed
|
// The DisableQueueNotify object is destroyed here, and has resumed
|
||||||
// waking up waiting threads. So the events should be triggered.
|
// waking up waiting threads. So the events should be triggered.
|
||||||
|
18
readme.md
18
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.
|
* The library: C++11.
|
||||||
* To develop the library
|
* To develop the library
|
||||||
* Unit tests: C++17.
|
* Unit tests: C++17.
|
||||||
* Tutorials: C++11.
|
* Tutorials: C++11.
|
||||||
* Benchmakrs: C++11.
|
* Benchmakrs: C++11.
|
||||||
|
|
||||||
## Quick start
|
## 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"
|
#include "eventpp/callbacklist.h"
|
||||||
eventpp::CallbackList<void (const std::string &, const bool)> callbackList;
|
eventpp::CallbackList<void (const std::string &, const bool)> callbackList;
|
||||||
callbackList.append([](const std::string & s, const bool b) {
|
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) {
|
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);
|
callbackList("Hello world", true);
|
||||||
```
|
```
|
||||||
@ -114,13 +114,13 @@ callbackList("Hello world", true);
|
|||||||
#include "eventpp/eventdispatcher.h"
|
#include "eventpp/eventdispatcher.h"
|
||||||
eventpp::EventDispatcher<int, void ()> dispatcher;
|
eventpp::EventDispatcher<int, void ()> dispatcher;
|
||||||
dispatcher.appendListener(3, []() {
|
dispatcher.appendListener(3, []() {
|
||||||
std::cout << "Got event 3." << std::endl;
|
std::cout << "Got event 3." << std::endl;
|
||||||
});
|
});
|
||||||
dispatcher.appendListener(5, []() {
|
dispatcher.appendListener(5, []() {
|
||||||
std::cout << "Got event 5." << std::endl;
|
std::cout << "Got event 5." << std::endl;
|
||||||
});
|
});
|
||||||
dispatcher.appendListener(5, []() {
|
dispatcher.appendListener(5, []() {
|
||||||
std::cout << "Got another event 5." << std::endl;
|
std::cout << "Got another event 5." << std::endl;
|
||||||
});
|
});
|
||||||
// dispatch event 3
|
// dispatch event 3
|
||||||
dispatcher.dispatch(3);
|
dispatcher.dispatch(3);
|
||||||
@ -133,10 +133,10 @@ dispatcher.dispatch(5);
|
|||||||
eventpp::EventQueue<int, void (const std::string &, const bool)> queue;
|
eventpp::EventQueue<int, void (const std::string &, const bool)> queue;
|
||||||
|
|
||||||
queue.appendListener(3, [](const std::string s, bool b) {
|
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) {
|
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.
|
// The listeners are not triggered during enqueue.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user