mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-13 00:31:14 +00:00
- FairMQ options:
a) move the XML parser into the FairMQ/options/FairMQParser.h b) add a routine in FairMQProgOption to check whether the necessary XML or JSON input files are there, and send an error message if not there - Policy based devices: a) rename GenericSampler to base_GenericSampler and use an alias template named GenericSampler b) in base_GenericSampler, rename template parameter to simple variables <T,U,… > and use typedef for clarity c) introduce an anonymous function container in the base_GenericSampler host class with a register task template member function and an Executetasks() d) add two new template parameters in base_GenericSampler for the anonymous function container map. parameter is K for the key type (default=int) and L for the value type (default=std::function<void()>) - Tutorial7: a) use FairMQProgOption to configure devices in tutorial7 b) introduce several template functions helper in tutorial7 to reduce code redundancy c) show examples in tutorial7 of task registration with callback and lambda expression for the sampler devices d) separate the executable build of the tutorial7 data generator to remove the Roofit banner when executing the MQdevices
This commit is contained in:
parent
6ed9cc3da1
commit
d1bba61939
|
@ -155,7 +155,7 @@ install(FILES ${FAIRMQHEADERS} DESTINATION include)
|
||||||
|
|
||||||
set(DEPENDENCIES
|
set(DEPENDENCIES
|
||||||
${DEPENDENCIES}
|
${DEPENDENCIES}
|
||||||
boost_thread boost_timer boost_system boost_program_options boost_random boost_chrono boost_exception
|
boost_thread boost_timer boost_system boost_filesystem boost_program_options boost_random boost_chrono boost_exception
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBRARY_NAME FairMQ)
|
set(LIBRARY_NAME FairMQ)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <functional>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
|
|
||||||
#include "FairMQDevice.h"
|
#include "FairMQDevice.h"
|
||||||
#include "FairMQLogger.h"
|
#include "FairMQLogger.h"
|
||||||
|
#include "FairMQTools.h"
|
||||||
|
|
||||||
/* GENERIC SAMPLER (data source) MQ-DEVICE */
|
/* GENERIC SAMPLER (data source) MQ-DEVICE */
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
|
@ -33,31 +35,55 @@
|
||||||
* Function to define in (parent) policy classes :
|
* Function to define in (parent) policy classes :
|
||||||
*
|
*
|
||||||
* -------- INPUT POLICY (SAMPLER POLICY) --------
|
* -------- INPUT POLICY (SAMPLER POLICY) --------
|
||||||
* SamplerPolicy::InitSampler()
|
* source_type::InitSampler() // must be there to compile
|
||||||
* int64_t SamplerPolicy::GetNumberOfEvent()
|
* int64_t source_type::GetNumberOfEvent() // must be there to compile
|
||||||
* CONTAINER_TYPE SamplerPolicy::GetDataBranch(int64_t eventNr)
|
* source_type::SetIndex(int64_t eventIdx) // must be there to compile
|
||||||
* SamplerPolicy::SetFileProperties(Args&... args)
|
* CONTAINER_TYPE source_type::GetOutData() // must be there to compile
|
||||||
|
* source_type::SetFileProperties(Args&... args) // must be there to compile
|
||||||
|
* source_type::ExecuteTasks() // must be there to compile
|
||||||
|
*
|
||||||
|
* void BindSendPart(std::function<void(int)> callback) // enabled if exists
|
||||||
|
* void BindGetSocketNumber(std::function<int()> callback) // enabled if exists
|
||||||
|
* void BindGetCurrentIndex(std::function<int()> callback) // enabled if exists
|
||||||
*
|
*
|
||||||
* -------- OUTPUT POLICY --------
|
* -------- OUTPUT POLICY --------
|
||||||
* OutputPolicy::SerializeMsg(CONTAINER_TYPE)
|
* serialization_type::SerializeMsg(CONTAINER_TYPE) // must be there to compile
|
||||||
* OutputPolicy::SetMessage(FairMQMessage* msg)
|
* serialization_type::SetMessage(FairMQMessage* msg) // must be there to compile
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
//template <typename source_type, typename serialization_type, typename key_type, typename task_type>
|
||||||
class GenericSampler : public FairMQDevice, public SamplerPolicy, public OutputPolicy
|
//class base_GenericSampler : public FairMQDevice, public source_type, public serialization_type
|
||||||
|
template <typename T, typename U, typename K, typename L>
|
||||||
|
class base_GenericSampler : public FairMQDevice, public T, public U
|
||||||
{
|
{
|
||||||
|
typedef T source_type;
|
||||||
|
typedef U serialization_type;
|
||||||
|
typedef K key_type;
|
||||||
|
typedef L task_type;
|
||||||
|
typedef base_GenericSampler<T,U,K,L> self_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
InputFile = FairMQDevice::Last,
|
EventRate = FairMQDevice::Last,
|
||||||
Branch,
|
OutChannelName
|
||||||
ParFile,
|
|
||||||
EventRate
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GenericSampler();
|
base_GenericSampler();
|
||||||
virtual ~GenericSampler();
|
virtual ~base_GenericSampler();
|
||||||
|
/*
|
||||||
|
struct trait : source_type::trait, serialization_type::trait
|
||||||
|
{
|
||||||
|
//static const SerializationTag serialization = serialization_type::trait::serialization;
|
||||||
|
//static const FileTag
|
||||||
|
static const DeviceTag device = kSampler;
|
||||||
|
typedef base_GenericSampler<source_type,serialization_type> self_type;
|
||||||
|
typedef source_type source_type;
|
||||||
|
typedef serialization_type serialization_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
virtual void SetTransport(FairMQTransportFactory* factory);
|
virtual void SetTransport(FairMQTransportFactory* factory);
|
||||||
void ResetEventCounter();
|
void ResetEventCounter();
|
||||||
|
@ -65,36 +91,103 @@ class GenericSampler : public FairMQDevice, public SamplerPolicy, public OutputP
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void SetFileProperties(Args&... args)
|
void SetFileProperties(Args&... args)
|
||||||
{
|
{
|
||||||
SamplerPolicy::SetFileProperties(args...);
|
source_type::SetFileProperties(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetProperty(const int key, const std::string& value);
|
|
||||||
virtual std::string GetProperty(const int key, const std::string& default_ = "");
|
|
||||||
virtual void SetProperty(const int key, const int value);
|
virtual void SetProperty(const int key, const int value);
|
||||||
virtual int GetProperty(const int key, const int default_ = 0);
|
virtual int GetProperty(const int key, const int default_ = 0);
|
||||||
|
virtual void SetProperty(const int key, const std::string& value);
|
||||||
/**
|
virtual std::string GetProperty(const int key, const std::string& default_ = "");
|
||||||
* Sends the currently available output of the Sampler Task as part of a multipart message
|
|
||||||
* and reinitializes the message to be filled with the next part.
|
void SendPart(int socketIdx);
|
||||||
* This method can be given as a callback to the SamplerTask.
|
int GetSocketNumber() const;
|
||||||
* The final message part must be sent with normal Send method.
|
int GetCurrentIndex() const;
|
||||||
*/
|
void SetContinuous(bool flag);
|
||||||
// temporary disabled
|
|
||||||
//void SendPart();
|
|
||||||
|
/// ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
void SetContinuous(bool flag);
|
/*
|
||||||
|
register the tasks you want to process and, which will be
|
||||||
|
called by ExecuteTasks() member function. The registration is done by filling
|
||||||
|
a std::map<key_type, task_type > where key_type is int and task_type
|
||||||
|
is std::function<void()> by default (when using GenericSampler alias template).
|
||||||
|
The template parameter <RegistrationManager> must take a pointer to this class or derived class as first argument,
|
||||||
|
and a reference to a std::map<key_type, task_type > as second argument.
|
||||||
|
It is convenient to use a lambda expression in the place of the <RegistrationManager> template argument.
|
||||||
|
For example if we want to register the simple function,
|
||||||
|
//<
|
||||||
|
void myfunction() {std::cout << "hello World" << std::endl;}
|
||||||
|
//>
|
||||||
|
,and the MultiPartTask() template function member of this class , then
|
||||||
|
we can do in the main function as follow :
|
||||||
|
|
||||||
|
sampler.RegisterTask(
|
||||||
|
[&](TSampler* s, std::map<int, std::function<void()> >& task_list)
|
||||||
|
{
|
||||||
|
task_list[0]=std::bind(myfunction);
|
||||||
|
task_list[1]=std::bind(&U::template MultiPartTask<5>, s);
|
||||||
|
});
|
||||||
|
|
||||||
|
To communicate with the Host derived class via callback, three methods from the host class are callable (only
|
||||||
|
after binding these methods in the GenericSampler<I,O>::InitTask() )
|
||||||
|
|
||||||
|
*/
|
||||||
|
template<typename RegistrationManager>
|
||||||
|
void RegisterTask(RegistrationManager manage)
|
||||||
|
{
|
||||||
|
manage(this,fTaskList);
|
||||||
|
LOG(DEBUG)<<"Current Number of registered tasks = "<<fTaskList.size();
|
||||||
|
}
|
||||||
|
/// ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void ExecuteTasks()
|
||||||
|
{
|
||||||
|
for(const auto& p : fTaskList)
|
||||||
|
{
|
||||||
|
LOG(DEBUG)<<"Execute Task "<< p.first;
|
||||||
|
p.second();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void InitTask();
|
virtual void InitTask();
|
||||||
virtual void Run();
|
virtual void Run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string fOutChanName;
|
||||||
int64_t fNumEvents;
|
int64_t fNumEvents;
|
||||||
|
int64_t fCurrentIdx;
|
||||||
int fEventRate;
|
int fEventRate;
|
||||||
int fEventCounter;
|
int fEventCounter;
|
||||||
bool fContinuous;
|
bool fContinuous;
|
||||||
std::string fInputFile; // Filename of a root file containing the simulated digis.
|
std::map<key_type, task_type > fTaskList; // to handle Task list
|
||||||
std::string fParFile;
|
|
||||||
std::string fBranch; // The name of the sub-detector branch to stream the digis from.
|
|
||||||
|
// automatically enable or disable the call of policy function members for binding of host functions.
|
||||||
|
// this template functions use SFINAE to detect the existence of the policy function signature.
|
||||||
|
template<typename S = source_type ,FairMQ::tools::enable_if_hasNot_BindSendPart<S> = 0 >
|
||||||
|
void BindingSendPart(){}
|
||||||
|
template<typename S = source_type ,FairMQ::tools::enable_if_has_BindSendPart<S> = 0 >
|
||||||
|
void BindingSendPart()
|
||||||
|
{
|
||||||
|
source_type::BindSendPart(std::bind(&base_GenericSampler::SendPart,this,std::placeholders::_1) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename S = source_type ,FairMQ::tools::enable_if_hasNot_BindGetSocketNumber<S> = 0 >
|
||||||
|
void BindingGetSocketNumber(){}
|
||||||
|
template<typename S = source_type ,FairMQ::tools::enable_if_has_BindGetSocketNumber<S> = 0 >
|
||||||
|
void BindingGetSocketNumber()
|
||||||
|
{
|
||||||
|
source_type::BindGetSocketNumber(std::bind(&base_GenericSampler::GetSocketNumber,this) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename S = source_type ,FairMQ::tools::enable_if_hasNot_BindGetCurrentIndex<S> = 0 >
|
||||||
|
void BindingGetCurrentIndex(){}
|
||||||
|
template<typename S = source_type ,FairMQ::tools::enable_if_has_BindGetCurrentIndex<S> = 0 >
|
||||||
|
void BindingGetCurrentIndex()
|
||||||
|
{
|
||||||
|
source_type::BindGetCurrentIndex(std::bind(&base_GenericSampler::GetCurrentIndex,this) );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "GenericSampler.tpl"
|
#include "GenericSampler.tpl"
|
||||||
|
|
|
@ -5,72 +5,82 @@
|
||||||
* Created on November 24, 2014, 3:59 PM
|
* Created on November 24, 2014, 3:59 PM
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
template <typename T, typename U, typename K, typename L>
|
||||||
GenericSampler<SamplerPolicy,OutputPolicy>::GenericSampler()
|
base_GenericSampler<T,U,K,L>::base_GenericSampler()
|
||||||
: fNumEvents(0)
|
: fOutChanName("data-out")
|
||||||
|
, fNumEvents(0)
|
||||||
|
, fCurrentIdx(0)
|
||||||
, fEventRate(1)
|
, fEventRate(1)
|
||||||
, fEventCounter(0)
|
, fEventCounter(0)
|
||||||
, fContinuous(false)
|
, fContinuous(false)
|
||||||
, fInputFile()
|
|
||||||
, fParFile()
|
|
||||||
, fBranch()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
template <typename T, typename U, typename K, typename L>
|
||||||
GenericSampler<SamplerPolicy,OutputPolicy>::~GenericSampler()
|
base_GenericSampler<T,U,K,L>::~base_GenericSampler()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
template <typename T, typename U, typename K, typename L>
|
||||||
void GenericSampler<SamplerPolicy,OutputPolicy>::SetTransport(FairMQTransportFactory* factory)
|
void base_GenericSampler<T,U,K,L>::SetTransport(FairMQTransportFactory* factory)
|
||||||
{
|
{
|
||||||
FairMQDevice::SetTransport(factory);
|
FairMQDevice::SetTransport(factory);
|
||||||
// OutputPolicy::SetTransport(factory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
template <typename T, typename U, typename K, typename L>
|
||||||
void GenericSampler<SamplerPolicy,OutputPolicy>::InitTask()
|
void base_GenericSampler<T,U,K,L>::InitTask()
|
||||||
{
|
{
|
||||||
SamplerPolicy::InitSampler();
|
BindingSendPart();
|
||||||
fNumEvents = SamplerPolicy::GetNumberOfEvent();
|
BindingGetSocketNumber();
|
||||||
|
BindingGetCurrentIndex();
|
||||||
|
|
||||||
|
source_type::InitSampler();
|
||||||
|
fNumEvents = source_type::GetNumberOfEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
|
||||||
void GenericSampler<SamplerPolicy,OutputPolicy>::Run()
|
|
||||||
|
|
||||||
|
template <typename T, typename U, typename K, typename L>
|
||||||
|
void base_GenericSampler<T,U,K,L>::Run()
|
||||||
{
|
{
|
||||||
// boost::thread resetEventCounter(boost::bind(&GenericSampler::ResetEventCounter, this));
|
// boost::thread resetEventCounter(boost::bind(&GenericSampler::ResetEventCounter, this));
|
||||||
|
|
||||||
int sentMsgs = 0;
|
int sentMsgs = 0;
|
||||||
|
|
||||||
boost::timer::auto_cpu_timer timer;
|
boost::timer::auto_cpu_timer timer;
|
||||||
|
|
||||||
LOG(INFO) << "Number of events to process: " << fNumEvents;
|
LOG(INFO) << "Number of events to process: " << fNumEvents;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
for (int64_t eventNr = 0; eventNr < fNumEvents; ++eventNr)
|
for (fCurrentIdx = 0; fCurrentIdx < fNumEvents; fCurrentIdx++)
|
||||||
{
|
{
|
||||||
//fSamplerTask->SetEventIndex(eventNr);
|
for(auto& p : fChannels[fOutChanName])
|
||||||
FairMQMessage* msg = fTransportFactory->CreateMessage();
|
|
||||||
OutputPolicy::SetMessage(msg);
|
|
||||||
fChannels["data-out"].at(0).Send(OutputPolicy::SerializeMsg(SamplerPolicy::GetDataBranch(eventNr)));
|
|
||||||
++sentMsgs;
|
|
||||||
|
|
||||||
if (msg)
|
|
||||||
{
|
{
|
||||||
msg->CloseMessage();
|
FairMQMessage* msg = fTransportFactory->CreateMessage();
|
||||||
}
|
serialization_type::SetMessage(msg);
|
||||||
|
source_type::SetIndex(fCurrentIdx);
|
||||||
|
ExecuteTasks();
|
||||||
|
p.Send(serialization_type::SerializeMsg(source_type::GetOutData()));
|
||||||
|
if (msg)
|
||||||
|
msg->CloseMessage();
|
||||||
|
sentMsgs++;
|
||||||
|
|
||||||
// Optional event rate limiting
|
if(fChannels[fOutChanName].size()>1)
|
||||||
// --fEventCounter;
|
fCurrentIdx++;
|
||||||
// while (fEventCounter == 0) {
|
|
||||||
// boost::this_thread::sleep(boost::posix_time::milliseconds(1));
|
// Optional event rate limiting
|
||||||
// }
|
// --fEventCounter;
|
||||||
|
// while (fEventCounter == 0) {
|
||||||
if (GetCurrentState() != RUNNING)
|
// boost::this_thread::sleep(boost::posix_time::milliseconds(1));
|
||||||
{
|
// }
|
||||||
break;
|
|
||||||
|
if (GetCurrentState() != RUNNING)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
// if more than one socket, remove the last incrementation
|
||||||
|
if(fChannels[fOutChanName].size()>1)
|
||||||
|
fCurrentIdx--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ( GetCurrentState() == RUNNING && fContinuous );
|
while ( GetCurrentState() == RUNNING && fContinuous );
|
||||||
|
@ -80,23 +90,43 @@ void GenericSampler<SamplerPolicy,OutputPolicy>::Run()
|
||||||
LOG(INFO) << "Sent " << sentMsgs << " messages!";
|
LOG(INFO) << "Sent " << sentMsgs << " messages!";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
|
||||||
void GenericSampler<SamplerPolicy,OutputPolicy>::SendPart()
|
|
||||||
{
|
|
||||||
fChannels["data-out"].at(0).Send(OutputPolicy::GetMessage(), "snd-more");
|
|
||||||
OutputPolicy::CloseMessage();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
template <typename T, typename U, typename K, typename L>
|
||||||
void GenericSampler<SamplerPolicy,OutputPolicy>::SetContinuous(bool flag)
|
void base_GenericSampler<T,U,K,L>::SendPart(int socketIdx)
|
||||||
|
{
|
||||||
|
fCurrentIdx++;
|
||||||
|
if(fCurrentIdx<fNumEvents)
|
||||||
|
{
|
||||||
|
FairMQMessage* msg = fTransportFactory->CreateMessage();
|
||||||
|
serialization_type::SetMessage(msg);
|
||||||
|
source_type::SetIndex(fCurrentIdx);
|
||||||
|
fChannels[fOutChanName].at(socketIdx).Send(serialization_type::SerializeMsg(source_type::GetOutData()), "snd-more");
|
||||||
|
if (msg)
|
||||||
|
msg->CloseMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T, typename U, typename K, typename L>
|
||||||
|
int base_GenericSampler<T,U,K,L>::GetSocketNumber() const
|
||||||
|
{
|
||||||
|
return fChannels.at(fOutChanName).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U, typename K, typename L>
|
||||||
|
int base_GenericSampler<T,U,K,L>::GetCurrentIndex() const
|
||||||
|
{
|
||||||
|
return fCurrentIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U, typename K, typename L>
|
||||||
|
void base_GenericSampler<T,U,K,L>::SetContinuous(bool flag)
|
||||||
{
|
{
|
||||||
fContinuous = flag;
|
fContinuous = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
template <typename T, typename U, typename K, typename L>
|
||||||
void GenericSampler<SamplerPolicy,OutputPolicy>::ResetEventCounter()
|
void base_GenericSampler<T,U,K,L>::ResetEventCounter()
|
||||||
{
|
{
|
||||||
while (GetCurrentState() == RUNNING)
|
while (GetCurrentState() == RUNNING)
|
||||||
{
|
{
|
||||||
|
@ -114,44 +144,8 @@ void GenericSampler<SamplerPolicy,OutputPolicy>::ResetEventCounter()
|
||||||
LOG(DEBUG) << ">>>>>>> stopping resetEventCounter <<<<<<<";
|
LOG(DEBUG) << ">>>>>>> stopping resetEventCounter <<<<<<<";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
template <typename T, typename U, typename K, typename L>
|
||||||
void GenericSampler<SamplerPolicy,OutputPolicy>::SetProperty(const int key, const std::string& value)
|
void base_GenericSampler<T,U,K,L>::SetProperty(const int key, const int value)
|
||||||
{
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case InputFile:
|
|
||||||
fInputFile = value;
|
|
||||||
break;
|
|
||||||
case ParFile:
|
|
||||||
fParFile = value;
|
|
||||||
break;
|
|
||||||
case Branch:
|
|
||||||
fBranch = value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
FairMQDevice::SetProperty(key, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
|
||||||
std::string GenericSampler<SamplerPolicy,OutputPolicy>::GetProperty(const int key, const std::string& default_/*= ""*/)
|
|
||||||
{
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case InputFile:
|
|
||||||
return fInputFile;
|
|
||||||
case ParFile:
|
|
||||||
return fParFile;
|
|
||||||
case Branch:
|
|
||||||
return fBranch;
|
|
||||||
default:
|
|
||||||
return FairMQDevice::GetProperty(key, default_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
|
||||||
void GenericSampler<SamplerPolicy,OutputPolicy>::SetProperty(const int key, const int value)
|
|
||||||
{
|
{
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
@ -164,8 +158,8 @@ void GenericSampler<SamplerPolicy,OutputPolicy>::SetProperty(const int key, cons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SamplerPolicy, typename OutputPolicy>
|
template <typename T, typename U, typename K, typename L>
|
||||||
int GenericSampler<SamplerPolicy,OutputPolicy>::GetProperty(const int key, const int default_/*= 0*/)
|
int base_GenericSampler<T,U,K,L>::GetProperty(const int key, const int default_/*= 0*/)
|
||||||
{
|
{
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
@ -175,3 +169,35 @@ int GenericSampler<SamplerPolicy,OutputPolicy>::GetProperty(const int key, const
|
||||||
return FairMQDevice::GetProperty(key, default_);
|
return FairMQDevice::GetProperty(key, default_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U, typename K, typename L>
|
||||||
|
void base_GenericSampler<T,U,K,L>::SetProperty(const int key, const std::string& value)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case OutChannelName:
|
||||||
|
fOutChanName = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FairMQDevice::SetProperty(key, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U, typename K, typename L>
|
||||||
|
std::string base_GenericSampler<T,U,K,L>::GetProperty(const int key, const std::string& default_)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case OutChannelName:
|
||||||
|
return fOutChanName;
|
||||||
|
default:
|
||||||
|
return FairMQDevice::GetProperty(key, default_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
using GenericSampler = base_GenericSampler<T,U,int,std::function<void()> >;
|
||||||
|
typedef std::map<int, std::function<void()> > SamplerTasksMap;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include "FairMQParser.h"
|
#include "FairMQParser.h"
|
||||||
#include "FairMQLogger.h"
|
#include "FairMQLogger.h"
|
||||||
|
#include <boost/property_tree/xml_parser.hpp>
|
||||||
// WARNING : pragma commands to hide boost (1.54.0) warning
|
// WARNING : pragma commands to hide boost (1.54.0) warning
|
||||||
// TODO : remove these pragma commands when boost will fix this issue in future release
|
// TODO : remove these pragma commands when boost will fix this issue in future release
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
|
@ -188,4 +188,22 @@ FairMQMap JSON::UserParser(std::stringstream& input, const std::string& deviceId
|
||||||
return ptreeToMQMap(pt, deviceId, rootNode,"json");
|
return ptreeToMQMap(pt, deviceId, rootNode,"json");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
FairMQMap XML::UserParser(const std::string& filename, const std::string& deviceId, const std::string& rootNode)
|
||||||
|
{
|
||||||
|
boost::property_tree::ptree pt;
|
||||||
|
boost::property_tree::read_xml(filename, pt);
|
||||||
|
return ptreeToMQMap(pt,deviceId,rootNode,"xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
FairMQMap XML::UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode)
|
||||||
|
{
|
||||||
|
boost::property_tree::ptree pt;
|
||||||
|
boost::property_tree::read_xml(input, pt);
|
||||||
|
return ptreeToMQMap(pt,deviceId,rootNode,"xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end FairMQParser namespace
|
} // end FairMQParser namespace
|
|
@ -32,6 +32,12 @@ struct JSON
|
||||||
FairMQMap UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode = "fairMQOptions");
|
FairMQMap UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode = "fairMQOptions");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct XML
|
||||||
|
{
|
||||||
|
FairMQMap UserParser(const std::string& filename, const std::string& deviceId, const std::string& root_node="fairMQOptions");
|
||||||
|
FairMQMap UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode="fairMQOptions");
|
||||||
|
};
|
||||||
|
|
||||||
} // FairMQParser namespace
|
} // FairMQParser namespace
|
||||||
#endif /* FAIRMQPARSER_H */
|
#endif /* FAIRMQPARSER_H */
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,11 @@
|
||||||
FairMQProgOptions::FairMQProgOptions()
|
FairMQProgOptions::FairMQProgOptions()
|
||||||
: FairProgOptions()
|
: FairProgOptions()
|
||||||
, fMQParserOptions("MQ-Device parser options")
|
, fMQParserOptions("MQ-Device parser options")
|
||||||
|
, fMQOptionsInCmd("MQ-Device options")
|
||||||
|
, fMQOptionsInCfg("MQ-Device options")
|
||||||
, fMQtree()
|
, fMQtree()
|
||||||
, fFairMQmap()
|
, fFairMQmap()
|
||||||
{
|
{
|
||||||
InitOptionDescription();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FairMQProgOptions::~FairMQProgOptions()
|
FairMQProgOptions::~FairMQProgOptions()
|
||||||
|
@ -30,53 +31,62 @@ FairMQProgOptions::~FairMQProgOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
int FairMQProgOptions::ParseAll(const int argc, char** argv, bool AllowUnregistered)
|
int FairMQProgOptions::ParseAll(const int argc, char** argv, bool AllowUnregistered)
|
||||||
{
|
{
|
||||||
// before parsing, define cmdline and optionally cfgfile description,
|
// init description
|
||||||
// and also what is visible for the user
|
InitOptionDescription();
|
||||||
AddToCmdLineOptions(fGenericDesc);
|
// parse command line options
|
||||||
AddToCmdLineOptions(fMQParserOptions);
|
|
||||||
|
|
||||||
// if config file option enabled then id non required in cmdline but required in configfile
|
|
||||||
// else required in cmdline
|
|
||||||
if (fUseConfigFile)
|
|
||||||
{
|
|
||||||
fCmdline_options.add_options()
|
|
||||||
("id", po::value< std::string >(), "Device ID");
|
|
||||||
fConfig_file_options.add_options()
|
|
||||||
("id", po::value< std::string >()->required(), "Device ID");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fCmdline_options.add_options()
|
|
||||||
("id", po::value< std::string >()->required(), "Device ID");
|
|
||||||
}
|
|
||||||
|
|
||||||
fVisible_options.add_options()
|
|
||||||
("id", po::value< std::string >()->required(), "Device ID (required value)");
|
|
||||||
|
|
||||||
// parse command line
|
|
||||||
if (ParseCmdLine(argc,argv,fCmdline_options,fvarmap,AllowUnregistered))
|
if (ParseCmdLine(argc,argv,fCmdline_options,fvarmap,AllowUnregistered))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if txt/INI configuration file enabled then parse it
|
// if txt/INI configuration file enabled then parse it as well
|
||||||
if (fUseConfigFile && !fConfigFile.empty())
|
if (fUseConfigFile)
|
||||||
{
|
{
|
||||||
AddToCfgFileOptions(fMQParserOptions,false);
|
// check if file exist
|
||||||
|
if (fs::exists(fConfigFile))
|
||||||
if (ParseCfgFile(fConfigFile, fConfig_file_options, fvarmap, AllowUnregistered))
|
|
||||||
{
|
{
|
||||||
|
if (ParseCfgFile(fConfigFile.string(), fConfig_file_options, fvarmap, AllowUnregistered))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(ERROR)<<"config file '"<< fConfigFile <<"' not found";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set log level before printing (default is 0 = DEBUG level)
|
// set log level before printing (default is 0 = DEBUG level)
|
||||||
int verbose=GetValue<int>("verbose");
|
int verbose=GetValue<int>("verbose");
|
||||||
SET_LOGGER_LEVEL(verbose);
|
SET_LOGGER_LEVEL(verbose);
|
||||||
|
|
||||||
PrintOptions();
|
PrintOptions();
|
||||||
|
|
||||||
|
// check if one of required MQ config option is there
|
||||||
|
auto parserOption_shptr = fMQParserOptions.options();
|
||||||
|
bool option_exists=false;
|
||||||
|
std::vector<std::string> MQParserKeys;
|
||||||
|
for(const auto& p : parserOption_shptr)
|
||||||
|
{
|
||||||
|
MQParserKeys.push_back( p->canonical_display_name() );
|
||||||
|
if( fvarmap.count( p->canonical_display_name() ) )
|
||||||
|
{
|
||||||
|
option_exists=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!option_exists)
|
||||||
|
{
|
||||||
|
LOG(ERROR)<<"Required option to configure the MQ device is not there.";
|
||||||
|
LOG(ERROR)<<"Please provide the value of one of the following key:";
|
||||||
|
for(const auto& p : MQParserKeys)
|
||||||
|
{
|
||||||
|
LOG(ERROR)<<p;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,13 +94,13 @@ int FairMQProgOptions::NotifySwitchOption()
|
||||||
{
|
{
|
||||||
if ( fvarmap.count("help") )
|
if ( fvarmap.count("help") )
|
||||||
{
|
{
|
||||||
std::cout << "***** FAIRMQ Program Options ***** \n" << fVisible_options;
|
LOG(INFO) << "***** FAIRMQ Program Options ***** \n" << fVisible_options;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fvarmap.count("version"))
|
if (fvarmap.count("version"))
|
||||||
{
|
{
|
||||||
std::cout << "Beta version 0.1\n";
|
LOG(INFO) << "Beta version 0.1\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,13 +110,39 @@ int FairMQProgOptions::NotifySwitchOption()
|
||||||
|
|
||||||
void FairMQProgOptions::InitOptionDescription()
|
void FairMQProgOptions::InitOptionDescription()
|
||||||
{
|
{
|
||||||
fMQParserOptions.add_options()
|
// Id required in command line if config txt file not enabled
|
||||||
("config-xml-string", po::value< std::vector<std::string> >()->multitoken(), "XML input as command line string.")
|
if (fUseConfigFile)
|
||||||
("config-xml-file", po::value< std::string >(), "XML input as file.")
|
{
|
||||||
("config-json-string", po::value< std::vector<std::string> >()->multitoken(), "JSON input as command line string.")
|
fMQOptionsInCmd.add_options()
|
||||||
("config-json-file", po::value< std::string >(), "JSON input as file.")
|
("id", po::value< std::string >(), "Device ID (required argument)")
|
||||||
|
("io-threads", po::value<int>()->default_value(1), "io threads number");
|
||||||
|
|
||||||
// ("ini.config.string", po::value< std::vector<std::string> >()->multitoken(), "INI input as command line string.")
|
fMQOptionsInCfg.add_options()
|
||||||
// ("ini.config.file", po::value< std::string >(), "INI input as file.")
|
("id", po::value< std::string >()->required(), "Device ID (required argument)")
|
||||||
;
|
("io-threads", po::value<int>()->default_value(1), "io threads number");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fMQOptionsInCmd.add_options()
|
||||||
|
("id", po::value< std::string >()->required(), "Device ID (required argument)")
|
||||||
|
("io-threads", po::value<int>()->default_value(1), "io threads number");
|
||||||
|
}
|
||||||
|
|
||||||
|
fMQParserOptions.add_options()
|
||||||
|
("config-xml-string", po::value< std::vector<std::string> >()->multitoken(), "XML input as command line string.")
|
||||||
|
("config-xml-file", po::value< std::string >(), "XML input as file.")
|
||||||
|
("config-json-string", po::value< std::vector<std::string> >()->multitoken(), "JSON input as command line string.")
|
||||||
|
("config-json-file", po::value< std::string >(), "JSON input as file.");
|
||||||
|
|
||||||
|
|
||||||
|
AddToCmdLineOptions(fGenericDesc);
|
||||||
|
AddToCmdLineOptions(fMQOptionsInCmd);
|
||||||
|
AddToCmdLineOptions(fMQParserOptions);
|
||||||
|
|
||||||
|
if (fUseConfigFile)
|
||||||
|
{
|
||||||
|
AddToCfgFileOptions(fMQOptionsInCfg,false);
|
||||||
|
AddToCfgFileOptions(fMQParserOptions,false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -74,6 +74,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
po::options_description fMQParserOptions;
|
po::options_description fMQParserOptions;
|
||||||
|
po::options_description fMQOptionsInCfg;
|
||||||
|
po::options_description fMQOptionsInCmd;
|
||||||
pt::ptree fMQtree;
|
pt::ptree fMQtree;
|
||||||
FairMQMap fFairMQmap;
|
FairMQMap fFairMQmap;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,10 @@ int FairProgOptions::AddToCmdLineOptions(const po::options_description& optdesc,
|
||||||
|
|
||||||
int FairProgOptions::AddToCfgFileOptions(const po::options_description& optdesc, bool visible)
|
int FairProgOptions::AddToCfgFileOptions(const po::options_description& optdesc, bool visible)
|
||||||
{
|
{
|
||||||
|
//if UseConfigFile() not yet called, then enable it with required file name to be provided by command line
|
||||||
|
if(!fUseConfigFile)
|
||||||
|
UseConfigFile();
|
||||||
|
|
||||||
fConfig_file_options.add(optdesc);
|
fConfig_file_options.add(optdesc);
|
||||||
if(visible)
|
if(visible)
|
||||||
fVisible_options.add(optdesc);
|
fVisible_options.add(optdesc);
|
||||||
|
@ -82,8 +86,9 @@ void FairProgOptions::UseConfigFile(const std::string& filename)
|
||||||
fUseConfigFile = true;
|
fUseConfigFile = true;
|
||||||
if (filename.empty())
|
if (filename.empty())
|
||||||
{
|
{
|
||||||
fCmdline_options.add_options()
|
fConfigDesc.add_options()
|
||||||
("config,c", po::value<std::string>(&fConfigFile)->required(), "Path to configuration file");
|
("config,c", po::value<boost::filesystem::path>(&fConfigFile)->required(), "Path to configuration file (required argument)");
|
||||||
|
AddToCmdLineOptions(fConfigDesc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -464,6 +469,7 @@ FairProgOptions::VarValInfo_t FairProgOptions::Get_variable_value_info(const po:
|
||||||
if(auto q = boost::any_cast<boost::filesystem::path>(&value))
|
if(auto q = boost::any_cast<boost::filesystem::path>(&value))
|
||||||
{
|
{
|
||||||
std::string val_str = (*q).string();
|
std::string val_str = (*q).string();
|
||||||
|
//std::string val_str = (*q).filename().generic_string();
|
||||||
return std::make_tuple(val_str,std::string(" [Type=boost::filesystem::path]"),defaulted_val,empty_val);
|
return std::make_tuple(val_str,std::string(" [Type=boost::filesystem::path]"),defaulted_val,empty_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
class FairProgOptions
|
class FairProgOptions
|
||||||
{
|
{
|
||||||
|
@ -87,12 +88,6 @@ public:
|
||||||
{
|
{
|
||||||
val = fvarmap[key].as<T>();
|
val = fvarmap[key].as<T>();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(ERROR) << "Key '"<< key <<"' not found in boost variable map";
|
|
||||||
LOG(INFO) << "Command line / txt config file options are the following : ";
|
|
||||||
this->PrintHelp();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -144,7 +139,7 @@ protected:
|
||||||
|
|
||||||
int fVerboseLvl;
|
int fVerboseLvl;
|
||||||
bool fUseConfigFile;
|
bool fUseConfigFile;
|
||||||
std::string fConfigFile;
|
boost::filesystem::path fConfigFile;
|
||||||
virtual int NotifySwitchOption();
|
virtual int NotifySwitchOption();
|
||||||
|
|
||||||
// UpadateVarMap() and replace() --> helper functions to modify the value of variable map after calling po::store
|
// UpadateVarMap() and replace() --> helper functions to modify the value of variable map after calling po::store
|
||||||
|
|
|
@ -13,29 +13,6 @@
|
||||||
namespace FairMQParser
|
namespace FairMQParser
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
//----------- filename version
|
|
||||||
FairMQMap XML::UserParser(const std::string& filename, const std::string& device_id, const std::string& root_node)
|
|
||||||
{
|
|
||||||
boost::property_tree::ptree pt;
|
|
||||||
boost::property_tree::read_xml(filename, pt);
|
|
||||||
return ptreeToMQMap(pt,device_id,root_node,"xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------- stringstream version
|
|
||||||
FairMQMap XML::UserParser(std::stringstream& input_ss, const std::string& device_id, const std::string& root_node)
|
|
||||||
{
|
|
||||||
boost::property_tree::ptree pt;
|
|
||||||
boost::property_tree::read_xml(input_ss, pt);
|
|
||||||
return ptreeToMQMap(pt,device_id,root_node,"xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// other xml examples
|
// other xml examples
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
boost::property_tree::ptree MQXML2::UserParser(const std::string& filename)
|
boost::property_tree::ptree MQXML2::UserParser(const std::string& filename)
|
||||||
|
|
|
@ -27,15 +27,7 @@ namespace FairMQParser
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////// XML ////////////////////////////////////
|
/////////////////////////////////// XML ////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// xml example 1
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
struct XML
|
|
||||||
{
|
|
||||||
FairMQMap UserParser(const std::string& filename, const std::string& device_id, const std::string& root_node="fairMQOptions");
|
|
||||||
FairMQMap UserParser(std::stringstream& input_ss, const std::string& device_id, const std::string& root_node="fairMQOptions");
|
|
||||||
};
|
|
||||||
|
|
||||||
// xml example 2
|
// xml example 2
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
struct MQXML2
|
struct MQXML2
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -58,6 +59,85 @@ int getHostIPs(map<string, string>& addressMap)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// below are SFINAE template functions to check for function member signatures of class
|
||||||
|
namespace details
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// test, at compile time, whether T has BindSendPart member function with returned type R and argument ...Args type
|
||||||
|
template<class T, class Sig, class=void>
|
||||||
|
struct has_BindSendPart:std::false_type{};
|
||||||
|
|
||||||
|
template<class T, class R, class... Args>
|
||||||
|
struct has_BindSendPart
|
||||||
|
<T, R(Args...),
|
||||||
|
typename std::enable_if
|
||||||
|
<
|
||||||
|
std::is_convertible< decltype(std::declval<T>().BindSendPart(std::declval<Args>()...)), R >::value
|
||||||
|
|| std::is_same<R, void>::value
|
||||||
|
>::type
|
||||||
|
>:std::true_type{};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// test, at compile time, whether T has BindGetSocketNumber member function with returned type R and argument ...Args type
|
||||||
|
template<class T, class Sig, class=void>
|
||||||
|
struct has_BindGetSocketNumber:std::false_type{};
|
||||||
|
|
||||||
|
template<class T, class R, class... Args>
|
||||||
|
struct has_BindGetSocketNumber
|
||||||
|
<T, R(Args...),
|
||||||
|
typename std::enable_if
|
||||||
|
<
|
||||||
|
std::is_convertible< decltype(std::declval<T>().BindGetSocketNumber(std::declval<Args>()...)), R >::value
|
||||||
|
|| std::is_same<R, void>::value
|
||||||
|
>::type
|
||||||
|
>:std::true_type{};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// test, at compile time, whether T has BindGetCurrentIndex member function with returned type R and argument ...Args type
|
||||||
|
template<class T, class Sig, class=void>
|
||||||
|
struct has_BindGetCurrentIndex:std::false_type{};
|
||||||
|
|
||||||
|
template<class T, class R, class... Args>
|
||||||
|
struct has_BindGetCurrentIndex
|
||||||
|
<T, R(Args...),
|
||||||
|
typename std::enable_if
|
||||||
|
<
|
||||||
|
std::is_convertible< decltype(std::declval<T>().BindGetCurrentIndex(std::declval<Args>()...)), R >::value
|
||||||
|
|| std::is_same<R, void>::value
|
||||||
|
>::type
|
||||||
|
>:std::true_type{};
|
||||||
|
|
||||||
|
}// end namespace details
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Alias template of the above structs
|
||||||
|
template<class T, class Sig>
|
||||||
|
using has_BindSendPart = std::integral_constant<bool, details::has_BindSendPart<T, Sig>::value>;
|
||||||
|
|
||||||
|
template<class T, class Sig>
|
||||||
|
using has_BindGetSocketNumber = std::integral_constant<bool, details::has_BindGetSocketNumber<T, Sig>::value>;
|
||||||
|
|
||||||
|
template<class T, class Sig>
|
||||||
|
using has_BindGetCurrentIndex = std::integral_constant<bool, details::has_BindGetCurrentIndex<T, Sig>::value>;
|
||||||
|
|
||||||
|
// enable_if Alias template
|
||||||
|
template<typename T>
|
||||||
|
using enable_if_has_BindSendPart = typename std::enable_if<has_BindSendPart<T,void(int)>::value,int>::type;
|
||||||
|
template<typename T>
|
||||||
|
using enable_if_hasNot_BindSendPart = typename std::enable_if<!has_BindSendPart<T,void(int)>::value,int>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using enable_if_has_BindGetSocketNumber = typename std::enable_if<has_BindGetSocketNumber<T,int()>::value,int>::type;
|
||||||
|
template<typename T>
|
||||||
|
using enable_if_hasNot_BindGetSocketNumber = typename std::enable_if<!has_BindGetSocketNumber<T,int()>::value,int>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using enable_if_has_BindGetCurrentIndex = typename std::enable_if<has_BindGetCurrentIndex<T,int()>::value,int>::type;
|
||||||
|
template<typename T>
|
||||||
|
using enable_if_hasNot_BindGetCurrentIndex = typename std::enable_if<!has_BindGetCurrentIndex<T,int()>::value,int>::type;
|
||||||
|
|
||||||
} // namespace tools
|
} // namespace tools
|
||||||
} // namespace FairMQ
|
} // namespace FairMQ
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user