2525#include < system_error>
2626#include < unordered_map>
2727
28+ #include " asio/dispatch.hpp"
2829#include " asio/ip/address.hpp"
2930#include " asio/posix/stream_descriptor.hpp"
3031#include " ib_buffer.hpp"
@@ -334,6 +335,19 @@ class ib_device_t : public std::enable_shared_from_this<ib_device_t> {
334335 return buffer_pool_;
335336 }
336337
338+ struct async_event_watcher_manager_t
339+ : public std::unordered_map<ib_device_t *, std::weak_ptr<ib_device_t >> {
340+ ~async_event_watcher_manager_t () {
341+ for (auto & [_, dev] : *this ) {
342+ if (auto ptr = dev.lock (); ptr) {
343+ ptr->stop_async_event_watcher ();
344+ }
345+ }
346+ }
347+ };
348+
349+ ~ib_device_t () { stop_async_event_watcher (); }
350+
337351 private:
338352 int ipv6_addr_v4mapped (const struct in6_addr * a) {
339353 return ((a->s6_addr32 [0 ] | a->s6_addr32 [1 ]) |
@@ -362,6 +376,12 @@ class ib_device_t : public std::enable_shared_from_this<ib_device_t> {
362376 return default_gid_index;
363377 }
364378
379+ template <typename T>
380+ static bool weak_ptrs_equal (const std::weak_ptr<T>& a,
381+ const std::weak_ptr<T>& b) {
382+ return !a.owner_before (b) && !b.owner_before (a);
383+ }
384+
365385 void start_async_event_watcher () {
366386 if (!ctx_) {
367387 return ;
@@ -373,32 +393,35 @@ class ib_device_t : public std::enable_shared_from_this<ib_device_t> {
373393 << " Error, failed to change file descriptor of async event queue\n " ;
374394 return ;
375395 }
376-
377- auto fd_deleter = [](asio::posix::stream_descriptor* fd) {
378- fd->release ();
379- delete fd;
380- };
381- auto fd =
382- std::unique_ptr<asio::posix::stream_descriptor, decltype (fd_deleter)>(
383- new asio::posix::stream_descriptor (
384- coro_io::get_global_executor ()->get_asio_executor (),
385- ctx_->async_fd ));
396+ auto executor = coro_io::get_global_executor ();
397+ async_event_watcher_fd_ = std::unique_ptr<asio::posix::stream_descriptor>(
398+ new asio::posix::stream_descriptor (executor->get_asio_executor (),
399+ ctx_->async_fd ));
386400 auto listen_event = [](std::weak_ptr<ib_device_t > dev,
387- auto fd) -> async_simple::coro::Lazy<void > {
401+ coro_io::ExecutorWrapper<>* executor)
402+ -> async_simple::coro::Lazy<void > {
388403 std::error_code ec;
389- auto name = std::string{dev.lock ()->name ()};
404+ auto self = dev.lock ();
405+ if (self == nullptr ) {
406+ co_return ;
407+ }
408+ auto self_raw_ptr = self.get ();
409+ (*executor->get_data_with_default <async_event_watcher_manager_t >(
410+ " ylt_ib_watch" ))[self_raw_ptr] = dev;
411+ auto name = std::string{self->name ()};
390412 ELOG_INFO << " start_async_event_watcher of device:" << name << " start" ;
391413 while (!ec) {
392414 coro_io::callback_awaitor<std::error_code> awaitor;
393- ec = co_await awaitor.await_resume ([&fd](auto handler) {
394- fd->async_wait (asio::posix::stream_descriptor::wait_read,
395- [handler](const std::error_code& ec) mutable {
396- handler.set_value_then_resume (ec);
397- });
415+ ec = co_await awaitor.await_resume ([&self](auto handler) {
416+ self->async_event_watcher_fd_ ->async_wait (
417+ asio::posix::stream_descriptor::wait_read,
418+ [handler](const std::error_code& ec) mutable {
419+ handler.set_value_then_resume (ec);
420+ });
421+ self = nullptr ;
398422 });
399-
400423 if (!ec) {
401- auto self = dev.lock ();
424+ self = dev.lock ();
402425 if (!self) {
403426 ELOG_DEBUG
404427 << " ib_device async event stop listening by close device:"
@@ -412,14 +435,28 @@ class ib_device_t : public std::enable_shared_from_this<ib_device_t> {
412435 << ec.message () << " ,device:" << name;
413436 }
414437 }
438+ auto * table = executor->get_data <async_event_watcher_manager_t >(
439+ " ib_device_async_event_watcher" );
440+ if (table) {
441+ auto iter = table->find (self_raw_ptr);
442+ if (iter != table->end () && weak_ptrs_equal (iter->second , dev)) {
443+ table->erase (iter);
444+ }
445+ }
415446 };
416- listen_event (shared_from_this (), std::move (fd)).start ([](auto && ec) {
417- });
447+ listen_event (shared_from_this (), executor).via (executor).detach ();
448+ }
449+
450+ void stop_async_event_watcher () {
451+ std::error_code ec;
452+ [[maybe_unused]] auto _ = async_event_watcher_fd_->cancel (ec);
453+ async_event_watcher_fd_->release ();
418454 }
419455
420456 std::string name_;
421457 std::unique_ptr<ibv_context, ib_deleter> ctx_;
422458 std::unique_ptr<ibv_pd, ib_deleter> pd_;
459+ std::unique_ptr<asio::posix::stream_descriptor> async_event_watcher_fd_;
423460 std::shared_ptr<ib_buffer_pool_t > buffer_pool_;
424461 std::atomic<bool > support_inline_data_ = true ;
425462 ibv_port_attr attr_;
0 commit comments