|
21 | 21 | #include <atomic>
|
22 | 22 | #include <unordered_map>
|
23 | 23 | #include "function_traits.h"
|
| 24 | +#include "onceToken.h" |
24 | 25 | #if defined(_WIN32)
|
25 | 26 | #undef FD_SETSIZE
|
26 | 27 | //修改默认64为1024路 [AUTO-TRANSLATED:90567e14]
|
@@ -504,6 +505,81 @@ class AnyStorage : public std::unordered_map<std::string, Any> {
|
504 | 505 | using Ptr = std::shared_ptr<AnyStorage>;
|
505 | 506 | };
|
506 | 507 |
|
| 508 | +template <class R, class... ArgTypes> |
| 509 | +class function_safe; |
| 510 | + |
| 511 | +template <typename R, typename... ArgTypes> |
| 512 | +class function_safe<R(ArgTypes...)> { |
| 513 | +public: |
| 514 | + using func = std::function<R(ArgTypes...)>; |
| 515 | + using this_type = function_safe<R(ArgTypes...)>; |
| 516 | + |
| 517 | + template <class F> |
| 518 | + using enable_if_not_this = typename std::enable_if<!std::is_same<this_type, typename std::decay<F>::type>::value, typename std::decay<F>::type>::type; |
| 519 | + |
| 520 | + R operator()(ArgTypes... args) const { |
| 521 | + onceToken token([&]() { _doing = true; checkUpdate(); }, [&]() { checkUpdate(); _doing = false; }); |
| 522 | + if (!_impl) { |
| 523 | + throw std::invalid_argument("try to invoke a empty functional"); |
| 524 | + } |
| 525 | + return _impl(std::forward<ArgTypes>(args)...); |
| 526 | + } |
| 527 | + |
| 528 | + function_safe(std::nullptr_t) { |
| 529 | + update(func{}); |
| 530 | + } |
| 531 | + |
| 532 | + function_safe &operator=(std::nullptr_t) { |
| 533 | + update(func{}); |
| 534 | + return *this; |
| 535 | + } |
| 536 | + |
| 537 | + template <typename F, typename = enable_if_not_this<F>> |
| 538 | + function_safe(F &&f) { |
| 539 | + update(func { std::forward<F>(f) }); |
| 540 | + } |
| 541 | + |
| 542 | + template <typename F, typename = enable_if_not_this<F>> |
| 543 | + this_type &operator=(F &&f) { |
| 544 | + update(func { std::forward<F>(f) }); |
| 545 | + return *this; |
| 546 | + } |
| 547 | + |
| 548 | + function_safe() = default; |
| 549 | + function_safe(this_type &&) = default; |
| 550 | + function_safe(const this_type &) = default; |
| 551 | + this_type &operator=(this_type &&) = default; |
| 552 | + this_type &operator=(const this_type &) = default; |
| 553 | + |
| 554 | + operator bool() const { return _update ? (bool)_tmp : (bool)_impl; } |
| 555 | + |
| 556 | +private: |
| 557 | + void checkUpdate() const { |
| 558 | + if (_update) { |
| 559 | + _update = false; |
| 560 | + _impl = std::move(_tmp); |
| 561 | + } |
| 562 | + } |
| 563 | + void update(func in) { |
| 564 | + if (!_doing) { |
| 565 | + // 没在执行中,那么立即覆写 |
| 566 | + _impl = std::move(in); |
| 567 | + _tmp = nullptr; |
| 568 | + _update = false; |
| 569 | + } else { |
| 570 | + // 正在执行中,延后覆写 |
| 571 | + _tmp = std::move(in); |
| 572 | + _update = true; |
| 573 | + } |
| 574 | + } |
| 575 | + |
| 576 | +private: |
| 577 | + mutable bool _update = false; |
| 578 | + mutable bool _doing = false; |
| 579 | + mutable func _tmp; |
| 580 | + mutable func _impl; |
| 581 | +}; |
| 582 | + |
507 | 583 | } // namespace toolkit
|
508 | 584 |
|
509 | 585 | #ifdef __cplusplus
|
|
0 commit comments