8
8
#include < asyncio/concept/future.h>
9
9
#include < asyncio/selector/selector.h>
10
10
#include < utility>
11
- #include < set >
11
+ #include < unordered_set >
12
12
#include < algorithm>
13
13
#include < queue>
14
14
#include < chrono>
17
17
ASYNCIO_NS_BEGIN
18
18
class EventLoop : private NonCopyable {
19
19
using MSDuration = std::chrono::milliseconds;
20
+ // handle maybe destroyed, using the increasing id to track the lifetime of handle.
21
+ // don't directly using a raw pointer to track coroutine lifetime,
22
+ // because a destroyed coroutine may has the same address as a new ready coroutine has created.
23
+ struct HandleInfo {
24
+ HandleId id;
25
+ Handle* handle;
26
+ };
20
27
21
28
public:
22
- EventLoop () {
23
- auto now = std::chrono::system_clock::now ();
29
+ EventLoop () { auto now = std::chrono::system_clock::now ();
24
30
start_time_ = duration_cast<MSDuration>(now.time_since_epoch ());
25
31
}
26
32
@@ -29,6 +35,10 @@ class EventLoop: private NonCopyable {
29
35
return duration_cast<MSDuration>(now.time_since_epoch ()) - start_time_;
30
36
}
31
37
38
+ HandleId allocate_handle_id () {
39
+ return handle_alloc_id_++;
40
+ }
41
+
32
42
bool is_stop () {
33
43
return schedule_.empty () && ready_.empty () && selector_.is_stop ();
34
44
}
@@ -41,17 +51,18 @@ class EventLoop: private NonCopyable {
41
51
template <typename Rep, typename Period>
42
52
void call_at (std::chrono::duration<Rep, Period> when, Handle& callback) {
43
53
callback.set_state (PromiseState::PENDING);
44
- schedule_.emplace_back (std::make_pair (duration_cast<MSDuration>(when), &callback));
54
+ schedule_.emplace_back (std::make_pair (duration_cast<MSDuration>(when),
55
+ HandleInfo{callback.get_handle_id (), &callback}));
45
56
std::ranges::push_heap (schedule_, std::ranges::greater{}, &TimerHandle::first);
46
57
}
47
58
48
59
void cancel_handle (Handle& handle) {
49
- cancelled_.insert (& handle);
60
+ cancelled_.insert (handle. get_handle_id () );
50
61
}
51
62
52
63
void call_soon (Handle& callback) {
53
64
callback.set_state (PromiseState::PENDING);
54
- ready_.emplace ( &callback);
65
+ ready_.push ({callback. get_handle_id (), &callback} );
55
66
}
56
67
57
68
template <concepts::Future Fut>
@@ -90,14 +101,15 @@ class EventLoop: private NonCopyable {
90
101
91
102
private:
92
103
MSDuration start_time_;
93
- std::queue<Handle* > ready_;
94
- std::set<Handle* > cancelled_;
104
+ std::queue<HandleInfo > ready_;
105
+ std::unordered_set<HandleId > cancelled_;
95
106
Selector selector_;
96
- using TimerHandle = std::pair<MSDuration, Handle* >;
107
+ using TimerHandle = std::pair<MSDuration, HandleInfo >;
97
108
std::vector<TimerHandle> schedule_; // min time heap
109
+ static HandleId handle_alloc_id_;
98
110
};
99
111
100
112
EventLoop& get_event_loop ();
101
113
ASYNCIO_NS_END
102
114
103
- #endif // ASYNCIO_EVENT_LOOP_H
115
+ #endif // ASYNCIO_EVENT_LOOP_H
0 commit comments