Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Checks:
- -bugprone-assert-side-effect
- -readability-named-parameter
- -readability-identifier-length
- -readability-redundant-member-init

CheckOptions:
performance-move-const-arg.CheckTriviallyCopyableMove: false
Expand Down
20 changes: 13 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,35 @@ work versus an explicit `Start()` method.
`Event` owns its handlers. `EventSubscriber` is a non-owning façade used to
subscribe and emit through an owning object.

`Subscribe()` returns `EventHandlerDeleter`. It is lightweight and is **not** an
RAII object: destroying or discarding it does not unsubscribe the handler. Call
Use `Subscription` to control the handler lifetime; do not manage the returned
deleter directly.
`Subscribe()` returns `RegEventHandler`. It is lightweight and is **not** an
RAII object: destroying or discarding it does not unsubscribe the handler.
`RegEventHandler` remains a copyable aggregate, but every returned token must
be transferred to exactly one `Subscription` or `MultiSubscription`; copying or
retaining it for multiple owners is unsupported misuse. Use `Subscription` to
control the handler lifetime; do not manage the returned deleter directly.

Use RAII lifetime control when a callback should have an owner lifetime:

- `Subscription` owns one `EventHandlerDeleter`; destruction/reset unsubscribes.
- `Subscription` owns one `RegEventHandler`; destruction/reset unsubscribes.
- `MultiSubscription` owns several deleters and unsubscribes them together.
- A temporary `Subscription` unsubscribes at the end of its scope.
- Retain the subscription for as long as its callback may run.

Unregistering an event rejects new invocations and registrations. Handlers
already captured by an active invocation snapshot continue unless individually
unsubscribed.

Define events with a private `Event<void(...)>` member and expose a subscriber:

```cpp
using ChangedEvent = Event<void(Value const&)>;
ChangedEvent::Subscriber changed_event();
ChangedEvent const& changed_event();

private:
ChangedEvent changed_event_;
```

Return `EventSubscriber{changed_event_}` from the accessor and emit from the
Return `changed_event_ const&` from the accessor and emit from the
owner with `changed_event_.Emit(value)`.

## Actions
Expand Down
20 changes: 7 additions & 13 deletions aether/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ list(APPEND aether_srcs
"server.cpp"
"server_keys.cpp"
"socket_initializer.cpp"
"tele_statistics.cpp")
"tele_statistics.cpp"
"env.cpp"
)

list(APPEND aether_srcs
"aether_c/c_uid.cpp"
Expand All @@ -35,12 +37,6 @@ list(APPEND aether_srcs
list(APPEND aether_srcs
"types/address.cpp")

list(APPEND aether_srcs
"events/event_list.cpp"
"events/event_deleter.cpp"
"events/event_subscription.cpp"
"events/multi_subscription.cpp")

list(APPEND aether_srcs
"poller/epoll_poller.cpp"
"poller/kqueue_poller.cpp"
Expand All @@ -60,9 +56,7 @@ list(APPEND aether_srcs
"ae_actions/select_client.cpp")

list(APPEND aether_srcs
"registration/api/client_reg_api_safe.cpp"
"registration/api/client_reg_api_unsafe.cpp"
"registration/api/global_reg_client_api.cpp"
"registration/api/global_reg_server_api.cpp"
"registration/api/registration_root_api.cpp"
"registration/api/server_registration_api.cpp"
Expand Down Expand Up @@ -143,17 +137,17 @@ list(APPEND aether_srcs

list(APPEND aether_srcs
"stream_api/sized_packet_gate.cpp"
"stream_api/stream_api.cpp"
)

list(APPEND aether_srcs
"write_action/buffer_write.cpp"
)

list(APPEND aether_srcs
"api_protocol/protocol_context.cpp"
"api_protocol/api_pack_parser.cpp"
"api_protocol/return_result_api.cpp"
"api_protocol/details/protocol_context.cpp"
"api_protocol/details/api_packer.cpp"
"api_protocol/details/api_parser.cpp"
"api_protocol/details/packet_reader.cpp"
)

list(APPEND aether_srcs
Expand Down
2 changes: 1 addition & 1 deletion aether/access_points/lora_module_access_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# include "aether/actions/action.h"
# include "aether/actions/action_ptr.h"
# include "aether/adapters/lora_module_adapter.h"
# include "aether/events/event_subscription.h"
# include "aether/events/events.h"
# include "aether/lora_modules/ilora_module_driver.h"
# include "aether/types/state_machine.h"

Expand Down
8 changes: 5 additions & 3 deletions aether/access_points/modem_access_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@
namespace ae {
ModemConnectAction::ModemConnectAction(AeContext const& ae_context,
IModemDriver& driver)
: driver_{&driver},
: Action{ae_context},
driver_{&driver},
connection_event_{ae_context},
task_sub_{ae_context.scheduler().Task([&]() noexcept { Start(); })} {
AE_TELED_DEBUG("ModemConnectAction created");
}

ModemConnectAction::ConnectionEvent::Subscriber
ModemConnectAction::ConnectionEvent const&
ModemConnectAction::connection_event() {
return EventSubscriber{connection_event_};
return connection_event_;
}

void ModemConnectAction::Start() {
Expand Down
3 changes: 1 addition & 2 deletions aether/access_points/modem_access_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
# include "aether/actions/action.h"
# include "aether/adapters/modem_adapter.h"
# include "aether/ae_context.h"
# include "aether/events/event_subscription.h"
# include "aether/events/events.h"

namespace ae {
Expand All @@ -38,7 +37,7 @@ class ModemConnectAction final : public Action {
explicit ModemConnectAction(AeContext const& ae_context,
IModemDriver& driver);

ConnectionEvent::Subscriber connection_event();
ConnectionEvent const& connection_event();

private:
void Start();
Expand Down
10 changes: 6 additions & 4 deletions aether/access_points/wifi_access_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,22 @@ WifiConnectAction::WifiConnectAction(
AeContext const& ae_context, WifiAccessPoint& access_point,
WifiDriver& driver, WiFiAp wifi_ap, std::optional<WiFiPowerSaveParam> psp,
std::optional<WiFiBaseStation> base_station)
: ae_context_{ae_context},
: Action{ae_context},
ae_context_{ae_context},
access_point_{&access_point},
driver_{&driver},
wifi_ap_{std::move(wifi_ap)},
psp_{std::move(psp)},
base_station_{std::move(base_station)},
connection_event_{ae_context_},
scheduler_sub_{
ae_context_.scheduler().Task([this]() { EnsureConnected(); })} {
AE_TELED_DEBUG("WifiConnectAction created");
}

WifiConnectAction::ConnectionEvent::Subscriber
WifiConnectAction::ConnectionEvent const&
WifiConnectAction::connection_event() {
return EventSubscriber{connection_event_};
return connection_event_;
}

void WifiConnectAction::EnsureConnected() {
Expand All @@ -65,7 +67,7 @@ void WifiConnectAction::EnsureConnected() {

void WifiConnectAction::Connect() {
connect_sub_ = driver_->connect_res_event().Subscribe(
[&](Result<WiFiBaseStation, int>&& res) {
[&](Result<WiFiBaseStation, int>& res) {
connect_sub_.Reset();
if (res) {
AE_TELED_INFO("Wifi connected");
Expand Down
2 changes: 1 addition & 1 deletion aether/access_points/wifi_access_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class WifiConnectAction final : public Action {
std::optional<WiFiPowerSaveParam> psp,
std::optional<WiFiBaseStation> base_station);

ConnectionEvent::Subscriber connection_event();
ConnectionEvent const& connection_event();

private:
void EnsureConnected();
Expand Down
7 changes: 3 additions & 4 deletions aether/actions/action.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class Action {
public:
using FinishedEvent = Event<void()>;

Action() noexcept = default;
template <EventContext Ec>
explicit Action(Ec const& ec) noexcept : finished_event_{ec} {}
virtual ~Action() noexcept = default;

AE_CLASS_MOVE_ONLY(Action)
Expand All @@ -35,9 +36,7 @@ class Action {
finished_event_.Emit();
}

FinishedEvent::Subscriber finished_event() noexcept {
return EventSubscriber{finished_event_};
}
FinishedEvent const& finished_event() noexcept { return finished_event_; }

bool is_finished() const noexcept { return is_finished_; }

Expand Down
2 changes: 2 additions & 0 deletions aether/actions/action_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <chrono>

#include "aether/events/events.h"
#include "aether/tasks/details/task_subsctiption.h"

namespace ae {
Expand All @@ -34,6 +35,7 @@ concept AsyncScheduler = requires(T& t) {
template <typename T>
concept ActionContext = requires(T t) {
{ t.scheduler() } -> AsyncScheduler;
{ t.event_system() } -> events::EventSystemConcept;
};
} // namespace ae

Expand Down
6 changes: 3 additions & 3 deletions aether/actions/actions_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
#ifndef AETHER_ACTIONS_ACTIONS_QUEUE_H_
#define AETHER_ACTIONS_ACTIONS_QUEUE_H_

#include <queue>
#include <functional>
#include <memory>
#include <queue>
#include <utility>
#include <functional>

#include "aether-miscpp/types/small_function.h"
#include "aether/events/event_subscription.h"
#include "aether/events/events.h"

namespace ae {
namespace actions_queue_internal {
Expand Down
14 changes: 9 additions & 5 deletions aether/actions/repeatable_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
#include <chrono>
#include <functional>

#include "aether/actions/action.h"
#include "aether-miscpp/meta/time_traits.h"
#include "aether-miscpp/types/small_function.h"

#include "aether/actions/action.h"
#include "aether/actions/action_context.h"
#include "aether/events/events.h"

namespace ae {
/**
Expand All @@ -39,20 +41,22 @@ class RepeatableTask : public Action {
requires(IsDuration_v<D>)
RepeatableTask(AC const& ac, Task&& task, D interval,
int max_repeat_count = kRepeatCountInfinite)
: ac_{ac},
: Action{ac},
ac_{ac},
task_{std::move(task)},
interval_{
std::chrono::duration_cast<std::chrono::milliseconds>(interval)},
max_repeat_count_{max_repeat_count} {
max_repeat_count_{max_repeat_count},
repeat_count_exceeded_event_{ac_} {
Run();
}

AE_CLASS_MOVE_ONLY(RepeatableTask)

void Stop() { stopped_ = true; }

Event<void()>::Subscriber repeat_count_exceeded() noexcept {
return EventSubscriber{repeat_count_exceeded_event_};
Event<void()> const& repeat_count_exceeded() noexcept {
return repeat_count_exceeded_event_;
}

private:
Expand Down
15 changes: 12 additions & 3 deletions aether/adapters/adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,21 @@

#include "aether/adapters/adapter.h"

#include <cassert>

#include "aether/ae_context.h"

namespace ae {
#ifdef AE_DISTILLATION
Adapter::Adapter(ObjProp prop) : Obj{prop} {}
Adapter::Adapter(ObjProp prop)
: Obj{prop}, new_access_point_event_{AeContext{*this}} {}
#endif // AE_DISTILLATION

Adapter::NewAccessPoint::Subscriber Adapter::new_access_point() {
return EventSubscriber{new_access_point_event_};
Adapter::NewAccessPoint const& Adapter::new_access_point() {
assert(!!new_access_point_event_);
return *new_access_point_event_;
}

void Adapter::Loaded() { new_access_point_event_.emplace(AeContext{*this}); }

} // namespace ae
5 changes: 3 additions & 2 deletions aether/adapters/adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ class Adapter : public Obj {

virtual std::vector<AccessPoint::ptr> access_points() = 0;

virtual NewAccessPoint::Subscriber new_access_point();
virtual NewAccessPoint const& new_access_point();

protected:
NewAccessPoint new_access_point_event_;
void Loaded();
std::optional<NewAccessPoint> new_access_point_event_;
};

} // namespace ae
Expand Down
35 changes: 18 additions & 17 deletions aether/ae_actions/check_access_for_send_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,31 @@ CheckAccessForSendMessage::CheckAccessForSendMessage(
AeContext const& ae_context, Uid destination,
CloudServerConnections& cloud_connection,
RequestPolicy::Variant request_policy)
: destination_{destination},
: Action{ae_context},
destination_{destination},
cloud_request_{
ae_context,
ApiRequestHandler{[this](ApiContext<AuthorizedApi>& auth_api, auto*,
auto* request) {
wait_check_sub_ =
auth_api->check_access_for_send_message(destination_)
.Subscribe([&](auto const& res) {
if (res) {
ResponseReceived();
request->Succeeded();
} else {
ErrorReceived();
request->Failed();
}
});
auto* request) {
wait_check_sub_ = auth_api->CheckAccessForSendMessage(destination_)
.Subscribe([&](auto const& res) {
if (res) {
ResponseReceived();
request->Succeeded();
} else {
ErrorReceived();
request->Failed();
}
});
}},
cloud_connection,
request_policy,
} {}
},
result_event_{ae_context} {}

CheckAccessForSendMessage::ResultEvent::Subscriber
CheckAccessForSendMessage::result_event() noexcept {
return EventSubscriber{result_event_};
auto CheckAccessForSendMessage::result_event() const noexcept
-> ResultEvent const& {
return result_event_;
}

void CheckAccessForSendMessage::ResponseReceived() {
Expand Down
Loading
Loading