aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/core/executelater.h
blob: e7a13c10053862c83209c07f1f342c579e3b2d79 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#pragma once

#include "actor_bootstrapped.h"

#include <utility>

namespace NActors {
    template <typename TCallback>
    class TExecuteLater: public TActorBootstrapped<TExecuteLater<TCallback>> {
    public:
        static constexpr IActor::EActivityType ActorActivityType() {
            return IActor::ACTORLIB_COMMON;
        }

        TExecuteLater(
            TCallback&& callback,
            IActor::EActivityType activityType,
            ui32 channel = 0,
            ui64 cookie = 0,
            const TActorId& reportCompletionTo = TActorId(),
            const TActorId& reportExceptionTo = TActorId()) noexcept
            : Callback(std::move(callback))
            , Channel(channel)
            , Cookie(cookie)
            , ReportCompletionTo(reportCompletionTo)
            , ReportExceptionTo(reportExceptionTo)
        {
            this->SetActivityType(activityType);
        }

        void Bootstrap(const TActorContext& ctx) noexcept {
            try {
                {
                    /* RAII, Callback should be destroyed right before sending
                   TEvCallbackCompletion */

                    auto local = std::move(Callback);
                    using T = decltype(local);

                    if constexpr (std::is_invocable_v<T, const TActorContext&>) {
                        local(ctx);
                    } else {
                        local();
                    }
                }

                if (ReportCompletionTo) {
                    ctx.Send(ReportCompletionTo,
                             new TEvents::TEvCallbackCompletion(ctx.SelfID),
                             Channel, Cookie);
                }
            } catch (...) {
                if (ReportExceptionTo) {
                    const TString msg = CurrentExceptionMessage();
                    ctx.Send(ReportExceptionTo,
                             new TEvents::TEvCallbackException(ctx.SelfID, msg),
                             Channel, Cookie);
                }
            }

            this->Die(ctx);
        }

    private:
        TCallback Callback;
        const ui32 Channel;
        const ui64 Cookie;
        const TActorId ReportCompletionTo;
        const TActorId ReportExceptionTo;
    };

    template <typename T>
    IActor* CreateExecuteLaterActor(
        T&& func,
        IActor::EActivityType activityType,
        ui32 channel = 0,
        ui64 cookie = 0,
        const TActorId& reportCompletionTo = TActorId(),
        const TActorId& reportExceptionTo = TActorId()) noexcept {
        return new TExecuteLater<T>(std::forward<T>(func),
                                    activityType,
                                    channel,
                                    cookie,
                                    reportCompletionTo,
                                    reportExceptionTo);
    }
}