2018-12-31 20:04:05 +01:00
|
|
|
//
|
2022-12-31 22:28:08 +01:00
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
|
2018-12-31 20:04:05 +01:00
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "td/actor/actor.h"
|
|
|
|
|
|
|
|
namespace td {
|
2018-07-03 19:28:00 +02:00
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
class Slot;
|
2018-07-03 19:28:00 +02:00
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
class Signal {
|
|
|
|
public:
|
|
|
|
void emit();
|
|
|
|
|
2021-10-19 17:11:16 +02:00
|
|
|
explicit Signal(ActorId<Slot> slot_id) : slot_id_(std::move(slot_id)) {
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ActorId<Slot> slot_id_;
|
|
|
|
};
|
2018-07-03 19:28:00 +02:00
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
class Slot final : public Actor {
|
|
|
|
public:
|
|
|
|
Slot() = default;
|
2023-05-05 12:51:19 +02:00
|
|
|
Slot(const Slot &) = delete;
|
|
|
|
Slot &operator=(const Slot &) = delete;
|
2018-12-31 20:04:05 +01:00
|
|
|
Slot(Slot &&) = default;
|
|
|
|
Slot &operator=(Slot &&) = default;
|
2021-07-03 22:51:36 +02:00
|
|
|
~Slot() final {
|
2018-12-31 20:04:05 +01:00
|
|
|
close();
|
|
|
|
}
|
|
|
|
void set_event(EventFull &&event) {
|
|
|
|
was_signal_ = false;
|
|
|
|
event_ = std::move(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool has_event() {
|
|
|
|
return !event_.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool was_signal() {
|
|
|
|
return was_signal_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear_event() {
|
|
|
|
event_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void close() {
|
|
|
|
if (!empty()) {
|
|
|
|
do_stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_timeout_in(double timeout_in) {
|
|
|
|
register_if_empty();
|
|
|
|
Actor::set_timeout_in(timeout_in);
|
|
|
|
}
|
|
|
|
void set_timeout_at(double timeout_at) {
|
|
|
|
register_if_empty();
|
|
|
|
Actor::set_timeout_at(timeout_at);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend class Signal;
|
|
|
|
Signal get_signal() {
|
|
|
|
register_if_empty();
|
|
|
|
return Signal(actor_id(this));
|
|
|
|
}
|
|
|
|
ActorShared<> get_signal_new() {
|
|
|
|
register_if_empty();
|
2020-08-27 00:27:34 +02:00
|
|
|
return actor_shared(this);
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool was_signal_ = false;
|
|
|
|
EventFull event_;
|
|
|
|
|
2021-07-03 22:51:36 +02:00
|
|
|
void timeout_expired() final {
|
2018-12-31 20:04:05 +01:00
|
|
|
signal();
|
|
|
|
}
|
|
|
|
|
2021-07-03 22:51:36 +02:00
|
|
|
void start_up() final {
|
2018-12-31 20:04:05 +01:00
|
|
|
empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void register_if_empty() {
|
|
|
|
if (empty()) {
|
|
|
|
register_actor("Slot", this).release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// send event only once
|
|
|
|
void signal() {
|
|
|
|
if (!was_signal_) {
|
|
|
|
was_signal_ = true;
|
|
|
|
event_.try_emit_later();
|
|
|
|
}
|
|
|
|
}
|
2021-07-03 22:51:36 +02:00
|
|
|
void hangup_shared() final {
|
2018-12-31 20:04:05 +01:00
|
|
|
signal();
|
|
|
|
}
|
|
|
|
};
|
2018-07-03 19:28:00 +02:00
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
inline void Signal::emit() {
|
|
|
|
send_closure(slot_id_, &Slot::signal);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace td
|