ChimeraTK-DeviceAccess
03.18.00
|
The DomainsContainer has a container with Domains and is performing actions on all of them. More...
#include <DomainsContainer.h>
Classes | |
class | StopThread |
Public Member Functions | |
~DomainsContainer () | |
void | sendExceptions (const std::string &exceptionMessage) |
Request the sending of exceptions. More... | |
bool | isSendingExceptions () |
Check whether an exception distribution is started and not completed yet. More... | |
template<typename BackendType , typename BackendSpecificDataType , typename UserDataType > | |
boost::shared_ptr< AsyncNDRegisterAccessor< UserDataType > > | subscribe (boost::shared_ptr< BackendType > backend, size_t domainId, bool activate, RegisterPath name, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags) |
Get an accessor from a particular domain. More... | |
boost::shared_ptr< Domain > | getDomain (size_t key) |
Return the shared pointer to the Domain for a key. More... | |
void | forEach (const std::function< void(size_t, boost::shared_ptr< Domain > &)> &executeMe) |
Iterate all Domains under the container lock. More... | |
Protected Member Functions | |
void | distributeExceptions () |
Endless loop executed in the thread. More... | |
Protected Attributes | |
std::atomic_bool | _isSendingExceptions {false} |
cppext::future_queue< std::string > | _startExceptionDistribution {2} |
std::thread | _distributorThread |
std::mutex | _threadCreationMutex |
std::atomic_bool | _threadIsRunning {false} |
std::mutex | _domainsMutex |
std::map< size_t, boost::weak_ptr< Domain > > | _domains |
The DomainsContainer has a container with Domains and is performing actions on all of them.
The key type to identify the domain is of type size_t, which is the return type of std::hash, so you can easily use the hashes in case the backend uses a different key type.
Sending exceptions is implemented via a thread. sendExceptions() is pushing the exception message into a queue and returns immediately. A distributor thread is waiting for data in the queue and is sending the exceptions in all Domains.
The reason for having a thread is a possible lock order inversion. In the distribution tree, accessor creation must be mutually exclusibe with data distribution, hence locks cannot be avoided. As excaption can occur during data distribution. and backend::setException() is called, this would lead to recursive calls to the distribution tree, which might result in lock order inversions and deadlocks. To avoid this, setException will only put the exception message into the queue and return, allowing the failing distribution call to complete. The exception distribution will then be done by the thread in the DomainsContainer, after the mutex in the Domain is free again.
Definition at line 34 of file DomainsContainer.h.
ChimeraTK::async::DomainsContainer::~DomainsContainer | ( | ) |
Definition at line 41 of file DomainsContainer.cc.
|
protected |
Endless loop executed in the thread.
Definition at line 12 of file DomainsContainer.cc.
void ChimeraTK::async::DomainsContainer::forEach | ( | const std::function< void(size_t, boost::shared_ptr< Domain > &)> & | executeMe | ) |
Iterate all Domains under the container lock.
Each weak pointer is locked and the argument function is executed if the share_ptr is not nullptr.
The first parameter of the callback function is the domain key, the second a shared pointer to the domain itself.
Definition at line 91 of file DomainsContainer.cc.
boost::shared_ptr< Domain > ChimeraTK::async::DomainsContainer::getDomain | ( | size_t | key | ) |
Return the shared pointer to the Domain for a key.
The shared pointer might be nullptr if locking of the weak pointer failed.
Definition at line 82 of file DomainsContainer.cc.
|
inline |
Check whether an exception distribution is started and not completed yet.
Definition at line 45 of file DomainsContainer.h.
void ChimeraTK::async::DomainsContainer::sendExceptions | ( | const std::string & | exceptionMessage | ) |
Request the sending of exceptions.
This function stores the request and returns immediately. The actual exception distribution is done asynchronously and has not necessarily finished when the function call returns. Use isSendingExceptions() to check whether the exception distribution has finished.
Definition at line 65 of file DomainsContainer.cc.
boost::shared_ptr< AsyncNDRegisterAccessor< UserDataType > > ChimeraTK::async::DomainsContainer::subscribe | ( | boost::shared_ptr< BackendType > | backend, |
size_t | domainId, | ||
bool | activate, | ||
RegisterPath | name, | ||
size_t | numberOfWords, | ||
size_t | wordOffsetInRegister, | ||
AccessModeFlags | flags | ||
) |
Get an accessor from a particular domain.
At the moment the catalogue does not provide enough information to extract the domain ID from the register path. Hence the backend has to do it from its specific catalogue.
If the domain does not exist, it is created while holding the container lock.
The function is templated to three types. The first two parameters, backend type and a BackendSpecificDataType, are needed for the domain creation. The BackendSpecificDataType might vary for different Domains in the same backend. The UserDataType is the data type of the returned accessor.
The backend has to provide a function to get the initial value for that Domain.
This function is returning the initial value for the domain with the according domainID. If the version number can be determined from the initial value data, the version number is set here. Otherwise the version number must be VersionNumber{nullptr}. If the version number cannot be determined from the initial value do not create a new version number here!. This must happen inside the Domain under the Domain lock to avoid race conditions.
Parameters for the async Domain creation:
backend | Shared pointer to the exact backend type. As template functions cannot be virtual, we need a pointer of the type that implements getAsyncDomainInitialValue(). |
domainId | The domainId is the key for the container (map). |
activate | Flag whether to activate the async domain if it is created. |
Parameters for the actual accessor subscription:
name | The register path of the accessor |
numberOfWords | Entries in the accessor |
wordOffsetInRegister | Accessor starts at an offset |
flags | The access mode flags. They have to include wait_for_new_data. |
Definition at line 122 of file DomainsContainer.h.
|
protected |
Definition at line 109 of file DomainsContainer.h.
|
protected |
Definition at line 116 of file DomainsContainer.h.
|
protected |
Definition at line 115 of file DomainsContainer.h.
|
protected |
Definition at line 103 of file DomainsContainer.h.
|
protected |
Definition at line 108 of file DomainsContainer.h.
|
protected |
Definition at line 110 of file DomainsContainer.h.
|
protected |
Definition at line 111 of file DomainsContainer.h.