diff --git a/doc/cn/callbacklist.md b/doc/cn/callbacklist.md index 7dd9bfa..d2dcd6d 100644 --- a/doc/cn/callbacklist.md +++ b/doc/cn/callbacklist.md @@ -18,7 +18,7 @@ CallbackList 是 eventpp 中最为核心、基础的类。EventDispatcher、EventQueue 都是以 CallbackList 类为基础开发的。 -CallbackList 内部维护一个回调函数的列表。在 CallbackList 被调用时,其会逐个调用列表中的所有回调函数。可以将 CallbackList 看做 Qt 中的信号/槽系统,或某些 Windows API 中的回调函数指针(例如 `ReadFileEx` 中的 IpCompletionRoutine )。 +CallbackList 内部维护一个回调函数的列表。在 CallbackList 被调用时,其会逐个调用列表中的所有回调函数。可以将 CallbackList 看做 Qt 中的信号/槽系统,或某些 Windows API 中的回调函数指针(例如 `ReadFileEx` 中的 IpCompletionRoutine )。 回调函数可以是任何回调目标 —— 函数、函数指针、指向成员函数的指针、lambda 表达式、函数对象等。 @@ -41,7 +41,7 @@ template < class CallbackList; ``` -`Prototype`:回调函数原型。该参数应为 C++ 函数类型,如 `void(int, std::string, const MyClass *)`。 +`Prototype`:回调函数原型。该参数应为 C++ 函数类型,如 `void(int, std::string, const MyClass *)`。 `Policies`:用于配置和扩展回调函数列表的规则。默认值为 `DefaultPolicies` 。详见 [policy 文档](https://github.com/marsCatXdu/eventpp/blob/master/doc/policies.md) @@ -71,7 +71,7 @@ CallbackList 可以被拷贝、move、赋值、move 赋值和交换。 bool empty() const; ``` -当回调列表为空时返回 true 。 +当回调列表为空时返回 true 。 提示:在多线程程序中,该函数的返回值无法保证确定就是列表的真实状态。可能会出现刚刚返回 true 之后列表马上变为非空的情况,反之亦然。 #### bool 转换运算符 @@ -80,7 +80,7 @@ bool empty() const; operator bool() const; ``` -若回调列表非空则返回 true。 +若回调列表非空则返回 true。 借助该运算符,能够实现在条件语句中使用 CallbackList 实例 #### append @@ -89,10 +89,10 @@ operator bool() const; Handle append(const Callback & callback); ``` -向回调函数列表中添加回调函数。 -新的回调函数会被加在回调函数列表的末尾。 -该函数返回一个代表回调函数的句柄。该句柄能够用于移除该回调函数,或在该回调函数前插入其他的回调函数。 -如果`append`在回调函数列表执行的过程中被其他的回调函数调用,则新添加的回调函数一定不会在该回调函数列表执行的过程中被执行。 +向回调函数列表中添加回调函数。 +新的回调函数会被加在回调函数列表的末尾。 +该函数返回一个代表回调函数的句柄。该句柄能够用于移除该回调函数,或在该回调函数前插入其他的回调函数。 +如果`append`在回调函数列表执行的过程中被其他的回调函数调用,则新添加的回调函数一定不会在该回调函数列表执行的过程中被执行。 该函数的时间复杂度为 O(1) 。 #### prepend @@ -101,10 +101,10 @@ Handle append(const Callback & callback); Handle prepend(const Callback & callback); ``` -向回调函数列表中添加回调函数。 -回调函数将被加在回调函数列表的最前端。 +向回调函数列表中添加回调函数。 +回调函数将被加在回调函数列表的最前端。 该函数会返回一个代表回调函数的句柄(handler)。该句柄可被用于移除该回调函数,也可用于在该回调函数前插入其他回调函数。 -如果 `prepend` 在回调函数列表执行的过程中被其他回调函数调用,则新添加的回调函数一定不会在该回调函数列表执行的过程中被执行。 +如果 `prepend` 在回调函数列表执行的过程中被其他回调函数调用,则新添加的回调函数一定不会在该回调函数列表执行的过程中被执行。 该函数的时间复杂度为 O(1) 。 #### insert @@ -113,12 +113,12 @@ Handle prepend(const Callback & callback); Handle insert(const Callback & callback, const Handle & before); ``` -将 *callback* 插入到回调列表中 *before* 前面的一个位置处。若找不到 *before* ,则 *callback* 会被加到回调列表的末尾。 -该函数返回一个代表回调函数的句柄。该句柄可被用于移除该回调函数,也可用于在该回调函数前插入其他回调函数。 -如果 `insert` 是在回调函数列表执行的过程中被其他回调函数调用的,则新添加的回调函数一定不会在该回调函数列表执行的过程中被执行。 +将 *callback* 插入到回调列表中 *before* 前面的一个位置处。若找不到 *before* ,则 *callback* 会被加到回调列表的末尾。 +该函数返回一个代表回调函数的句柄。该句柄可被用于移除该回调函数,也可用于在该回调函数前插入其他回调函数。 +如果 `insert` 是在回调函数列表执行的过程中被其他回调函数调用的,则新添加的回调函数一定不会在该回调函数列表执行的过程中被执行。 该函数的时间复杂度为 O(1) 。 -提示:该函数的调用者必须提前确定 `before` 是由 `this` 所指向的 CallbackList 调用的。如果不能确定,可以用 `ownsHandle` 函数来检查 `before` 是否属于 `this` CallbackList 。`insert` 函数仅能在 `ownsHandle(before)` 返回 true 的时候被调用,否则可能引发未定义的行为并带来诡异的 bug 。 +提示:该函数的调用者必须提前确定 `before` 是由 `this` 所指向的 CallbackList 调用的。如果不能确定,可以用 `ownsHandle` 函数来检查 `before` 是否属于 `this` CallbackList 。`insert` 函数仅能在 `ownsHandle(before)` 返回 true 的时候被调用,否则可能引发未定义的行为并带来诡异的 bug 。 需要确保只在 `assert(ownsHandle(before))` 时 `insert` ,但出于性能方面的考量,发布的代码中没有包含相关的检查。 #### remove @@ -127,8 +127,8 @@ Handle insert(const Callback & callback, const Handle & before); bool remove(const Handle & handle); ``` -从回调函数列表中移除 *handle* 指向的回调函数。 -移除成功会返回 true ,找不到回调函数则会返回 false 。 +从回调函数列表中移除 *handle* 指向的回调函数。 +移除成功会返回 true ,找不到回调函数则会返回 false 。 该函数的时间复杂度为 O(1) 提示:`handle` 必须是由 `this` 指向的 CallbackList 所创建的。更多细节请查看 `insert` 中的“提示”部分 @@ -139,7 +139,7 @@ bool remove(const Handle & handle); bool ownsHandle(const Handle & handle) const; ``` -当 `handle` 是由当前 CallbackList 创建时返回 true,否则返回 false 。 +当 `handle` 是由当前 CallbackList 创建时返回 true,否则返回 false 。 该函数时间复杂度为 O(N) #### forEach @@ -149,7 +149,7 @@ template void forEach(Func && func) const; ``` -对所有的回调函数使用 `func` 。 +对所有的回调函数使用 `func` 。 `func` 可以是下面两种原型的其中一种: ```C++ @@ -166,7 +166,7 @@ template bool forEachIf(Func && func) const; ``` -对所有的回调函数使用 `func` 。 `func` 必须返回一个 bool 值,若返回值为 false ,则 forEachIf 将会立即停止循环。 +对所有的回调函数使用 `func` 。 `func` 必须返回一个 bool 值,若返回值为 false ,则 forEachIf 将会立即停止循环。 当所有回调函数都被触发后,或未找到 `event` 时,该函数会返回 true 。当 `func` 返回 `false` 时返回 `false` #### 调用运算符 @@ -175,8 +175,8 @@ bool forEachIf(Func && func) const; void operator() (Args ...args) const; ``` -触发回调函数列表中所有回调函数的运行。 -回调函数会被用 `args` 参数作为参数调用。 +触发回调函数列表中所有回调函数的运行。 +回调函数会被用 `args` 参数作为参数调用。 回调函数会在 `operator()` 所在的线程中调用。 @@ -198,6 +198,6 @@ void operator() (Args ...args) const; ## 内部数据结构 -CallbackList 使用双向链表管理回调函数。 +CallbackList 使用双向链表管理回调函数。 每个节点都使用共享指针(shared pointer)连接。使用共享指针可以实现在迭代的过程中移除节点。 diff --git a/doc/cn/readme.md b/doc/cn/readme.md index 6f57c7e..513d44c 100644 --- a/doc/cn/readme.md +++ b/doc/cn/readme.md @@ -15,3 +15,4 @@ * [EventQueue 类参考手册](eventqueue.md) * [Policies -- 配置 eventpp](policies.md) * [Mixins -- 扩展 eventpp](mixins.md) + diff --git a/doc/cn/tutorial_callbacklist.md b/doc/cn/tutorial_callbacklist.md index 58ed865..10c88bc 100644 --- a/doc/cn/tutorial_callbacklist.md +++ b/doc/cn/tutorial_callbacklist.md @@ -26,7 +26,7 @@ callbackList(); **输出** -> Got callback 1. +> Got callback 1. > Got callback 2. **解读** @@ -37,7 +37,7 @@ callbackList(); eventpp::CallbackList callbackList; ``` -CallbackList 需要至少一个模板参数,作为回调函数的“原型”( prototype )。 +CallbackList 需要至少一个模板参数,作为回调函数的“原型”( prototype )。 “原型”指 C++ 函数类型,例如 `void (int)`, `void (const std::string &, const MyClass &, int, bool)` 然后,添加一个回调函数 @@ -48,7 +48,7 @@ callbackList.append([]() { }); ``` -`append` 函数接收一个回调函数作为参数。 +`append` 函数接收一个回调函数作为参数。 回调函数可以使任何回调目标——函数、函数指针、指向成员函数的指针、lambda 表达式、函数对象等。该回调函数必须可以使用 `callbackList` 中声明的原型调用。 接下来启动回调列表 @@ -82,12 +82,12 @@ callbackList("Hello world", true); **输出** -> Got callback 1, s is Hello world b is true +> Got callback 1, s is Hello world b is true > Got callback 2, s is Hello world b is 1 **解读** -本例中,回调函数列表的回调函数原型接收两个参数: `const std::string &` 和 `const bool`。 +本例中,回调函数列表的回调函数原型接收两个参数: `const std::string &` 和 `const bool`。 回调函数的原型并不需要和回调完全一致,只要两个函数中的参数能够兼容即可。正如上面例子中的第二个回调函数,其参数为 `[](std::string s, int b)`,其原型与回调列表中的并不相同。 ### CallbackList 教程 3, 移除 @@ -119,7 +119,7 @@ callbackList(); **输出** -> Got callback 1. +> Got callback 1. > Got callback 3. ### CallbackList 教程 4, for each @@ -165,11 +165,11 @@ callbackList(); **输出** -> forEach(Handle, Callback), invoked 0 -> forEach(Handle, Callback), invoked 1 -> forEach(Handle, Callback), removed second callback -> forEach(Handle, Callback), invoked 2 -> forEach(Callback), invoked -> forEach(Callback), invoked -> Got callback 1. +> forEach(Handle, Callback), invoked 0 +> forEach(Handle, Callback), invoked 1 +> forEach(Handle, Callback), removed second callback +> forEach(Handle, Callback), invoked 2 +> forEach(Callback), invoked +> forEach(Callback), invoked +> Got callback 1. > Got callback 3. \ No newline at end of file diff --git a/doc/cn/tutorial_eventdispatcher.md b/doc/cn/tutorial_eventdispatcher.md index f8686dd..0e26b4f 100644 --- a/doc/cn/tutorial_eventdispatcher.md +++ b/doc/cn/tutorial_eventdispatcher.md @@ -32,8 +32,8 @@ dispatcher.dispatch(5); **输出** -> Got event 3. -> Got event 5. +> Got event 3. +> Got event 5. > Got another event 5. **解读** @@ -44,8 +44,8 @@ dispatcher.dispatch(5); eventpp::EventDispatcher dispatcher; ``` -EventDispatcher 类接收两个模板参数。第一个是*事件类型*,此处是 `int` 。第二个是监听器的*原型*。 -*事件类型* 必须能够用作 `std::map` 的 key。也就是说该类型必须支持 `operator <`。 +EventDispatcher 类接收两个模板参数。第一个是*事件类型*,此处是 `int` 。第二个是监听器的*原型*。 +*事件类型* 必须能够用作 `std::map` 的 key。也就是说该类型必须支持 `operator <`。 *原型* 是 C++ 函数类型,例如 `void (int)`, `void (const std::string &, const MyClass &, int, bool)` 然后添加一个监听器 @@ -56,8 +56,8 @@ dispatcher.appendListener(3, []() { }); ``` -`appendListener` 函数接收两个参数。第一个是 *事件类型* 的 *事件* (译注:此处的“事件类型”指的是用于区分事件的数据类型,此处为 int 。“事件”则是具体的时间值,此处为整数 3 ),此处为 `int` 类型。第二个参数是*回调函数*。 -回调函数可以是任何能够回调的目标——函数、函数指针、成员函数指针、lambda表达式、函数对象等。其必须能够被 `dispatcher` 中声明的 *原型* 调用。 +`appendListener` 函数接收两个参数。第一个是 *事件类型* 的 *事件* (译注:此处的“事件类型”指的是用于区分事件的数据类型,此处为 int 。“事件”则是具体的时间值,此处为整数 3 ),此处为 `int` 类型。第二个参数是*回调函数*。 +回调函数可以是任何能够回调的目标——函数、函数指针、成员函数指针、lambda表达式、函数对象等。其必须能够被 `dispatcher` 中声明的 *原型* 调用。 在上面这段代码的下面,我们还为 事件5 添加了两个监听器。 接下来,使用下面的代码分发事件 @@ -67,7 +67,7 @@ dispatcher.dispatch(3); dispatcher.dispatch(5); ``` -这里分发了两个事件,分别是事件 3 和 5 。 +这里分发了两个事件,分别是事件 3 和 5 。 在事件分发的过程中,所有对应事件的监听器都会按照它们被添加进 EventDispatcher 的顺序逐个执行。 ### 教程 2 —— 带参数的监听器 @@ -96,13 +96,13 @@ dispatcher.dispatch(5, "World", false); **输出** -> Got event 3, s is Hello b is true -> Got event 5, s is World b is 0 +> Got event 3, s is Hello b is true +> Got event 5, s is World b is 0 > Got another event 5, s is World b is false **解读** -此处的 dispatcher 回调函数原型接收两个参数:`const std::string &` 和 `const bool`。 +此处的 dispatcher 回调函数原型接收两个参数:`const std::string &` 和 `const bool`。 监听器原型不需要和 dispatcher 完全一致,只要参数类型能够兼容即可。例如第二个监听器,`[](std::string s, int b)`,其原型和 dispatcher 并不相同 ### 教程 3 —— 自定义事件结构 @@ -151,10 +151,10 @@ dispatcher.dispatch(MyEvent { 3, "Hello world", 38 }, true); **输出** -> Got event 3 -> Event::type is 3 -> Event::message is Hello world -> Event::param is 38 +> Got event 3 +> Event::type is 3 +> Event::message is Hello world +> Event::param is 38 > b is true **解读** diff --git a/doc/cn/tutorial_eventqueue.md b/doc/cn/tutorial_eventqueue.md index ca3091e..de33faf 100644 --- a/doc/cn/tutorial_eventqueue.md +++ b/doc/cn/tutorial_eventqueue.md @@ -31,15 +31,15 @@ queue.process(); **输出** -> Got event 3, s is Hello n is 38 -> Got event 5, s is World n is 58 -> Got another event 5, s is World n is 58 +> Got event 3, s is Hello n is 38 +> Got event 5, s is World n is 58 +> Got another event 5, s is World n is 58 **解读** -`EventDispatcher<>::dispatch()` 触发监听器的动作是同步的。但异步事件队列在某些场景下能发挥更大的作用(例如 Windows 消息队列、游戏中的消息队列等)。EventQueue 就是用于满足该类需求的事件队列。 -`EventQueue<>::enqueue()` 将事件加入队列,其参数和 `dispatch` 的参数完全相同。 -`EventQueue<>::process()` 用于分发队列中的事件。不调用 process ,事件就不会被分发。 -事件队列的典型用例:在 GUI 应用中,每个组件都调用 `EventQueue<>::enqueue()` 来发布事件,然后主事件循环调用 `EventQueue<>()::process()` 来 dispatch 所有队列中的事件。 +`EventDispatcher<>::dispatch()` 触发监听器的动作是同步的。但异步事件队列在某些场景下能发挥更大的作用(例如 Windows 消息队列、游戏中的消息队列等)。EventQueue 就是用于满足该类需求的事件队列。 +`EventQueue<>::enqueue()` 将事件加入队列,其参数和 `dispatch` 的参数完全相同。 +`EventQueue<>::process()` 用于分发队列中的事件。不调用 process ,事件就不会被分发。 +事件队列的典型用例:在 GUI 应用中,每个组件都调用 `EventQueue<>::enqueue()` 来发布事件,然后主事件循环调用 `EventQueue<>()::process()` 来 dispatch 所有队列中的事件。 `EventQueue` 支持将不可拷贝对象作为事件参数,例如上面例子中的 unique_ptr ### 教程 2 —— 多线程 @@ -104,13 +104,13 @@ thread.join(); **输出** -> Got event, index is 1 -> Should have triggered event with index = 1 -> Got event, index is 2 -> Should have triggered event with index = 2 -> Should NOT trigger event with index = 10 -> Should NOT trigger event with index = 11 -> Got event, index is 10 -> Got event, index is 11 +> Got event, index is 1 +> Should have triggered event with index = 1 +> Got event, index is 2 +> Should have triggered event with index = 2 +> Should NOT trigger event with index = 10 +> Should NOT trigger event with index = 11 +> Got event, index is 10 +> Got event, index is 11 > Should have triggered events with index = 10 and 11