diff --git a/async_simple/Signal.h b/async_simple/Signal.h index bb74b9bc..af467d1a 100644 --- a/async_simple/Signal.h +++ b/async_simple/Signal.h @@ -95,7 +95,7 @@ class Signal : public std::enable_shared_from_this { // binding slots, then execute the slot callback functions. It will return // the signal which success triggered. If no signal success triggger, return // SignalType::none. - SignalType emit(SignalType state) noexcept; + SignalType emits(SignalType state) noexcept; // Return now signal type. SignalType state() const noexcept { @@ -320,7 +320,7 @@ class Slot { [chainedSignal = chainedSignal->weak_from_this()](SignalType type) { if (auto signal = chainedSignal.lock(); signal != nullptr) { - signal->emit(type); + signal->emits(type); } }), std::memory_order_release); @@ -451,7 +451,7 @@ inline detail::SignalSlotSharedState::~SignalSlotSharedState() { } } -inline SignalType Signal::emit(SignalType state) noexcept { +inline SignalType Signal::emits(SignalType state) noexcept { if (state != SignalType::None) { SignalType vaildSignal = UpdateState(_state, state); if (vaildSignal) { diff --git a/async_simple/coro/Collect.h b/async_simple/coro/Collect.h index 41f5487e..55ebebac 100644 --- a/async_simple/coro/Collect.h +++ b/async_simple/coro/Collect.h @@ -191,7 +191,7 @@ struct CollectAnyAwaiter { _result->_idx = i; _result->_value = std::move(result); if (auto ptr = local->getSlot(); ptr) { - ptr->signal()->emit(_SignalType); + ptr->signal()->emits(_SignalType); } c.resume(); } @@ -294,7 +294,7 @@ struct CollectAnyVariadicAwaiter { _result = std::make_unique( std::in_place_index_t(), std::move(res)); if (auto ptr = local->getSlot(); ptr) { - ptr->signal()->emit(_SignalType); + ptr->signal()->emits(_SignalType); } c.resume(); } @@ -409,7 +409,7 @@ struct CollectAllAwaiter { auto signalType = _SignalType; auto awaitingCoro = _event.down(oldCount, 1); if (oldCount == size) { - signal->emit(signalType); + signal->emits(signalType); } if (awaitingCoro) { awaitingCoro.resume(); @@ -582,7 +582,7 @@ struct CollectAllVariadicAwaiter { auto signalType = _SignalType; auto awaitingCoro = _event.down(oldCount, 1); if (oldCount == sizeof...(Ts)) { - signal->emit(signalType); + signal->emits(signalType); } if (awaitingCoro) { awaitingCoro.resume(); diff --git a/async_simple/coro/test/LazyTest.cpp b/async_simple/coro/test/LazyTest.cpp index bd694b63..8700b983 100644 --- a/async_simple/coro/test/LazyTest.cpp +++ b/async_simple/coro/test/LazyTest.cpp @@ -360,7 +360,7 @@ TEST_F(LazyTest, testYieldCancel) { EXPECT_EQ(result.hasError(), true); p.set_value(); }); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); p.get_future().wait(); } @@ -2020,7 +2020,7 @@ TEST_F(LazyTest, testForbiddenCancel) { EXPECT_EQ(slot->signal()->state(), SignalType::Terminate); }; lazy(p.getFuture()).setLazyLocal(signal.get()).via(&e).detach(); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); p.setValue(); } { @@ -2037,7 +2037,7 @@ TEST_F(LazyTest, testForbiddenCancel) { EXPECT_EQ(slot, nullptr); }; lazy(p.getFuture()).setLazyLocal(signal.get()).via(&e).detach(); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); p.setValue(); } } diff --git a/async_simple/coro/test/SleepTest.cpp b/async_simple/coro/test/SleepTest.cpp index 053024c7..14b138a2 100644 --- a/async_simple/coro/test/SleepTest.cpp +++ b/async_simple/coro/test/SleepTest.cpp @@ -137,7 +137,7 @@ Lazy cancelSleep() { EXPECT_TRUE(err.value() == async_simple::Terminate); } auto slot = co_await async_simple::coro::CurrentSlot{}; - auto ok = slot->signal()->emit(SignalType::Terminate); + auto ok = slot->signal()->emits(SignalType::Terminate); if (ok) { std::cout << "Coro " << i << " emit cancel work" << std::endl; } else { diff --git a/async_simple/coro/test/SpinLockTest.cpp b/async_simple/coro/test/SpinLockTest.cpp index 571a7c0e..3a8601bc 100644 --- a/async_simple/coro/test/SpinLockTest.cpp +++ b/async_simple/coro/test/SpinLockTest.cpp @@ -121,7 +121,7 @@ TEST_F(SpinLockTest, testSpinLockCancel) { auto signal = async_simple::Signal::create(); std::promise p; if (cancelFirst) { - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); } std::move(lazy) .setLazyLocal(signal.get()) @@ -132,7 +132,7 @@ TEST_F(SpinLockTest, testSpinLockCancel) { }); if (!cancelFirst) { std::this_thread::sleep_for(10ms); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); } p.get_future().wait(); }; diff --git a/async_simple/test/CancellationTest.cpp b/async_simple/test/CancellationTest.cpp index 604359b9..5a59b0aa 100644 --- a/async_simple/test/CancellationTest.cpp +++ b/async_simple/test/CancellationTest.cpp @@ -44,7 +44,7 @@ TEST_F(CancellationTest, testSimpleCancellation) { return slot->signal()->state(); }); EXPECT_EQ(signal->state() != 0, false); - EXPECT_EQ(signal->emit(SignalType::Terminate), true); + EXPECT_EQ(signal->emits(SignalType::Terminate), true); EXPECT_EQ(signal->state() != 0, true); EXPECT_EQ(result.get(), SignalType::Terminate); EXPECT_EQ(slot->canceled(), true); @@ -65,7 +65,7 @@ TEST_F(CancellationTest, testCancellationWithNoneType) { } return 1; }); - signal->emit(SignalType::None); + signal->emits(SignalType::None); std::this_thread::sleep_for(10ms); flag = 1; EXPECT_EQ(result.get(), 0); @@ -88,7 +88,7 @@ TEST_F(CancellationTest, testCancellationWithSlotFilter) { } return 1; }); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); std::this_thread::sleep_for(10ms); flag = 1; EXPECT_EQ(result.get(), 0); @@ -109,7 +109,7 @@ TEST_F(CancellationTest, testMultiSlotsCancellationCallback) { j++; }); } - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); EXPECT_EQ(j, 100); } @@ -122,7 +122,7 @@ TEST_F(CancellationTest, testMultiSlotsCancellation) { [[maybe_unused]] auto _ = slots.back()->emplace( SignalType::Terminate, [&j](SignalType, Signal*) mutable { j++; }); } - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); EXPECT_EQ(j, 100); } @@ -143,9 +143,9 @@ TEST_F(CancellationTest, testMultiSlotsCancellationWithFilter) { EXPECT_EQ(type, expected_type); }); } - signal->emit(expected_type); + signal->emits(expected_type); EXPECT_EQ(j, 75); - signal->emit(static_cast(0b100)); + signal->emits(static_cast(0b100)); EXPECT_EQ(j, 75); } { @@ -164,7 +164,7 @@ TEST_F(CancellationTest, testMultiSlotsCancellationWithFilter) { EXPECT_EQ(type, expected_type & filter); }); } - signal->emit(expected_type); + signal->emits(expected_type); EXPECT_EQ(j, 100); } } @@ -176,7 +176,7 @@ TEST_F(CancellationTest, testScopeFilterGuard) { [[maybe_unused]] auto _ = slot->emplace(SignalType::Terminate, [](SignalType type, Signal*) { EXPECT_TRUE(true); }); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); { auto guard = slot->setScopedFilter(static_cast(1)); EXPECT_TRUE(slot->canceled()); @@ -191,7 +191,7 @@ TEST_F(CancellationTest, testScopeFilterGuard) { [](SignalType type, Signal*) { EXPECT_TRUE(false); }); { auto guard = slot->setScopedFilter(static_cast(0b10)); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); EXPECT_TRUE(slot->signal()->state() == SignalType::Terminate); EXPECT_TRUE(slot->canceled() == false); } @@ -205,7 +205,7 @@ TEST_F(CancellationTest, testScopeFilterGuard) { [](SignalType type, Signal*) { EXPECT_TRUE(true); }); { auto guard = slot->setScopedFilter(SignalType::All); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); EXPECT_TRUE(slot->canceled()); } EXPECT_TRUE(slot->canceled()); @@ -224,7 +224,7 @@ TEST_F(CancellationTest, testScopeFilterGuardNested) { { auto guard = slot->setScopedFilter(static_cast(0b11100)); - signal->emit(static_cast(0b100)); + signal->emits(static_cast(0b100)); EXPECT_EQ(slot->getFilter(), static_cast(0b100)); EXPECT_EQ(slot->hasTriggered(static_cast(0b100)), true); @@ -246,7 +246,7 @@ TEST_F(CancellationTest, testScopeFilterGuardNested) { { auto guard = slot->setScopedFilter(static_cast(0b11100)); - signal->emit(static_cast(0b011)); + signal->emits(static_cast(0b011)); EXPECT_EQ(slot->getFilter(), static_cast(0b100)); EXPECT_EQ(slot->canceled(), false); } @@ -274,7 +274,7 @@ TEST_F(CancellationTest, testMultiThreadEmit) { res.emplace_back(std::async([&]() { while (!start_flag) std::this_thread::yield(); - return signal->emit(SignalType::Terminate); + return signal->emits(SignalType::Terminate); })); start_flag = true; int cnt = 0; @@ -316,7 +316,7 @@ TEST_F(CancellationTest, testMultiThreadEmitDifferentSignal) { res.emplace_back(std::async([i, &start_flag, &signal]() { while (!start_flag) std::this_thread::yield(); - return signal->emit( + return signal->emits( i % 2 ? static_cast(0b101 | (uint64_t{1} << 63)) : static_cast(0b110 | (uint64_t{1} << 63))); @@ -378,7 +378,7 @@ TEST_F(CancellationTest, testMultiThreadEmitWhenEmplace) { res.emplace_back(std::async([&]() { while (!start_flag) std::this_thread::yield(); - return static_cast(signal->emit(SignalType::Terminate)); + return static_cast(signal->emits(SignalType::Terminate)); })); start_flag = true; int cnt = 0; @@ -423,7 +423,7 @@ TEST_F(CancellationTest, testMultiThreadEmitWhenSetScopedFilter) { while (!start_flag) { std::this_thread::yield(); } - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); }); } while (start_flag2 < 200) { @@ -441,7 +441,7 @@ TEST_F(CancellationTest, testMultiThreadEmitWhenSetScopedFilter) { TEST_F(CancellationTest, testRegistSignalAfterCancellation) { { auto signal = Signal::create(); - signal->emit(SignalType::Terminate); + signal->emits(SignalType::Terminate); Slot s{signal.get()}; EXPECT_FALSE( s.emplace(SignalType::Terminate, [](SignalType, Signal*) {})); @@ -469,6 +469,6 @@ TEST_F(CancellationTest, testDerivedSignal) { EXPECT_EQ(mySignal->myState, 1); }); mySignal->myState = 1; - mySignal->emit(SignalType::Terminate); + mySignal->emits(SignalType::Terminate); } } // namespace async_simple \ No newline at end of file diff --git "a/docs/docs.cn/\344\277\241\345\217\267\344\270\216\344\273\273\345\212\241\347\232\204\345\217\226\346\266\210.md" "b/docs/docs.cn/\344\277\241\345\217\267\344\270\216\344\273\273\345\212\241\347\232\204\345\217\226\346\266\210.md" index 39599c11..6ac87271 100644 --- "a/docs/docs.cn/\344\277\241\345\217\267\344\270\216\344\273\273\345\212\241\347\232\204\345\217\226\346\266\210.md" +++ "b/docs/docs.cn/\344\277\241\345\217\267\344\270\216\344\273\273\345\212\241\347\232\204\345\217\226\346\266\210.md" @@ -41,7 +41,7 @@ for (int i=0;i<10;++i) { } // ... // 提交取消信号 -signal->emit(SignalType::terminate); +signal->emits(SignalType::terminate); for (auto &e:works) e.get(); ``` @@ -49,8 +49,8 @@ for (auto &e:works) 除了直接查询取消状态,我们可以在`Slot`中注册信号处理函数来接受信号。信号处理函数的签名应为`void(SignalType, Signal*)`。第一个参数SignalType代表经过滤后,本次成功触发的信号类型,第二个参数是指向信号的指针。 需要注意的是: -1. 信号处理函数不应该阻塞。调用`emit()`函数并触发信号时,程序会遍历绑定在`Signal`上的信号处理函数并立即执行。 -2. 注意线程安全问题:信号处理函数会由调用`emit()`的线程执行,32号以上的信号处理函数还可能由多个线程并发执行。 +1. 信号处理函数不应该阻塞。调用`emits()`函数并触发信号时,程序会遍历绑定在`Signal`上的信号处理函数并立即执行。 +2. 注意线程安全问题:信号处理函数会由调用`emits()`的线程执行,32号以上的信号处理函数还可能由多个线程并发执行。 3. 信号处理函数禁止持有槽绑定的信号,这会导致信号的内存泄漏。用户应通过`Signal*`参数访问信号。 例如,下面这段代码通过信号回调函数取消睡眠。 @@ -76,7 +76,7 @@ for (int i=0;i<10;++i) { } slot->clear(); // 清除回调函数 if (slot->signal()) { //如果槽被绑定在信号上 - slot->signal()->emit(SignalType::terminate); // 触发取消信号。 + slot->signal()->emits(SignalType::terminate); // 触发取消信号。 } return; }); @@ -97,7 +97,7 @@ class Signal : public std::enable_shared_from_this { public: // 提交信号(允许一次提交多种信号),并返回本次请求成功触发的信号,线程安全。 - SignalType emit(SignalType state) noexcept; + SignalType emits(SignalType state) noexcept; // 获取当前的信号,线程安全。 SignalType state() const noexcept; // 创建信号的工厂方法,返回信号的shared_ptr,线程安全。 @@ -140,11 +140,11 @@ std::shared_ptr signal = Signal::create(); auto slot = std::make_unique(signal.get()); std::shared_ptr chainedSignal = Signal::create(); slot->addChainedSignal(chainedSignal); -signal->emit(SignalType::terminate); +signal->emits(SignalType::terminate); assert(chainedSignal->state()==SignalType::terminate); // 信号会被转发给chainedSignal // 然而,chainedSignal触发的信号不会触发给signal -chainedSignal->emit(static_cast(0b10)); +chainedSignal->emits(static_cast(0b10)); assert(signal->state()!=static_cast(0b10)); ``` @@ -164,7 +164,7 @@ slot->emplace([](SignalType type, Signal* signal) { std::cout << "myState:" << mySignal->myState << std::endl; }); mySignal->myState=1; -mySignal->emit(SignalType::terminate); +mySignal->emits(SignalType::terminate); ``` diff --git a/docs/docs.en/SignalAndCancellation.md b/docs/docs.en/SignalAndCancellation.md index 4a23a24f..dab3c768 100644 --- a/docs/docs.en/SignalAndCancellation.md +++ b/docs/docs.en/SignalAndCancellation.md @@ -40,7 +40,7 @@ for (int i=0;i<10;++i) { } // ... // Submit a cancellation signal -signal->emit(SignalType::terminate); +signal->emits(SignalType::terminate); for (auto &e:works) e.get(); ``` @@ -48,8 +48,8 @@ for (auto &e:works) Apart from directly checking the cancellation status, we can register signal handlers in a `Slot` to receive signals. The signature for a signal handler should be `void(SignalType, Signal*)`. The first parameter, `SignalType`, represents the signal type successfully triggered after filtering, and the second parameter is a pointer to the signal. Note: -1. Signal handlers should not block. When the `emit()` function is called and a signal is triggered, the program will immediately traverse and execute the signal handlers bound to the `Signal`. -2. Be cautious of thread safety: Signal handlers will be executed by the thread calling `emit()`, and signal handlers for signals above the 32nd bit might be executed concurrently by multiple threads. +1. Signal handlers should not block. When the `emits()` function is called and a signal is triggered, the program will immediately traverse and execute the signal handlers bound to the `Signal`. +2. Be cautious of thread safety: Signal handlers will be executed by the thread calling `emits()`, and signal handlers for signals above the 32nd bit might be executed concurrently by multiple threads. 3. Signal handlers should not hold the signal bound to the slot, as it would cause a memory leak. Users should access the signal via the `Signal*` parameter. For example, the following code cancels a sleep operation through a signal callback function: @@ -74,7 +74,7 @@ for (int i=0;i<10;++i) { } slot->clear(); // Clear the callback function if (slot->signal()) { // If the slot is bound to a signal - slot->signal()->emit(SignalType::terminate); // Trigger the cancellation signal. + slot->signal()->emits(SignalType::terminate); // Trigger the cancellation signal. } return; }); @@ -94,7 +94,7 @@ class Signal : public std::enable_shared_from_this { public: // Submit a signal (allows submitting multiple signals at once) and returns the successfully triggered signals in the current request. Thread-safe. - SignalType emit(SignalType state) noexcept; + SignalType emits(SignalType state) noexcept; // Get the current signal, thread-safe. SignalType state() const noexcept; // Factory method to create a signal, returns a shared_ptr of the signal. Thread-safe. @@ -135,11 +135,11 @@ std::shared_ptr signal = Signal::create(); auto slot = std::make_unique(signal.get()); std::shared_ptr chainedSignal = Signal::create(); slot->addChainedSignal(chainedSignal); -signal->emit(SignalType::terminate); +signal->emits(SignalType::terminate); assert(chainedSignal->state()==SignalType::terminate); // The signal will be forwarded to chainedSignal // However, the signals triggered by chainedSignal will not be forwarded to signal -chainedSignal->emit(static_cast(0b10)); +chainedSignal->emits(static_cast(0b10)); assert(signal->state()!=static_cast(0b10)); ``` @@ -159,7 +159,7 @@ slot->emplace([](SignalType type, Signal* signal) { std::cout << "myState:" << mySignal->myState << std::endl; }); mySignal->myState=1; -mySignal->emit(SignalType::terminate); +mySignal->emits(SignalType::terminate); ``` ## Support for Stackless Coroutines