88#include < asyncio/concept/future.h>
99#include < asyncio/selector/selector.h>
1010#include < utility>
11- #include < set >
11+ #include < unordered_set >
1212#include < algorithm>
1313#include < queue>
1414#include < chrono>
1717ASYNCIO_NS_BEGIN
1818class EventLoop : private NonCopyable {
1919 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+ };
2027
2128public:
22- EventLoop () {
23- auto now = std::chrono::system_clock::now ();
29+ EventLoop () { auto now = std::chrono::system_clock::now ();
2430 start_time_ = duration_cast<MSDuration>(now.time_since_epoch ());
2531 }
2632
@@ -29,6 +35,10 @@ class EventLoop: private NonCopyable {
2935 return duration_cast<MSDuration>(now.time_since_epoch ()) - start_time_;
3036 }
3137
38+ HandleId allocate_handle_id () {
39+ return handle_alloc_id_++;
40+ }
41+
3242 bool is_stop () {
3343 return schedule_.empty () && ready_.empty () && selector_.is_stop ();
3444 }
@@ -41,17 +51,18 @@ class EventLoop: private NonCopyable {
4151 template <typename Rep, typename Period>
4252 void call_at (std::chrono::duration<Rep, Period> when, Handle& callback) {
4353 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}));
4556 std::ranges::push_heap (schedule_, std::ranges::greater{}, &TimerHandle::first);
4657 }
4758
4859 void cancel_handle (Handle& handle) {
49- cancelled_.insert (& handle);
60+ cancelled_.insert (handle. get_handle_id () );
5061 }
5162
5263 void call_soon (Handle& callback) {
5364 callback.set_state (PromiseState::PENDING);
54- ready_.emplace ( &callback);
65+ ready_.push ({callback. get_handle_id (), &callback} );
5566 }
5667
5768 template <concepts::Future Fut>
@@ -90,14 +101,15 @@ class EventLoop: private NonCopyable {
90101
91102private:
92103 MSDuration start_time_;
93- std::queue<Handle* > ready_;
94- std::set<Handle* > cancelled_;
104+ std::queue<HandleInfo > ready_;
105+ std::unordered_set<HandleId > cancelled_;
95106 Selector selector_;
96- using TimerHandle = std::pair<MSDuration, Handle* >;
107+ using TimerHandle = std::pair<MSDuration, HandleInfo >;
97108 std::vector<TimerHandle> schedule_; // min time heap
109+ static HandleId handle_alloc_id_;
98110};
99111
100112EventLoop& get_event_loop ();
101113ASYNCIO_NS_END
102114
103- #endif // ASYNCIO_EVENT_LOOP_H
115+ #endif // ASYNCIO_EVENT_LOOP_H
0 commit comments