-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathaiotimer.hpp
149 lines (127 loc) · 4.01 KB
/
aiotimer.hpp
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// solid/frame/aio/aiotimer.hpp
//
// Copyright (c) 2015 Valentin Palade (vipalade @ gmail . com)
//
// This file is part of SolidFrame framework.
//
// 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 "solid/system/common.hpp"
#include "solid/system/socketdevice.hpp"
#include "aiocompletion.hpp"
#include "aioerror.hpp"
#include "aioreactorcontext.hpp"
namespace solid {
namespace frame {
namespace aio {
struct ActorProxy;
class ReactorContext;
class SteadyTimer : public CompletionHandler {
friend class impl::Reactor;
typedef SteadyTimer ThisT;
static void on_init_completion(CompletionHandler& _rch, ReactorContext& _rctx)
{
ThisT& rthis = static_cast<ThisT&>(_rch);
rthis.completionCallback(SteadyTimer::on_completion);
}
static void on_completion(CompletionHandler& _rch, ReactorContext& _rctx)
{
ThisT& rthis = static_cast<ThisT&>(_rch);
switch (rthis.reactorEvent(_rctx)) {
case ReactorEventE::Timer:
rthis.doExec(_rctx);
break;
case ReactorEventE::Clear:
rthis.doClear(_rctx);
rthis.function_ = &on_dummy;
break;
default:
solid_assert_log(false, generic_logger);
}
}
static void on_dummy(ReactorContext& _rctx)
{
}
typedef solid_function_t(void(ReactorContext&)) FunctionT;
FunctionT function_;
size_t storeidx_;
NanoTime expiry_;
public:
SteadyTimer(
ActorProxy const& _ract)
: CompletionHandler(_ract, SteadyTimer::on_init_completion)
, storeidx_(-1)
{
}
~SteadyTimer()
{
// MUST call here and not in the ~CompletionHandler
this->deactivate(false);
}
const NanoTime& expiry() const
{
return expiry_;
}
bool hasPending() const
{
return !solid_function_empty(function_);
}
// Returns false when the operation is scheduled for completion. On completion _f(...) will be called.
// Returns true when operation could not be scheduled for completion - e.g. operation already in progress.
template <class Rep, class Period, typename F>
bool waitFor(ReactorContext& _rctx, std::chrono::duration<Rep, Period> const& _rd, F&& _function)
{
return waitUntil(_rctx, _rctx.nanoTime() + _rd, std::forward<F>(_function));
}
// Returns true when the operation completed. Check _rctx.error() for success or fail
// Returns false when operation is scheduled for completion. On completion _f(...) will be called.
template <class Clock, class Duration, typename F>
bool waitUntil(ReactorContext& _rctx, std::chrono::time_point<Clock, Duration> const& _rtp, F&& _function)
{
function_ = std::forward<F>(_function);
expiry_ = NanoTime{time_point_clock_cast<std::chrono::steady_clock>(_rtp)};
this->addTimer(_rctx, expiry_, storeidx_);
return false;
}
template <typename F>
bool waitUntil(ReactorContext& _rctx, const NanoTime& _expiry, F&& _function)
{
function_ = std::forward<F>(_function);
expiry_ = _expiry;
this->addTimer(_rctx, expiry_, storeidx_);
return false;
}
void silentCancel(ReactorContext& _rctx)
{
doClear(_rctx);
}
void cancel(ReactorContext& _rctx)
{
if (!solid_function_empty(function_)) {
remTimer(_rctx, storeidx_);
error(_rctx, error_timer_cancel);
doExec(_rctx);
} else {
doClear(_rctx);
}
}
private:
void doExec(ReactorContext& _rctx)
{
FunctionT tmpf;
std::swap(tmpf, function_);
storeidx_ = InvalidIndex();
tmpf(_rctx);
}
void doClear(ReactorContext& _rctx)
{
solid_function_clear(function_);
remTimer(_rctx, storeidx_);
storeidx_ = InvalidIndex();
}
};
} // namespace aio
} // namespace frame
} // namespace solid