Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cberge/dynamic-graph
  • ostasse/dynamic-graph
  • gsaurel/dynamic-graph
  • stack-of-tasks/dynamic-graph
4 results
Show changes
Showing
with 719 additions and 810 deletions
// -*- mode: c++ -*-
// Copyright 2018, Joseph Mirabel LAAS-CNRS
//
#ifndef DYNAMIC_GRAPH_LOGGER_REAL_TIME_DEF_H
#define DYNAMIC_GRAPH_LOGGER_REAL_TIME_DEF_H
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <dynamic-graph/config.hh>
#include <sstream>
#include <vector>
namespace dynamicgraph {
/// \ingroup debug
///
/// \brief Stream for the real-time logger.
///
/// You should inherit from this class in order to redirect the logs where you
/// want.
/// \sa LoggerIOStream
class LoggerStream {
public:
virtual void write(const char *c) = 0;
};
/// Write to an ostream object.
///
/// The easieast is to use the macro dgADD_OSTREAM_TO_RTLOG(ostr) where
/// `ostr` can be `std::cout` or an std::ofstream...
class LoggerIOStream : public LoggerStream {
public:
LoggerIOStream(std::ostream &os) : os_(os) {}
virtual ~LoggerIOStream() {}
virtual void write(const char *c) { os_ << c; }
private:
std::ostream &os_;
};
typedef boost::shared_ptr<LoggerStream> LoggerStreamPtr_t;
class RealTimeLogger;
/// \cond DEVEL
/// \brief write entries to intenal buffer.
///
/// The entry starts when an instance is created and ends when is is deleted.
/// This class is only used by RealTimeLogger.
class RTLoggerStream {
public:
inline RTLoggerStream(RealTimeLogger *logger, std::ostream &os)
: ok_(logger != NULL), logger_(logger), os_(os) {}
template <typename T>
inline RTLoggerStream &operator<<(T t) {
if (ok_) os_ << t;
return *this;
}
inline RTLoggerStream &operator<<(std::ostream &(*pf)(std::ostream &)) {
if (ok_) os_ << pf;
return *this;
}
inline ~RTLoggerStream();
inline bool isNull() { return !ok_; }
private:
const bool ok_;
RealTimeLogger *logger_;
std::ostream &os_;
};
/// \endcond DEVEL
/// \ingroup debug
///
/// \brief Main class of the real-time logger.
///
/// It is intended to be used like this:
/// \code
/// #define ENABLE_RT_LOG
/// #include <dynamic-graph/real-time-logger.h>
///
/// // Somewhere in the main function of your executable
/// int main (int argc, char** argv) {
/// dgADD_OSTREAM_TO_RTLOG (std::cout);
/// }
///
/// // Somewhere in your library
/// dgRTLOG() << "your message. Prefer to use \n than std::endl."
/// \endcode
///
/// \note Thread safety. This class expects to have:
/// - only one reader: the one who take the log entries and write them
/// somewhere.
/// - one writer at a time. Writing to the logs is **never** a blocking
/// operation. If the resource is busy, the log entry is discarded.
class DYNAMIC_GRAPH_DLLAPI RealTimeLogger {
public:
static RealTimeLogger &instance();
static void destroy();
/// \todo add an argument to preallocate the internal string
/// to a given size.
RealTimeLogger(const std::size_t &bufferSize);
inline void clearOutputStreams() { outputs_.clear(); }
inline void addOutputStream(const LoggerStreamPtr_t &os) {
outputs_.push_back(os);
}
/// Write next message to output.
/// It does nothing if the buffer is empty.
/// \return true if it wrote something
bool spinOnce();
/// Return an object onto which a real-time thread can write.
/// The message is considered finished when the object is destroyed.
RTLoggerStream front();
/// Return an empty stream object.
RTLoggerStream emptyStream() { return RTLoggerStream(NULL, oss_); }
inline void frontReady() {
backIdx_ = (backIdx_ + 1) % buffer_.size();
wmutex.unlock();
}
inline bool empty() const { return frontIdx_ == backIdx_; }
inline bool full() const {
return ((backIdx_ + 1) % buffer_.size()) == frontIdx_;
}
inline std::size_t size() const {
if (frontIdx_ <= backIdx_)
return backIdx_ - frontIdx_;
else
return backIdx_ + buffer_.size() - frontIdx_;
}
inline std::size_t getBufferSize() { return buffer_.size(); }
~RealTimeLogger();
private:
struct Data {
std::stringbuf buf;
};
std::vector<LoggerStreamPtr_t> outputs_;
std::vector<Data *> buffer_;
/// Index of the next value to be read.
std::size_t frontIdx_;
/// Index of the slot where to write next value
/// (does not contain valid data).
std::size_t backIdx_;
std::ostream oss_;
/// The writer mutex.
boost::mutex wmutex;
std::size_t nbDiscarded_;
struct thread;
static RealTimeLogger *instance_;
static thread *thread_;
};
RTLoggerStream::~RTLoggerStream() {
if (ok_) {
os_ << std::ends;
logger_->frontReady();
}
}
} // end of namespace dynamicgraph
#endif //! DYNAMIC_GRAPH_LOGGER_REAL_TIME_DEF_H
......@@ -4,182 +4,23 @@
#ifndef DYNAMIC_GRAPH_LOGGER_REAL_TIME_H
#define DYNAMIC_GRAPH_LOGGER_REAL_TIME_H
#include <sstream>
#include <vector>
#include <boost/circular_buffer.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <dynamic-graph/config.hh>
#include <dynamic-graph/debug.h>
namespace dynamicgraph {
/// \ingroup debug
///
/// \brief Stream for the real-time logger.
///
/// You should inherit from this class in order to redirect the logs where you
/// want.
/// \sa LoggerIOStream
class LoggerStream {
public:
virtual void write(const char *c) = 0;
};
/// Write to an ostream object.
///
/// The easieast is to use the macro \ref dgADD_OSTREAM_TO_RTLOG(ostr) where
/// `ostr` can be `std::cout` or an std::ofstream...
class LoggerIOStream : public LoggerStream {
public:
LoggerIOStream(std::ostream &os) : os_(os) {}
virtual void write(const char *c) { os_ << c; }
private:
std::ostream &os_;
};
typedef boost::shared_ptr<LoggerStream> LoggerStreamPtr_t;
class RealTimeLogger;
/// \cond DEVEL
/// \brief write entries to intenal buffer.
///
/// The entry starts when an instance is created and ends when is is deleted.
/// This class is only used by RealTimeLogger.
class RTLoggerStream {
public:
RTLoggerStream(RealTimeLogger *logger, std::ostream &os)
: logger_(logger), os_(os) {}
template <typename T> inline RTLoggerStream &operator<<(T t) {
if (logger_ != NULL)
os_ << t;
return *this;
}
inline RTLoggerStream &operator<<(std::ostream &(*pf)(std::ostream &)) {
if (logger_ != NULL)
os_ << pf;
return *this;
}
~RTLoggerStream();
private:
RealTimeLogger *logger_;
std::ostream &os_;
};
/// \endcond DEVEL
/// \ingroup debug
///
/// \brief Main class of the real-time logger.
///
/// It is intended to be used like this:
/// \code
/// #define ENABLE_RT_LOG
/// #include <dynamic-graph/real-time-logger.h>
///
/// // Somewhere in the main function of your executable
/// int main (int argc, char** argv) {
/// dgADD_OSTREAM_TO_RTLOG (std::cout);
/// }
///
/// // Somewhere in your library
/// dgRTLOG() << "your message. Prefer to use \n than std::endl."
/// \endcode
///
/// \note Thread safety. This class expects to have:
/// - only one reader: the one who take the log entries and write them
/// somewhere.
/// - one writer at a time. Writing to the logs is **never** a blocking
/// operation. If the resource is busy, the log entry is discarded.
class DYNAMIC_GRAPH_DLLAPI RealTimeLogger {
public:
static RealTimeLogger &instance();
static void destroy();
/// \todo add an argument to preallocate the internal string
/// to a given size.
RealTimeLogger(const std::size_t &bufferSize);
inline void clearOutputStreams() { outputs_.clear(); }
inline void addOutputStream(const LoggerStreamPtr_t &os) {
outputs_.push_back(os);
}
/// Write next message to output.
/// It does nothing if the buffer is empty.
/// \return true if it wrote something
bool spinOnce();
/// Return an object onto which a real-time thread can write.
/// The message is considered finished when the object is destroyed.
RTLoggerStream front();
inline void frontReady() {
backIdx_ = (backIdx_ + 1) % buffer_.size();
wmutex.unlock();
}
inline bool empty() const { return frontIdx_ == backIdx_; }
inline bool full() const {
return ((backIdx_ + 1) % buffer_.size()) == frontIdx_;
}
inline std::size_t size() const {
if (frontIdx_ <= backIdx_)
return backIdx_ - frontIdx_;
else
return backIdx_ + buffer_.size() - frontIdx_;
}
inline std::size_t getBufferSize() { return buffer_.size(); }
~RealTimeLogger();
private:
struct Data {
std::stringbuf buf;
};
std::vector<LoggerStreamPtr_t> outputs_;
std::vector<Data *> buffer_;
/// Index of the next value to be read.
std::size_t frontIdx_;
/// Index of the slot where to write next value
/// (does not contain valid data).
std::size_t backIdx_;
std::ostream oss_;
/// The writer mutex.
boost::mutex wmutex;
std::size_t nbDiscarded_;
struct thread;
static RealTimeLogger *instance_;
static thread *thread_;
};
} // end of namespace dynamicgraph
#ifdef ENABLE_RT_LOG
#define dgADD_OSTREAM_TO_RTLOG(ostr) \
::dynamicgraph::RealTimeLogger::instance().addOutputStream( \
::dynamicgraph::LoggerStreamPtr_t( \
#define dgADD_OSTREAM_TO_RTLOG(ostr) \
::dynamicgraph::RealTimeLogger::instance().addOutputStream( \
::dynamicgraph::LoggerStreamPtr_t( \
new ::dynamicgraph::LoggerIOStream(ostr)))
#define dgRTLOG() ::dynamicgraph::RealTimeLogger::instance().front()
#else // ENABLE_RT_LOG
#else // ENABLE_RT_LOG
#define dgADD_OSTREAM_TO_RTLOG(ostr) struct __end_with_semicolon
#define dgRTLOG() \
if (1) \
; \
else \
#define dgRTLOG() \
if (1) \
; \
else \
__null_stream()
#endif
#endif //! DYNAMIC_GRAPH_LOGGER_REAL_TIME_H
#include <dynamic-graph/real-time-logger-def.h>
#endif //! DYNAMIC_GRAPH_LOGGER_REAL_TIME_H
......@@ -8,6 +8,7 @@
#include <dynamic-graph/dynamic-graph-api.h>
#include <dynamic-graph/signal-base.h>
#include <stdio.h>
#include <vector>
namespace dynamicgraph {
......@@ -15,16 +16,16 @@ namespace dynamicgraph {
/// \ingroup dgraph
///
/// \brief TODO
template <class Time> class SignalArray_const {
public:
template <class Time>
class SignalArray_const {
public:
static const int DEFAULT_SIZE = 20;
protected:
protected:
std::vector<const SignalBase<Time> *> const_array;
unsigned int size, rank;
public:
public:
SignalArray_const<Time>(const unsigned int &sizeARG = DEFAULT_SIZE)
: const_array(sizeARG), size(sizeARG), rank(0) {}
......@@ -34,22 +35,22 @@ public:
}
SignalArray_const<Time>(const SignalArray<Time> &siga)
: const_array(siga.getSize()), size(siga.getSize()),
: const_array(siga.getSize()),
size(siga.getSize()),
rank(siga.getSize()) {
for (unsigned int i = 0; i < rank; ++i)
const_array[i] = &siga[i];
for (unsigned int i = 0; i < rank; ++i) const_array[i] = &siga[i];
}
SignalArray_const<Time>(const SignalArray_const<Time> &siga)
: const_array(siga.getSize()), size(siga.getSize()),
: const_array(siga.getSize()),
size(siga.getSize()),
rank(siga.getSize()) {
for (unsigned int i = 0; i < rank; ++i)
const_array[i] = &siga[i];
for (unsigned int i = 0; i < rank; ++i) const_array[i] = &siga[i];
}
virtual ~SignalArray_const<Time>() {}
protected:
protected:
void addElmt(const SignalBase<Time> *el) {
if (rank >= size) {
size += DEFAULT_SIZE;
......@@ -58,13 +59,13 @@ protected:
const_array[rank++] = el;
}
public:
public:
virtual SignalArray_const<Time> &operator<<(const SignalBase<Time> &sig) {
addElmt(&sig);
return *this;
}
public:
public:
virtual const SignalBase<Time> &operator[](const unsigned int &idx) const {
return *const_array[idx];
}
......@@ -82,16 +83,17 @@ SignalArray_const<Time> operator<<(const SignalBase<Time> &sig1,
/// \ingroup dgraph
///
/// \brief TODO
template <class Time> class SignalArray : public SignalArray_const<Time> {
public:
template <class Time>
class SignalArray : public SignalArray_const<Time> {
public:
using SignalArray_const<Time>::DEFAULT_SIZE;
using SignalArray_const<Time>::size;
using SignalArray_const<Time>::rank;
protected:
protected:
mutable std::vector<SignalBase<Time> *> array;
public:
public:
SignalArray<Time>(const unsigned int &sizeARG = DEFAULT_SIZE)
: SignalArray_const<Time>(0), array(sizeARG) {
size = sizeARG;
......@@ -106,13 +108,12 @@ public:
SignalArray<Time>(const SignalArray<Time> &siga)
: SignalArray_const<Time>(siga.getSize()), array(siga.getSize()) {
rank = siga.getSize();
for (unsigned int i = 0; i < rank; ++i)
array[i] = &siga[i];
for (unsigned int i = 0; i < rank; ++i) array[i] = &siga[i];
}
virtual ~SignalArray<Time>() {}
protected:
protected:
void addElmt(SignalBase<Time> *el) {
if (rank >= size) {
size += DEFAULT_SIZE;
......@@ -121,14 +122,14 @@ protected:
array[rank++] = el;
}
public:
public:
virtual SignalArray<Time> &operator<<(SignalBase<Time> &sig) {
addElmt(&sig);
return *this;
}
virtual SignalArray_const<Time>
operator<<(const SignalBase<Time> &sig) const {
virtual SignalArray_const<Time> operator<<(
const SignalBase<Time> &sig) const {
SignalArray_const<Time> res(*this);
res << sig;
return res;
......@@ -148,6 +149,6 @@ SignalArray<Time> operator<<(SignalBase<Time> &sig1, SignalBase<Time> &sig2) {
DYNAMIC_GRAPH_DLLAPI extern SignalArray<int> sotNOSIGNAL;
} // end of namespace dynamicgraph.
} // end of namespace dynamicgraph.
#endif //! DYNAMIC_GRAPH_SIGNAL_ARRAY_H
#endif //! DYNAMIC_GRAPH_SIGNAL_ARRAY_H
......@@ -6,14 +6,14 @@
#ifndef DYNAMIC_GRAPH_SIGNAL_BASE_H
#define DYNAMIC_GRAPH_SIGNAL_BASE_H
#include <dynamic-graph/exception-signal.h>
#include <boost/noncopyable.hpp>
#include <dynamic-graph/fwd.hh>
#include <sstream>
#include <string>
#include <typeinfo>
#include <dynamic-graph/exception-signal.h>
#include <dynamic-graph/fwd.hh>
namespace dynamicgraph {
/** \brief The base class for signals: not to be used as such.
......@@ -23,8 +23,9 @@ namespace dynamicgraph {
value of the signal, which can involve an extra computation,
while the latter accesses a cached value, or 'copy'.
*/
template <class Time> class SignalBase : public boost::noncopyable {
public:
template <class Time>
class SignalBase : public boost::noncopyable {
public:
explicit SignalBase(std::string name = "")
: name(name), signalTime(0), ready(false) {}
......@@ -195,7 +196,7 @@ public:
}
/// \}
protected:
protected:
std::string name;
Time signalTime;
bool ready;
......@@ -206,6 +207,6 @@ template <class Time>
std::ostream &operator<<(std::ostream &os, const SignalBase<Time> &sig) {
return sig.display(os);
}
} // end of namespace dynamicgraph.
} // end of namespace dynamicgraph.
#endif //! DYNAMIC_GRAPH_SIGNAL_BASE_H
#endif //! DYNAMIC_GRAPH_SIGNAL_BASE_H
......@@ -5,191 +5,7 @@
#ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
#define DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
#include <map>
#include <typeinfo>
#include <vector>
#include <boost/any.hpp>
#include <boost/format.hpp>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
#pragma warning "This file is now useless"
#include <dynamic-graph/eigen-io.h>
#include "dynamic-graph/exception-signal.h"
#include "dynamic-graph/signal-caster.h"
#include <dynamic-graph/dynamic-graph-api.h>
namespace dynamicgraph {
/* --- NON GENERIC CASTER ------------------------------------------------- */
/// This class can be used to register default casts, i.e. casts
/// already supported by the object to an std::iostream through the
/// operators >> and << .
template <typename T>
class DefaultCastRegisterer : public SignalCastRegisterer {
public:
DefaultCastRegisterer()
: SignalCastRegisterer(typeid(T), disp, cast, trace) {}
static boost::any cast(std::istringstream &iss);
static void disp(const boost::any &object, std::ostream &os) {
os << boost::any_cast<T>(object) << std::endl;
}
static void trace(const boost::any &object, std::ostream &os) {
disp(object, os);
}
};
/// A default version of the caster, to serialize directly from
/// std::in.
template <typename T>
boost::any DefaultCastRegisterer<T>::cast(std::istringstream &iss) {
T inst;
iss >> inst;
if (iss.fail()) {
boost::format fmt("failed to serialize %s ");
fmt % iss.str();
throw ExceptionSignal(ExceptionSignal::GENERIC, fmt.str());
}
return inst;
}
/* --- GENERIC CASTER ----------------------------------------------------- */
/*!
* This class is only used to group together static functions who differ by
* a template parameter. It is never actually instanced
* (the private constructor
* makes sure of that).
* Typical use of this class is to add the caster in the dg graph:
* dynamicgraph::SignalCastRegisterer sotCastRegisterer_TYPE
* (typeid(TYPE),
* SignalCast<TYPE>::disp_,
* SignalCast<TYPE>::cast_,
* SignalCast<TYPE>::trace_);
* NMSD: I don't really understand the use of this additional class. IMHO
* (comme on dit), it should be possible to rewrite the same-spec macros
* using specialization of the template class DefaultCastRegisterer. No?
*/
template <class T> class SignalCast {
public:
static T cast(std::istringstream &) { throw 1; }
static void disp(const T &, std::ostream &) { throw 1; }
static void trace(const T &t, std::ostream &os) { disp(t, os); }
public:
// adapter functions for SignalCast
static boost::any cast_(std::istringstream &stringValue) {
return boost::any_cast<T>(cast(stringValue));
}
static void disp_(const boost::any &t, std::ostream &os) {
disp(boost::any_cast<T>(t), os);
}
static void trace_(const boost::any &t, std::ostream &os) {
trace(boost::any_cast<T>(t), os);
}
private:
SignalCast() {}
};
} // namespace dynamicgraph
/* -------------------------------------------------------------------------- */
/* --- MACROS --------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Declaration macro: one instance of each class needs to be present in
* order for casts to be registered.
*/
#define DG_SIGNAL_CAST_DECLARATION(TYPE) \
::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##TYPE( \
typeid(TYPE), SignalCast<TYPE>::disp_, SignalCast<TYPE>::cast_, \
SignalCast<TYPE>::trace_)
#define DG_SIGNAL_CAST_DECLARATION_NAMED(TYPE, NAME) \
::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##NAME( \
typeid(TYPE), SignalCast<TYPE>::disp_, SignalCast<TYPE>::cast_, \
SignalCast<TYPE>::trace_)
/* Standard definition macros: the three functions can be specified
* in the macros. To define then in the cpp, just put ';' in the args.
*/
#define DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, CAST, DISP, TRACE) \
template <> class SignalCast<TYPE> { \
public: \
static TYPE cast(std::istringstream &iss) CAST \
static void disp(TYPE const &t, std::ostream &os) DISP \
static void trace(TYPE const &t, std::ostream &os) TRACE public \
: static boost::any cast_(std::istringstream &stringValue) { \
return boost::any_cast<TYPE>(cast(stringValue)); \
} \
static void disp_(const boost::any &t, std::ostream &os) { \
disp(boost::any_cast<TYPE>(t), os); \
} \
static void trace_(const boost::any &t, std::ostream &os) { \
trace(boost::any_cast<TYPE>(t), os); \
} \
}
/* Standard definition macros: the functions <cast> and <disp> have
* to be implemented in the cpp files. The function <trace> is
* implemented as a proxy on <disp>.
*/
#define DG_SIGNAL_CAST_DEFINITION_HPP(TYPE) \
DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, ;, ;, { disp(t, os); })
/* Lazy definition: <cast> and <disp> are to proxys on the standard
* std input (>>) and output (<<). The function <trace> has to be
* implemented in the cpp.
*/
#define DG_SIGNAL_CAST_DEFINITION_TRACE_HPP(TYPE, TRACE) \
DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, \
{ \
TYPE res; \
iss >> res; \
return res; \
}, \
{ os << t << std::endl; }, TRACE)
/* Lazy lazy definition: the three functions are implemented as
* proxys on std::io operation.
*/
#define DG_SIGNAL_CAST_DEFINITION(TYPE) \
DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, \
{ \
TYPE res; \
iss >> res; \
return res; \
}, \
{ os << t << std::endl; }, { disp(t, os); })
/* Lazy definition of <cast> and <disp> with implementation of
* <trace> in the cpp.
*/
#define DG_SIGNAL_CAST_DEFINITION_TRACE(TYPE) \
DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, \
{ \
TYPE res; \
iss >> res; \
return res; \
}, \
{ os << t << std::endl; }, \
;)
/* Macro to add the define SignalCast in the dg graph. Typical use is:
* DG_ADD_CASTER( Matrix,matrix )
*/
#define DG_ADD_CASTER(TYPE, ID) \
::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##ID( \
typeid(TYPE), SignalCast<TYPE>::disp_, SignalCast<TYPE>::cast_, \
SignalCast<TYPE>::trace_)
#endif // #ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
#endif // #ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
......@@ -4,114 +4,142 @@
#ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HH
#define DYNAMIC_GRAPH_SIGNAL_CASTER_HH
#include <map>
#include <typeinfo>
#include <vector>
#include <dynamic-graph/dynamic-graph-api.h>
#include <dynamic-graph/eigen-io.h>
#include <dynamic-graph/linear-algebra.h>
#include <boost/any.hpp>
#include <boost/format.hpp>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
#include <map>
#include <vector>
#include "dynamic-graph/exception-signal.h"
#include <dynamic-graph/dynamic-graph-api.h>
namespace dynamicgraph {
/// This singleton class allows serialization of a number of objects into
/// (disp) and from (cast) std i/o streams.
///
/// The transformation is done at run-time, i.e. SignalCaster
/// doesn't know about the type of objects it casts to.
///
/// It also allows registering of user-defined casts. A cast is
/// identified by the compiler. The mapping from a type to a
/// serialization function is dynamic, hence it is more complex than
/// a typical template-based compile-time resolve. So disp, cast and
/// trace are costly functions and should be used as such.
class DYNAMIC_GRAPH_DLLAPI SignalCaster {
public:
virtual ~SignalCaster();
/// Destroy the unique instance.
static void destroy();
/// Typedef of displayer functions that take an encapsulated 'any'
/// object and displays, cast, or trace it on an output stream
/// (serialization).
typedef boost::function2<void, const boost::any &, std::ostream &>
displayer_type;
typedef boost::function1<boost::any, std::istringstream &> caster_type;
typedef boost::function2<void, const boost::any &, std::ostream &>
tracer_type;
/// Get a reference to the unique object of the class.
static SignalCaster *getInstance(void);
/// Displays an object using a registered displayer function.
void disp(const boost::any &object, std::ostream &os);
/// Traces an object using a registered trace function.
void trace(const boost::any &object, std::ostream &os);
/// Casts an object using a registered cast function.
boost::any cast(const std::type_info &, std::istringstream &iss);
/// Registers a cast.
void registerCast(const std::type_info &type, displayer_type displayer,
caster_type caster, tracer_type tracer);
/// Unregister a cast.
void unregisterCast(const std::type_info &type);
/// Checks if there is a displayer registered with type_name.
bool existsCast(const std::type_info &type) const;
/// Return the list of type names registered.
std::vector<std::string> listTypenames() const;
private:
/// Container for the three cast functions.
typedef boost::tuple<displayer_type, caster_type, tracer_type>
cast_functions_type;
/// \brief Retrieve cast structure from its name.
cast_functions_type &getCast(const std::string &type_name);
/// This map associates the typename of objects and the corresponding
/// using boost::function with 'compatible' syntax
std::map<std::string, cast_functions_type> functions_;
std::map<std::string, const std::type_info *> type_info_;
private:
explicit SignalCaster();
/// Pointer to the unique instance of the class.
static SignalCaster *instance_;
/// Inherit from this class if you want to keep default implementation for some
/// functions.
template <typename T>
struct signal_io_base {
/// serialize a signal value.
inline static void disp(const T &value, std::ostream &os) { os << value; }
/// deserialize a signal value.
inline static T cast(std::istringstream &is) {
T inst;
is >> inst;
if (is.fail()) {
throw ExceptionSignal(ExceptionSignal::GENERIC,
"failed to serialize " + is.str());
}
return inst;
}
/// write a signal value to log file
inline static void trace(const T &value, std::ostream &os) { os << value; }
};
/// The SignalCast registerer class. Can be used to automatically
/// register a cast when instanced somewhere in a cpp file. Pass the
/// typeid () of the type you want to register a cast to as the first
/// argument. The code is provided here so the class does not need
/// to be exported.
class DYNAMIC_GRAPH_DLLAPI SignalCastRegisterer {
public:
inline SignalCastRegisterer(const std::type_info &type,
SignalCaster::displayer_type displayer,
SignalCaster::caster_type caster,
SignalCaster::tracer_type tracer) {
SignalCaster::getInstance()->registerCast(type, displayer, caster, tracer);
/// Inherit from this class if tracing is not implemented for a given type.
template <typename T>
struct signal_io_unimplemented {
inline static void disp(const T &, std::ostream &) {
throw std::logic_error("this disp is not implemented.");
}
inline static T cast(std::istringstream &) {
throw std::logic_error("this cast is not implemented.");
}
inline static void trace(const T &, std::ostream &) {
throw std::logic_error("this trace is not implemented.");
}
};
/// Class used for I/O operations in Signal<T,Time>
template <typename T>
struct signal_io : signal_io_base<T> {};
/// Template specialization of signal_disp for Eigen objects
template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
int _MaxCols>
struct signal_io<
Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>>
: signal_io_base<
Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> {
typedef Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
matrix_type;
inline static void disp(const matrix_type &value, std::ostream &os) {
static const Eigen::IOFormat row_format(
Eigen::StreamPrecision, Eigen::DontAlignCols, " ", " ", "", "", "", "");
os << value.format(row_format);
}
inline static void trace(const matrix_type &value, std::ostream &os) {
static const Eigen::IOFormat row_format(Eigen::StreamPrecision,
Eigen::DontAlignCols, "\t", "\t",
"", "", "", "");
os << value.format(row_format);
}
};
/// Global signal cast template (helper) functions
/// Template specialization of signal_io for Eigen quaternion objects
template <typename _Scalar, int _Options>
struct signal_io<Eigen::Quaternion<_Scalar, _Options>>
: signal_io_base<Eigen::Quaternion<_Scalar, _Options>> {
typedef Eigen::Quaternion<_Scalar, _Options> quat_type;
typedef Eigen::Matrix<_Scalar, 4, 1, _Options> matrix_type;
inline static void disp(const quat_type &value, std::ostream &os) {
signal_io<matrix_type>::disp(value.coeffs(), os);
}
inline static quat_type cast(std::istringstream &is) {
return quat_type(signal_io<matrix_type>::cast(is));
}
inline static void trace(const quat_type &value, std::ostream &os) {
signal_io<matrix_type>::trace(value.coeffs(), os);
}
};
/// Template specialization of signal_io for std::string.
/// Do not print '\n' at the end.
template <>
struct signal_io<std::string> : signal_io_base<std::string> {
inline static std::string cast(std::istringstream &iss) { return iss.str(); }
};
/// Template specialization of signal_io for double
/// to workaround the limitations of the stream based approach.
///
/// When dealing with double: displaying a double on a stream
/// is *NOT* the opposite of reading a double from a stream.
///
/// In practice, it means that there is no way to read
/// a NaN, +inf, -inf from a stream!
///
/// Using these avoid using the typeid () operator and keeps the
/// implementation details hidden.
template <typename T> void signal_disp(const T &value, std::ostream &os) {
SignalCaster::getInstance()->disp(value, os);
}
template <typename T> T signal_cast(std::istringstream &iss) {
return boost::any_cast<T>(SignalCaster::getInstance()->cast(typeid(T), iss));
}
template <typename T> void signal_trace(const T &value, std::ostream &os) {
SignalCaster::getInstance()->trace(value, os);
}
} // end of namespace dynamicgraph.
#endif //! DYNAMIC_GRAPH_SIGNAL_CASTER_HH
/// To workaround this problem, parse special values manually
/// (the strings used are the one produces by displaying special
/// values on a stream).
template <>
struct signal_io<double> : signal_io_base<double> {
inline static double cast(std::istringstream &iss) {
std::string tmp(iss.str());
if (tmp == "nan")
return std::numeric_limits<double>::quiet_NaN();
else if (tmp == "inf" || tmp == "+inf")
return std::numeric_limits<double>::infinity();
else if (tmp == "-inf")
return -1. * std::numeric_limits<double>::infinity();
try {
return boost::lexical_cast<double>(tmp);
} catch (boost::bad_lexical_cast &) {
boost::format fmt("failed to serialize %s (to double)");
fmt % tmp;
throw ExceptionSignal(ExceptionSignal::GENERIC, fmt.str());
}
}
};
} // end of namespace dynamicgraph.
#endif //! DYNAMIC_GRAPH_SIGNAL_CASTER_HH
......@@ -19,18 +19,18 @@
/* --- MACROS ---------------------------------------------------------- */
#define SIGNAL_OUT_FUNCTION_NAME(name) name##SOUT_function
#define DECLARE_SIGNAL(name, IO, type) \
#define DECLARE_SIGNAL(name, IO, type) \
::dynamicgraph::Signal<type, int> m_##name##S##IO
#define CONSTRUCT_SIGNAL(name, IO, type) \
m_##name##S##IO(getClassName() + "(" + getName() + ")::" + #IO + "put(" + \
#define CONSTRUCT_SIGNAL(name, IO, type) \
m_##name##S##IO(getClassName() + "(" + getName() + ")::" + #IO + "put(" + \
#type + ")::" + #name)
#define BIND_SIGNAL_TO_FUNCTION(name, IO, type) \
m_##name##S##IO.setFunction(boost::bind( \
#define BIND_SIGNAL_TO_FUNCTION(name, IO, type) \
m_##name##S##IO.setFunction(boost::bind( \
&EntityClassName::SIGNAL_OUT_FUNCTION_NAME(name), this, _1, _2));
/**/
#define DECLARE_SIGNAL_IN(name, type) \
#define DECLARE_SIGNAL_IN(name, type) \
::dynamicgraph::SignalPtr<type, int> m_##name##SIN
#define CONSTRUCT_SIGNAL_IN(name, type) \
m_##name##SIN(NULL, getClassName() + "(" + getName() + ")::input(" + #type + \
......@@ -38,40 +38,40 @@
/**/
#define DECLARE_SIGNAL_OUT_FUNCTION(name, type) \
#define DECLARE_SIGNAL_OUT_FUNCTION(name, type) \
type &SIGNAL_OUT_FUNCTION_NAME(name)(type &, int)
#define DEFINE_SIGNAL_OUT_FUNCTION(name, type) \
#define DEFINE_SIGNAL_OUT_FUNCTION(name, type) \
type &EntityClassName::SIGNAL_OUT_FUNCTION_NAME(name)(type & s, int iter)
#define SIGNAL_OUT_FUNCTION(name) name##SOUT_function
#define DECLARE_SIGNAL_OUT(name, type) \
public: \
::dynamicgraph::SignalTimeDependent<type, int> m_##name##SOUT; \
\
protected: \
#define DECLARE_SIGNAL_OUT(name, type) \
public: \
::dynamicgraph::SignalTimeDependent<type, int> m_##name##SOUT; \
\
protected: \
type &SIGNAL_OUT_FUNCTION(name)(type &, int)
#define CONSTRUCT_SIGNAL_OUT(name, type, dep) \
m_##name##SOUT( \
boost::bind(&EntityClassName::name##SOUT_function, this, _1, _2), dep, \
#define CONSTRUCT_SIGNAL_OUT(name, type, dep) \
m_##name##SOUT( \
boost::bind(&EntityClassName::name##SOUT_function, this, _1, _2), dep, \
getClassName() + "(" + getName() + ")::output(" + #type + ")::" + #name)
/**************** INNER SIGNALS *******************/
#define SIGNAL_INNER_FUNCTION_NAME(name) name##SINNER_function
#define DECLARE_SIGNAL_INNER_FUNCTION(name, type) \
#define DECLARE_SIGNAL_INNER_FUNCTION(name, type) \
type &SIGNAL_INNER_FUNCTION_NAME(name)(type &, int)
#define DEFINE_SIGNAL_INNER_FUNCTION(name, type) \
#define DEFINE_SIGNAL_INNER_FUNCTION(name, type) \
type &EntityClassName::SIGNAL_INNER_FUNCTION_NAME(name)(type & s, int iter)
#define DECLARE_SIGNAL_INNER(name, type) \
public: \
::dynamicgraph::SignalTimeDependent<type, int> m_##name##SINNER; \
\
protected: \
#define DECLARE_SIGNAL_INNER(name, type) \
public: \
::dynamicgraph::SignalTimeDependent<type, int> m_##name##SINNER; \
\
protected: \
DECLARE_SIGNAL_INNER_FUNCTION(name, type)
#define CONSTRUCT_SIGNAL_INNER(name, type, dep) \
......@@ -79,4 +79,4 @@ protected: \
boost::bind(&EntityClassName::name##SINNER_function, this, _1, _2), dep, \
getClassName() + "(" + getName() + ")::inner(" + #type + ")::" + #name)
#endif // __dynamic_graph_signal_helper_H__
#endif // __dynamic_graph_signal_helper_H__
......@@ -9,8 +9,6 @@
#include <dynamic-graph/exception-signal.h>
#include <dynamic-graph/signal.h>
#include <dynamic-graph/deprecated.hh>
namespace dynamicgraph {
/// \ingroup dgraph
///
......@@ -20,12 +18,17 @@ namespace dynamicgraph {
/// In that sense, when plugged into, it acts as a "pointer" to the
/// input signal, hence the name. Operator -> is also overloaded and
/// can be used to access the pointed signal.
///
/// If the signal provided as a parameter of the plug operation
/// cannot be casted in type T, but is compatible then the class
/// holds a reference to an abstract object.
///
template <class T, class Time>
class SignalPtr : public virtual Signal<T, Time> {
public:
public:
using SignalBase<Time>::getName;
protected:
protected:
Signal<T, Time> *signalPtr;
bool modeNoThrow;
bool transmitAbstract;
......@@ -34,19 +37,22 @@ protected:
inline bool autoref() const { return signalPtr == this; }
public: /* --- CONSTRUCTORS --- */
public: /* --- CONSTRUCTORS --- */
SignalPtr(Signal<T, Time> *ptr, std::string name = "")
: Signal<T, Time>(name), signalPtr(ptr), modeNoThrow(false),
transmitAbstract(false), abstractTransmitter(NULL) {}
: Signal<T, Time>(name),
signalPtr(ptr),
modeNoThrow(false),
transmitAbstract(false),
abstractTransmitter(NULL) {}
virtual ~SignalPtr() { signalPtr = NULL; }
public:
public:
/* --- PLUG-IN OPERATION --- */
Signal<T, Time> *getPtr(); // throw
const Signal<T, Time> *getPtr() const; // throw
SignalBase<Time> *getAbstractPtr(); // throw
const SignalBase<Time> *getAbstractPtr() const; // throw
Signal<T, Time> *getPtr(); // throw
const Signal<T, Time> *getPtr() const; // throw
SignalBase<Time> *getAbstractPtr(); // throw
const SignalBase<Time> *getAbstractPtr() const; // throw
virtual void plug(SignalBase<Time> *ref);
virtual void unplug() { plug(NULL); }
......@@ -63,7 +69,7 @@ public:
inline const Signal<T, Time> &operator*() const { return *getPtr(); }
inline operator bool() const { return isPlugged(); }
public: /* --- INHERITANCE --- */
public: /* --- INHERITANCE --- */
virtual bool needUpdate(const Time &t) const;
virtual std::ostream &writeGraph(std::ostream &os) const;
virtual std::ostream &display(std::ostream &os) const;
......@@ -87,7 +93,7 @@ public: /* --- INHERITANCE --- */
virtual void checkCompatibility();
public: /* --- INHERITANCE --- */
public: /* --- INHERITANCE --- */
/* SignalPtr could be used as a classical signal, through the normal
* setting functions. The behavior is to plugged the signalPtr on
* the classical mother Signal layer of the object.
......@@ -123,7 +129,7 @@ public: /* --- INHERITANCE --- */
std::string next1 = "",
std::string next2 = "") const;
protected: // Interdiction of the rest of the heritage
protected: // Interdiction of the rest of the heritage
using Signal<T, Time>::addDependency;
virtual void addDependency() {}
using Signal<T, Time>::removeDependency;
......@@ -131,7 +137,7 @@ protected: // Interdiction of the rest of the heritage
virtual void clearDependencies() {}
};
} // end of namespace dynamicgraph
} // end of namespace dynamicgraph
#include <dynamic-graph/signal-ptr.t.cpp>
#endif //! DYNAMIC_GRAPH_SIGNAL_PTR_H
#endif //! DYNAMIC_GRAPH_SIGNAL_PTR_H
......@@ -17,10 +17,10 @@ bool SignalPtr<T, Time>::isAbstractPluged() const {
return ((NULL != signalPtr) || (abstractTransmitter));
}
template <class T, class Time> Signal<T, Time> *SignalPtr<T, Time>::getPtr() {
template <class T, class Time>
Signal<T, Time> *SignalPtr<T, Time>::getPtr() {
dgTDEBUGIN(25);
if (!isPlugged())
DG_THROW
if (!isPlugged()) DG_THROW
ExceptionSignal(ExceptionSignal::NOT_INITIALIZED,
"In SignalPtr: SIN ptr not set.", " (in signal <%s>)",
getName().c_str());
......@@ -110,7 +110,8 @@ void SignalPtr<T, Time>::plug(SignalBase<Time> *unknown_ref) {
dgTDEBUGOUT(5);
}
template <class T, class Time> void SignalPtr<T, Time>::checkCompatibility() {
template <class T, class Time>
void SignalPtr<T, Time>::checkCompatibility() {
if (isPlugged() && (!autoref())) {
getPtr()->checkCompatibility();
} else if (isAbstractPluged() && (!autoref())) {
......@@ -127,7 +128,8 @@ bool SignalPtr<T, Time>::needUpdate(const Time &t) const {
return Signal<T, Time>::needUpdate(t);
}
template <class T, class Time> const Time &SignalPtr<T, Time>::getTime() const {
template <class T, class Time>
const Time &SignalPtr<T, Time>::getTime() const {
if ((isAbstractPluged()) && (!autoref())) {
return getAbstractPtr()->getTime();
}
......@@ -158,7 +160,8 @@ const T &SignalPtr<T, Time>::access(const Time &t) {
}
}
template <class T, class Time> const T &SignalPtr<T, Time>::accessCopy() const {
template <class T, class Time>
const T &SignalPtr<T, Time>::accessCopy() const {
if (modeNoThrow && (!isPlugged()) && Signal<T, Time>::copyInit)
return Signal<T, Time>::accessCopy();
else if (autoref())
......@@ -204,10 +207,11 @@ std::ostream &SignalPtr<T, Time>::display(std::ostream &os) const {
}
template <class T, class Time>
std::ostream &
SignalPtr<T, Time>::displayDependencies(std::ostream &os, const int depth,
std::string space, std::string next1,
std::string next2) const {
std::ostream &SignalPtr<T, Time>::displayDependencies(std::ostream &os,
const int depth,
std::string space,
std::string next1,
std::string next2) const {
dgTDEBUGIN(25);
if ((isAbstractPluged()) && (!autoref())) {
getAbstractPtr()->displayDependencies(
......@@ -220,6 +224,6 @@ SignalPtr<T, Time>::displayDependencies(std::ostream &os, const int depth,
return os;
}
} // end of namespace dynamicgraph.
} // end of namespace dynamicgraph.
#endif //! DYNAMIC_GRAPH_SIGNAL_PTR_T_CPP
#endif //! DYNAMIC_GRAPH_SIGNAL_PTR_T_CPP
......@@ -13,23 +13,58 @@ namespace dynamicgraph {
signals,
making sure its inputs are up to date on access, using a incrementing time
tick as reference.
It works this way: for a given SignalTimeDependent S, the user manually
adds dependent signals through the
use of the addDependency function. On access (calling the signal S
operator () or access(Time) function),
if the dependent signals are not up-to-date, i.e. if their [last update]
time is less than the
current time, their value will be access ()'ed to bring them up-to-date.
Thus, the value of dependent
signals can be accessed \b quickly and \b repeatedly through the
accessCopy () function.
It works this way. For a given SignalTimeDependent S,
- the user manually adds dependent signals through the use of the
SignalTimeDependent::addDependency function.
- On access (calling the signal S SignalTimeDependent::operator()(const Time&)
or SignalTimeDependent::access(const Time&) function), if the dependent
signals are not up-to-date, i.e. if their [last update] time is less than the
current time, their value will be SignalTimeDependent::access ()'ed to bring
them up-to-date.
Thus, the value of dependent signals can be accessed \b quickly and
\b repeatedly through the Signal::accessCopy () function.
An example:
\code
class MyEntity : public Entity {
public:
// Some signal dependencies
SignalPtr<T,int> dep1, dep2;
SignalTimeDependent<T,int> signal;
MyEntity (const std::string& name)
: Entity (name)
, signal (
// Set the function that computes the signal value
boost::bind (&Entity::computeSignal, this, _1, _2),
// Declare the dependencies
dep1 << dep2,
"signalname")
{}
T& computeSignal (T& res, int time)
{
// The accesses below update the signal if necessary.
dep1(time);
dep1.access(time);
dep1.recompute(time);
// If dep1 and dep2 are already up-to-date, for a faster access, use
dep1.accessCopy();
dep2.accessCopy();
// Compute res
return res;
}
\endcode
*/
template <class T, class Time>
class SignalTimeDependent : public virtual Signal<T, Time>,
public TimeDependency<Time> {
// TimeDependency<Time> timeDependency;
public:
public:
SignalTimeDependent(std::string name = "");
SignalTimeDependent(const SignalArray_const<Time> &arr,
std::string name = "");
......@@ -128,6 +163,6 @@ Time SignalTimeDependent<T, Time>::getPeriodTime() const {
return TimeDependency<Time>::getPeriodTime();
}
} // end of namespace dynamicgraph
} // end of namespace dynamicgraph
#endif //! DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H
#endif //! DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H
......@@ -10,14 +10,13 @@
#ifndef __SIGNAL_HH
#define __SIGNAL_HH
#include <dynamic-graph/exception-signal.h>
#include <dynamic-graph/signal-base.h>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <string>
#include <dynamic-graph/exception-signal.h>
#include <dynamic-graph/signal-base.h>
#ifdef HAVE_LIBBOOST_THREAD
#include <boost/thread.hpp>
#endif
......@@ -38,8 +37,9 @@ namespace dynamicgraph {
\li using the function setFunction(boost::function2) that will be called
when the signal's value is accessed.
*/
template <class T, class Time> class Signal : public SignalBase<Time> {
protected:
template <class T, class Time>
class Signal : public SignalBase<Time> {
protected:
enum SignalType { CONSTANT, REFERENCE, REFERENCE_NON_CONST, FUNCTION };
static const SignalType SIGNAL_TYPE_DEFAULT = CONSTANT;
......@@ -55,7 +55,7 @@ protected:
bool keepReference;
const static bool KEEP_REFERENCE_DEFAULT = false;
public:
public:
#ifdef HAVE_LIBBOOST_THREAD
typedef boost::try_mutex Mutex;
typedef boost::lock_error MutexError;
......@@ -64,14 +64,14 @@ public:
typedef int *MutexError;
#endif
protected:
protected:
Mutex *providerMutex;
using SignalBase<Time>::signalTime;
public:
public:
using SignalBase<Time>::setReady;
public:
public:
/* --- Constructor/destrusctor --- */
Signal(std::string name);
virtual ~Signal() {}
......@@ -106,21 +106,23 @@ public:
aClassName = typeid(this).name();
}
public:
public:
/// checkCompatibility is used to get the object contained in the
/// signal. This used to verify if a dynamic cast is possible or not.
virtual void checkCompatibility() { throw Tcopy; }
private:
private:
const T &setTcopy(const T &t);
T &getTwork();
const T &getTwork() const;
const T &switchTcopy();
};
} // end of namespace dynamicgraph
} // end of namespace dynamicgraph
#include <dynamic-graph/signal.t.cpp>
#endif // #ifndef __SIGNAL_HH
#endif // #ifndef __SIGNAL_HH
/*
* Local variables:
......
......@@ -12,10 +12,10 @@
#define VP_TEMPLATE_DEBUG_MODE 0
#include <dynamic-graph/debug.h>
#define __SIGNAL_INIT(name, Tcpy, Tref, TrefNC, mutex) \
SignalBase<Time>(name), signalType(SIGNAL_TYPE_DEFAULT), Tcopy1(Tcpy), \
Tcopy2(Tcpy), Tcopy(&Tcopy1), Treference(Tref), \
TreferenceNonConst(TrefNC), Tfunction(), \
#define __SIGNAL_INIT(name, Tcpy, Tref, TrefNC, mutex) \
SignalBase<Time>(name), signalType(SIGNAL_TYPE_DEFAULT), Tcopy1(Tcpy), \
Tcopy2(Tcpy), Tcopy(&Tcopy1), Treference(Tref), \
TreferenceNonConst(TrefNC), Tfunction(), \
keepReference(KEEP_REFERENCE_DEFAULT), providerMutex(mutex)
namespace dynamicgraph {
......@@ -30,18 +30,18 @@ Signal<T, Time>::Signal(std::string name)
template <class T, class Time>
void Signal<T, Time>::set(std::istringstream &stringValue) {
(*this) = signal_cast<T>(stringValue);
(*this) = signal_io<T>::cast(stringValue);
}
template <class T, class Time>
void Signal<T, Time>::get(std::ostream &os) const {
signal_disp<T>(this->accessCopy(), os);
signal_io<T>::disp(this->accessCopy(), os);
}
template <class T, class Time>
void Signal<T, Time>::trace(std::ostream &os) const {
try {
signal_trace<T>(this->accessCopy(), os);
signal_io<T>::trace(this->accessCopy(), os);
} catch DG_RETHROW catch (...) {
DG_THROW ExceptionSignal(ExceptionSignal::SET_IMPOSSIBLE,
"TRACE operation not possible with this signal. ",
......@@ -52,7 +52,8 @@ void Signal<T, Time>::trace(std::ostream &os) const {
/* ------------------------------------------------------------------------ */
template <class T, class Time> const T &Signal<T, Time>::setTcopy(const T &t) {
template <class T, class Time>
const T &Signal<T, Time>::setTcopy(const T &t) {
if (Tcopy == &Tcopy1) {
Tcopy2 = t;
copyInit = true;
......@@ -66,21 +67,24 @@ template <class T, class Time> const T &Signal<T, Time>::setTcopy(const T &t) {
}
}
template <class T, class Time> T &Signal<T, Time>::getTwork() {
template <class T, class Time>
T &Signal<T, Time>::getTwork() {
if (Tcopy == &Tcopy1)
return Tcopy2;
else
return Tcopy1;
}
template <class T, class Time> const T &Signal<T, Time>::getTwork() const {
template <class T, class Time>
const T &Signal<T, Time>::getTwork() const {
if (Tcopy == &Tcopy1)
return Tcopy2;
else
return Tcopy1;
}
template <class T, class Time> const T &Signal<T, Time>::switchTcopy() {
template <class T, class Time>
const T &Signal<T, Time>::switchTcopy() {
if (Tcopy == &Tcopy1) {
Tcopy = &Tcopy2;
return Tcopy2;
......@@ -90,7 +94,8 @@ template <class T, class Time> const T &Signal<T, Time>::switchTcopy() {
}
}
template <class T, class Time> void Signal<T, Time>::setConstant(const T &t) {
template <class T, class Time>
void Signal<T, Time>::setConstant(const T &t) {
signalType = CONSTANT;
setTcopy(t);
setReady();
......@@ -125,62 +130,64 @@ void Signal<T, Time>::setFunction(boost::function2<T &, T &, Time> t,
setReady();
}
template <class T, class Time> const T &Signal<T, Time>::accessCopy() const {
template <class T, class Time>
const T &Signal<T, Time>::accessCopy() const {
return *Tcopy;
}
template <class T, class Time> const T &Signal<T, Time>::access(const Time &t) {
template <class T, class Time>
const T &Signal<T, Time>::access(const Time &t) {
switch (signalType) {
case REFERENCE:
case REFERENCE_NON_CONST: {
if (NULL == providerMutex) {
copyInit = true;
signalTime = t;
return setTcopy(*Treference);
} else {
try {
#ifdef HAVE_LIBBOOST_THREAD
boost::try_mutex::scoped_try_lock lock(*providerMutex);
#endif
case REFERENCE:
case REFERENCE_NON_CONST: {
if (NULL == providerMutex) {
copyInit = true;
signalTime = t;
return setTcopy(*Treference);
} catch (const MutexError &) {
return accessCopy();
} else {
try {
#ifdef HAVE_LIBBOOST_THREAD
boost::try_mutex::scoped_try_lock lock(*providerMutex);
#endif
copyInit = true;
signalTime = t;
return setTcopy(*Treference);
} catch (const MutexError &) {
return accessCopy();
}
}
}
break;
}
break;
}
case FUNCTION: {
if (NULL == providerMutex) {
signalTime = t;
Tfunction(getTwork(), t);
copyInit = true;
return switchTcopy();
} else {
try {
#ifdef HAVE_LIBBOOST_THREAD
boost::try_mutex::scoped_try_lock lock(*providerMutex);
#endif
case FUNCTION: {
if (NULL == providerMutex) {
signalTime = t;
Tfunction(getTwork(), t);
copyInit = true;
return switchTcopy();
} catch (const MutexError &) {
return accessCopy();
} else {
try {
#ifdef HAVE_LIBBOOST_THREAD
boost::try_mutex::scoped_try_lock lock(*providerMutex);
#endif
signalTime = t;
Tfunction(getTwork(), t);
copyInit = true;
return switchTcopy();
} catch (const MutexError &) {
return accessCopy();
}
}
break;
}
break;
}
case CONSTANT:
default:
if (this->getReady()) {
setReady(false);
this->setTime(t);
}
return accessCopy();
case CONSTANT:
default:
if (this->getReady()) {
setReady(false);
this->setTime(t);
}
return accessCopy();
};
}
......@@ -211,23 +218,23 @@ template <class T, class Time>
std::ostream &Signal<T, Time>::display(std::ostream &os) const {
os << "Sig:" << this->name << " (Type ";
switch (this->signalType) {
case Signal<T, Time>::CONSTANT:
os << "Cst";
break;
case Signal<T, Time>::REFERENCE:
os << "Ref";
break;
case Signal<T, Time>::REFERENCE_NON_CONST:
os << "RefNonCst";
break;
case Signal<T, Time>::FUNCTION:
os << "Fun";
break;
case Signal<T, Time>::CONSTANT:
os << "Cst";
break;
case Signal<T, Time>::REFERENCE:
os << "Ref";
break;
case Signal<T, Time>::REFERENCE_NON_CONST:
os << "RefNonCst";
break;
case Signal<T, Time>::FUNCTION:
os << "Fun";
break;
}
return os << ")";
}
} // end of namespace dynamicgraph.
} // end of namespace dynamicgraph.
#undef __SIGNAL_INIT
#endif //! DYNAMIC_GRAPH_SIGNAL_T_CPP
#endif //! DYNAMIC_GRAPH_SIGNAL_T_CPP
......@@ -5,23 +5,24 @@
#ifndef DYNAMIC_GRAPH_TIME_DEPENDENCY_H
#define DYNAMIC_GRAPH_TIME_DEPENDENCY_H
#include <list>
#include <dynamic-graph/fwd.hh>
#include <dynamic-graph/signal-array.h>
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/fwd.hh>
#include <list>
namespace dynamicgraph {
/** \brief A helper class for setting and specifying dependencies
between signals.
*/
template <class Time> class TimeDependency {
public:
template <class Time>
class TimeDependency {
public:
enum DependencyType { TIME_DEPENDENT, BOOL_DEPENDENT, ALWAYS_READY };
mutable Time lastAskForUpdate;
public:
public:
SignalBase<Time> &leader;
typedef std::list<const SignalBase<Time> *> Dependencies;
......@@ -36,13 +37,14 @@ public:
Time periodTime;
static const Time PERIOD_TIME_DEFAULT = 1;
public:
public:
TimeDependency(SignalBase<Time> *sig,
const DependencyType dep = DEPENDENCY_TYPE_DEFAULT);
TimeDependency(SignalBase<Time> *sig, const SignalArray_const<Time> &arr,
const DependencyType dep = DEPENDENCY_TYPE_DEFAULT);
virtual ~TimeDependency() {}
void addDependencies(const SignalArray_const<Time> &arr);
void addDependency(const SignalBase<Time> &sig);
void removeDependency(const SignalBase<Time> &sig);
void clearDependency();
......@@ -66,7 +68,7 @@ public:
Time getPeriodTime() const { return periodTime; }
};
} // end of namespace dynamicgraph
} // end of namespace dynamicgraph
#include <dynamic-graph/time-dependency.t.cpp>
#endif //! DYNAMIC_GRAPH_TIME_DEPENDENCY_H
#endif //! DYNAMIC_GRAPH_TIME_DEPENDENCY_H
......@@ -11,8 +11,8 @@
#define VP_TEMPLATE_DEBUG_MODE 0
#include <dynamic-graph/debug.h>
#define __TIME_DEPENDENCY_INIT(sig, dep) \
leader(*sig), dependencies(), updateFromAllChildren(ALL_READY_DEFAULT), \
#define __TIME_DEPENDENCY_INIT(sig, dep) \
leader(*sig), dependencies(), updateFromAllChildren(ALL_READY_DEFAULT), \
dependencyType(dep), periodTime(PERIOD_TIME_DEFAULT)
namespace dynamicgraph {
......@@ -26,14 +26,19 @@ TimeDependency<Time>::TimeDependency(SignalBase<Time> *sig,
const SignalArray_const<Time> &ar,
const DependencyType dep)
: __TIME_DEPENDENCY_INIT(sig, dep) {
for (unsigned int i = 0; i < ar.getSize(); ++i) {
addDependency(ar[i]);
}
addDependencies(ar);
return;
}
/* ------------------------------------------------------------------------ */
template <class Time>
void TimeDependency<Time>::addDependencies(const SignalArray_const<Time> &ar) {
for (unsigned int i = 0; i < ar.getSize(); ++i) {
addDependency(ar[i]);
}
}
template <class Time>
void TimeDependency<Time>::addDependency(const SignalBase<Time> &sig) {
dependencies.push_front(&sig);
......@@ -44,7 +49,8 @@ void TimeDependency<Time>::removeDependency(const SignalBase<Time> &sig) {
dependencies.remove(&sig);
}
template <class Time> void TimeDependency<Time>::clearDependency() {
template <class Time>
void TimeDependency<Time>::clearDependency() {
dependencies.clear();
}
......@@ -63,19 +69,19 @@ bool TimeDependency<Time>::needUpdate(const Time &t1) const {
}
switch (dependencyType) {
case ALWAYS_READY: {
dgTDEBUGOUT(15);
return true;
}
case BOOL_DEPENDENT:
break;
case TIME_DEPENDENT: {
if (t1 < leader.getTime() + periodTime) {
case ALWAYS_READY: {
dgTDEBUGOUT(15);
return false;
return true;
}
case BOOL_DEPENDENT:
break;
case TIME_DEPENDENT: {
if (t1 < leader.getTime() + periodTime) {
dgTDEBUGOUT(15);
return false;
}
break;
}
break;
}
};
bool res = updateFromAllChildren;
......@@ -108,43 +114,27 @@ bool TimeDependency<Time>::needUpdate(const Time &t1) const {
template <class Time>
std::ostream &TimeDependency<Time>::writeGraph(std::ostream &os) const {
std::string LeaderLocalName;
std::string LeaderNodeName;
leader.ExtractNodeAndLocalNames(LeaderLocalName, LeaderNodeName);
if (dependencies.size() != 0) {
const typename Dependencies::const_iterator itend = dependencies.end();
for (typename Dependencies::const_iterator it = dependencies.begin();
it != itend; ++it) {
std::string itLocalName, itNodeName;
(*it)->ExtractNodeAndLocalNames(itLocalName, itNodeName);
os << "\"" << itNodeName << "\" -> \"" << LeaderNodeName << "\""
<< std::endl
<< " [ headlabel = \"" << LeaderLocalName << "\" , taillabel = \""
<< itLocalName << "\" ]" << std::endl;
}
}
return os;
}
template <class Time>
std::ostream &
TimeDependency<Time>::displayDependencies(std::ostream &os, const int depth,
std::string space, std::string next1,
std::string next2) const {
std::ostream &TimeDependency<Time>::displayDependencies(
std::ostream &os, const int depth, std::string space, std::string next1,
std::string next2) const {
leader.SignalBase<Time>::displayDependencies(os, depth, space, next1, next2)
<< " (";
switch (dependencyType) {
case ALWAYS_READY:
os << "A";
break;
case BOOL_DEPENDENT:
os << "ready=" << ((leader.getReady()) ? "TRUE" : "FALSE");
break;
case TIME_DEPENDENT:
os << "t=" << leader.getTime() << " (/" << periodTime << ") ";
break;
case ALWAYS_READY:
os << "A";
break;
case BOOL_DEPENDENT:
os << "ready=" << ((leader.getReady()) ? "TRUE" : "FALSE");
break;
case TIME_DEPENDENT:
os << "t=" << leader.getTime() << " (/" << periodTime << ") ";
break;
};
os << ")"; //<<std::endl;
os << ")"; //<<std::endl;
{
const typename Dependencies::const_iterator itend = dependencies.end();
for (typename Dependencies::const_iterator it = dependencies.begin();
......@@ -154,7 +144,7 @@ TimeDependency<Time>::displayDependencies(std::ostream &os, const int depth,
std::string ajout = "|";
std::string ajout2 = "|";
typename Dependencies::const_iterator it2 = it;
it2++;
++it2;
if (it2 == dependencies.end()) {
ajout = "`";
ajout2 = " ";
......@@ -169,7 +159,7 @@ TimeDependency<Time>::displayDependencies(std::ostream &os, const int depth,
return os;
}
} // end of namespace dynamicgraph
} // end of namespace dynamicgraph
#undef __TIME_DEPENDENCY_INIT
#endif //! DYNAMIC_GRAPH_TIME_DEPENDENCY_T_CPP
#endif //! DYNAMIC_GRAPH_TIME_DEPENDENCY_T_CPP
......@@ -5,25 +5,25 @@
#ifndef DYNAMIC_GRAPH_TRACER_REAL_TIME_H
#define DYNAMIC_GRAPH_TRACER_REAL_TIME_H
#include <sstream>
#include <dynamic-graph/tracer.h>
#include <dynamic-graph/config-tracer-real-time.hh>
#include <dynamic-graph/fwd.hh>
#include <dynamic-graph/tracer.h>
#include <sstream>
namespace dynamicgraph {
/// \ingroup plugin
///
/// \brief Stream for the tracer real-time.
class DG_TRACERREALTIME_DLLAPI OutStringStream : public std::ostringstream {
public:
public:
char *buffer;
std::streamsize index;
std::streamsize bufferSize;
bool full;
std::string givenname;
public:
public:
OutStringStream();
~OutStringStream();
......@@ -39,7 +39,7 @@ public:
class DG_TRACERREALTIME_DLLAPI TracerRealTime : public Tracer {
DYNAMIC_GRAPH_ENTITY_DECL();
public:
public:
TracerRealTime(const std::string &n);
virtual ~TracerRealTime() {}
......@@ -47,26 +47,27 @@ public:
virtual void trace();
void display(std::ostream &os) const;
DG_TRACERREALTIME_DLLAPI friend std::ostream &
operator<<(std::ostream &os, const TracerRealTime &t);
protected:
virtual void openFile(const SignalBase<int> &sig,
const std::string &filename);
DG_TRACERREALTIME_DLLAPI friend std::ostream &operator<<(
std::ostream &os, const TracerRealTime &t);
virtual void recordSignal(std::ostream &os, const SignalBase<int> &sig);
void emptyBuffers();
void setBufferSize(const int &SIZE) { bufferSize = SIZE; }
const int &getBufferSize() { return bufferSize; }
protected:
virtual void openFile(const SignalBase<int> &sig,
const std::string &filename);
virtual void recordSignal(std::ostream &os, const SignalBase<int> &sig);
typedef std::list<std::ofstream *> HardFileList;
static const int BUFFER_SIZE_DEFAULT = 1048576; // 1Mo
static const int BUFFER_SIZE_DEFAULT = 1048576; // 1Mo
int bufferSize;
HardFileList hardFiles;
};
} // end of namespace dynamicgraph
} // end of namespace dynamicgraph
#endif //! DYNAMIC_GRAPH_TRACER_REAL_TIME_H
#endif //! DYNAMIC_GRAPH_TRACER_REAL_TIME_H
......@@ -5,17 +5,17 @@
#ifndef DYNAMIC_GRAPH_TRACER_H
#define DYNAMIC_GRAPH_TRACER_H
#include <boost/function.hpp>
#include <list>
#include <string>
#include <dynamic-graph/entity.h>
#include <dynamic-graph/exception-traces.h>
#include <dynamic-graph/signal-base.h>
#include <dynamic-graph/signal-time-dependent.h>
#include <dynamic-graph/time-dependency.h>
#include <boost/function.hpp>
#include <dynamic-graph/config-tracer.hh>
#include <list>
#include <mutex>
#include <string>
namespace dynamicgraph {
/// \ingroup plugin
......@@ -24,11 +24,12 @@ namespace dynamicgraph {
class DG_TRACER_DLLAPI Tracer : public Entity {
DYNAMIC_GRAPH_ENTITY_DECL();
protected:
protected:
typedef std::list<const SignalBase<int> *> SignalList;
SignalList toTraceSignals;
std::mutex files_mtx;
public:
public:
enum TraceStyle {
WHEN_SAID
/// Record, then trace to file only when said to.
......@@ -54,7 +55,7 @@ public:
bool play;
int timeStart;
public:
public:
Tracer(const std::string n);
virtual ~Tracer() { closeFiles(); }
......@@ -68,11 +69,11 @@ public:
const std::string &suffix);
virtual void closeFiles();
protected:
protected:
virtual void openFile(const SignalBase<int> &sig,
const std::string &filename);
public:
public:
void setTraceStyle(const TraceStyle &style) { traceStyle = style; }
TraceStyle getTraceStyle() { return traceStyle; }
......@@ -87,7 +88,7 @@ public:
void start() { play = true; }
void stop() { play = false; }
public:
public:
// SignalTrigerer<int> triger;
SignalTimeDependent<int, int> triger;
......@@ -99,6 +100,6 @@ public:
void display(std::ostream &os) const;
};
} // end of namespace dynamicgraph
} // end of namespace dynamicgraph
#endif //! DYNAMIC_GRAPH_TRACER_H
#endif //! DYNAMIC_GRAPH_TRACER_H
......@@ -7,65 +7,86 @@
#ifndef DYNAMIC_GRAPH_VALUE_H
#define DYNAMIC_GRAPH_VALUE_H
#include "dynamic-graph/dynamic-graph-api.h"
#include <cassert>
#include <dynamic-graph/linear-algebra.h>
#include <cassert>
#include <string>
#include <typeinfo>
#include <vector>
#include "dynamic-graph/dynamic-graph-api.h"
namespace dynamicgraph {
namespace command {
class Value;
typedef std::vector<Value> Values;
class DYNAMIC_GRAPH_DLLAPI EitherType {
public:
public:
EitherType(const Value &value);
~EitherType();
operator bool() const;
operator unsigned() const;
operator unsigned long int() const;
operator int() const;
operator long int() const;
operator float() const;
operator double() const;
operator std::string() const;
operator Vector() const;
operator Eigen::MatrixXd() const;
operator Eigen::Matrix4d() const;
operator Values() const;
private:
private:
const Value *value_;
};
/** \ingroup dgraph
\brief This class implements a variant design pattern to handle basic types
in Command.
*/
class DYNAMIC_GRAPH_DLLAPI Value {
public:
public:
enum Type {
NONE,
BOOL,
UNSIGNED,
UNSIGNEDLONGINT,
INT,
LONGINT,
FLOAT,
DOUBLE,
STRING,
VECTOR,
MATRIX,
MATRIX4D,
VALUES,
NB_TYPES
};
~Value();
void deleteValue();
explicit Value(const bool &value);
explicit Value(const unsigned &value);
explicit Value(const unsigned long int &value);
explicit Value(const int &value);
explicit Value(const long int &value);
explicit Value(const float &value);
explicit Value(const double &value);
explicit Value(const std::string &value);
explicit Value(const Vector &value);
explicit Value(const Eigen::MatrixXd &value);
explicit Value(const Eigen::Matrix4d &value);
explicit Value(const Values &value);
/// Copy constructor
Value(const Value &value);
// Construct an empty value (None)
explicit Value();
// operator assignement
Value operator=(const Value &value);
// Equality operator
bool operator==(const Value &other) const;
/// Return the type of the value
Type type() const;
......@@ -88,17 +109,21 @@ public:
DYNAMIC_GRAPH_DLLAPI friend std::ostream &operator<<(std::ostream &os,
const Value &value);
public:
public:
friend class EitherType;
bool boolValue() const;
unsigned unsignedValue() const;
unsigned long int unsignedlongintValue() const;
int intValue() const;
long int longintValue() const;
float floatValue() const;
double doubleValue() const;
std::string stringValue() const;
Vector vectorValue() const;
Eigen::MatrixXd matrixXdValue() const;
Eigen::Matrix4d matrix4dValue() const;
Values valuesValue() const;
const Values &constValuesValue() const;
Type type_;
const void *const value_;
};
......@@ -107,10 +132,11 @@ public:
// Note: to ensure the WIN32 compatibility, it is necessary to export
// the template specialization. Also, it is forbidden to do the template
// specialization declaration in the header file, for the same reason.
template <typename T> struct DYNAMIC_GRAPH_DLLAPI ValueHelper {
template <typename T>
struct DYNAMIC_GRAPH_DLLAPI ValueHelper {
static const Value::Type TypeID;
};
} // namespace command
} // namespace dynamicgraph
} // namespace command
} // namespace dynamicgraph
#endif // DYNAMIC_GRAPH_VALUE_H
#endif // DYNAMIC_GRAPH_VALUE_H
......@@ -6,7 +6,7 @@
<script>
function renderDOTFile() {
var fileInputElement = document.getElementById("fileInputElement");
var reader = new FileReader();
var graphtextres = ""
reader.onloadend = function(e) {
......@@ -27,7 +27,7 @@
.catch(error => {
// Create a new Viz instance (@see Caveats page for more info)
viz = new Viz();
// Possibly display the error
console.error(error);
});
......@@ -37,7 +37,7 @@
</script>
<input type="file" id="fileInputElement">
<input type="file" id="fileInputElement">
<input id="Rendering" type="button" value="Rendering" onclick="renderDOTFile();" />
<script>
var el = document.getElementById("Rendering");
......@@ -49,4 +49,3 @@
</body>
</html>
<?xml version="1.0"?>
<package format="3">
<name>dynamic-graph</name>
<version>4.4.3</version>
<description>
Dynamic graph library
</description>
<maintainer email="guilhem.saurel@laas.fr">Guilhem saurel</maintainer>
<license>BSD</license>
<url>http://github.com/stack-of-tasks/dynamic-graph</url>
<author>Nicolas Mansard</author>
<author>Olivier Stasse</author>
<build_depend>git</build_depend>
<build_depend>doxygen</build_depend>
<!-- The following tags are recommended by REP-136 -->
<exec_depend condition="$ROS_VERSION == 1">catkin</exec_depend>
<exec_depend condition="$ROS_VERSION == 2">ament_cmake</exec_depend>
<depend>eigen</depend>
<depend>boost</depend>
<depend>graphviz</depend>
<buildtool_depend>cmake</buildtool_depend>
<export>
<build_type>cmake</build_type>
</export>
</package>
# Copyright 2010, Olivier Stasse, JRL, CNRS/AIST
#
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
####################################
### Main Library
####################################
SET(LIBRARY_NAME ${PROJECT_NAME})
set(plugins traces/tracer traces/tracer-real-time)
# Verbosity level
IF (NOT (\"${CMAKE_VERBOSITY_LEVEL}\" STREQUAL \"\"))
ADD_DEFINITIONS(-DVP_DEBUG_MODE=${CMAKE_VERBOSITY_LEVEL} -DVP_DEBUG)
ENDIF (NOT (\"${CMAKE_VERBOSITY_LEVEL}\" STREQUAL \"\"))
set(tracer-real-time_deps tracer)
# Declare boost include directories
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
foreach(plugin ${plugins})
get_filename_component(LIBRARY_NAME ${plugin} NAME)
add_library(${LIBRARY_NAME} SHARED "${plugin}.cpp")
ADD_LIBRARY(${LIBRARY_NAME}
SHARED
debug/debug.cpp
debug/real-time-logger.cpp
debug/logger.cpp
if(SUFFIX_SO_VERSION)
set_target_properties(${LIBRARY_NAME} PROPERTIES SOVERSION
${PROJECT_VERSION})
endif(SUFFIX_SO_VERSION)
set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH $ORIGIN)
dgraph/entity.cpp
dgraph/factory.cpp
dgraph/pool.cpp
target_link_libraries(${LIBRARY_NAME} PUBLIC ${PROJECT_NAME}
${${LIBRARY_NAME}_deps})
exception/exception-abstract.cpp
exception/exception-factory.cpp
exception/exception-signal.cpp
exception/exception-traces.cpp
mt/process-list.cpp
signal/signal-array.cpp
signal/signal-caster.cpp
signal/signal-cast-helper.cpp
command/value.cpp
command/command.cpp
)
SET_TARGET_PROPERTIES(${LIBRARY_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
IF (UNIX)
TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${CMAKE_DL_LIBS} pthread)
ENDIF (UNIX)
TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${Boost_LIBRARIES})
#IF (UNIX AND NOT APPLE)
# TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${JRL_MAL_LDFLAGS_OTHER})
#ENDIF (UNIX AND NOT APPLE)
INSTALL(TARGETS ${LIBRARY_NAME}
DESTINATION ${CMAKE_INSTALL_LIBDIR})
####################################
### Plugins
####################################
SET(plugins_list
traces/tracer
traces/tracer-real-time
)
SET(tracer-real-time_dependency tracer)
FOREACH(plugin_file ${plugins_list})
GET_FILENAME_COMPONENT(plugin ${plugin_file} NAME)
ADD_LIBRARY(${plugin} SHARED "${plugin_file}.cpp")
TARGET_LINK_LIBRARIES(${plugin}
${PROJECT_NAME} ${${plugin}_dependency}
${Boost_LIBRARIES})
SET_TARGET_PROPERTIES(${plugin}
PROPERTIES
PREFIX ""
)
INSTALL(TARGETS ${plugin} DESTINATION ${PLUGINDIR})
ENDFOREACH(plugin_file)
install(
TARGETS ${LIBRARY_NAME}
EXPORT ${TARGETS_EXPORT_NAME}
DESTINATION ${DYNAMIC_GRAPH_PLUGINDIR})
endforeach(plugin)