NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
signals.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_ASYNC_SIGNALS_HPP__
2#define NEFORCE_CORE_ASYNC_SIGNALS_HPP__
3
11
17NEFORCE_BEGIN_NAMESPACE__
18
24
31enum class callback_result {
34};
35
36
43struct oneshot_t {
44 constexpr oneshot_t() noexcept = default;
45};
46
50NEFORCE_INLINE17 constexpr oneshot_t oneshot{};
51
58enum class nshot_t : size_t {
59};
60
61
70private:
71 shared_ptr<bool> connected_;
72
73public:
78 connected_(_NEFORCE make_shared<bool>(true)) {}
79
86 void disconnect() noexcept {
87 if (connected_) {
88 *connected_ = false;
89 }
90 }
91
96 bool connected() const noexcept { return connected_ && *connected_; }
97
102 shared_ptr<bool> flag() const noexcept { return connected_; }
103};
104
105
113private:
114 connection conn_{};
115
116public:
120 scoped_connection() = default;
121
126 explicit scoped_connection(connection conn) noexcept :
127 conn_(_NEFORCE move(conn)) {}
128
132 ~scoped_connection() { conn_.disconnect(); }
133
134 scoped_connection(const scoped_connection&) = delete;
135 scoped_connection& operator=(const scoped_connection&) = delete;
136
142 conn_(_NEFORCE move(other.conn_)) {}
143
150 if (addressof(other) == this) {
151 return *this;
152 }
153 conn_.disconnect();
154 conn_ = _NEFORCE move(other.conn_);
155 return *this;
156 }
157
161 void disconnect() noexcept { conn_.disconnect(); }
162
167 bool connected() const noexcept { return conn_.connected(); }
168
175 connection release() noexcept { return _NEFORCE move(conn_); }
176};
177
178
179template <typename... Types>
180struct signal;
181
188template <typename... Types>
190private:
191 shared_ptr<bool> blocked_flag_;
192 bool old_value_;
193 bool released_ = false;
194
195public:
200 explicit signal_blocker(signal<Types...>& sig) noexcept :
201 blocked_flag_(sig.block_flag()) {
202 old_value_ = *blocked_flag_;
203 *blocked_flag_ = true;
204 }
205
210 if (blocked_flag_ && !released_) {
211 *blocked_flag_ = old_value_;
212 }
213 }
214
215 signal_blocker(const signal_blocker&) = delete;
216 signal_blocker& operator=(const signal_blocker&) = delete;
217
223 void unblock() noexcept {
224 if (blocked_flag_ && !released_) {
225 *blocked_flag_ = old_value_;
226 released_ = true;
227 }
228 }
229};
230
231
239template <typename... Types>
240struct signal {
241private:
246 struct slot_entry {
247 using callback_type = function<callback_result(Types...)>;
248
249 callback_type callback;
250 shared_ptr<bool> connected_flag;
251 int priority;
252
253 slot_entry(callback_type cb, shared_ptr<bool> flag, const int pri = 0) :
254 callback(_NEFORCE move(cb)),
255 connected_flag(_NEFORCE move(flag)),
256 priority(pri) {}
257 };
258
259 vector<slot_entry> slots_{};
260 shared_ptr<bool> blocked_flag_{_NEFORCE make_shared<bool>(false)};
261 mutable mutex mutex_;
262
263 template <typename T>
264 static shared_ptr<T> lock_if_weak(const weak_ptr<T>& self) {
265 return self.lock();
266 }
267 template <typename T>
268 static const shared_ptr<T>& lock_if_weak(const shared_ptr<T>& self) noexcept {
269 return self;
270 }
271 template <typename T>
272 static T* lock_if_weak(T* self) noexcept {
273 return self;
274 }
275
276 template <typename Func>
277 auto with_lock(Func&& func) const {
278 lock<mutex> lock(mutex_);
279 return _NEFORCE forward<Func>(func)();
280 }
281
282 template <typename Func>
283 auto with_lock(Func&& func) {
284 lock<mutex> lock(mutex_);
285 return _NEFORCE forward<Func>(func)();
286 }
287
296 template <typename Self, typename MemFn>
297 auto bind(Self self, MemFn memfn) {
298 return [self = _NEFORCE move(self), memfn](Types... args) {
299 auto ptr = signal::lock_if_weak(self);
300 if (ptr == nullptr) {
302 }
303 ((*ptr).*memfn)(_NEFORCE forward<Types>(args)...);
305 };
306 }
307
317 template <typename Self, typename MemFn>
318 auto bind(Self self, MemFn memfn, oneshot_t one) {
319 return [self = _NEFORCE move(self), memfn](Types... args) {
320 auto ptr = signal::lock_if_weak(self);
321 if (ptr == nullptr) {
323 }
324 ((*ptr).*memfn)(_NEFORCE forward<Types>(args)...);
326 };
327 }
328
338 template <typename Self, typename MemFn>
339 auto bind(Self self, MemFn memfn, nshot_t n) {
340 return [self = _NEFORCE move(self), memfn, n = static_cast<size_t>(n)](Types... args) mutable {
341 if (n == 0) {
343 }
344 auto ptr = signal::lock_if_weak(self);
345 if (ptr == nullptr) {
347 }
348 ((*ptr).*memfn)(_NEFORCE forward<Types>(args)...);
349 --n;
350 if (n == 0) {
352 }
354 };
355 }
356
364 template <typename Func>
365 enable_if_t<is_invocable_r_v<callback_result, Func, Types...>, connection> connect_impl(Func callback,
366 int priority) {
367 connection conn{};
368
369 auto it = slots_.begin();
370 while (it != slots_.end() && it->priority >= priority) {
371 ++it;
372 }
373 slots_.emplace(it, _NEFORCE move(callback), conn.flag(), priority);
374
375 return conn;
376 }
377
385 template <typename Func>
386 enable_if_t<!is_invocable_r_v<callback_result, Func, Types...>, connection> connect_impl(Func callback,
387 int priority) {
388 connection conn{};
389
390 auto wrapped = [callback = _NEFORCE move(callback)](Types... args) mutable {
391 callback(_NEFORCE forward<Types>(args)...);
393 };
394
395 auto it = slots_.begin();
396 while (it != slots_.end() && it->priority >= priority) {
397 ++it;
398 }
399 slots_.emplace(it, _NEFORCE move(wrapped), conn.flag(), priority);
400
401 return conn;
402 }
403
404 size_t slot_count_unlocked() const noexcept {
405 size_t count = 0;
406 for (const auto& slot: slots_) {
407 if (slot.connected_flag && *slot.connected_flag) {
408 ++count;
409 }
410 }
411 return count;
412 }
413
414public:
415 signal() = default;
416 signal(const signal&) = delete;
417 signal& operator=(const signal&) = delete;
418 signal(signal&&) = default;
419 signal& operator=(signal&&) = default;
420
431 template <typename Self, typename MemFn, typename... Tag>
432 connection connect(Self self, MemFn memfn, Tag... tag) {
433 return this->connect(_NEFORCE move(self), memfn, 0, tag...);
434 }
435
443 template <typename Func>
444 connection connect(Func callback, int priority = 0) {
445 return this->with_lock([this, callback = _NEFORCE move(callback), priority] {
446 return this->connect_impl(_NEFORCE move(callback), priority);
447 });
448 }
449
461 template <typename Self, typename MemFn, typename... Tag>
462 connection connect(Self self, MemFn memfn, int priority, Tag... tag) {
463 static_assert(sizeof...(Tag) <= 1, "only zero or one tag is allowed");
464
465 return this->with_lock([this, self = _NEFORCE move(self), memfn = _NEFORCE move(memfn), priority, tag...] {
466 connection conn{};
467
468 auto it = slots_.begin();
469 while (it != slots_.end() && it->priority >= priority) {
470 ++it;
471 }
472 slots_.emplace(it, this->bind(_NEFORCE move(self), memfn, tag...), conn.flag(), priority);
473
474 return conn;
475 });
476 }
477
485 void emit(Types... args) {
486 vector<slot_entry> snapshot;
487 {
488 lock<mutex> lk(mutex_);
489 if (is_blocked()) {
490 return;
491 }
492 snapshot = slots_;
493 }
494
495 for (auto& slot: snapshot) {
496 if (!slot.connected_flag || !(*slot.connected_flag)) {
497 continue;
498 }
499
500 const callback_result res = slot.callback(args...);
501 if (res == callback_result::erase) {
502 *slot.connected_flag = false;
503 }
504 }
505
506 {
507 lock<mutex> lk(mutex_);
508 slots_.erase(
509 _NEFORCE remove_if(slots_.begin(), slots_.end(),
510 [](const slot_entry& s) { return !s.connected_flag || !(*s.connected_flag); }),
511 slots_.end());
512 }
513 }
514
523 template <typename Executor>
524 void emit_executor(Executor& executor, Types... args) {
525 auto weak_flag = weak_ptr<bool>(blocked_flag_);
526 auto args_tuple = _NEFORCE make_tuple(_NEFORCE forward<Types>(args)...);
527
528 executor.post([this, weak_flag = _NEFORCE move(weak_flag), args_tuple = _NEFORCE move(args_tuple)]() mutable {
529 if (weak_flag.expired()) {
530 return;
531 }
532
533 _NEFORCE apply([this](auto&&... a) { this->emit(_NEFORCE forward<decltype(a)>(a)...); },
534 _NEFORCE move(args_tuple));
535 });
536 }
537
542 template <typename... Args>
543 void operator()(Args&&... args) {
544 this->emit(_NEFORCE forward<Args>(args)...);
545 }
546
551 this->with_lock([this] { slots_.clear(); });
552 }
553
562 connection connect_signal(signal& other, int priority = 0) {
563 return this->connect(
564 [other_ptr = &other](Types... args) {
565 other_ptr->emit(args...);
566 return callback_result::keep;
567 },
568 priority);
569 }
570
579 connection connect_signal(signal* other, int priority = 0) {
580 return this->connect(
581 [other](Types... args) {
582 if (other) {
583 other->emit(args...);
584 }
586 },
587 priority);
588 }
589
601 template <typename Func, typename Predicate>
602 connection connect_if(Func callback, Predicate pred, int priority = 0) {
603 using result_type = invoke_result_t<Predicate, Types...>;
604 static_assert(is_boolean_v<result_type>, "only boolean results are allowed");
605
606 return this->connect(
607 [callback = _NEFORCE move(callback), pred = _NEFORCE move(pred)](Types... args) mutable {
608 if (pred(args...)) {
609 callback(_NEFORCE forward<Types>(args)...);
610 }
612 },
613 priority);
614 }
615
629 template <typename Self, typename MemFn, typename Predicate, typename... Tag>
630 connection connect_if(Self self, MemFn memfn, Predicate pred, int priority, Tag... tag) {
631 using result_type = invoke_result_t<Predicate, Types...>;
632 static_assert(is_boolean_v<result_type>, "only boolean results are allowed");
633 static_assert(sizeof...(Tag) <= 1, "only zero or one tag is allowed");
634
635 auto bound = this->bind(_NEFORCE move(self), memfn, tag...);
636
637 return this->connect(
638 [bound = _NEFORCE move(bound), pred = _NEFORCE move(pred)](Types... args) mutable {
639 if (pred(args...)) {
640 return bound(_NEFORCE forward<Types>(args)...);
641 }
643 },
644 priority);
645 }
646
658 template <typename Func, typename Filter>
659 connection connect_filtered(Func callback, Filter filter, int priority = 0) {
660 using result_type = invoke_result_t<Filter, Types...>;
661 static_assert(is_optional_v<result_type>, "only optional results are allowed");
662
663 return this->connect(
664 [callback = _NEFORCE move(callback), filter = _NEFORCE move(filter)](Types... args) mutable {
665 auto filtered = filter(args...);
666 if (filtered) {
667 _NEFORCE apply(
668 [&callback](auto&&... filtered_args) {
669 callback(_NEFORCE forward<decltype(filtered_args)>(filtered_args)...);
670 },
671 _NEFORCE move(*filtered));
672 }
674 },
675 priority);
676 }
677
689 template <typename Func, typename Transform>
690 connection connect_transformed(Func callback, Transform transform, int priority = 0) {
691 static_assert(is_invocable_v<Transform, Types...>, "only function inputs are allowed");
692
693 return this->connect(
694 [callback = _NEFORCE move(callback), transform = _NEFORCE move(transform)](Types... args) mutable {
695 callback(transform(_NEFORCE forward<Types>(args)...));
696 return callback_result::keep;
697 },
698 priority);
699 }
700
705 shared_ptr<bool> block_flag() const noexcept { return blocked_flag_; }
706
711 bool is_blocked() const noexcept { return blocked_flag_ && *blocked_flag_; }
712
717 size_t slot_count() const noexcept {
718 return this->with_lock([this] { return slot_count_unlocked(); });
719 }
720
725 NEFORCE_NODISCARD bool empty() const noexcept {
726 return this->with_lock([this] { return slot_count_unlocked() == 0; });
727 }
728};
729 // Signals
731
732NEFORCE_END_NAMESPACE__
733#endif // NEFORCE_CORE_ASYNC_SIGNALS_HPP__
元组应用函数
连接句柄
bool connected() const noexcept
检查连接是否有效
connection()
默认构造函数,创建处于已连接状态的对象
void disconnect() noexcept
断开连接
shared_ptr< bool > flag() const noexcept
获取连接标志的内部指针
函数包装器主模板声明
锁管理器模板
非递归互斥锁
作用域连接
scoped_connection(connection conn) noexcept
从连接构造
connection release() noexcept
释放连接所有权
bool connected() const noexcept
检查连接是否有效
void disconnect() noexcept
手动断开连接
scoped_connection(scoped_connection &&other) noexcept
移动构造函数
scoped_connection & operator=(scoped_connection &&other) noexcept
移动赋值运算符
scoped_connection()=default
默认构造函数
~scoped_connection()
析构函数,自动断开连接
共享智能指针类模板
信号阻塞器
~signal_blocker()
析构函数,恢复原状态
void unblock() noexcept
手动解除阻塞
signal_blocker(signal< Types... > &sig) noexcept
构造函数,阻塞指定信号
动态大小数组容器
弱智能指针类模板
NEFORCE_NODISCARD shared_ptr< T > lock() const noexcept
尝试获取共享智能指针
NEFORCE_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
NEFORCE_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
NEFORCE_INLINE17 constexpr bool is_boolean_v
is_boolean的便捷变量模板
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
NEFORCE_INLINE17 constexpr bool is_invocable_v
is_invocable的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_invocable_r_v
is_invocable_r的便捷变量模板
typename inner::__invoke_result_aux< F, Args... >::type invoke_result_t
invoke_result的便捷别名
constexpr Iterator remove_if(Iterator first, Iterator last, Predicate pred)
移除范围中满足谓词的元素
constexpr size_t erase(Container &cont, const U &value)
从容器中删除所有等于指定值的元素
enable_if_t<!is_unbounded_array_v< T > &&is_constructible_v< T, Args... >, shared_ptr< T > > make_shared(Args &&... args)
融合分配创建共享指针
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
nshot_t
多次连接标签
callback_result
回调结果枚举
NEFORCE_INLINE17 constexpr oneshot_t oneshot
一次性连接标签实例
@ keep
保留回调
@ erase
调用后自动删除
bool NEFORCE_API priority(int priority) noexcept
设置线程优先级
NEFORCE_NODISCARD constexpr tuple< unwrap_ref_decay_t< Types >... > make_tuple(Types &&... args)
从参数创建元组
constexpr decltype(auto) apply(Func &&f, Tuple &&t) noexcept(inner::__apply_unpack_tuple< _NEFORCE is_nothrow_invocable, Func, Tuple >::value)
将元组元素解包作为参数调用函数
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
互斥锁
可选值类型
一次性连接标签
信号类
connection connect_transformed(Func callback, Transform transform, int priority=0)
变换连接
void disconnect_all()
断开所有连接
connection connect_signal(signal &other, int priority=0)
连接另一个信号
void emit(Types... args)
触发信号
connection connect(Self self, MemFn memfn, int priority, Tag... tag)
连接成员函数
connection connect_filtered(Func callback, Filter filter, int priority=0)
过滤连接
bool is_blocked() const noexcept
检查信号是否被阻塞
shared_ptr< bool > block_flag() const noexcept
获取阻塞标志
NEFORCE_NODISCARD bool empty() const noexcept
检查信号是否为空(无活跃槽)
connection connect_signal(signal *other, int priority=0)
连接另一个信号(指针版本)
size_t slot_count() const noexcept
获取活跃槽的数量
void operator()(Args &&... args)
函数调用操作符
connection connect_if(Self self, MemFn memfn, Predicate pred, int priority, Tag... tag)
条件连接(成员函数版本)
connection connect_if(Func callback, Predicate pred, int priority=0)
条件连接
connection connect(Func callback, int priority=0)
连接普通函数/lambda
void emit_executor(Executor &executor, Types... args)
执行器触发信号
connection connect(Self self, MemFn memfn, Tag... tag)
连接成员函数(默认优先级0)
动态大小数组容器
弱智能指针实现