Skip to content

Commit

Permalink
Drain the io_context instead of destroying it
Browse files Browse the repository at this point in the history
  • Loading branch information
heifner committed Oct 14, 2024
1 parent 454a161 commit 71ed3d7
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 18 deletions.
9 changes: 3 additions & 6 deletions examples/executor_example/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@
#include <appbase/execution_priority_queue.hpp>

#include <limits>
#include <optional>

class my_executor {
public:
template <typename Func>
auto post( int priority, Func&& func ) {
return boost::asio::post(*io_serv, pri_queue.wrap(priority, --order, std::forward<Func>(func)));
return boost::asio::post(io_serv, pri_queue.wrap(priority, --order, std::forward<Func>(func)));
}

auto& get_priority_queue() { return pri_queue; }
Expand All @@ -34,13 +33,11 @@ class my_executor {

void clear() { pri_queue.clear(); }

void reset() { io_serv.emplace(); }

boost::asio::io_service& get_io_service() { return *io_serv; }
boost::asio::io_service& get_io_service() { return io_serv; }

private:
// members are ordered taking into account that the last one is destructed first
std::optional<boost::asio::io_service> io_serv{std::in_place};
boost::asio::io_context io_serv;
appbase::execution_priority_queue pri_queue;
std::size_t order = std::numeric_limits<size_t>::max(); // to maintain FIFO ordering in queue within priority
};
Expand Down
15 changes: 11 additions & 4 deletions include/appbase/application_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,17 @@ class application_base {

try {
// plugins shutdown down at this point,
exec.clear(); // make sure the queue is empty
// Recreate the io_context since it doesn't provide a clear and we want the destructors of all the
// lambdas posted to the io_context to execute before destroying the plugins
exec.reset();

// Drain the io_service of anything that could be referencing plugins.
// Note this does not call exec.execute_highest(), so only drains into the priority queue assuming nothing
// has hijacked the io_service for other purposes.
io_serv.restart();
while (io_serv.poll())
;
// clear priority queue of anything pushed by poll()
exec.clear();

// destroy the plugins now that all lambda that reference them have been destroyed
destroy_plugins();
} catch (...) {
if (!eptr)
Expand Down
11 changes: 3 additions & 8 deletions include/appbase/default_executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
#include <appbase/execution_priority_queue.hpp>

#include <limits>
#include <optional>

namespace appbase {

class default_executor {
public:
template <typename Func>
auto post(int priority, Func&& func) {
return boost::asio::post(*io_serv, pri_queue.wrap(priority, --order, std::forward<Func>(func)));
return boost::asio::post(io_serv, pri_queue.wrap(priority, --order, std::forward<Func>(func)));
}

/**
Expand All @@ -35,21 +34,17 @@ class default_executor {
pri_queue.clear();
}

void reset() {
io_serv.emplace();
}

/**
* Do not run io_service in any other threads, as application assumes single-threaded execution in exec().
* @return io_serivice of application
*/
boost::asio::io_service& get_io_service() {
return *io_serv;
return io_serv;
}

private:
// members are ordered taking into account that the last one is destructed first
std::optional<boost::asio::io_service> io_serv{std::in_place};
boost::asio::io_context io_serv;
execution_priority_queue pri_queue;
std::size_t order = std::numeric_limits<size_t>::max(); // to maintain FIFO ordering in queue within priority
};
Expand Down

0 comments on commit 71ed3d7

Please sign in to comment.