Changeset 155:784bc286a24d in finroc_plugins_data_ports


Ignore:
Timestamp:
28.03.2020 13:46:45 (11 months ago)
Author:
Max Reichardt <mreichardt@…>
Branch:
17.03
Children:
156:9e42f886e71e, 158:9dfbc0672376
Phase:
public
Message:

Revises implementation of bounded ports. Feature-wise this includes improved support in generic ports. Efficiency-wise it results in much smaller binaries.

Files:
11 edited

Legend:

Unmodified
Added
Removed
  • api/tBoundedPort.h

    r123 r155  
    4444// Internal includes with "" 
    4545//---------------------------------------------------------------------- 
    46 #include "plugins/data_ports/tPortCreationInfo.h" 
     46#include "plugins/data_ports/common/tAbstractDataPortCreationInfo.h" 
    4747#include "plugins/data_ports/optimized/tCheapCopyPort.h" 
    4848#include "plugins/data_ports/api/tSingleThreadedCheapCopyPort.h" 
     49#include "plugins/data_ports/api/tPortImplementationTypeTrait.h" 
    4950 
    5051//---------------------------------------------------------------------- 
     
    7172 * Port with upper and lower bounds for values. 
    7273 */ 
    73 template <typename T, tPortImplementationType TYPE> 
     74template <typename T> 
    7475class tBoundedPort : public std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<T>, optimized::tCheapCopyPort>::type 
    7576{ 
    76   typedef tPortImplementation<T, TYPE> tImplementationVariation; 
     77  typedef tPortImplementation<T, tPortImplementationTypeTrait<T>::type> tImplementationVariation; 
    7778  typedef typename std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<T>, optimized::tCheapCopyPort>::type tPortBase; 
    7879 
     
    8283public: 
    8384 
    84   tBoundedPort(const tPortCreationInfo<T>& creation_info) : 
     85  tBoundedPort(common::tAbstractDataPortCreationInfo creation_info) : 
    8586    tPortBase(AdjustCreationInfo(creation_info)), 
    86     bounds(creation_info.GetBounds()) 
    87   { 
     87    bounds(static_cast<const tBounds<T>&>(*creation_info.GetBoundsGeneric())) 
     88  { 
     89  } 
     90 
     91  /*! 
     92   * \param creation_info Port creation info 
     93   * \return Created port 
     94   */ 
     95  static common::tAbstractDataPort* CreateInstance(const common::tAbstractDataPortCreationInfo& creation_info) 
     96  { 
     97    return new tBoundedPort(creation_info); 
    8898  } 
    8999 
     
    115125    if (!bounds.InBounds(value)) 
    116126    { 
    117       typename tPortBase::tUnusedManagerPointer new_buffer(optimized::tGlobalBufferPools::Instance().GetUnusedBuffer(this->GetCheaplyCopiedTypeBufferPoolIndex()).release()); 
     127      typename tPortBase::tUnusedManagerPointer new_buffer(optimized::tGlobalBufferPools::Instance().GetUnusedBuffer(this->GetCheaplyCopiedTypeBufferPoolIndex(), this->GetDataType()).release()); 
    118128      tImplementationVariation::Assign(new_buffer->GetObject().template GetData<T>(), bounds.GetOutOfBoundsDefault()); 
    119129      this->BrowserPublishRaw(new_buffer); // If port is already connected, could this have undesirable side-effects? (I do not think so - otherwise we need to do something more sophisticated here) 
     
    140150   * Make sure non-standard assign flag is set 
    141151   */ 
    142   inline static tPortCreationInfo<T> AdjustCreationInfo(tPortCreationInfo<T> creation_info) 
    143   { 
     152  static common::tAbstractDataPortCreationInfo& AdjustCreationInfo(common::tAbstractDataPortCreationInfo& creation_info) 
     153  { 
     154    if (creation_info.data_type != rrlib::rtti::tDataType<T>() || creation_info.bounds_type != rrlib::rtti::tDataType<T>() || creation_info.bounds.size() < sizeof(tBounds<T>)) 
     155    { 
     156      throw std::invalid_argument("Invalid port creation info passed to tBoundedPort"); 
     157    } 
    144158    creation_info.flags |= core::tFrameworkElement::tFlag::NON_STANDARD_ASSIGN; 
    145159    return creation_info; 
  • api/tGenericPortImplementation.cpp

    r135 r155  
    8181  virtual core::tAbstractPort* CreatePort(const common::tAbstractDataPortCreationInfo& creation_info) override 
    8282  { 
    83     return new tPortBase(creation_info); 
     83    if (creation_info.create_port_function) 
     84    { 
     85      return (*creation_info.create_port_function)(creation_info); 
     86    } 
     87    else 
     88    { 
     89      return new tPortBase(creation_info); 
     90    } 
    8491  } 
    8592 
     
    149156  virtual core::tAbstractPort* CreatePort(const common::tAbstractDataPortCreationInfo& creation_info) override 
    150157  { 
    151     return new tPortBase(creation_info); 
     158    if (creation_info.create_port_function) 
     159    { 
     160      return (*creation_info.create_port_function)(creation_info); 
     161    } 
     162    else 
     163    { 
     164      return new tPortBase(creation_info); 
     165    } 
    152166  } 
    153167 
  • api/tPortImplementation.h

    r123 r155  
    5151#include "plugins/data_ports/api/tSingleThreadedCheapCopyPort.h" 
    5252#include "plugins/data_ports/standard/tStandardPort.h" 
     53#include "plugins/data_ports/tPortCreationInfo.h" 
    5354 
    5455//---------------------------------------------------------------------- 
     
    7980 * Common implementation for all ports derived from tCheapCopyPort 
    8081 */ 
    81 template <typename TWrapper, typename TBuffer, tPortImplementationType TYPE, bool BOUNDABLE> 
     82template <typename T, tPortImplementationType TYPE> 
    8283struct tCheapCopyPortBaseImplementation 
    8384{ 
    84   typedef typename std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<TBuffer>, optimized::tCheapCopyPort>::type tPortBase; 
    85  
    86   static core::tAbstractPort* CreatePort(tPortCreationInfo<TWrapper> creation_info) 
    87   { 
    88     creation_info.UnsetDefaultValue(); // TBuffer might differ from TWrapper => corrupts default value (it is set later in tPort) 
    89     if (creation_info.BoundsSet()) 
     85  typedef typename std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<T>, optimized::tCheapCopyPort>::type tPortBase; 
     86 
     87  static core::tAbstractPort* CreatePort(const tPortCreationInfo<T>& creation_info) 
     88  { 
     89    if (creation_info.create_port_function) 
    9090    { 
    91 #ifdef __nios2__ 
    92       return new tPortBase(creation_info); 
    93 #else 
    94       return new tBoundedPort<TWrapper, TYPE>(creation_info);  // Crashes with release mode in gcc 4.6 and nios gcc 4.8 
    95 #endif 
     91      return (*creation_info.create_port_function)(creation_info); 
    9692    } 
    9793    else 
     
    10298}; 
    10399 
    104 // for non-boundable types 
    105 template <typename TWrapper, typename TBuffer, tPortImplementationType TYPE> 
    106 struct tCheapCopyPortBaseImplementation<TWrapper, TBuffer, TYPE, false> 
    107 { 
    108   typedef typename std::conditional<definitions::cSINGLE_THREADED, api::tSingleThreadedCheapCopyPort<TBuffer>, optimized::tCheapCopyPort>::type tPortBase; 
    109  
    110   static core::tAbstractPort* CreatePort(tPortCreationInfo<TWrapper> creation_info) 
    111   { 
    112     creation_info.UnsetDefaultValue(); // TBuffer might differ from TWrapper => corrupts default value (it is set later in tPort) 
    113     if (creation_info.BoundsSet()) 
    114     { 
    115       FINROC_LOG_PRINT_STATIC(WARNING, "Bounds are not supported for type '", creation_info.data_type.GetName(), "'. Ignoring."); 
    116     } 
    117     return new tPortBase(creation_info); 
    118   } 
    119 }; 
    120  
    121  
    122100// standard cheap-copy implementation 
    123101template <typename T, tPortImplementationType TYPE> 
    124102struct tCheapCopyPortImplementation : 
    125   public tCheapCopyPortBaseImplementation<T, T, tPortImplementationType::CHEAP_COPY, IsBoundable<T>::value> 
     103  public tCheapCopyPortBaseImplementation<T, tPortImplementationType::CHEAP_COPY> 
    126104{ 
    127105  typedef T tPortBuffer; 
     
    220198template <typename T> 
    221199struct tPortImplementation<T, tPortImplementationType::CHEAP_COPY_SINGLE_THREADED> : 
    222   public tCheapCopyPortBaseImplementation<T, T, tPortImplementationType::CHEAP_COPY_SINGLE_THREADED, IsBoundable<T>::value> 
     200  public tCheapCopyPortBaseImplementation<T, tPortImplementationType::CHEAP_COPY_SINGLE_THREADED> 
    223201{ 
    224202  typedef api::tSingleThreadedCheapCopyPort<T> tPortBase; 
     
    289267  static core::tAbstractPort* CreatePort(tPortCreationInfo<T>& pci) 
    290268  { 
    291     if (pci.BoundsSet()) 
    292     { 
    293       FINROC_LOG_PRINT_STATIC(WARNING, "Bounds are not supported for type '", pci.data_type.GetName(), "'. Ignoring."); 
    294     } 
    295269    return new standard::tStandardPort(pci); 
    296270  } 
  • common/tAbstractDataPortCreationInfo.cpp

    r101 r155  
    3737// Internal includes with "" 
    3838//---------------------------------------------------------------------- 
     39#include "plugins/data_ports/api/tBoundedPort.h" 
     40#include "plugins/data_ports/numeric/tNumber.h" 
    3941 
    4042//---------------------------------------------------------------------- 
     
    6971//---------------------------------------------------------------------- 
    7072 
     73namespace 
     74{ 
     75 
     76struct tCreateBoundedPortFunctionRegister 
     77{ 
     78  rrlib::thread::tMutex mutex; 
     79  std::vector<std::pair<rrlib::rtti::tType, tAbstractDataPortCreationInfo::tCreatePortFunction>> functions; 
     80 
     81  tCreateBoundedPortFunctionRegister() 
     82  { 
     83    Add<unsigned char>(); 
     84    Add<signed char>(); 
     85    Add<char>(); 
     86    Add<short>(); 
     87    Add<unsigned short>(); 
     88    Add<int>(); 
     89    Add<unsigned int>(); 
     90    Add<long int>(); 
     91    Add<unsigned long int>(); 
     92    Add<long long int>(); 
     93    Add<unsigned long long int>(); 
     94    Add<size_t>(); 
     95    Add<float>(); 
     96    Add<double>(); 
     97    Add<rrlib::time::tDuration>(); 
     98    Add<numeric::tNumber>(); 
     99  } 
     100 
     101  template <typename T> 
     102  void Add() 
     103  { 
     104    functions.emplace_back(rrlib::rtti::tDataType<T>(), &api::tBoundedPort<T>::CreateInstance); 
     105  } 
     106}; 
     107 
     108tCreateBoundedPortFunctionRegister& CreateBoundedPortFunctionRegister() 
     109{ 
     110  static tCreateBoundedPortFunctionRegister function_register; 
     111  return function_register; 
     112} 
     113 
     114} 
     115 
    71116tAbstractDataPortCreationInfo::tAbstractDataPortCreationInfo() : 
    72117  max_queue_size(-1), 
     
    77122  name_set(false) 
    78123{} 
     124 
     125void tAbstractDataPortCreationInfo::RegisterBoundedPortCreateFunction(const rrlib::rtti::tType& type, tCreatePortFunction function) 
     126{ 
     127  auto& function_register = CreateBoundedPortFunctionRegister(); 
     128  rrlib::thread::tLock lock(function_register.mutex); 
     129  for (auto & entry : function_register.functions) 
     130  { 
     131    if (entry.first == type) 
     132    { 
     133      return; 
     134    } 
     135  } 
     136  function_register.functions.emplace_back(type, function); 
     137} 
     138 
     139void tAbstractDataPortCreationInfo::SetBoundsGeneric(const rrlib::rtti::tGenericObject& min, const rrlib::rtti::tGenericObject& max, tOutOfBoundsAction out_of_bounds_action) 
     140{ 
     141  if (min.GetType() != max.GetType()) 
     142  { 
     143    throw std::invalid_argument("SetBoundsGeneric: min and max need the same type"); 
     144  } 
     145 
     146  bounds_type = min.GetType(); 
     147  size_t type_size = bounds_type.GetSize(); 
     148  bounds.resize(sizeof(size_t) + 3 * type_size + 7);  // This will always be enough 
     149  memcpy(bounds.data(), &out_of_bounds_action, sizeof(size_t)); 
     150  memcpy(bounds.data() + sizeof(size_t), min.GetRawDataPointer(), type_size); 
     151  memcpy(bounds.data() + sizeof(size_t) + type_size, max.GetRawDataPointer(), type_size); 
     152 
     153  auto& function_register = CreateBoundedPortFunctionRegister(); 
     154  for (auto & entry : function_register.functions) 
     155  { 
     156    if (entry.first == bounds_type) 
     157    { 
     158      create_port_function = entry.second; 
     159      return; 
     160    } 
     161  } 
     162  RRLIB_LOG_PRINT(WARNING, "No function to create bounded port for type ", min.GetType(), " registered. Creating unbounded port."); 
     163} 
    79164 
    80165void tAbstractDataPortCreationInfo::SetString(const tString& s) 
  • common/tAbstractDataPortCreationInfo.h

    r101 r155  
    5555namespace data_ports 
    5656{ 
     57 
     58//---------------------------------------------------------------------- 
     59// Forward declarations / typedefs / enums 
     60//---------------------------------------------------------------------- 
     61 
     62namespace api 
     63{ 
     64template <typename T> 
     65class tBoundedPort; 
     66} 
     67 
    5768namespace common 
    5869{ 
    59  
    60 //---------------------------------------------------------------------- 
    61 // Forward declarations / typedefs / enums 
    62 //---------------------------------------------------------------------- 
     70class tAbstractDataPort; 
    6371 
    6472//---------------------------------------------------------------------- 
     
    93101  tString config_entry; 
    94102 
     103  /*! Custom create port function */ 
     104  typedef common::tAbstractDataPort* (*tCreatePortFunction)(const tAbstractDataPortCreationInfo&); 
     105  tCreatePortFunction create_port_function = nullptr; 
     106 
    95107  /*! 
    96108   * Creates port creation info with default values 
     
    100112 
    101113  /*! 
     114   * Registers create function for bounded port of type 'type' 
     115   */ 
     116  template <typename T> 
     117  static tCreatePortFunction RegisterBoundedPortCreateFunction() 
     118  { 
     119    RegisterBoundedPortCreateFunction(rrlib::rtti::tDataType<T>(), &api::tBoundedPort<T>::CreateInstance); 
     120    return &api::tBoundedPort<T>::CreateInstance; 
     121  } 
     122 
     123  /*! 
    102124   * \return Have bounds for port been set? 
    103125   */ 
    104126  bool BoundsSet() const 
    105127  { 
    106     return bounds.GetSize() > 0; 
     128    return bounds.size(); 
    107129  } 
    108130 
     
    116138 
    117139  /*! 
    118    * \return Bounds (when their exact type is not known at compile time) 
    119    */ 
    120   const rrlib::serialization::tConstSource& GetBoundsGeneric() const 
    121   { 
    122     return bounds; 
    123   } 
    124  
    125   /*! 
    126    * \return Bounds (when their exact type is not known at compile time) 
     140   * \return Bounds (when their exact type is not known at compile time). nullptr if no bounds have been set 
     141   */ 
     142  const tBoundsBase* GetBoundsGeneric() const 
     143  { 
     144    return bounds.size() ? reinterpret_cast<const tBoundsBase*>(bounds.data()) : nullptr; 
     145  } 
     146 
     147  /*! 
     148   * \return Default (when its exact type is not known at compile time) 
    127149   */ 
    128150  const rrlib::serialization::tConstSource& GetDefaultGeneric() const 
     
    154176   * \param out_of_bounds_action How to proceed if an incoming value is out of bounds 
    155177   */ 
    156   void SetBoundsGeneric(const rrlib::rtti::tGenericObject& min, const rrlib::rtti::tGenericObject& max, 
    157                         tOutOfBoundsAction out_of_bounds_action = tOutOfBoundsAction::ADJUST_TO_RANGE) 
    158   { 
    159     rrlib::serialization::tOutputStream stream(bounds); 
    160     // critical: needs to be the same serialization as used in tBounds 
    161     min.Serialize(stream); 
    162     max.Serialize(stream); 
    163     stream << out_of_bounds_action; 
    164   } 
     178  void SetBoundsGeneric(const rrlib::rtti::tGenericObject& min, const rrlib::rtti::tGenericObject& max, tOutOfBoundsAction out_of_bounds_action = tOutOfBoundsAction::ADJUST_TO_RANGE); 
    165179 
    166180  void SetDefaultGeneric(const rrlib::rtti::tGenericObject& default_val) 
     
    182196//---------------------------------------------------------------------- 
    183197protected: 
     198 
     199  template <typename T> 
     200  friend class data_ports::api::tBoundedPort; 
    184201 
    185202  /*! 
     
    210227 
    211228  /*! Storage for bounds */ 
    212   tStorage<300> bounds; 
     229  std::vector<unsigned char> bounds; 
     230  rrlib::rtti::tType bounds_type; 
    213231 
    214232  /*! Has name been set? (we do not check name for zero length, because ports without names may be created) */ 
     
    217235 
    218236  /*! 
     237   * Adds create function for bounded port of type 'type' 
     238   * 
     239   * \param type Port data type 
     240   * \param function Create function 
     241   */ 
     242  static void RegisterBoundedPortCreateFunction(const rrlib::rtti::tType& type, tCreatePortFunction function); 
     243 
     244  /*! 
    219245   * Processes next string argument 
    220246   */ 
  • tBounds.h

    r77 r155  
    6262 
    6363/*! How to proceed if an incoming value is out of bounds */ 
    64 enum class tOutOfBoundsAction 
     64enum class tOutOfBoundsAction : size_t 
    6565{ 
    6666  DISCARD,          //!< Discard incoming values that are out of bounds 
     
    6969}; 
    7070 
     71/*! Common base class for tBounds */ 
     72class tBoundsBase 
     73{ 
     74public: 
     75 
     76  /*! 
     77   * \return Action to perform when value is out of range 
     78   */ 
     79  inline tOutOfBoundsAction GetOutOfBoundsAction() const 
     80  { 
     81    return action; 
     82  } 
     83 
     84protected: 
     85 
     86  /*! Action to perform when value is out of range */ 
     87  tOutOfBoundsAction action = tOutOfBoundsAction::DISCARD; 
     88}; 
     89 
    7190//---------------------------------------------------------------------- 
    7291// Class declaration 
     
    81100 */ 
    82101template <typename T> 
    83 class tBounds 
     102class tBounds : public tBoundsBase 
    84103{ 
    85104  static_assert(IsBoundable<T>::value, "Type T is not boundable"); 
     
    98117  tBounds(TMin min, TMax max, tOutOfBoundsAction out_of_bounds_action = tOutOfBoundsAction::ADJUST_TO_RANGE) : 
    99118    min(min), max(max), 
    100     action(out_of_bounds_action), 
    101119    out_of_bounds_default() 
    102120  { 
     121    this->action = out_of_bounds_action; 
    103122    out_of_bounds_default = ToBounds(out_of_bounds_default); 
    104123  } 
     
    112131  tBounds(TMin min, TMax max, T out_of_bounds_default) : 
    113132    min(min), max(max), 
    114     action(tOutOfBoundsAction::APPLY_DEFAULT), 
    115133    out_of_bounds_default(out_of_bounds_default) 
    116134  { 
     135    this->action = tOutOfBoundsAction::APPLY_DEFAULT; 
    117136  } 
    118137 
     
    139158  { 
    140159    return out_of_bounds_default; 
    141   } 
    142  
    143   /*! 
    144    * \return Action to perform when value is out of range 
    145    */ 
    146   inline tOutOfBoundsAction GetOutOfBoundsAction() const 
    147   { 
    148     return action; 
    149160  } 
    150161 
     
    185196  T min, max; 
    186197 
    187   /*! Action to perform when value is out of range */ 
    188   tOutOfBoundsAction action; 
    189  
    190198  /*! Default value when value is out of bounds */ 
    191199  T out_of_bounds_default; 
  • tPort.cpp

    r128 r155  
    7575template class tPort<rrlib::serialization::tMemoryBuffer>; 
    7676 
     77template class api::tBoundedPort<uint8_t>; 
     78template class api::tBoundedPort<int8_t>; 
     79template class api::tBoundedPort<uint16_t>; 
     80template class api::tBoundedPort<int16_t>; 
     81template class api::tBoundedPort<uint32_t>; 
     82template class api::tBoundedPort<int32_t>; 
     83template class api::tBoundedPort<uint64_t>; 
     84template class api::tBoundedPort<int64_t>; 
     85template class api::tBoundedPort<float>; 
     86template class api::tBoundedPort<double>; 
     87template class api::tBoundedPort<numeric::tNumber>; 
     88 
     89 
    7790//---------------------------------------------------------------------- 
    7891// End of namespace declaration 
  • tPort.h

    r154 r155  
    213213  inline typename std::enable_if<AVAILABLE, tBounds<T>>::type GetBounds() const 
    214214  { 
    215     typedef api::tBoundedPort<T, api::tPortImplementationTypeTrait<T>::type> tBoundedPort; 
     215    typedef api::tBoundedPort<T> tBoundedPort; 
    216216    if ((!GetWrapped()) || typeid(*GetWrapped()) != typeid(tBoundedPort)) 
    217217    { 
     
    266266  inline void SetBounds(const typename std::enable_if<AVAILABLE, tBounds<T>>::type& new_bounds) 
    267267  { 
    268     typedef api::tBoundedPort<T, api::tPortImplementationTypeTrait<T>::type> tBoundedPort; 
     268    typedef api::tBoundedPort<T> tBoundedPort; 
    269269    if ((!GetWrapped()) || typeid(*GetWrapped()) != typeid(tBoundedPort)) 
    270270    { 
     
    332332extern template class tPort<rrlib::serialization::tMemoryBuffer>; 
    333333 
     334extern template class api::tBoundedPort<uint8_t>; 
     335extern template class api::tBoundedPort<int8_t>; 
     336extern template class api::tBoundedPort<uint16_t>; 
     337extern template class api::tBoundedPort<int16_t>; 
     338extern template class api::tBoundedPort<uint32_t>; 
     339extern template class api::tBoundedPort<int32_t>; 
     340extern template class api::tBoundedPort<uint64_t>; 
     341extern template class api::tBoundedPort<int64_t>; 
     342extern template class api::tBoundedPort<float>; 
     343extern template class api::tBoundedPort<double>; 
     344extern template class api::tBoundedPort<numeric::tNumber>; 
     345 
    334346//---------------------------------------------------------------------- 
    335347// End of namespace declaration 
  • tPortCreationInfo.h

    r145 r155  
    4646//---------------------------------------------------------------------- 
    4747#include "plugins/data_ports/common/tAbstractDataPortCreationInfo.h" 
     48#include "plugins/data_ports/api/tBoundedPort.h" 
    4849 
    4950//---------------------------------------------------------------------- 
     
    8990  typename std::enable_if<AVAILABLE, tBounds<T>>::type GetBounds() const 
    9091  { 
     92    if (BoundsSet()) 
     93    { 
     94      return *reinterpret_cast<const tBounds<T>*>(bounds.data()); 
     95    } 
    9196    T t = T(); 
    92     tBounds<T> result(t, t); 
    93     if (!BoundsSet()) 
    94     { 
    95       FINROC_LOG_PRINT_STATIC(DEBUG_WARNING, "Bounds were not set"); 
    96       return result; 
    97     } 
    98     rrlib::serialization::tInputStream is(bounds); 
    99     is >> result; 
    100     return result; 
     97    return tBounds<T>(t, t); 
    10198  } 
    10299 
     
    135132  void Set(const typename std::enable_if<AVAILABLE, tBounds<T>>::type& bounds) 
    136133  { 
    137     rrlib::serialization::tOutputStream os(this->bounds); 
    138     os << bounds; 
     134    this->bounds.resize(sizeof(tBounds<T>)); 
     135    memcpy(this->bounds.data(), &bounds, sizeof(tBounds<T>)); 
     136    create_port_function = tAbstractDataPortCreationInfo::RegisterBoundedPortCreateFunction<T>(); 
     137    this->bounds_type = rrlib::rtti::tDataType<T>(); 
    139138  } 
    140139 
  • tests/test_collection.cpp

    r143 r155  
    400400} 
    401401 
     402template <typename T> 
     403void SetBoundsGeneric(T min, T max, tOutOfBoundsAction action) 
     404{ 
     405  common::tAbstractDataPortCreationInfo creation_info; 
     406  creation_info.name = "Bounds Test"; 
     407  creation_info.flags = cDEFAULT_INPUT_PORT_FLAGS; 
     408  creation_info.parent = &core::tRuntimeEnvironment::GetInstance(); 
     409  creation_info.data_type = rrlib::rtti::tDataType<T>(); 
     410 
     411  if (!std::is_arithmetic<T>::value) 
     412  { 
     413    common::tAbstractDataPortCreationInfo::RegisterBoundedPortCreateFunction<T>(); 
     414  } 
     415 
     416  rrlib::rtti::tGenericObjectWrapper<T> min_object(min); 
     417  rrlib::rtti::tGenericObjectWrapper<T> max_object(max); 
     418  creation_info.SetBoundsGeneric(min_object, max_object, action); 
     419 
     420  tGenericPort port(creation_info); 
     421  RRLIB_UNIT_TESTS_ASSERT(typeid(*port.GetWrapped()) == typeid(api::tBoundedPort<T>)); 
     422  api::tBoundedPort<T>& bounded_port = static_cast<api::tBoundedPort<T>&>(*port.GetWrapped()); 
     423  auto bounds = bounded_port.GetBounds(); 
     424  RRLIB_UNIT_TESTS_ASSERT(bounds.GetMin() == min); 
     425  RRLIB_UNIT_TESTS_ASSERT(bounds.GetMax() == max); 
     426  RRLIB_UNIT_TESTS_ASSERT(bounds.GetOutOfBoundsAction() == action); 
     427  port.ManagedDelete(); 
     428} 
     429 
    402430class DataPortsTestCollection : public rrlib::util::tUnitTestSuite 
    403431{ 
     
    431459    TestHijackedPublishing<int>(42); 
    432460    TestGenericPorts<bool>(true, false); 
     461 
     462    SetBoundsGeneric<uint8_t>(4, 9, tOutOfBoundsAction::ADJUST_TO_RANGE); 
     463    SetBoundsGeneric<int16_t>(-12, 900, tOutOfBoundsAction::APPLY_DEFAULT); 
     464    SetBoundsGeneric<int32_t>(-121, 5235623, tOutOfBoundsAction::DISCARD); 
     465    SetBoundsGeneric<int64_t>(-552121, 523511352456623, tOutOfBoundsAction::ADJUST_TO_RANGE); 
     466    SetBoundsGeneric<double>(-552121., 523511352456623, tOutOfBoundsAction::ADJUST_TO_RANGE); 
     467    SetBoundsGeneric<numeric::tNumber>(-552121., 523511352456623, tOutOfBoundsAction::ADJUST_TO_RANGE); 
     468    SetBoundsGeneric<std::pair<int, uint8_t>>(std::pair<int, uint8_t>(-44315, 90), std::pair<int, uint8_t>(-2, 177), tOutOfBoundsAction::APPLY_DEFAULT); 
     469    SetBoundsGeneric<std::array<short, 3>>({ -2, 5, 2}, { 5, -11233, 77 }, tOutOfBoundsAction::APPLY_DEFAULT); 
     470    SetBoundsGeneric<std::tuple<double, short, float>>(std::tuple<double, short, float>(-0.5, 1133, 0.11), std::tuple<double, short, float>(55, -1133, 6436.2), tOutOfBoundsAction::APPLY_DEFAULT); 
    433471  } 
    434472 
  • type_traits.h

    r138 r155  
    142142struct IsBoundable 
    143143{ 
    144   enum { value = tIsCheaplyCopiedType<T>::value && HasSmallerThanOperator<T>::value && (!std::is_same<bool, T>::value) }; 
     144  enum { value = tIsCheaplyCopiedType<T>::value && HasSmallerThanOperator<T>::value && (!std::is_same<bool, T>::value) && rrlib::rtti::IsDefaultConstructionZeroMemory<T>::value }; 
    145145}; 
    146146 
Note: See TracChangeset for help on using the changeset viewer.