diff --git a/source/mijin/async/signal.hpp b/source/mijin/async/signal.hpp index 9152c0f..d9cfbbe 100644 --- a/source/mijin/async/signal.hpp +++ b/source/mijin/async/signal.hpp @@ -75,10 +75,70 @@ public: template using Signal = BaseSignal; +template typename TAllocator, typename... TArgs> +class SignalAutoToken +{ +public: + using signal_t = BaseSignal; +private: + signal_t* signal_ = nullptr; + signal_token_t token_ = INVALID_SIGNAL_TOKEN; +public: + SignalAutoToken() = default; + SignalAutoToken(const SignalAutoToken&) = delete; + SignalAutoToken(SignalAutoToken&& other) MIJIN_NOEXCEPT + : signal_(std::exchange(other.signal_, nullptr)), token_(std::exchange(other.token_, INVALID_SIGNAL_TOKEN)) {} + + template + SignalAutoToken(signal_t& signal, THandler&& handler, Oneshot oneshot = Oneshot::NO) MIJIN_NOEXCEPT + : signal_(&signal), token_(signal.connect(std::forward(handler), oneshot)) + {} + + template + SignalAutoToken(signal_t& signal, TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot = Oneshot::NO) MIJIN_NOEXCEPT + : signal_(&signal), token_(signal.connect(object, handler, oneshot)) {} + + template + SignalAutoToken(signal_t& signal, TObject& object, void (TObject::* handler)(TArgs...) const, Oneshot oneshot = Oneshot::NO) MIJIN_NOEXCEPT + : signal_(&signal), token_(signal.connect(object, handler, oneshot)) {} + + ~SignalAutoToken() noexcept + { + reset(); + } + + SignalAutoToken& operator=(const SignalAutoToken&) = delete; + SignalAutoToken& operator=(SignalAutoToken&& other) MIJIN_NOEXCEPT + { + if (this != &other) + { + reset(); + signal_ = std::exchange(other.signal_, nullptr); + token_ = std::exchange(other.token_, INVALID_SIGNAL_TOKEN); + } + return *this; + } +private: + void reset() MIJIN_NOEXCEPT; + + friend signal_t; +}; + // // public functions // +template typename TAllocator, typename... TArgs> +void SignalAutoToken::reset() MIJIN_NOEXCEPT +{ + if (signal_ != nullptr && token_ != INVALID_SIGNAL_TOKEN) + { + signal_->disconnect(token_); + signal_ = nullptr; + token_ = INVALID_SIGNAL_TOKEN; + } +} + template typename TAllocator, typename... TArgs> template inline auto BaseSignal::connect(THandler handler, Oneshot oneshot, std::weak_ptr referenced) MIJIN_NOEXCEPT -> token_t