helics  2.8.1
AsioContextManager.h
1 /*
2 Copyright (c) 2017-2021,
3 Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable
4 Energy, LLC. See the top-level NOTICE for additional details. All rights reserved.
5 SPDX-License-Identifier: BSD-3-Clause
6 */
7 
8 /*
9  * LLNS Copyright Start
10  * Copyright (c) 2017, Lawrence Livermore National Security
11  * This work was performed under the auspices of the U.S. Department
12  * of Energy by Lawrence Livermore National Laboratory in part under
13  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
14  * Produced at the Lawrence Livermore National Laboratory.
15  * All rights reserved.
16  * For details, see the LICENSE file.
17  * LLNS Copyright End
18  */
19 
20 #pragma once
21 
22 #include <atomic>
23 #include <future>
24 #include <map>
25 #include <memory>
26 #include <mutex>
27 #include <string>
28 #include <utility>
29 
30 // The choice for noexcept isn't set correctly in asio::io_context (including asio.hpp instead
31 // didn't help) With Boost 1.58 this resulted in a compile error, apparently from the BOOST_NOEXCEPT
32 // define being empty
33 #ifdef ASIO_ERROR_CATEGORY_NOEXCEPT
34 # undef ASIO_ERROR_CATEGORY_NOEXCEPT
35 #endif
36 
37 #define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
38 #include <asio/io_context.hpp>
39 #undef ASIO_ERROR_CATEGORY_NOEXCEPT
40 
42 class AsioContextManager: public std::enable_shared_from_this<AsioContextManager> {
43  private:
44  enum class loop_mode : int { stopped = 0, starting = 1, running = 2 };
45  static std::map<std::string, std::shared_ptr<AsioContextManager>>
46  contexts;
47  std::atomic<int> runCounter{
48  0};
49  std::string name;
50  std::unique_ptr<asio::io_context> ictx;
51  std::unique_ptr<asio::io_context::work>
52  nullwork;
53  bool leakOnDelete = false;
54  std::atomic<loop_mode> running{loop_mode::stopped};
55  std::mutex runningLoopLock;
56  std::atomic<bool> terminateLoop{false};
57  std::future<void> loopRet;
59  explicit AsioContextManager(const std::string& contextName);
60 
62  class Servicer {
63  public:
64  explicit Servicer(std::shared_ptr<AsioContextManager> manager):
65  contextManager(std::move(manager))
66  {
67  }
69  ~Servicer()
70  {
71  if (contextManager) {
72  try {
73  contextManager->haltContextLoop();
74  }
75  catch (...) {
76  // no exceptions in a destructor
77  }
78  }
79  }
81  Servicer(Servicer&& sv) = default;
82 
83  private:
84  std::shared_ptr<AsioContextManager> contextManager;
85  };
86 
87  public:
88  using LoopHandle = std::unique_ptr<Servicer>;
89 
94  static std::shared_ptr<AsioContextManager>
95  getContextPointer(const std::string& contextName = std::string());
101  static std::shared_ptr<AsioContextManager>
102  getExistingContextPointer(const std::string& contextName = std::string());
105  static asio::io_context& getContext(const std::string& contextName = std::string());
109  static asio::io_context& getExistingContext(const std::string& contextName = std::string());
110 
111  static void closeContext(const std::string& contextName = std::string());
119  static void setContextToLeakOnDelete(const std::string& contextName = std::string());
120  virtual ~AsioContextManager();
121 
123  const std::string& getName() const { return name; }
124 
126  asio::io_context& getBaseContext() const { return *ictx; }
127 
134  static LoopHandle runContextLoop(const std::string& contextName = std::string{});
135 
141  LoopHandle startContextLoop();
143  bool isRunning() const { return (running.load() != loop_mode::stopped); }
144 
145  private:
150  void haltContextLoop();
151 
152  friend void contextProcessingLoop(std::shared_ptr<AsioContextManager> ptr);
153 };
154 
155 void contextProcessingLoop(std::shared_ptr<AsioContextManager> ptr);
AsioContextManager::getContextPointer
static std::shared_ptr< AsioContextManager > getContextPointer(const std::string &contextName=std::string())
Definition: AsioContextManager.cpp:38
AsioContextManager::isRunning
bool isRunning() const
Definition: AsioContextManager.h:143
AsioContextManager::getContext
static asio::io_context & getContext(const std::string &contextName=std::string())
Definition: AsioContextManager.cpp:70
AsioContextManager::getName
const std::string & getName() const
Definition: AsioContextManager.h:123
AsioContextManager::getBaseContext
asio::io_context & getBaseContext() const
Definition: AsioContextManager.h:126
AsioContextManager
Definition: AsioContextManager.h:42
AsioContextManager::getExistingContext
static asio::io_context & getExistingContext(const std::string &contextName=std::string())
Definition: AsioContextManager.cpp:75
AsioContextManager::setContextToLeakOnDelete
static void setContextToLeakOnDelete(const std::string &contextName=std::string())
Definition: AsioContextManager.cpp:102
AsioContextManager::runContextLoop
static LoopHandle runContextLoop(const std::string &contextName=std::string{})
Definition: AsioContextManager.cpp:139
AsioContextManager::startContextLoop
LoopHandle startContextLoop()
Definition: AsioContextManager.cpp:151
AsioContextManager::getExistingContextPointer
static std::shared_ptr< AsioContextManager > getExistingContextPointer(const std::string &contextName=std::string())
Definition: AsioContextManager.cpp:57