Adds further ext deps as-is binaries copies from customers env.
Qt6 Migration CI / migrate (push) Canceled after 0s
Qt6 Migration CI / migrate (push) Canceled after 0s
This commit is contained in:
3700 files changed
+2132394
No files matched your search
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <ostream>
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
struct ActorInfo;
|
||||
struct ActorConfiguration;
|
||||
|
||||
// serviceName must be simple (a-z...)
|
||||
void checkApiServiceName(const std::string& serviceName);
|
||||
void checkServiceNameIntern(const std::string& serviceName);
|
||||
|
||||
// M_Mount::IService
|
||||
std::string interfaceNameApi(bool isService, const std::string& module);
|
||||
|
||||
// M_Mount::Service
|
||||
std::string serviceClientNameApi(bool isService, const std::string& module);
|
||||
|
||||
std::ostream& operator<<(std::ostream& s, ActorConfiguration const& rhs);
|
||||
|
||||
struct ActorConfiguration {
|
||||
|
||||
ActorConfiguration(
|
||||
const std::string& module,
|
||||
bool isService,
|
||||
int domain,
|
||||
const std::string& serviceName);
|
||||
ActorConfiguration(const ddkit::actors::ActorInfo& actorInfo);
|
||||
ActorConfiguration() = default;
|
||||
|
||||
operator std::string() const {
|
||||
if (serviceName.empty()) {
|
||||
return std::string() + "(" + serviceClientNameApi(isService, module) + ", " + std::to_string(domain) + ", <no-servicename>)";
|
||||
}
|
||||
return std::string() + "(" + serviceClientNameApi(isService, module) + ", " + std::to_string(domain) + ", \"" + serviceName + "\")";
|
||||
}
|
||||
|
||||
bool operator==(ActorConfiguration const& rhs) const;
|
||||
bool operator<(ActorConfiguration const& rhs) const;
|
||||
|
||||
std::string module;
|
||||
bool isService;
|
||||
int domain;
|
||||
std::string serviceName;
|
||||
};
|
||||
|
||||
|
||||
/// @brief this is "ServiceInfo" / "ClientInfo" really. Do not mistake this for ddkit_intern::ActorInfo (idl-generated class)
|
||||
/// for monitoring applications like Listener
|
||||
/// - do not use in other cases.
|
||||
struct ActorInfo {
|
||||
|
||||
ActorInfo() = default;
|
||||
|
||||
ActorConfiguration config;
|
||||
|
||||
// also part of config (needed to disambiguate clients (multiple of same config allowed in network), also useful for error-detection of services)
|
||||
std::string actorId;
|
||||
|
||||
int32_t processId;
|
||||
std::string hostName;
|
||||
std::string procName;
|
||||
|
||||
bool isReading;
|
||||
std::vector<std::string> openReaders;
|
||||
bool isWriting;
|
||||
std::vector<std::string> openWriters;
|
||||
|
||||
// todo: maybe implement more informations here about the inherited interfaces? See section 7,
|
||||
// possible Inspector-improvements
|
||||
// maybe something like 'std::map<std::string, std::vector<std::string>> m_module2openReadersModule' would be
|
||||
// fine here, but probably it's only a matter of display. Inspector can show everything without changes here.
|
||||
|
||||
std::string clientName; // client-display-Name, on service: filled with "undefined"
|
||||
// on client: actorId or setName/create/add-given user-value
|
||||
|
||||
// bool isMonitor - no, not needed, the monitoring-actorInfos are not sent to the dds ... so true never shows up
|
||||
|
||||
// debug
|
||||
friend std::ostream& operator<<(std::ostream& s, ActorInfo const& rhs);
|
||||
operator std::string() const;
|
||||
|
||||
// set-order
|
||||
bool operator<(ActorInfo const& rhs) const;
|
||||
|
||||
// default copying
|
||||
};
|
||||
|
||||
typedef ActorInfo ServiceInfo;
|
||||
typedef ActorInfo ClientInfo;
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/base/ThreadSync.hpp"
|
||||
#include "ddkit/access/TopicPoolWrite.hpp"
|
||||
#include "ddkit/access/TopicPoolRead.hpp"
|
||||
#include "ddkit/idls/ActorInfo.hpp"
|
||||
#include "ddkit/actors/ActorInfo.hpp"
|
||||
#include "ddkit/actors/ILocalServices.hpp"
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
/// @brief DDS-Database for all ddkit_intern::ActorInfo on the network.
|
||||
/// The data is added/removed by the ActorInfoDbCaretaker.
|
||||
class ActorInfoDb {
|
||||
|
||||
public:
|
||||
ActorInfoDb(ILocalServices& localServices);
|
||||
~ActorInfoDb();
|
||||
|
||||
void updateActorInfo(ddkit_intern::ActorInfo actorInfo, int domainId);
|
||||
void removeActorInfo(ddkit_intern::ActorInfo actorInfo, int domainId);
|
||||
|
||||
// for "find()"
|
||||
std::vector<ActorInfo> findActorInfo(const std::string& module, bool isService, int domain);
|
||||
std::vector<ActorInfo> findActorInfo(
|
||||
const std::string& module, bool isService, int domain, const std::string& serviceName);
|
||||
std::vector<ActorInfo> findActorInfo(ActorConfiguration config);
|
||||
std::vector<ActorInfo> findActorInfo(const std::string& actorId);
|
||||
|
||||
// for "isRunning()"
|
||||
bool hasService(const std::string& module, int domain, const std::string& serviceName);
|
||||
|
||||
// for "wait()"
|
||||
void waitForService(const std::string& module, int domain, const std::string& serviceName);
|
||||
|
||||
// access meta-infos for callbackInfo
|
||||
std::string clientActorId2clientName(const std::string& clientActorId);
|
||||
|
||||
private:
|
||||
std::recursive_mutex m_mutex;
|
||||
std::condition_variable_any m_dbChanged;
|
||||
ILocalServices& m_localServices;
|
||||
|
||||
std::vector<ddkit_intern::ActorInfo> m_actorInfos;
|
||||
std::map<std::string, std::string> m_discardedActorIdToClientName;
|
||||
|
||||
// no copying
|
||||
ActorInfoDb(ActorInfoDb const&) = delete;
|
||||
ActorInfoDb(ActorInfoDb&&) = delete;
|
||||
void operator=(ActorInfoDb const&) = delete;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/base/ThreadSync.hpp"
|
||||
#include "ddkit/access/TopicPoolWrite.hpp"
|
||||
#include "ddkit/access/TopicPoolRead.hpp"
|
||||
#include "ddkit/idls/ActorInfo.hpp"
|
||||
#include "ddkit/actors/ActorInfo.hpp"
|
||||
#include "ddkit/actors/ActorInfoDb.hpp"
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
ActorConfiguration actorInfoToActorConfiguration(ddkit_intern::ActorInfo actorInfo);
|
||||
ActorInfo actorInfoToActorInfo(const ddkit_intern::ActorInfo& ddsActorInfo);
|
||||
|
||||
/// @brief Caretaker for actorInfo.
|
||||
/// Registers for ActorInfo-msgs on dds and stores them in ActorInfoDb.
|
||||
class ActorInfoDbCaretaker {
|
||||
|
||||
public:
|
||||
ActorInfoDbCaretaker(ActorInfoDb& db);
|
||||
~ActorInfoDbCaretaker();
|
||||
|
||||
void init(access::Participant& participant, std::shared_ptr<access::Dispatcher> dispatcher);
|
||||
void close();
|
||||
|
||||
void onWrite_actorInfo(const ddkit_intern::ActorInfo& actorInfo);
|
||||
void onDispose_actorInfo(const ddkit_intern::ActorInfo& actorInfo);
|
||||
|
||||
private:
|
||||
ActorInfoDb& m_db;
|
||||
|
||||
access::IQosStrategyPtr m_qosStrategy;
|
||||
access::ITopicStrategyPtr m_topicStrategy;
|
||||
|
||||
std::unique_ptr<access::TopicPoolRead> m_topicPoolRead;
|
||||
|
||||
int m_domainId;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/base/ThreadSync.hpp"
|
||||
#include "ddkit/access/TopicPoolWrite.hpp"
|
||||
#include "ddkit/access/TopicPoolRead.hpp"
|
||||
#include "ddkit/idls/ActorInfo.hpp"
|
||||
#include "ddkit/actors/ActorInfo.hpp"
|
||||
#include "ddkit/actors/ActorInfoDb.hpp"
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
/// @brief Encapsulation of a dds-writer for ActorInfo-messages (per domain) / SessionImpl uses.
|
||||
class ActorInfoWriter {
|
||||
|
||||
public:
|
||||
explicit ActorInfoWriter(access::Participant& participant);
|
||||
void write(const ddkit_intern::ActorInfo& actorInfo);
|
||||
void dispose(const ddkit_intern::ActorInfo& actorInfo);
|
||||
|
||||
private:
|
||||
int m_domain;
|
||||
access::IQosStrategyPtr m_qosStrategy;
|
||||
access::ITopicStrategyPtr m_topicStrategy;
|
||||
access::TopicPoolWrite m_topicPoolWrite;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,382 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/utils/assert.hpp"
|
||||
#include "ddkit/actors/Key.hpp"
|
||||
#include "ddkit/actors/SessionManager.hpp"
|
||||
#include "ddkit/actors/SessionImpl.hpp"
|
||||
#include "ddkit/actors/SimpleActor.hpp"
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
/// @brief The calls (add/create/remove/remove/shutdown/shutdown) from the generated code are delegated here.
|
||||
/// We try to create/remove Actors as much as "normal" as it would be done via Session/Service/Client
|
||||
/// but of course there are some differences, as two calls may create only one Actor etc.
|
||||
/// Keep one SimpleActorPtr as replacement for the not-existing Service/Client-proxys in own list.
|
||||
class BackwardManager {
|
||||
|
||||
public:
|
||||
static BackwardManager& instance();
|
||||
|
||||
/// @brief called from generated code: ObsFactory::add()
|
||||
template <typename Observer>
|
||||
void createObserver(
|
||||
const std::string& serviceName,
|
||||
int domain,
|
||||
bool isService,
|
||||
const std::string& moduleName,
|
||||
typename Observer::TypeUser* callbacks,
|
||||
const std::vector<std::string>& methods,
|
||||
const std::string& clientName = "") {
|
||||
|
||||
DDKIT_LOG_TRACE;
|
||||
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
ddkit::log::warn() << "add(): You are using the deprecated C-Style API. "
|
||||
<< "It is recommended to upgrade to the new object-oriented API. "
|
||||
<< " Please note that it may be removed in future versions.";
|
||||
|
||||
ddkit::log::debug() << "create observer by key api: " << serviceName << ", " << std::to_string(domain);
|
||||
|
||||
checkApiServiceName(serviceName);
|
||||
|
||||
checkObserverType<Observer>();
|
||||
|
||||
ActorConfiguration config(moduleName, isService, domain, serviceName);
|
||||
SimpleActorPtr actor = createOrGetActor(serviceName, domain, isService, moduleName);
|
||||
|
||||
DDKIT_THROW_ON_FALSE_INFO(actor, "Failed to create actor");
|
||||
|
||||
IObserverPtr observer = actor->createObserver<Observer>(*callbacks, methods);
|
||||
|
||||
// if empty there is no need to send data over the wire
|
||||
if (!clientName.empty() && !isService) {
|
||||
actor->setClientName(clientName);
|
||||
}
|
||||
|
||||
// global maps
|
||||
m_observer2actorConfig.insert(std::make_pair(observer, config));
|
||||
typeUser2observerMap<Observer>().insert(std::make_pair(callbacks, observer));
|
||||
}
|
||||
|
||||
/// @brief called from generated code: Factory::create()
|
||||
template <typename Sender>
|
||||
typename Sender::TypeUser* createSender(
|
||||
const std::string& serviceName,
|
||||
int domain,
|
||||
bool isService,
|
||||
const std::string& moduleName,
|
||||
const std::vector<std::string>& methods,
|
||||
const std::string& clientName = "") {
|
||||
|
||||
DDKIT_LOG_TRACE;
|
||||
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
ddkit::log::warn() << "create(): You are using the deprecated C-Style API. "
|
||||
<< "It is recommended to upgrade to the new object-oriented API. "
|
||||
<< "Please note that it may be removed in future versions.";
|
||||
|
||||
ddkit::log::debug() << "create sender by key api: " << moduleName;
|
||||
|
||||
checkApiServiceName(serviceName);
|
||||
|
||||
checkSenderType<Sender>();
|
||||
|
||||
ActorConfiguration config(moduleName, isService, domain, serviceName);
|
||||
SimpleActorPtr actor = createOrGetActor(serviceName, domain, isService, moduleName);
|
||||
|
||||
DDKIT_THROW_ON_FALSE_INFO(actor, "Failed to create actor");
|
||||
|
||||
ISenderPtr isender = actor->createSender<Sender>(methods);
|
||||
|
||||
DDKIT_THROW_ON_FALSE_INFO(isender, "BackwardManager::createSender: could not create sender");
|
||||
|
||||
// if empty there is no need to send data over the wire
|
||||
if (!clientName.empty()) {
|
||||
actor->setClientName(clientName);
|
||||
}
|
||||
|
||||
// return raw-ptr for old C-API
|
||||
Sender* sender = dynamic_cast<Sender*>(isender.get()); // downcast - Sender inherits ISender
|
||||
DDKIT_THROW_ON_FALSE(sender);
|
||||
typename Sender::TypeUser* senderUser = sender; // upcast - Sender inherits IService/IClient
|
||||
|
||||
// global maps
|
||||
std::unique_lock<std::recursive_mutex> lockMaps(m_mutex);
|
||||
m_sender2actorConfig.insert(std::make_pair(isender, config));
|
||||
|
||||
typeUser2senderMap<Sender>().insert(std::make_pair(senderUser, isender));
|
||||
|
||||
return senderUser;
|
||||
}
|
||||
|
||||
/// @brief called from generated code: ObsFactory::remove()
|
||||
template <typename Observer>
|
||||
void removeObserverByObserverUser(
|
||||
typename Observer::TypeUser* observerUser, bool isService, const std::string& moduleName) {
|
||||
|
||||
DDKIT_LOG_TRACE;
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
ddkit::log::warn() << "remove(): You are using the deprecated C-Style API. "
|
||||
<< "It is recommended to upgrade to the new object-oriented API. "
|
||||
<< "Please note that it may be removed in future versions.";
|
||||
|
||||
ddkit::log::debug() << "Remove Observer By Observer User: " << moduleName;
|
||||
|
||||
{
|
||||
checkObserverType<Observer>();
|
||||
|
||||
DDKIT_THROW_ON_FALSE_INFO(observerUser, interfaceNameApi(isService, moduleName) + "ObsFactory::remove()"
|
||||
+ " called with Observer* == nullptr ?");
|
||||
|
||||
// global maps
|
||||
DDKIT_THROW_ON_FALSE_INFO(typeUser2observerMap<Observer>().find(observerUser) != typeUser2observerMap<Observer>().end(),
|
||||
interfaceNameApi(isService, moduleName) + "ObsFactory::remove()"
|
||||
+ " called with Observer* not given to " + interfaceNameApi(isService, moduleName)
|
||||
+ "ObsFactory::add*() before? (or removed twice?)");
|
||||
|
||||
IObserverPtr observer = typeUser2observerMap<Observer>().at(observerUser);
|
||||
DDKIT_THROW_ON_FALSE_INFO(observer, "removeObserverByObserverUser: observer not found");
|
||||
|
||||
ActorConfiguration config = m_observer2actorConfig.at(observer);
|
||||
ddkit::log::debug() << "called Obs...remove() on " << config;
|
||||
|
||||
DDKIT_THROW_ON_FALSE(config.isService == isService);
|
||||
DDKIT_THROW_ON_FALSE(config.module == moduleName);
|
||||
|
||||
// global maps
|
||||
m_observer2actorConfig.erase(observer);
|
||||
typeUser2observerMap<Observer>().erase(typeUser2observerMap<Observer>().find(observerUser));
|
||||
|
||||
SessionImplPtr sessionImpl = findSession(config.domain);
|
||||
if (sessionImpl) {
|
||||
SimpleActorPtr actor = sessionImpl->findActor(config.serviceName, config.isService, config.module);
|
||||
if (actor) {
|
||||
if (actor->hasSender()) {
|
||||
ddkit::log::warn() << "The actor still has a sender, the observer will be deleted after sender is also destoryed!"
|
||||
<< " Consider using the OO-Api.";
|
||||
} else {
|
||||
auto it = m_config2actor.find(config);
|
||||
if (it != m_config2actor.end()) {
|
||||
if (m_config2actor.at(config) == actor) {
|
||||
m_config2actor.erase(it);
|
||||
|
||||
actor->shutdown();
|
||||
|
||||
// wait until dispatcher etc are done.
|
||||
while (actor.use_count() > 1) {
|
||||
ddkit::utils::system::msSleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sessionImpl.reset(); // local hold ptr
|
||||
removeSessionIfEmpty(config.domain);
|
||||
}
|
||||
}
|
||||
checkIfEmpty();
|
||||
}
|
||||
|
||||
/// @brief called from generated code: Factory::remove()
|
||||
template <typename Sender>
|
||||
void removeSenderBySenderUser(typename Sender::TypeUser* senderUser, bool isService, const std::string& moduleName) {
|
||||
DDKIT_LOG_TRACE;
|
||||
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
ddkit::log::warn() << "remove(): You are using the deprecated C-Style API. "
|
||||
<< "It is recommended to upgrade to the new object-oriented API. "
|
||||
<< "Please note that it may be removed in future versions.";
|
||||
|
||||
ddkit::log::debug() << "RemoveSender By Sender User: " << moduleName;
|
||||
|
||||
{
|
||||
checkSenderType<Sender>();
|
||||
|
||||
DDKIT_THROW_ON_FALSE_INFO(senderUser, interfaceNameApi(isService, moduleName) + "Factory::remove()"
|
||||
+ " called with Sender* == nullptr ?");
|
||||
// global maps
|
||||
DDKIT_THROW_ON_FALSE_INFO(typeUser2senderMap<Sender>().find(senderUser) != typeUser2senderMap<Sender>().end(),
|
||||
interfaceNameApi(isService, moduleName) + "Factory::remove()"
|
||||
+ " called with Sender* not received from " + interfaceNameApi(isService, moduleName)
|
||||
+ "Factory::create() before? (or removed twice?)");
|
||||
|
||||
ISenderPtr sender = typeUser2senderMap<Sender>().at(senderUser);
|
||||
DDKIT_THROW_ON_FALSE_INFO(sender, "Sender not found");
|
||||
|
||||
ActorConfiguration config = m_sender2actorConfig.at(sender);
|
||||
ddkit::log::debug() << "called ...remove() on " << config;
|
||||
DDKIT_THROW_ON_FALSE(config.isService == isService);
|
||||
DDKIT_THROW_ON_FALSE(config.module == moduleName);
|
||||
|
||||
// remove sender from global maps
|
||||
m_sender2actorConfig.erase(sender);
|
||||
typeUser2senderMap<Sender>().erase(typeUser2senderMap<Sender>().find(senderUser));
|
||||
|
||||
SessionImplPtr sessionImpl = findSession(config.domain);
|
||||
if (sessionImpl) {
|
||||
SimpleActorPtr actor = sessionImpl->findActor(config.serviceName, config.isService, config.module);
|
||||
if (actor) {
|
||||
actor->discardSender();
|
||||
if (actor->hasObserver()) {
|
||||
// still has a observer dont shutdown actor!
|
||||
ddkit::log::warn() << "There is still a observer, make sure to delete it too."
|
||||
<< " Consider using the new OO-Api.";
|
||||
} else {
|
||||
ddkit::log::debug() << "Does not have a observer, we can shutdown the actor.";
|
||||
auto configIt = m_config2actor.find(config);
|
||||
if (configIt != m_config2actor.end()) {
|
||||
if (m_config2actor.at(config) == actor) {
|
||||
m_config2actor.erase(configIt);
|
||||
|
||||
actor->shutdown();
|
||||
|
||||
// wait until dispatcher etc are done.
|
||||
while (actor.use_count() > 1) {
|
||||
ddkit::utils::system::msSleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sessionImpl.reset(); // local hold session-ptr
|
||||
removeSessionIfEmpty(config.domain);
|
||||
}
|
||||
}
|
||||
checkIfEmpty();
|
||||
}
|
||||
|
||||
/// @brief called from generated code: ObsFactory::shutdown()
|
||||
template <typename Observer>
|
||||
void shutdownObservers(bool isService, const std::string& moduleName) {
|
||||
DDKIT_LOG_TRACE;
|
||||
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
ddkit::log::warn() << "shutdown(): You are using the deprecated C-Style API. "
|
||||
<< "It is recommended to upgrade to the new object-oriented API. "
|
||||
<< "Please note that it may be removed in future versions.";
|
||||
|
||||
ddkit::log::debug() << "shutdown observers: " << moduleName;
|
||||
|
||||
checkObserverType<Observer>();
|
||||
typedef typename Observer::TypeUser TypeUser;
|
||||
|
||||
std::vector<TypeUser*> observerUsers;
|
||||
for (auto& p : typeUser2observerMap<Observer>()) {
|
||||
observerUsers.push_back(p.first);
|
||||
}
|
||||
for (TypeUser* typeUser : observerUsers) {
|
||||
removeObserverByObserverUser<Observer>(typeUser, isService, moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief called from generated code: Factory::shutdown()
|
||||
template <typename Sender>
|
||||
void shutdownSenders(bool isService, const std::string& moduleName) {
|
||||
DDKIT_LOG_TRACE;
|
||||
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
ddkit::log::warn() << "shutdown(): You are using the deprecated C-Style API. "
|
||||
<< "It is recommended to upgrade to the new object-oriented API. "
|
||||
<< "Please note that it may be removed in future versions.";
|
||||
|
||||
ddkit::log::debug() << "Shutdown senders: " << moduleName;
|
||||
|
||||
checkSenderType<Sender>();
|
||||
typedef typename Sender::TypeUser TypeUser;
|
||||
|
||||
std::vector<TypeUser*> senderUsers;
|
||||
for (auto& p : typeUser2senderMap<Sender>()) {
|
||||
senderUsers.push_back(p.first);
|
||||
}
|
||||
for (TypeUser* typeUser : senderUsers) {
|
||||
removeSenderBySenderUser<Sender>(typeUser, isService, moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief called from generated code: ObsFactory::getSource()
|
||||
template <typename Observer>
|
||||
std::string getSource(bool isService, const std::string& moduleName) {
|
||||
|
||||
DDKIT_LOG_TRACE;
|
||||
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
ddkit::log::warn() << "getSource(): You are using the deprecated C-Style API. "
|
||||
<< "It is recommended to upgrade to the new object-oriented API. "
|
||||
<< "Please note that it may be removed in future versions. "
|
||||
<< "Use ddkit::actors::CallbackInfo::current(); instead.";
|
||||
|
||||
CallbackInfo callbackInfo = SessionManager::instance().callbackInfo();
|
||||
|
||||
bool isToServiceReal = callbackInfo.isFromClient;
|
||||
|
||||
if (isService != isToServiceReal) {
|
||||
ddkit::log::warn() << "getSource() was called on ObsFactory of " << interfaceNameApi(isService, moduleName)
|
||||
<< " but callback right now is sending data to "
|
||||
<< serviceClientNameApi(isToServiceReal, moduleName) << ". Probably one should use \""
|
||||
<< interfaceNameApi(isToServiceReal, moduleName) << "ObsFactory\" instead of \""
|
||||
<< interfaceNameApi(isService, moduleName) << "ObsFactory\", to remove this warning.";
|
||||
}
|
||||
|
||||
// as "source" we gave back the serviceName or the clientId, depending on the side
|
||||
if (callbackInfo.isFromClient) {
|
||||
// client called service
|
||||
return callbackInfo.clientName; // this is sendingActor (=clientActorId) or user-given clientName
|
||||
} else {
|
||||
// service called client
|
||||
return callbackInfo.serviceName;
|
||||
}
|
||||
}
|
||||
|
||||
SessionImplPtr createOrGetSession_(int domain);
|
||||
|
||||
bool isClean() const;
|
||||
|
||||
private:
|
||||
std::recursive_mutex m_mutex;
|
||||
std::map<int, SessionImplPtr> m_domain2session;
|
||||
std::map<ActorConfiguration, SimpleActorPtr> m_config2actor; // holding Actors exactly as long, as add/create/remove tells
|
||||
|
||||
// Pointers to actors-configs
|
||||
std::map<IObserverPtr, ActorConfiguration> m_observer2actorConfig;
|
||||
std::map<ISenderPtr, ActorConfiguration> m_sender2actorConfig;
|
||||
|
||||
BackwardManager();
|
||||
~BackwardManager();
|
||||
|
||||
SimpleActorPtr createOrGetActor(const std::string& serviceName, int domain, bool isService, const std::string& moduleName);
|
||||
SessionImplPtr findSession(int domain);
|
||||
SessionImplPtr createOrGetSession(int domain);
|
||||
void removeSessionIfEmpty(int domain);
|
||||
void checkIfEmpty();
|
||||
|
||||
// these functions are used to circumvent the fact das data members cant be templated
|
||||
// which is only somewhat fine since BackwardManger is a singleton class
|
||||
template <typename Sender> std::map<typename Sender::TypeUser*, ISenderPtr>& typeUser2senderMap() {
|
||||
static std::map<typename Sender::TypeUser*, ISenderPtr> s_typeUser2sender;
|
||||
return s_typeUser2sender;
|
||||
}
|
||||
|
||||
template <typename Observer> std::map<typename Observer::TypeUser*, IObserverPtr>& typeUser2observerMap() {
|
||||
static std::map<typename Observer::TypeUser*, IObserverPtr> s_typeUser2observer;
|
||||
return s_typeUser2observer;
|
||||
}
|
||||
|
||||
// no copying
|
||||
BackwardManager(BackwardManager const&) = delete;
|
||||
BackwardManager(BackwardManager&&) = delete;
|
||||
void operator=(BackwardManager const&) = delete;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <memory>
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class IActor;
|
||||
typedef std::shared_ptr<IActor> ActorPtr;
|
||||
|
||||
struct CallbackInfo {
|
||||
std::string serviceName; // serviceName of sending actor (client or service), this is always a real name
|
||||
std::string sendingActor; // clientActorId or serviceActorId
|
||||
std::string operationName; // rmodel-operationName, for example "ConfigAbc"
|
||||
|
||||
bool isFromClient;
|
||||
bool isFromService;
|
||||
bool isToClient;
|
||||
bool isToService;
|
||||
|
||||
std::string clientName; // filled, if isFromClient, clientActorId, if user set clientName, clientName
|
||||
|
||||
int64_t timestampInMsSinceEpoch;
|
||||
|
||||
/// @brief Get informations about the current callback
|
||||
/// This function should only be used inside a callback.
|
||||
/// @return The current CallbackInfo object.
|
||||
static CallbackInfo current();
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, CallbackInfo const& rhs);
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "SessionImpl.hpp"
|
||||
#include "ddkit/utils/container.hpp"
|
||||
|
||||
#include "ddkit/actors/SessionImpl.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class IActor;
|
||||
typedef std::shared_ptr<IActor> ActorPtr;
|
||||
|
||||
class SessionImpl;
|
||||
typedef std::shared_ptr<SessionImpl> SessionImplPtr;
|
||||
typedef std::weak_ptr<SessionImpl> SessionImplWeakPtr;
|
||||
|
||||
class IActor : public std::enable_shared_from_this<IActor> {
|
||||
public:
|
||||
virtual ~IActor();
|
||||
SessionImplPtr sessionImpl();
|
||||
|
||||
bool isMonitor();
|
||||
|
||||
virtual void shutdown() = 0;
|
||||
virtual bool isValid() = 0;
|
||||
|
||||
protected:
|
||||
IActor(const SessionImplPtr& sessionImpl);
|
||||
|
||||
IActor() = delete;
|
||||
IActor(IActor&) = delete;
|
||||
IActor(IActor&&) = delete;
|
||||
|
||||
// todo nth: for which members exactly the syncing is needed? for now: try for all
|
||||
std::recursive_mutex m_mutex;
|
||||
std::condition_variable_any m_condition;
|
||||
|
||||
SessionImplWeakPtr m_sessionImplWeak;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/actors/ActorInfo.hpp"
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
/// @brief an ActorInfoDb must know about those services, which are 'important',
|
||||
/// - that is: services local to the session, in/for which the actorInfoDb works.
|
||||
/// - if some service is recognized twice in the network (normally a warning), and the local session is accountable
|
||||
/// for it, the local process must die
|
||||
/// so a session creating an ActorInfoDb must provide a function for up-to-date-knowledge about the local services
|
||||
class ILocalServices {
|
||||
|
||||
public:
|
||||
virtual bool isLocalService(ActorConfiguration config) = 0;
|
||||
virtual ~ILocalServices() = default;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/utils/Logger.hpp"
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
//
|
||||
// IComponent, IObserver, ISender
|
||||
//
|
||||
|
||||
// IObserver or ISender
|
||||
class IComponent {
|
||||
|
||||
public:
|
||||
virtual std::string module() = 0;
|
||||
virtual bool isService() = 0; // caution: these method-names refer to Service and Client (Actor),
|
||||
virtual bool isObserver() = 0; // in which the Sender/Observer live, not to IService/IClient!
|
||||
|
||||
// exceptionally we have (very lightweight) convenience-methods in the interface as well
|
||||
inline bool isClient() { return !isService(); }
|
||||
inline bool isSender() { return !isObserver(); }
|
||||
|
||||
virtual ~IComponent() = default;
|
||||
};
|
||||
|
||||
class IObserver : public IComponent {
|
||||
|
||||
public:
|
||||
// IComponent
|
||||
std::string module() override = 0;
|
||||
bool isService() override = 0;
|
||||
bool isObserver() override { return true; }
|
||||
|
||||
virtual void clearCallbacks() {}
|
||||
|
||||
virtual ~IObserver() = default;
|
||||
};
|
||||
typedef std::shared_ptr<IObserver> IObserverPtr;
|
||||
|
||||
class ISender : public IComponent {
|
||||
|
||||
public:
|
||||
// IComponent
|
||||
std::string module() override = 0;
|
||||
bool isService() override = 0;
|
||||
bool isObserver() override { return false; }
|
||||
|
||||
virtual ~ISender() = default;
|
||||
};
|
||||
typedef std::shared_ptr<ISender> ISenderPtr;
|
||||
|
||||
|
||||
//
|
||||
// static_asserts to be included in every template-function
|
||||
//
|
||||
// observer w/o object - call checkTypeOfObserver<Observer>();
|
||||
template <typename Observer>
|
||||
void checkObserverType() {
|
||||
DDKIT_LOG_TRACE;
|
||||
static_assert(std::is_base_of<IObserver, Observer>::value, "Observer not derived from IObserver");
|
||||
static_assert(!std::is_same<IObserver, Observer>::value, "Observer same class as IObserver");
|
||||
}
|
||||
|
||||
// observer with object - simply call checkTypeOfObserver(observer);
|
||||
template <typename Observer>
|
||||
void checkTypeOfObserver(Observer* observer) {
|
||||
DDKIT_LOG_TRACE << DDKIT_LOG_VAR_VALUE(observer);
|
||||
checkObserverType<Observer>();
|
||||
}
|
||||
|
||||
// sender w/o object - call checkSenderType<Sender>();
|
||||
template <typename Sender>
|
||||
void checkSenderType() {
|
||||
DDKIT_LOG_TRACE;
|
||||
static_assert(std::is_base_of<ISender, Sender>::value, "Sender not derived from ISender");
|
||||
static_assert(!std::is_same<ISender, Sender>::value, "Sender same class as ISender");
|
||||
static_assert(std::is_base_of<typename Sender::TypeUser, Sender>::value, "Sender not derived from TypeUser");
|
||||
}
|
||||
|
||||
// sender with object - simply call checkTypeOfSender(sender);
|
||||
template <typename Sender>
|
||||
void checkTypeOfSender(Sender* sender) {
|
||||
DDKIT_LOG_TRACE << DDKIT_LOG_VAR_VALUE(sender);
|
||||
checkSenderType<Sender>();
|
||||
}
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/actors/ActorInfo.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class SessionImpl;
|
||||
typedef std::shared_ptr<SessionImpl> SessionImplPtr;
|
||||
|
||||
class MonitorSession final {
|
||||
|
||||
public:
|
||||
MonitorSession(int domain);
|
||||
~MonitorSession();
|
||||
|
||||
std::vector<ServiceInfo> findServices(const std::string& module);
|
||||
std::vector<ClientInfo> findClients(const std::string& module);
|
||||
std::vector<ClientInfo> findClients(const std::string& serviceName, const std::string& module);
|
||||
|
||||
private:
|
||||
friend class SessionImpl;
|
||||
SessionImplPtr m_sessionImpl;
|
||||
|
||||
SessionImpl& sessionImpl();
|
||||
|
||||
// no copying
|
||||
MonitorSession(MonitorSession const&) = delete;
|
||||
MonitorSession(MonitorSession&&) = delete;
|
||||
void operator=(MonitorSession const&) = delete;
|
||||
void operator=(MonitorSession&&) = delete;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "SessionImpl.hpp"
|
||||
#include "ddkit/actors/IActor.hpp"
|
||||
#include "ddkit/actors/MultiplexActorThread.hpp"
|
||||
#include "ddkit/actors/SimpleActor.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class MultiplexActor : public IActor {
|
||||
|
||||
public:
|
||||
MultiplexActor(
|
||||
const SessionImplPtr& sessionImpl,
|
||||
bool isService,
|
||||
const std::string& module,
|
||||
const std::function<SimpleActorPtr(SessionImplPtr, const std::string&)>& createActor);
|
||||
~MultiplexActor();
|
||||
|
||||
bool isValid() override;
|
||||
void shutdown() override;
|
||||
|
||||
private:
|
||||
std::vector<SimpleActorPtr> m_actors;
|
||||
std::shared_ptr<MultiplexActorThread> m_threadActorMultiplex;
|
||||
|
||||
};
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/actors/SessionImpl.hpp"
|
||||
#include "ddkit/base/Thread.hpp"
|
||||
|
||||
#include "ddkit/actors/ActorInfo.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class SessionImpl;
|
||||
typedef std::shared_ptr<SessionImpl> SessionImplPtr;
|
||||
typedef std::weak_ptr<SessionImpl> SessionImplWeakPtr;
|
||||
|
||||
class SimpleActor;
|
||||
typedef std::shared_ptr<SimpleActor> SimpleActorPtr;
|
||||
|
||||
class MultiplexActorThread : public base::Thread {
|
||||
|
||||
public:
|
||||
MultiplexActorThread(
|
||||
std::vector<SimpleActorPtr>& actors,
|
||||
const SessionImplPtr& sessionImpl,
|
||||
const std::function<SimpleActorPtr(SessionImplPtr, const std::string&)>& createActor,
|
||||
const std::string& module,
|
||||
bool isService);
|
||||
~MultiplexActorThread();
|
||||
|
||||
// Thread
|
||||
void run() override;
|
||||
void shutdown();
|
||||
|
||||
private:
|
||||
void addNewActors(std::vector<ActorInfo> const& actorsCurrent, SessionImplPtr sessionImpl);
|
||||
void removeOldActors(std::vector<ActorInfo> const& actorsCurrent);
|
||||
|
||||
SessionImplWeakPtr m_sessionImpl;
|
||||
std::function<SimpleActorPtr(SessionImplPtr, const std::string&)> m_createActor;
|
||||
std::vector<SimpleActorPtr>& m_actors;
|
||||
std::string m_module;
|
||||
bool m_isService;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/actors/ActorInfo.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class SessionImpl;
|
||||
typedef std::shared_ptr<SessionImpl> SessionImplPtr;
|
||||
|
||||
/// @brief Typically there should be only one Session per domain.
|
||||
class Session final {
|
||||
|
||||
public:
|
||||
Session(int domain);
|
||||
~Session();
|
||||
|
||||
std::string sessionId();
|
||||
|
||||
std::vector<ServiceInfo> findServices(const std::string& module);
|
||||
std::vector<ClientInfo> findClients(const std::string& module);
|
||||
std::vector<ClientInfo> findClients(const std::string& serviceName, const std::string& module);
|
||||
|
||||
private:
|
||||
friend class SessionImpl;
|
||||
SessionImplPtr m_sessionImpl;
|
||||
|
||||
SessionImpl& sessionImpl();
|
||||
|
||||
Session() = delete;
|
||||
// no copying
|
||||
Session(Session const&) = delete;
|
||||
Session(Session&&) = delete;
|
||||
void operator=(Session const&) = delete;
|
||||
void operator=(Session&&) = delete;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/actors/Session.hpp"
|
||||
#include "ddkit/actors/MonitorSession.hpp"
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class SessionFactory {
|
||||
|
||||
public:
|
||||
/// @brief static
|
||||
static SessionFactory& instance() {
|
||||
static SessionFactory instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::shared_ptr<ddkit::actors::Session> getSession(int domain);
|
||||
std::shared_ptr<ddkit::actors::MonitorSession> getMonitorSession(int domain);
|
||||
|
||||
bool isClean() const;
|
||||
private:
|
||||
template <typename T>
|
||||
std::shared_ptr<T> get(int& domain, std::unordered_map<int, std::weak_ptr<T>>& map) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
auto it = map.find(domain);
|
||||
if (it != map.end()) {
|
||||
auto session_ptr = it->second.lock();
|
||||
if (session_ptr) {
|
||||
// Return existing session
|
||||
return session_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new session
|
||||
auto session = std::shared_ptr<T>(
|
||||
new T(domain),
|
||||
[domain, &map, this](T* s) {
|
||||
delete s;
|
||||
cleanup(domain, map);
|
||||
});
|
||||
map[domain] = session;
|
||||
return session;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void cleanup(int domain, std::unordered_map<int, std::weak_ptr<T>>& map) {
|
||||
// clean up
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
// We only erase if the weak pointer is expired, indicating no active shared_ptr exists.
|
||||
auto it = map.find(domain);
|
||||
if (it != map.end() && it->second.expired()) {
|
||||
map.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
SessionFactory() = default;
|
||||
SessionFactory(const SessionFactory&) = delete;
|
||||
SessionFactory& operator=(const SessionFactory&) = delete;
|
||||
|
||||
std::unordered_map<int, std::weak_ptr<ddkit::actors::Session>> m_sessions;
|
||||
std::unordered_map<int, std::weak_ptr<ddkit::actors::MonitorSession>> m_monitorSessions;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/base/IConfig.hpp"
|
||||
#include "ddkit/access/Dispatcher.hpp"
|
||||
#include "ddkit/access/ICleanup.hpp"
|
||||
#include "ddkit/actors/ActorInfoDbCaretaker.hpp"
|
||||
#include "ddkit/actors/ActorInfoDb.hpp"
|
||||
#include "ddkit/actors/ActorInfoWriter.hpp"
|
||||
#include "ddkit/actors/Session.hpp"
|
||||
#include "ddkit/actors/MonitorSession.hpp"
|
||||
#include "ddkit/actors/ILocalServices.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class IActor;
|
||||
typedef std::shared_ptr<IActor> ActorPtr;
|
||||
typedef std::weak_ptr<IActor> ActorPtrWeak;
|
||||
|
||||
class SimpleActor;
|
||||
typedef std::shared_ptr<SimpleActor> SimpleActorPtr;
|
||||
|
||||
class MultiplexActor;
|
||||
typedef std::shared_ptr<MultiplexActor> MultiplexActorPtr;
|
||||
|
||||
class SessionImpl final : public std::enable_shared_from_this<SessionImpl>,
|
||||
public access::ICleanup,
|
||||
public ILocalServices {
|
||||
public:
|
||||
SessionImpl(base::IConfig& config, int domain, bool isMonitor);
|
||||
~SessionImpl();
|
||||
|
||||
void init();
|
||||
|
||||
// create a new SessionImpl (even if another Session with same domain exists already)
|
||||
static SessionImplPtr create(int domain, bool isMonitor);
|
||||
|
||||
// needed from generated createSome (api) (friend access on Session)
|
||||
static SessionImplPtr getSessionImpl(Session& session);
|
||||
static SessionImplPtr getSessionImpl(MonitorSession& session);
|
||||
|
||||
// getter
|
||||
int domain();
|
||||
access::Participant& participant();
|
||||
std::string sessionId();
|
||||
std::shared_ptr<access::Dispatcher> dispatcher();
|
||||
ddkit_intern::Session sessionInfo();
|
||||
bool isMonitor();
|
||||
|
||||
bool isCheckMostDerivedClassType();
|
||||
int timeoutSecsWaitUntilConnected();
|
||||
|
||||
// key2actor
|
||||
bool hasActor(const std::string& serviceName, bool isService, const std::string& module);
|
||||
SimpleActorPtr findActor(const std::string& serviceName, bool isService, const std::string& module);
|
||||
SimpleActorPtr createActor(const std::string& serviceName, bool isService, const std::string& module);
|
||||
MultiplexActorPtr createActorMultiplex(
|
||||
bool isService,
|
||||
const std::string& module,
|
||||
const std::function<SimpleActorPtr(SessionImplPtr, const std::string&)>& createActor);
|
||||
SimpleActorPtr createOrFindActor(const std::string& serviceName, bool isService, const std::string& module);
|
||||
|
||||
// ICleanup
|
||||
void cleanup() override; // called from dispatcher regularly for removing non-referenced actors
|
||||
bool isShutdownRequested() override;
|
||||
|
||||
// ids for Actors
|
||||
int nextSequenceId() { return m_nextSequenceId++; }
|
||||
|
||||
// ActorInfo (sending to dds - actor-specific-part)
|
||||
void publishActorInfo(ddkit_intern::ActorInfo actorInfo);
|
||||
void disposeActorInfo(ddkit_intern::ActorInfo actorInfo);
|
||||
|
||||
// ActorInfo (using dds-meta-info)
|
||||
std::vector<ServiceInfo> findRunningServices(const std::string& module);
|
||||
std::vector<ServiceInfo> findRunningServices(const std::string& serviceName, const std::string& module); // max 1
|
||||
std::vector<ClientInfo> findRunningClients(const std::string& module);
|
||||
std::vector<ClientInfo> findRunningClients(const std::string& serviceName, const std::string& module);
|
||||
|
||||
// ILocalServices
|
||||
bool isLocalService(ActorConfiguration config); // called from ActorInfoDb
|
||||
|
||||
std::string clientActorId2clientName(const std::string& clientActorId); // access meta-infos for callbackInfo
|
||||
|
||||
void shutdownActors();
|
||||
void shutdownMultiplexActors();
|
||||
|
||||
void requestShutdown();
|
||||
void requestCleanup();
|
||||
|
||||
void removeMultiplexActor(std::shared_ptr<IActor> multiplexActor);
|
||||
|
||||
private:
|
||||
std::recursive_mutex m_mutex;
|
||||
std::condition_variable_any m_condition;
|
||||
|
||||
bool m_isMonitor;
|
||||
int m_domain;
|
||||
access::Participant m_participant;
|
||||
std::string m_sessionId; // identifies this session globally!
|
||||
int m_nextSequenceId; // identifiying-addition for Actors
|
||||
|
||||
std::shared_ptr<access::Dispatcher> m_dispatcher;
|
||||
|
||||
std::vector<SimpleActorPtr> m_simpleActors; // 'normal'-actors (including internal actors of multiplex)
|
||||
std::vector<MultiplexActorPtr> m_multiplexActors; // 'multiplex'-actors (have no serviceName for key, thus extra)
|
||||
|
||||
// ActorInfo (sending to dds - session-specific-part)
|
||||
ddkit_intern::Process m_process;
|
||||
ddkit_intern::Session m_sessionInfo;
|
||||
ActorInfoWriter m_actorInfoWriter;
|
||||
std::vector<ActorConfiguration> m_localServices; // log which services accountable for
|
||||
|
||||
// ActorInfo (reading from dds - monitor-intern-part)
|
||||
ActorInfoDb m_actorInfoDb;
|
||||
ActorInfoDbCaretaker m_ActorInfoDbCaretaker;
|
||||
|
||||
bool m_isCheckMostDerivedClassType;
|
||||
int m_timeoutSecsWaitUntilConnected;
|
||||
|
||||
std::atomic<bool> m_shutdownRequested;
|
||||
|
||||
// no copying
|
||||
SessionImpl(SessionImpl const&) = delete;
|
||||
SessionImpl(SessionImpl&&) = delete;
|
||||
void operator=(SessionImpl const&) = delete;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/base/ThreadInline.hpp"
|
||||
#include "ddkit/access/ConfigLoaderDds.hpp"
|
||||
#include "ddkit/actors/CallbackInfo.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class SessionImpl;
|
||||
typedef std::shared_ptr<SessionImpl> SessionImplPtr;
|
||||
typedef std::weak_ptr<SessionImpl> SessionImplWeakPtr;
|
||||
|
||||
class SessionManager {
|
||||
|
||||
public:
|
||||
static SessionManager& instance();
|
||||
|
||||
SessionImplPtr createSessionImpl(int domain, bool isMonitor); // called from SessionImpl
|
||||
|
||||
SessionImplPtr findSession(const std::string& sessionId); // called from BackwardManager
|
||||
|
||||
void removeExpiredSessions(); // called from BackwardManager, MonitorSession, Session
|
||||
void removeSession(const std::string& sessionId);
|
||||
|
||||
void setCallbackInfo(const CallbackInfo& callbackInfo); // called from ActorImpl
|
||||
void resetCallbackInfo(); // called from ActorImpl, generated Code
|
||||
CallbackInfo callbackInfo(); // called from ActorImpl, BackwardManager, CallbackInfo, generated Code
|
||||
|
||||
bool isClean() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<access::ConfigLoaderDds> m_configLoaderDds;
|
||||
|
||||
std::mutex m_sessionMutex;
|
||||
std::map<std::string, SessionImplWeakPtr> m_sessionId2sessionImpl; // holding map for sessions
|
||||
|
||||
std::mutex m_callbackMutex;
|
||||
std::map<std::string, CallbackInfo> m_threadId2callbackInfo; // per thread (typically one entry - while callback)
|
||||
|
||||
SessionManager();
|
||||
~SessionManager();
|
||||
|
||||
bool hasSession(const std::string& sessionId);
|
||||
bool hasSessions();
|
||||
|
||||
// no copying
|
||||
SessionManager(SessionManager const&) = delete;
|
||||
SessionManager(SessionManager&&) = delete;
|
||||
void operator=(SessionManager const&) = delete;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
#pragma once
|
||||
|
||||
#include "ddkit/utils/assert.hpp"
|
||||
#include "ddkit/access/TopicPoolRead.hpp"
|
||||
#include "ddkit/access/TopicPoolWrite.hpp"
|
||||
#include "ddkit/actors/CallbackInfo.hpp"
|
||||
#include "ddkit/actors/IActor.hpp"
|
||||
#include "ddkit/actors/SessionImpl.hpp"
|
||||
#include "ddkit/idls/ActorInfo.hpp"
|
||||
#include "ddkit/actors/Key.hpp"
|
||||
#include "ddkit/utils/CallbackWrapper.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace ddkit {
|
||||
namespace actors {
|
||||
|
||||
class SimpleActor : public IActor {
|
||||
|
||||
public:
|
||||
SimpleActor(const SessionImplPtr& sessionImpl,
|
||||
const std::string& serviceName,
|
||||
bool isService,
|
||||
const std::string& module);
|
||||
|
||||
~SimpleActor();
|
||||
|
||||
bool hasObserver();
|
||||
bool hasSender();
|
||||
|
||||
access::TopicPoolRead& topicPoolRead();
|
||||
access::TopicPoolWrite& topicPoolWrite();
|
||||
|
||||
std::string moduleName() const;
|
||||
bool isService() const;
|
||||
int domain() const;
|
||||
std::string serviceName() const;
|
||||
ActorConfiguration config() const;
|
||||
|
||||
std::string actorId() const;
|
||||
|
||||
bool operator==(const SimpleActor& other) const;
|
||||
|
||||
void setClientName(const std::string& clientName);
|
||||
|
||||
void waitUntilConnected();
|
||||
|
||||
void addConnectCheck(access::IConnectCheckPtr connectCheck);
|
||||
|
||||
// template-class-parameters Observer and Sender in the following methods must be the 'reader-class'
|
||||
// respectively the 'writer-class' of one of the rmodel-modules. They are called Observer and Sender
|
||||
// in the corresponding namespace and inherit the interface IObserver/ISender. They define a typedef TypeUser
|
||||
// to refer to the API-Interface-Type IClient/IService. Sender also inherits its TypeUser-Type
|
||||
|
||||
/// @brief - needed for access from generated Service/Client, to call write-stuff
|
||||
template <typename Sender>
|
||||
ISenderPtr sender() {
|
||||
DDKIT_LOG_TRACE;
|
||||
checkSenderType<Sender>();
|
||||
|
||||
if (hasSender()) {
|
||||
std::shared_ptr<Sender> sender = std::dynamic_pointer_cast<Sender>(m_sender); // Sender inherits ISender
|
||||
if (sender) {
|
||||
checkTypeOfSender(sender.get());
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ISenderPtr sender() {
|
||||
return m_sender;
|
||||
}
|
||||
|
||||
IObserverPtr observer() {
|
||||
return m_observer;
|
||||
}
|
||||
|
||||
bool hasSession() {
|
||||
return !m_sessionImplWeak.expired();
|
||||
}
|
||||
|
||||
template <typename Observer>
|
||||
IObserverPtr createObserver(typename Observer::TypeUser& callbacks, const std::vector<std::string>& methods) {
|
||||
|
||||
ddkit::log::info() << "Create observer";
|
||||
|
||||
SessionImplPtr sessionImpl = m_sessionImplWeak.lock();
|
||||
if (!sessionImpl) {
|
||||
throw std::runtime_error("Failure locking std::weak_ptr<SessionImpl> in ActorImpl");
|
||||
}
|
||||
|
||||
checkObserverType<Observer>();
|
||||
|
||||
typename Observer::TypeUser* userCallback = &callbacks; // (keep * inside ... else problems with capturing)
|
||||
|
||||
// insert observer
|
||||
DDKIT_THROW_ON_FALSE_INFO(
|
||||
!hasObserver(),
|
||||
"Inserting an observer to an actor already containing one."
|
||||
"Called ObsFactory::add() twice? (same serviceName + domain)");
|
||||
m_observer = std::make_shared<Observer>(*this, m_topicPoolRead, methods, userCallback);
|
||||
DDKIT_THROW_ON_FALSE_INFO(hasObserver(), "creation of observer failed");
|
||||
|
||||
// update actorInfo
|
||||
if (m_actorInfo.isReading()) {
|
||||
ddkit::log::warn() << "SimpleActor::createObserver: " << "actor is already reading";
|
||||
}
|
||||
m_actorInfo.isReading() = true;
|
||||
m_actorInfo.openReaders() = methods; // only vectors on dds
|
||||
|
||||
sessionImpl->publishActorInfo(m_actorInfo);
|
||||
|
||||
return m_observer;
|
||||
}
|
||||
|
||||
template <typename Observer>
|
||||
IObserverPtr createObserver(std::map<std::string, std::vector<ddkit::callback::Base*>> callbacks, const std::vector<std::string> methods) {
|
||||
|
||||
ddkit::log::info() << "Create observer";
|
||||
|
||||
SessionImplPtr sessionImpl = m_sessionImplWeak.lock();
|
||||
if (!sessionImpl) {
|
||||
throw std::runtime_error("Failure locking std::weak_ptr<SessionImpl> in ActorImpl");
|
||||
}
|
||||
|
||||
checkObserverType<Observer>();
|
||||
|
||||
// insert observer
|
||||
DDKIT_THROW_ON_FALSE_INFO(
|
||||
!hasObserver(),
|
||||
"Inserting an observer to an actor already containing one."
|
||||
"Called ObsFactory::add() twice? (same serviceName + domain)");
|
||||
m_observer = std::make_shared<Observer>(*this, m_topicPoolRead, methods, callbacks);
|
||||
DDKIT_THROW_ON_FALSE_INFO(hasObserver(), "creation of observer failed");
|
||||
|
||||
// update actorInfo
|
||||
if(m_actorInfo.isReading()) {
|
||||
ddkit::log::warn() << "SimpleActor::createObserver: actor is already reading";
|
||||
}
|
||||
m_actorInfo.isReading() = true;
|
||||
m_actorInfo.openReaders() = methods; // only vectors on dds
|
||||
|
||||
sessionImpl->publishActorInfo(m_actorInfo);
|
||||
|
||||
return m_observer;
|
||||
}
|
||||
|
||||
template <typename Sender>
|
||||
ISenderPtr createSender(const std::vector<std::string>& methods) {
|
||||
|
||||
ddkit::log::info() << "Create sender";
|
||||
|
||||
SessionImplPtr sessionImpl = m_sessionImplWeak.lock();
|
||||
if (!sessionImpl) {
|
||||
throw std::runtime_error("Failure locking std::weak_ptr<SessionImpl> in ActorImpl");
|
||||
}
|
||||
|
||||
checkSenderType<Sender>();
|
||||
|
||||
DDKIT_THROW_ON_FALSE_INFO(
|
||||
!hasSender(),
|
||||
"Inserting a sender to an actor already containing one. "
|
||||
"Called Factory::create() twice? (same serviceName + domain)");
|
||||
m_sender = std::make_shared<Sender>(*this, m_topicPoolWrite);
|
||||
Sender* sender2 = dynamic_cast<Sender*>(m_sender.get());
|
||||
checkTypeOfSender(sender2);
|
||||
DDKIT_THROW_ON_FALSE(sender2);
|
||||
DDKIT_THROW_ON_FALSE(hasSender());
|
||||
|
||||
// update actorInfo
|
||||
if (m_actorInfo.isWriting()) {
|
||||
ddkit::log::warn() << "SimpleActor::createSender: " << "actor is already writing";
|
||||
}
|
||||
m_actorInfo.isWriting() = true;
|
||||
m_actorInfo.openWriters() = methods; // only vectors on dds
|
||||
sessionImpl->publishActorInfo(m_actorInfo);
|
||||
return m_sender;
|
||||
}
|
||||
|
||||
void discardSender();
|
||||
void discardObserver();
|
||||
bool isValid() override;
|
||||
void shutdown() override;
|
||||
bool shutdownRequested();
|
||||
|
||||
CallbackInfo callbackInfoBase();
|
||||
CallbackInfo callbackInfo();
|
||||
void setCallbackInfo(CallbackInfo callbackInfo);
|
||||
void resetCallbackInfo();
|
||||
|
||||
private:
|
||||
ddkit_intern::ActorInfo m_actorInfo;
|
||||
|
||||
access::IQosStrategyPtr m_qosStrategy;
|
||||
access::ITopicStrategyPtr m_topicStrategy;
|
||||
access::TopicPoolRead m_topicPoolRead;
|
||||
access::TopicPoolWrite m_topicPoolWrite;
|
||||
std::vector<access::IConnectCheckPtr> m_connectCheckSet;
|
||||
|
||||
IObserverPtr m_observer; // or nullptr, if none
|
||||
ISenderPtr m_sender; // or nullptr, if none
|
||||
|
||||
CallbackInfo m_callbackInfoBase;
|
||||
|
||||
std::atomic<bool> m_shutdownRequested;
|
||||
};
|
||||
|
||||
} // namespace actors
|
||||
} // namespace ddkit
|
||||
Reference in new issue
Block a user