ChimeraTK-DeviceAccess  03.18.00
DomainsContainer.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2 // SPDX-License-Identifier: LGPL-3.0-or-later
3 
5 
6 #include "Exception.h"
7 
8 namespace ChimeraTK::async {
9 
10  /********************************************************************************************************************/
11 
13  std::string exceptionMessage;
14  while(true) {
15  // block to wait until setException has been called
16  try {
17  _startExceptionDistribution.pop_wait(exceptionMessage);
18  }
19  catch(StopThread&) {
20  return;
21  }
22 
23  auto ex = std::make_exception_ptr(ChimeraTK::runtime_error(exceptionMessage));
24 
25  {
26  std::lock_guard<std::mutex> containerLock(_domainsMutex);
27  for(auto& keyAndDomain : _domains) {
28  auto domain = keyAndDomain.second.lock();
29  if(domain) {
30  domain->sendException(ex);
31  }
32  }
33  } // lock scope
34 
35  _isSendingExceptions = false;
36  }
37  }
38 
39  /********************************************************************************************************************/
40 
42  try {
43  auto threadCreationLock = std::lock_guard(_threadCreationMutex);
44 
45  if(_distributorThread.joinable()) {
46  _startExceptionDistribution.push_overwrite_exception(std::make_exception_ptr(StopThread{}));
47  // Now we can join the thread.
48  _distributorThread.join();
49  }
50  }
51  catch(std::system_error& e) {
52  // Destructors must not throw. All exceptions that can occur here are system errors, which only show up if there
53  // is no hope anyway. All we can do is terminate.
54  std::cerr << "Unrecoverable system error in ~DomainsContainer(): " << e.what() << " !!! TERMINATING !!!"
55  << std::endl;
56  std::terminate();
57  }
58 
59  // Unblock a potentially waiting open call
60  _isSendingExceptions = false;
61  }
62 
63  /********************************************************************************************************************/
64 
65  void DomainsContainer::sendExceptions(const std::string& exceptionMessage) {
67  throw ChimeraTK::logic_error("DomainsContainer::sendExceptions() called before previous distribution was ready.");
68  }
69 
70  if(!_threadIsRunning) {
71  // No subscribers yet. Don't write anything into the queue.
72  return;
73  }
74 
75  _isSendingExceptions = true;
76 
77  _startExceptionDistribution.push(exceptionMessage);
78  }
79 
80  /********************************************************************************************************************/
81 
82  boost::shared_ptr<Domain> DomainsContainer::getDomain(size_t key) {
83  std::lock_guard<std::mutex> domainsLock(_domainsMutex);
84  // Creates the entry if it is not there. The returned shared pointer is empty in this case.
85  // (It might also be empty if the entry exists, but the async domain was deleted.)
86  return _domains[key].lock();
87  }
88 
89  /********************************************************************************************************************/
90 
91  void DomainsContainer::forEach(const std::function<void(size_t, boost::shared_ptr<Domain>&)>& executeMe) {
92  std::lock_guard<std::mutex> domainsLock(_domainsMutex);
93  for(auto& keyAndDomain : _domains) {
94  auto domain = keyAndDomain.second.lock();
95  if(domain) {
96  executeMe(keyAndDomain.first, domain);
97  }
98  }
99  }
100 
101 } // namespace ChimeraTK::async
ChimeraTK::async::DomainsContainer::_threadCreationMutex
std::mutex _threadCreationMutex
Definition: DomainsContainer.h:110
ChimeraTK::async::DomainsContainer::StopThread
Definition: DomainsContainer.h:113
ChimeraTK::async::DomainsContainer::sendExceptions
void sendExceptions(const std::string &exceptionMessage)
Request the sending of exceptions.
Definition: DomainsContainer.cc:65
DomainsContainer.h
ChimeraTK::async::DomainsContainer::_isSendingExceptions
std::atomic_bool _isSendingExceptions
Definition: DomainsContainer.h:103
ChimeraTK::async::DomainsContainer::forEach
void forEach(const std::function< void(size_t, boost::shared_ptr< Domain > &)> &executeMe)
Iterate all Domains under the container lock.
Definition: DomainsContainer.cc:91
ChimeraTK::async::DomainsContainer::_threadIsRunning
std::atomic_bool _threadIsRunning
Definition: DomainsContainer.h:111
ChimeraTK::async
Definition: design_AsyncNDRegisterAcessor_and_NumericAddressedBackend.dox:1
ChimeraTK::runtime_error
Exception thrown when a runtime error has occured.
Definition: Exception.h:18
ChimeraTK::async::DomainsContainer::getDomain
boost::shared_ptr< Domain > getDomain(size_t key)
Return the shared pointer to the Domain for a key.
Definition: DomainsContainer.cc:82
ChimeraTK::async::DomainsContainer::_domains
std::map< size_t, boost::weak_ptr< Domain > > _domains
Definition: DomainsContainer.h:116
ChimeraTK::async::DomainsContainer::distributeExceptions
void distributeExceptions()
Endless loop executed in the thread.
Definition: DomainsContainer.cc:12
ChimeraTK::async::DomainsContainer::_startExceptionDistribution
cppext::future_queue< std::string > _startExceptionDistribution
Definition: DomainsContainer.h:108
ChimeraTK::async::DomainsContainer::~DomainsContainer
~DomainsContainer()
Definition: DomainsContainer.cc:41
ChimeraTK::async::DomainsContainer::_domainsMutex
std::mutex _domainsMutex
Definition: DomainsContainer.h:115
Exception.h
ChimeraTK::async::DomainsContainer::_distributorThread
std::thread _distributorThread
Definition: DomainsContainer.h:109
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51