add a signal/slot mechanism. 2 APIs : one generic version, and one string API (commented)

This commit is contained in:
winckler
2016-08-09 14:02:43 +02:00
committed by Mohammad Al-Turany
parent 5e5ddd5b7b
commit 9ceab6099c
5 changed files with 415 additions and 27 deletions

View File

@@ -17,16 +17,22 @@
#define FAIRMQPROGOPTIONS_H
#include <unordered_map>
#include <map>
#include <set>
#include "FairProgOptions.h"
#include "FairProgOptions.h"
#include "FairMQEventManager.h"
#include "FairMQChannel.h"
class FairMQProgOptions : public FairProgOptions
class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
{
protected:
typedef std::unordered_map<std::string, std::vector<FairMQChannel>> FairMQMap;
using FairMQMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
//using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>;// string API
//using signal_type_ptr = boost::shared_ptr<signal_type>;// string API
public:
FairMQProgOptions();
@@ -52,9 +58,6 @@ class FairMQProgOptions : public FairProgOptions
return 0;
}
FairMQMap GetFairMQMap()
{
return fFairMQMap;
@@ -77,30 +80,156 @@ class FairMQProgOptions : public FairProgOptions
// - if UpdateChannelMap(const FairMQMap& map) method is called
// - if UserParser template method is called (it is called in the ParseAll method if json or xml MQ-config files is provided)
template<typename T>
int UpdateValue(const std::string& key, const T& val)
/* // string API
//overload for string literal
int UpdateValue(const std::string& key, const char* val) // string API
{
UpdateVarMap(key,val);
if(fMQKeyMap.count(key))
UpdateValue(key,std::string(val));
return 0;
}
// overload for string values
int UpdateValue(const std::string& key, const std::string& val) // string API
{
try
{
std::string channelName;
int index = 0;
std::string member;
std::tie(channelName, index, member) = fMQKeyMap.at(key);
if(fVarMap.count(key))
{
if(!fairmq::is_this_type<std::string>(fVarMap.at(key)))
{
LOG(ERROR) << "You try to update a value as string (for key="<< key <<") while it has been defined with a different type in the option description.";
abort();
}
// update variable map
UpdateVarMap(key,val);
if(fMQKeyMap.count(key))
{
std::string channelName;
int index = 0;
std::string member;
std::tie(channelName, index, member) = fMQKeyMap.at(key);
UpdateChannelMap(channelName, index, member, val);
}
// execute stored function of a given key if exist
//if(std::is_same<T, int>::value || std::is_same<T, std::string>::value)//if one wants to restrict type
if(fSignalMap.count(key))
EmitUpdate(key,val);
return 0;
}
else
{
LOG(ERROR) <<"UpdatedValue failed because the provided key '"
<<key
<<"' is not found in the variable map";
return 1;
}
}
catch (std::exception& e)
{
LOG(ERROR) << "Caught exception on key "<<key;
abort();
}
return 0;
}
*/
//overload for string literal
/*int UpdateValue(const std::string& key, const char* val) // string API
{
UpdateValue<std::string>(key,val);
return 0;
}*/
// specialization/overloading for string, pass by const ref
int UpdateValue(const std::string& key, const std::string& val) // string API
{
UpdateValue(key,val);
return 0;
}
int UpdateValue(const std::string& key, const char* val) // string API
{
UpdateValue<std::string>(key,std::string(val));
return 0;
}
template<typename T>
int UpdateValue(const std::string& key, T val)
{
if(fVarMap.count(key))
{
// update variable map
UpdateVarMap<typename std::decay<T>::type>(key,val);
// update FairMQChannel map, check first if data are int or string
if(std::is_same<T, int>::value || std::is_same<T, std::string>::value)
UpdateChannelMap(channelName, index, member, val);
if(fMQKeyMap.count(key))
{
std::string channelName;
int index = 0;
std::string member;
std::tie(channelName, index, member) = fMQKeyMap.at(key);
UpdateChannelMap(channelName, index, member, val);
}
// execute stored function of a given key if exist
//if(std::is_same<T, int>::value || std::is_same<T, std::string>::value)//if one wants to restrict type
if(EventKeyFound(key))
EmitUpdate<typename std::decay<T>::type >(key,val);
return 0;
}
else
{
LOG(ERROR) <<"UpdatedValue failed because the provided key '"
<<key
<<"' is not found in the variable map";
return 1;
}
return 0;
}
template <typename T, typename F>
void Subscribe(const std::string& key, F&& func)
{
static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
"In template member FairMQProgOptions::Subscribe<T>(key,Lambda) the types const char* or char* for the calback signatures are not supported.");
if(fVarMap.count(key))
FairMQEventManager::Connect<EventId::UpdateParam,T>(key,std::forward<F>(func));
}
/*
template <typename F>
void Subscribe(const std::string& key, F&& func)
{
if(fVarMap.count(key))
{
//if key-value not yet found, then add it
if(fSignalMap.find(key) == fSignalMap.end())
fSignalMap.emplace(key, boost::make_shared<signal_type>());
(*fSignalMap.at(key)).connect(std::forward<F>(func));
}
}
*/
// replace FairMQChannelMap, and update variable map accordingly
int UpdateChannelMap(const FairMQMap& map);
protected:
po::options_description fMQParserOptions;
po::options_description fMQOptionsInCfg;
@@ -109,6 +238,21 @@ class FairMQProgOptions : public FairProgOptions
std::string fHelpTitle;
std::string fVersion;
bool EventKeyFound(const std::string& key)
{
if (
FairMQEventManager::EventKeyFound<EventId::UpdateParam>(key)
)
return true;
else
return false;
}
typedef std::tuple<std::string,int,std::string> MQKey;//store key info
std::map<std::string,MQKey> fMQKeyMap;// key=full path - val=key info
@@ -120,7 +264,31 @@ class FairMQProgOptions : public FairProgOptions
void UpdateMQValues();
int Store(const FairMQMap& channels);
private:
/*
// string API
std::map<std::string, signal_type_ptr > fSignalMap;
void EmitUpdate(const std::string& key, const char* val)
{
EmitUpdate(key,std::string(val));
}
void EmitUpdate(const std::string& key, const std::string& val)
{
(*fSignalMap.at(key))(key,val);
}
*/
template<typename T>
void EmitUpdate(const std::string& key, T val)
{
//compile time check whether T is const char* or char*, and in that case a compile time error is thrown.
static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
"In template member FairMQProgOptions::EmitUpdate<T>(key,val) the types const char* or char* for the calback signatures are not supported.");
Emit<EventId::UpdateParam,T>(key,key,val);
}
int UpdateChannelMap(const std::string& channelName, int index, const std::string& member, const std::string& val);
int UpdateChannelMap(const std::string& channelName, int index, const std::string& member, int val);
// for cases other than int and string