Changeset 132:0e85c0363016 in finroc_plugins_blackboard


Ignore:
Timestamp:
30.11.2017 00:31:52 (4 years ago)
Author:
Max Reichardt <max.reichardt@…>
Branch:
17.03
Parents:
125:fffbda51ef62 (diff), 131:3158500c35a3 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Phase:
public
Message:

Merged with 14.08

Files:
13 edited

Legend:

Unmodified
Added
Removed
  • definitions.h

    r124 r132  
    7575}; 
    7676 
     77/*! 
     78 * Blackboard buffer mode 
     79 */ 
     80enum class tBlackboardBufferMode 
     81{ 
     82  SINGLE_BUFFERED,                   //!< Blackboard is single-buffered: parallel locks except of parallel read locks block; all blackboard accesses access the same buffer in memory 
     83  MULTI_BUFFERED,                    //!< Blackboard is multi-buffered: blackboard is copied on write access; only parallel write locks block (as changes should be made sequentially so that none of them are lost) 
     84  MULTI_BUFFERED_ON_PARALLEL_ACCESS, //!< Blackboard is single-buffered initially: if parallel locks occur that block and would not block in multi-buffered mode - switches to multi-buffered mode 
     85  NONE 
     86}; 
     87 
    7788 
    7889//---------------------------------------------------------------------- 
  • definitions.h

    r129 r132  
    3838// External includes (system with <>, local with "") 
    3939//---------------------------------------------------------------------- 
     40#include "plugins/structure/tComponent.h" 
    4041 
    4142//---------------------------------------------------------------------- 
     
    5556//---------------------------------------------------------------------- 
    5657 
    57 /*! Desired read port configuration (constructor parameter) */ 
    58 enum class tReadPorts 
    59 { 
    60   NONE,     //!< Do not create any read ports 
    61   INTERNAL, //!< Create read port in internal client 
    62   EXTERNAL, //!< Create read port in internal client and also in group's/module's external interface (e.g. "Output" or "Sensor Output") 
    63 }; 
     58/*! Component interface typedef */ 
     59typedef structure::tComponent::tInterface tInterface; 
    6460 
    6561/*! 
  • internal/tBlackboardServer.h

    r124 r132  
    111111  typedef data_ports::tOutputPort<tBuffer> tReadPort; 
    112112 
     113  class tReadLockedBufferPointer : public tConstBufferPointer 
     114  { 
     115    friend class tBlackboardServer; 
     116    typedef tConstBufferPointer tBase; 
     117 
     118    tBlackboardServer* process_pending_on_unlock; 
     119 
     120  public: 
     121    template <typename ... TArgs> 
     122    tReadLockedBufferPointer(TArgs && ... args) : 
     123      tBase(std::forward<TArgs>(args)...), 
     124      process_pending_on_unlock(nullptr) 
     125    { 
     126    } 
     127 
     128    tReadLockedBufferPointer(tReadLockedBufferPointer && other) : 
     129      tBase(std::forward<tBase>(other)), 
     130      process_pending_on_unlock(nullptr) 
     131    { 
     132      std::swap(process_pending_on_unlock, other.process_pending_on_unlock); 
     133    } 
     134 
     135    tReadLockedBufferPointer& operator=(tReadLockedBufferPointer && other) 
     136    { 
     137      tBase::operator=(std::forward<tBase>(other)); 
     138      std::swap(process_pending_on_unlock, other.process_pending_on_unlock); 
     139      return *this; 
     140    } 
     141 
     142    ~tReadLockedBufferPointer() 
     143    { 
     144      if (process_pending_on_unlock) 
     145      { 
     146        process_pending_on_unlock->HandleReadUnlock(*this); 
     147      } 
     148    } 
     149  }; 
     150 
     151 
    113152  /*! 
    114153   * \param name Name/Uid of blackboard 
    115154   * \param parent Parent of blackboard server (usually component-internal blackboard element) 
    116    * \param multi_buffered Create blackboard server that is in multi_buffered mode initially? 
     155   * \param buffer_mode Buffer mode - whether to use multiple buffers to avoid blocking (at the cost of copying content) 
    117156   * \param elements Initial number of elements 
    118157   * \param create_write_port_in Interface to create write port in 
     
    120159   * \param read_port_name Name for read port. If empty, blackboard name will be used. 
    121160   */ 
    122   tBlackboardServer(const std::string& name, core::tFrameworkElement& parent, bool multi_buffered, size_t elements, tInterface& create_write_port_in, tInterface* create_read_port_in = nullptr, const std::string& read_port_name = ""); 
     161  tBlackboardServer(const std::string& name, core::tFrameworkElement& parent, tBlackboardBufferMode buffer_mode, size_t elements, tInterface& create_write_port_in, tInterface* create_read_port_in = nullptr, const std::string& read_port_name = ""); 
    123162 
    124163  virtual ~tBlackboardServer() {} 
     
    147186 
    148187  /*! 
     188   * \return Blackboard's current buffer mode 
     189   */ 
     190  tBlackboardBufferMode GetBufferMode() const 
     191  { 
     192    return buffer_mode; 
     193  } 
     194 
     195  /*! 
    149196   * \return Output port for reading current blackboard data 
    150197   */ 
     
    169216    return write_port; 
    170217  } 
    171  
    172   /*! 
    173    * \return Is this a single buffered blackboard server? 
    174    */ 
    175   //bool IsSingleBuffered(); 
    176218 
    177219  /*! 
     
    182224   * \return Future on locked buffer 
    183225   */ 
    184   rpc_ports::tFuture<tConstBufferPointer> ReadLock(const rrlib::time::tDuration& timeout); 
     226  rpc_ports::tFuture<tReadLockedBufferPointer> ReadLock(const rrlib::time::tDuration& timeout); 
    185227 
    186228  /*! 
     
    198240private: 
    199241 
     242  friend class tReadLockedBuffer; 
     243 
    200244  /*! Wraps read and write lock requests for enqueueing */ 
    201245  class tLockRequest 
     
    210254 
    211255    /*! Promise for read lock, if read lock was requested */ 
    212     rpc_ports::tPromise<tConstBufferPointer> read_lock_promise; 
     256    rpc_ports::tPromise<tReadLockedBufferPointer> read_lock_promise; 
    213257 
    214258    /*! Timeout for lock request */ 
     
    227271    {} 
    228272 
    229     tLockRequest(rpc_ports::tPromise<tConstBufferPointer> && read_lock_promise, rrlib::time::tTimestamp timeout_time) : 
     273    tLockRequest(rpc_ports::tPromise<tReadLockedBufferPointer> && read_lock_promise, rrlib::time::tTimestamp timeout_time) : 
    230274      write_lock(false), 
    231275      write_lock_promise(), 
     
    271315  tUnlockFuture unlock_future; 
    272316 
    273   /*! True, if blackboard server is run in single-buffered mode */ 
    274   bool single_buffered; 
     317  /*! Buffer mode that blackboard server is currently using */ 
     318  tBlackboardBufferMode buffer_mode; 
    275319 
    276320 
     
    316360  void ConsiderPublishing() 
    317361  { 
    318     //if ((!single_buffered) || read_port.GetWrapped()->GetStrategy() > 0)  // TODO: Implementation needs to publish on strategy change, too (e.g. change log blackboard) 
     362    if (buffer_mode != tBlackboardBufferMode::SINGLE_BUFFERED) 
     363      //if ((!single_buffered) || read_port.GetWrapped()->GetStrategy() > 0)  // TODO: Implementation needs to publish on strategy change, too (e.g. change log blackboard) 
    319364    { 
    320365      assert(!current_buffer->IsUnused()); 
     
    349394  virtual void HandleException(rpc_ports::tFutureStatus exception_type) override; 
    350395 
     396  void HandleReadUnlock(tReadLockedBufferPointer& unlock); 
     397 
    351398  virtual void HandleResponse(tLockedBufferData<tBuffer> call_result) override; 
    352399 
  • internal/tBlackboardServer.h

    r129 r132  
    109109  typedef std::vector<tSingleChange> tChangeSet; 
    110110  typedef data_ports::tPortDataPointer<tChangeSet> tChangeSetPointer; 
     111  typedef data_ports::tOutputPort<tBuffer> tReadPort; 
    111112 
    112113  class tReadLockedBufferPointer : public tConstBufferPointer 
     
    151152  /*! 
    152153   * \param name Name/Uid of blackboard 
    153    * \param parent Parent of blackboard server 
     154   * \param parent Parent of blackboard server (usually component-internal blackboard element) 
    154155   * \param buffer_mode Buffer mode - whether to use multiple buffers to avoid blocking (at the cost of copying content) 
    155156   * \param elements Initial number of elements 
    156    * \param shared Share blackboard with other runtime environments? 
    157    */ 
    158   tBlackboardServer(const std::string& name, core::tFrameworkElement* parent = nullptr, tBlackboardBufferMode buffer_mode = tBlackboardBufferMode::MULTI_BUFFERED_ON_PARALLEL_ACCESS, size_t elements = 0, bool shared = true); 
     157   * \param create_write_port_in Interface to create write port in 
     158   * \param create_read_port_in If not nullptr, creates data port for reading blackboard in specified component interface (possibly relevant for data dependencies -> scheduling order) 
     159   * \param read_port_name Name for read port. If empty, blackboard name will be used. 
     160   */ 
     161  tBlackboardServer(const std::string& name, core::tFrameworkElement& parent, tBlackboardBufferMode buffer_mode, size_t elements, tInterface& create_write_port_in, tInterface* create_read_port_in = nullptr, const std::string& read_port_name = ""); 
    159162 
    160163  virtual ~tBlackboardServer() {} 
     
    412415  } 
    413416 
    414   virtual void PrepareDelete() override 
     417  virtual void OnManagedDelete() override 
    415418  { 
    416419    { 
     
    419422      unlock_future = tUnlockFuture(); 
    420423    } 
    421     tAbstractBlackboardServer::PrepareDelete(); 
     424    tAbstractBlackboardServer::OnManagedDelete(); 
     425    read_port.ManagedDelete(); 
     426    write_port.ManagedDelete(); 
    422427  } 
    423428 
  • internal/tBlackboardServer.hpp

    r124 r132  
    8585 
    8686template <typename T> 
    87 tBlackboardServer<T>::tBlackboardServer(const std::string& name, core::tFrameworkElement& parent, bool multi_buffered, size_t elements, tInterface& create_write_port_in, tInterface* create_read_port_in, const std::string& read_port_name) : 
     87tBlackboardServer<T>::tBlackboardServer(const std::string& name, core::tFrameworkElement& parent, tBlackboardBufferMode buffer_mode, size_t elements, tInterface& create_write_port_in, tInterface* create_read_port_in, const std::string& read_port_name) : 
    8888  tAbstractBlackboardServer(&parent, name), 
    8989  read_port(read_port_name.length() ? read_port_name : name, create_read_port_in ? static_cast<core::tFrameworkElement*>(create_read_port_in) : static_cast<core::tFrameworkElement*>(this), (create_read_port_in ? create_read_port_in->GetDefaultPortFlags() : tFlags()) | data_ports::cDEFAULT_OUTPUT_PORT_FLAGS | tFlag::FINSTRUCT_READ_ONLY), 
     
    9595  write_lock(tWriteLock::NONE), 
    9696  unlock_future(), 
    97   single_buffered(!multi_buffered) 
    98 { 
     97  buffer_mode(buffer_mode) 
     98{ 
     99  if (buffer_mode == tBlackboardBufferMode::NONE) 
     100  { 
     101    throw std::invalid_argument("Invalid buffer mode"); 
     102  } 
    99103  read_port.GetWrapped()->template EmplaceAnnotation<tPortWrapperResetter>(read_port); 
    100104  write_port.GetWrapped()->template EmplaceAnnotation<tPortWrapperResetter>(write_port); 
    101105 
    102106  this->Init(); 
     107 
    103108  read_port.Init(); 
    104109  write_port.Init(); 
     
    107112    NewCurrentBuffer(true); 
    108113    rrlib::rtti::ResizeVector(current_buffer->GetObject().GetData<tBuffer>(), elements); 
    109     read_port.GetWrapped()->Publish(current_buffer); 
    110     current_buffer = read_port.GetWrapped()->GetCurrentValueRaw(); 
     114    if (buffer_mode != tBlackboardBufferMode::SINGLE_BUFFERED) 
     115    { 
     116      read_port.GetWrapped()->Publish(current_buffer); 
     117      current_buffer = read_port.GetWrapped()->GetCurrentValueRaw(); 
     118    } 
    111119  } 
    112120  assert(!current_buffer->IsUnused()); 
     
    211219 
    212220template <typename T> 
     221void tBlackboardServer<T>::HandleReadUnlock(tReadLockedBufferPointer& unlock) 
     222{ 
     223  if (!unlock) 
     224  { 
     225    HandleException(rpc_ports::tFutureStatus::READY); 
     226    return; 
     227  } 
     228 
     229  rrlib::thread::tLock lock(this->BlackboardMutex()); 
     230  unlock.Reset(); 
     231  if (current_buffer->Unique()) 
     232  { 
     233    this->ProcessPendingLockRequests(); 
     234  } 
     235} 
     236 
     237template <typename T> 
    213238void tBlackboardServer<T>::HandleResponse(tLockedBufferData<tBuffer> unlock_data) 
    214239{ 
     
    247272 
    248273  // Any pending lock requests? 
     274  unlock_data = tLockedBufferData<tBuffer>(); 
    249275  this->ProcessPendingLockRequests(); 
    250276} 
     
    253279void tBlackboardServer<T>::ProcessPendingLockRequests() 
    254280{ 
     281  assert(current_buffer->Unique() || buffer_mode != tBlackboardBufferMode::SINGLE_BUFFERED); 
    255282  while (pending_lock_requests.size() > 0) 
    256283  { 
     
    260287      if (lock_request.write_lock) 
    261288      { 
    262         WriteLockImplementation(lock_request.write_lock_promise, lock_request.remote_call); 
    263         pending_lock_requests.pop_front(); 
     289        if (current_buffer->Unique() || buffer_mode != tBlackboardBufferMode::SINGLE_BUFFERED) 
     290        { 
     291          WriteLockImplementation(lock_request.write_lock_promise, lock_request.remote_call); 
     292          pending_lock_requests.pop_front(); 
     293        } 
    264294        return; 
    265295      } 
     
    267297      { 
    268298        current_buffer->AddLocks(1); 
    269         tConstBufferPointer pointer_clone(data_ports::standard::tStandardPort::tLockingManagerPointer(current_buffer.get()), *read_port.GetWrapped()); 
     299        tReadLockedBufferPointer pointer_clone(data_ports::standard::tStandardPort::tLockingManagerPointer(current_buffer.get()), *read_port.GetWrapped()); 
     300        pointer_clone.process_pending_on_unlock = this; 
    270301        lock_request.read_lock_promise.SetValue(pointer_clone); 
    271302      } 
     
    276307 
    277308template <typename T> 
    278 rpc_ports::tFuture<typename tBlackboardServer<T>::tConstBufferPointer> tBlackboardServer<T>::ReadLock(const rrlib::time::tDuration& timeout) 
    279 { 
    280   rrlib::thread::tLock lock(this->BlackboardMutex()); 
    281   rpc_ports::tPromise<tConstBufferPointer> promise; 
    282   rpc_ports::tFuture<tConstBufferPointer> future = promise.GetFuture(); 
    283   if (write_lock != tWriteLock::EXCLUSIVE) 
     309rpc_ports::tFuture<typename tBlackboardServer<T>::tReadLockedBufferPointer> tBlackboardServer<T>::ReadLock(const rrlib::time::tDuration& timeout) 
     310{ 
     311  rrlib::thread::tLock lock(this->BlackboardMutex()); 
     312  rpc_ports::tPromise<tReadLockedBufferPointer> promise; 
     313  rpc_ports::tFuture<tReadLockedBufferPointer> future = promise.GetFuture(); 
     314  //if ((buffer_mode != tBlackboardBufferMode::SINGLE_BUFFERED && write_lock != tWriteLock::EXCLUSIVE) || (buffer_mode == tBlackboardBufferMode::SINGLE_BUFFERED && current_buffer->Unique())) 
     315  if (write_lock != tWriteLock::EXCLUSIVE && (buffer_mode != tBlackboardBufferMode::SINGLE_BUFFERED || pending_lock_requests.empty() /*|| (!pending_lock_requests[0].write_lock)*/)) 
    284316  { 
    285317    assert(!current_buffer->IsUnused()); 
    286318    current_buffer->AddLocks(1); 
    287     tConstBufferPointer pointer_clone(data_ports::standard::tStandardPort::tLockingManagerPointer(current_buffer.get()), *read_port.GetWrapped()); 
     319    tReadLockedBufferPointer pointer_clone(data_ports::standard::tStandardPort::tLockingManagerPointer(current_buffer.get()), *read_port.GetWrapped()); 
     320    pointer_clone.process_pending_on_unlock = this; 
    288321    promise.SetValue(pointer_clone); 
    289322  } 
    290323  else 
    291324  { 
    292     FINROC_LOG_PRINT(DEBUG, "Attempt to read-lock during exclusive write lock. Enabling multi-buffered mode to avoid blocking in such situations in the future."); 
    293     single_buffered = false; 
     325    if (buffer_mode == tBlackboardBufferMode::MULTI_BUFFERED_ON_PARALLEL_ACCESS) 
     326    { 
     327      FINROC_LOG_PRINT(DEBUG, "Attempt to read-lock during exclusive write lock. Enabling multi-buffered mode to avoid blocking in such situations in the future."); 
     328      buffer_mode = tBlackboardBufferMode::MULTI_BUFFERED; 
     329    } 
    294330    if (timeout > rrlib::time::tDuration::zero()) 
    295331    { 
     
    306342  rpc_ports::tPromise<tLockedBuffer<tBuffer>> promise; 
    307343  rpc_ports::tFuture<tLockedBuffer<tBuffer>> future = promise.GetFuture(); 
    308   if (write_lock == tWriteLock::NONE) 
     344  if ((buffer_mode != tBlackboardBufferMode::SINGLE_BUFFERED && write_lock == tWriteLock::NONE) || (buffer_mode == tBlackboardBufferMode::SINGLE_BUFFERED && current_buffer->Unique())) 
    309345  { 
    310346    WriteLockImplementation(promise, lock_parameters.IsRemoteCall()); 
     
    338374  else 
    339375  { 
     376    assert(buffer_mode != tBlackboardBufferMode::SINGLE_BUFFERED); 
    340377    write_lock = tWriteLock::ON_COPY; 
    341378    lock_id++; 
  • internal/tBlackboardServer.hpp

    r129 r132  
    6565//---------------------------------------------------------------------- 
    6666 
    67 inline core::tFrameworkElement::tFlags GenerateConstructorFlags(bool shared) 
    68 { 
    69   return shared ? core::tFrameworkElement::tFlags(core::tFrameworkElement::tFlag::SHARED) : core::tFrameworkElement::tFlags(); 
    70 } 
    71  
    72 template <typename T> 
    73 tBlackboardServer<T>::tBlackboardServer(const std::string& name, core::tFrameworkElement* parent, tBlackboardBufferMode buffer_mode, size_t elements, bool shared) : 
    74   tAbstractBlackboardServer(parent, name, GenerateConstructorFlags(shared)), 
    75   read_port("read", this, core::tFrameworkElement::tFlag::FINSTRUCT_READ_ONLY | GenerateConstructorFlags(shared)), 
    76   write_port(rpc_ports::tServerPort<tBlackboardServer<T>>(*this, "write", this, GetRPCInterfaceType(), GenerateConstructorFlags(shared))), 
     67namespace 
     68{ 
     69// Used to reset port wrappers in BlackboardServer - to make sure that ManagedDelete() is not called on already deleted ports 
     70class tPortWrapperResetter : public core::tAnnotation 
     71{ 
     72public: 
     73  tPortWrapperResetter(core::tPortWrapperBase& wrapper) : wrapper(wrapper) 
     74  {} 
     75 
     76  core::tPortWrapperBase& wrapper; 
     77 
     78  virtual void OnManagedDelete() override 
     79  { 
     80    wrapper = core::tPortWrapperBase(); 
     81  } 
     82}; 
     83 
     84} 
     85 
     86template <typename T> 
     87tBlackboardServer<T>::tBlackboardServer(const std::string& name, core::tFrameworkElement& parent, tBlackboardBufferMode buffer_mode, size_t elements, tInterface& create_write_port_in, tInterface* create_read_port_in, const std::string& read_port_name) : 
     88  tAbstractBlackboardServer(&parent, name), 
     89  read_port(read_port_name.length() ? read_port_name : name, create_read_port_in ? static_cast<core::tFrameworkElement*>(create_read_port_in) : static_cast<core::tFrameworkElement*>(this), (create_read_port_in ? create_read_port_in->GetDefaultPortFlags() : tFlags()) | data_ports::cDEFAULT_OUTPUT_PORT_FLAGS | tFlag::FINSTRUCT_READ_ONLY), 
     90  write_port(rpc_ports::tServerPort<tBlackboardServer<T>>(*this, name, &create_write_port_in, GetRPCInterfaceType(), create_write_port_in.GetDefaultPortFlags())), 
    7791  pending_change_tasks(), 
    7892  pending_lock_requests(), 
     
    87101    throw std::invalid_argument("Invalid buffer mode"); 
    88102  } 
     103  read_port.GetWrapped()->template EmplaceAnnotation<tPortWrapperResetter>(read_port); 
     104  write_port.GetWrapped()->template EmplaceAnnotation<tPortWrapperResetter>(write_port); 
     105 
     106  this->Init(); 
    89107 
    90108  read_port.Init(); 
  • tBlackboard.h

    r124 r132  
    9393  typedef typename tServer::tReadPort tReadPort; 
    9494 
     95  struct tBlackboardBufferModeParameter 
     96  { 
     97    tBlackboardBufferModeParameter(tBlackboardBufferMode buffer_mode) : buffer_mode(buffer_mode) {} 
     98 
     99    // Constructor for legacy compatibility 
     100    tBlackboardBufferModeParameter(bool multi_buffered) : buffer_mode(multi_buffered ? tBlackboardBufferMode::MULTI_BUFFERED : tBlackboardBufferMode::MULTI_BUFFERED_ON_PARALLEL_ACCESS) {} 
     101 
     102    tBlackboardBufferMode buffer_mode; 
     103  }; 
     104 
     105 
    95106  /*! 
    96107   * Empty constructor for blackboards that are not initialized in 
     
    108119   * \param name Name of blackboard 
    109120   * \param parent Component that contains blackboard 
    110    * \param multi_buffered Create multi-buffered blackboard? 
     121   * \param buffer_mode Buffer mode - whether to use multiple buffers to avoid blocking (at the cost of copying content) 
    111122   * \param elements Initial number of elements 
    112123   * \param create_client Create Blackboard client? (to access blackboard using this object's GetClient()) 
     
    116127   */ 
    117128  template <typename TParent> 
    118   tBlackboard(const std::string& name, TParent* parent, bool multi_buffered = false, int elements = 0, bool create_client = true, 
     129  tBlackboard(const std::string& name, TParent* parent, const tBlackboardBufferModeParameter& buffer_mode = tBlackboardBufferMode::MULTI_BUFFERED_ON_PARALLEL_ACCESS, int elements = 0, bool create_client = true, 
    119130              tInterface* create_read_port_in = UseDefaultComponentInterface(), const std::string& read_port_name = "", bool create_read_port_in_client = true) : 
    120131    wrapped_server(nullptr), 
     
    122133    read_port() 
    123134  { 
     135    create_read_port_in = buffer_mode.buffer_mode == tBlackboardBufferMode::SINGLE_BUFFERED ? nullptr : create_read_port_in; 
     136 
    124137    // Create blackboard server 
    125138    tInterface& blackboards_parent = GetBlackboardsParent(*parent); 
    126139    create_read_port_in = create_read_port_in == UseDefaultComponentInterface() ? GetDefaultReadPortInterface(parent, nullptr) : create_read_port_in; 
    127     wrapped_server = new internal::tBlackboardServer<T>(name, blackboards_parent, multi_buffered, elements, parent->GetServices(), create_read_port_in, read_port_name); 
     140    wrapped_server = new internal::tBlackboardServer<T>(name, blackboards_parent, buffer_mode.buffer_mode, elements, parent->GetServices(), create_read_port_in, read_port_name); 
    128141    write_port = wrapped_server->GetWritePort(); 
    129142    if (create_read_port_in && create_read_port_in_client) 
     
    190203 
    191204  /*! 
     205   * \return Blackboard's current buffer mode 
     206   */ 
     207  tBlackboardBufferMode GetBufferMode() const 
     208  { 
     209    return wrapped_server ? wrapped_server->GetBufferMode() : tBlackboardBufferMode::NONE; 
     210  } 
     211 
     212  /*! 
    192213   * \return Wrapped blackboard client - contains NULL pointer if no such client was created 
    193214   */ 
  • tBlackboard.h

    r129 r132  
    3131 * 
    3232 * This is a convenience class to create a blackboard server 
    33  * (and possibly client) in a group or module. 
    34  * 
    35  * This allows considering blackboard edges in scheduling. 
    36  * 
    37  * It can also be used in a group to allow access to a blackboard 
    38  * of an inner module or group. 
     33 * (and possibly client) in a (composite) component. 
     34 * 
     35 * Read ports in data port interface allow considering blackboard edges in scheduling. 
     36 * 
     37 * This class can furthermore be used in a composite component to allow access to a blackboard 
     38 * of an inner component. 
    3939 * 
    4040 */ 
     
    7171/*! 
    7272 * This is a convenience class to create a blackboard server 
    73  * (and possibly client) in a group or module. 
    74  * 
    75  * This allows considering blackboard edges in scheduling. 
    76  * 
    77  * It can also be used in a group to allow access to a blackboard 
    78  * of an inner module or group. 
     73 * (and possibly client) in a (composite) component. 
     74 * 
     75 * Read ports in data port interface allow considering blackboard edges in scheduling. 
     76 * 
     77 * This class can furthermore be used in a composite component to allow access to a blackboard 
     78 * of an inner component. 
    7979 */ 
    8080template <typename T> 
    8181class tBlackboard : public internal::tBlackboardBase 
    8282{ 
    83   template <typename TParent> 
    84   struct tGetReadPortType; 
    8583 
    8684//---------------------------------------------------------------------- 
     
    9189  typedef tBlackboardWriteAccess<T> tWriteAccess; 
    9290  typedef tBlackboardReadAccess<T> tReadAccess; 
    93  
    9491  typedef internal::tBlackboardServer<T> tServer; 
    95  
    9692  typedef typename tServer::tBuffer tBuffer; 
     93  typedef typename tServer::tReadPort tReadPort; 
    9794 
    9895  struct tBlackboardBufferModeParameter 
     
    112109   */ 
    113110  tBlackboard() : 
    114     wrapped_server(NULL), 
     111    wrapped_server(nullptr), 
    115112    wrapped_client(), 
    116113    read_port() 
     
    118115 
    119116  /*! 
    120    * Constructor for use in tGroup, tModule and tSenseControlModule 
    121    * (per default, full-blackboard-access-ports are created in Input/ControllerInput. 
    122    *  If this is not desired, the last two constructor parameters can be used to specify alternatives.) 
     117   * Constructor for creating a new blackboard in a component. 
    123118   * 
    124119   * \param name Name of blackboard 
    125    * \param parent Parent of blackboard 
     120   * \param parent Component that contains blackboard 
    126121   * \param buffer_mode Buffer mode - whether to use multiple buffers to avoid blocking (at the cost of copying content) 
    127122   * \param elements Initial number of elements 
    128    * \param create_client Create Blackboard client? 
    129    * \param create_read_port Which read ports to create for blackboard (no read ports are created for single-buffere blackboards) 
    130    * \param create_write_port_in If not NULL, creates write port in specified port group 
    131    * \param create_write_port_in2 If not NULL, creates another write port in specified port group 
     123   * \param create_client Create Blackboard client? (to access blackboard using this object's GetClient()) 
     124   * \param create_read_port_in If not nullptr, creates data port for reading blackboard in specified component interface (possibly relevant for data dependencies -> scheduling order) 
     125   * \param read_port_name Name for read port. If empty, blackboard name will be used. 
     126   * \param create_read_port_in_client Create a read port in the client? This is only relevant when 'create_client' is true and a read port is created. Use 'true', if you wish 'read locks' to occur via the data port. (This parameter exists for minor performance tweaking.) 
    132127   */ 
    133128  template <typename TParent> 
    134129  tBlackboard(const std::string& name, TParent* parent, const tBlackboardBufferModeParameter& buffer_mode = tBlackboardBufferMode::MULTI_BUFFERED_ON_PARALLEL_ACCESS, int elements = 0, bool create_client = true, 
    135               tReadPorts create_read_port = tReadPorts::EXTERNAL, core::tPortGroup* create_write_port_in = default_port_group, core::tPortGroup* create_write_port_in2 = NULL) : 
    136     wrapped_server(NULL), 
    137     wrapped_client(), 
    138     read_port() 
    139   { 
    140     create_read_port = buffer_mode.buffer_mode == tBlackboardBufferMode::SINGLE_BUFFERED ? tReadPorts::NONE : create_read_port; 
    141  
    142     // Get/create Framework element to put blackboard stuff beneath 
    143     core::tFrameworkElement* blackboard_parent = parent->GetChild("Blackboards"); 
    144     if (!blackboard_parent) 
    145     { 
    146       blackboard_parent = new core::tFrameworkElement(parent, "Blackboards"); 
    147     } 
     130              tInterface* create_read_port_in = UseDefaultComponentInterface(), const std::string& read_port_name = "", bool create_read_port_in_client = true) : 
     131    wrapped_server(nullptr), 
     132    wrapped_client(), 
     133    read_port() 
     134  { 
     135    create_read_port_in = buffer_mode.buffer_mode == tBlackboardBufferMode::SINGLE_BUFFERED ? nullptr : create_read_port_in; 
    148136 
    149137    // Create blackboard server 
    150     wrapped_server = new internal::tBlackboardServer<T>(name, blackboard_parent, buffer_mode.buffer_mode, elements, false); 
     138    tInterface& blackboards_parent = GetBlackboardsParent(*parent); 
     139    create_read_port_in = create_read_port_in == UseDefaultComponentInterface() ? GetDefaultReadPortInterface(parent, nullptr) : create_read_port_in; 
     140    wrapped_server = new internal::tBlackboardServer<T>(name, blackboards_parent, buffer_mode.buffer_mode, elements, parent->GetServices(), create_read_port_in, read_port_name); 
     141    write_port = wrapped_server->GetWritePort(); 
     142    if (create_read_port_in && create_read_port_in_client) 
     143    { 
     144      read_port = wrapped_server->GetReadPort(); 
     145    } 
    151146 
    152147    // Create blackboard client 
    153148    if (create_client) 
    154149    { 
    155       wrapped_client = tBlackboardClient<T>(*wrapped_server, blackboard_parent, "", false, create_read_port != tReadPorts::NONE); 
    156     } 
    157  
    158     // Possibly create read ports in module 
    159     if (create_read_port == tReadPorts::EXTERNAL && GetWritePortGroup(parent) != NULL) 
    160     { 
    161       typedef typename tGetReadPortType<typename std::remove_pointer<TParent>::type>::type tReadPort; 
    162       read_port = tReadPort(name, parent, core::tFrameworkElement::tFlag::ACCEPTS_DATA); // make this a proxy port 
    163       wrapped_server->GetReadPort().ConnectTo(read_port); 
    164     } 
    165  
    166     // create write/full-access ports 
    167     if (create_write_port_in != NULL && GetWritePortGroup(parent) != NULL) 
    168     { 
    169       write_port1 = ReplicateWritePort(*wrapped_server->GetWritePort().GetWrapped(), 
    170                                        *(create_write_port_in != default_port_group ? create_write_port_in : GetWritePortGroup(parent)), name); 
    171     } 
    172     if (create_write_port_in2 != NULL && GetWritePortGroup(parent) != NULL) 
    173     { 
    174       write_port2 = ReplicateWritePort(*wrapped_server->GetWritePort().GetWrapped(), *create_write_port_in2, name); 
     150      wrapped_client = tBlackboardClient<T>(false, blackboards_parent, name + " Internal Write", (create_read_port_in_client && create_read_port_in) ? (&blackboards_parent) : nullptr, name + " Internal Read"); 
     151      wrapped_client.ConnectTo(*this); 
    175152    } 
    176153  } 
     
    182159   * 
    183160   * \param replicated_bb Blackboard to provide access to 
    184    * \param parent Parent of blackboard 
    185    * \param create_read_port_in_co In case we have a plain tModule: Create read port in Controller Output (rather than Sensor Output?) 
    186    * \param forward_write_port_in_controller Forward write ports in controller port groups? 
    187    * \param forward_write_port_in_sensor Forward write ports in sensor port groups? 
    188    */ 
    189   tBlackboard(tBlackboard& replicated_bb, structure::tSenseControlGroup* parent, bool create_read_port_in_co = false, 
    190               bool forward_write_port_in_controller = true, bool forward_write_port_in_sensor = false) : 
    191     tBlackboardBase(replicated_bb, parent, create_read_port_in_co, forward_write_port_in_controller, forward_write_port_in_sensor), 
    192     wrapped_server(NULL), 
     161   * \param parent Composite component that replicates blackboard 
     162   * \param create_read_port_in If not nullptr and blackboard has a read port, creates data port for reading blackboard in specified component interface (possibly relevant for data dependencies -> scheduling order) 
     163   * \param blackboard_name Name for blackboard (== name for write port). If empty, replicated blackboard's name will be used. 
     164   * \param read_port_name Name for read port. If empty, replicated blackboard's read port name will be used. 
     165   */ 
     166  template <typename TParent> 
     167  tBlackboard(tBlackboard& replicated_bb, TParent* parent, tInterface* create_read_port_in = UseDefaultComponentInterface(), const std::string& blackboard_name = "", const std::string& read_port_name = "") : 
     168    tBlackboardBase(replicated_bb, parent->GetServices(), blackboard_name), 
     169    wrapped_server(nullptr), 
    193170    wrapped_client(), 
    194171    read_port() 
    195172  { 
    196173    // forward read port 
    197     if (replicated_bb.read_port.GetWrapped()) 
    198     { 
    199       // where do we create port? 
    200       core::tFrameworkElement* pg = replicated_bb.read_port.GetParent(); 
    201       if (pg->NameEquals("Sensor Output")) 
    202       { 
    203         create_read_port_in_co = false; 
    204       } 
    205       else if (pg->NameEquals("Controller Output")) 
    206       { 
    207         create_read_port_in_co = true; 
    208       } 
    209       else 
    210       { 
    211         assert(pg->NameEquals("Output") && "Have names changed?"); 
    212       } 
    213  
    214       // create port 
    215       if (create_read_port_in_co) 
    216       { 
    217         read_port = structure::tSenseControlGroup::tControllerOutput<std::vector<T>>(replicated_bb.read_port.GetName(), parent); 
    218       } 
    219       else 
    220       { 
    221         read_port = structure::tSenseControlGroup::tSensorOutput<std::vector<T>>(replicated_bb.read_port.GetName(), parent); 
    222       } 
     174    if (replicated_bb.read_port.GetWrapped() && create_read_port_in) 
     175    { 
     176      create_read_port_in = create_read_port_in == UseDefaultComponentInterface() ? GetDefaultReadPortInterface(parent, replicated_bb.GetReadPort().GetWrapped()) : create_read_port_in; 
     177      read_port = tReadPort(read_port_name.length() ? read_port_name : replicated_bb.read_port.GetName(), create_read_port_in, create_read_port_in->GetDefaultPortFlags() | tFlag::EMITS_DATA | tFlag::ACCEPTS_DATA | tFlag::PUSH_STRATEGY | tFlag::OUTPUT_PORT); 
    223178      replicated_bb.read_port.ConnectTo(read_port); 
    224179    } 
     
    228183  tBlackboard(tBlackboard && o) : 
    229184    tBlackboardBase(std::forward(o)), 
    230     wrapped_server(NULL), 
     185    wrapped_server(nullptr), 
    231186    wrapped_client(), 
    232187    read_port() 
     
    266221  const std::string& GetName() const 
    267222  { 
    268     return wrapped_server->GetName(); 
    269   } 
    270  
    271   /*! 
    272    * \return Port to use, when modules outside of group/module containing blackboard want to connect to this blackboard's read port 
    273    */ 
    274   data_ports::tPort<std::vector<T>> GetOutsideReadPort() const 
     223    return write_port.GetName(); 
     224  } 
     225 
     226  /*! 
     227   * \return Port to use, when modules inside group containing blackboard want to connect to this blackboard's read port 
     228   */ 
     229  tReadPort GetReadPort() const 
    275230  { 
    276231    return read_port; 
    277232  } 
    278  
    279   /*! 
    280    * \return Port to use, when modules outside of group/module containing blackboard want to connect to this blackboard's primary write port 
    281    */ 
    282   core::tAbstractPort* GetOutsideWritePort() const 
    283   { 
    284     return write_port1; 
    285   } 
    286  
    287   /*! 
    288    * \return Port to use, when modules outside of group/module containing blackboard want to connect to this blackboard's secondary write port 
    289    */ 
    290   core::tAbstractPort* GetOutsideWritePort2() const 
    291   { 
    292     return write_port2; 
    293   } 
    294  
    295   /*! 
    296    * \return Port to use, when modules inside group containing blackboard want to connect to this blackboard's read port 
    297    */ 
    298   data_ports::tOutputPort<tBuffer> GetReadPort() const 
    299   { 
    300     return wrapped_server->GetReadPort(); 
     233  tReadPort GetOutsideReadPort() const __attribute__((deprecated("USE GetReadPort() instead"))) 
     234  { 
     235    return read_port; 
    301236  } 
    302237 
     
    312247   * \return Port to use, when modules inside group containing blackboard want to connect to this blackboard's primary write port 
    313248   */ 
    314   rpc_ports::tServerPort<internal::tBlackboardServer<T>> GetWritePort() const 
    315   { 
    316     return rpc_ports::tServerPort<internal::tBlackboardServer<T>>::Wrap(*wrapped_server->GetWritePort().GetWrapped()); 
     249  core::tPortWrapperBase GetWritePort() const 
     250  { 
     251    return write_port; 
     252  } 
     253 
     254  /*! 
     255   * Deletes this blackboard (its server/client/ports in particular). Object is empty afterwards (equals to a tBlackboard()). 
     256   */ 
     257  void ManagedDelete() 
     258  { 
     259    if (wrapped_server) 
     260    { 
     261      wrapped_server->ManagedDelete(); 
     262    } 
     263    wrapped_client.ManagedDelete(); 
     264    read_port.ManagedDelete(); 
     265    write_port.ManagedDelete(); 
    317266  } 
    318267 
     
    328277  tBlackboardClient<T> wrapped_client; 
    329278 
    330   /*! Replicated read port in group's/module's tPortGroups */ 
    331   data_ports::tPort<std::vector<T>> read_port; 
    332  
    333  
    334   template <typename TParent> 
    335   struct tGetReadPortType 
    336   { 
    337     typedef std::vector<T> tBuffer; 
    338     typedef typename std::conditional < std::is_base_of<structure::tModule, TParent>::value, structure::tModule::tOutput<tBuffer>, 
    339             typename std::conditional < std::is_base_of<structure::tSenseControlModule, TParent>::value, structure::tSenseControlModule::tSensorOutput<tBuffer>, 
    340             typename std::conditional < std::is_base_of<structure::tSenseControlGroup, TParent>::value, structure::tSenseControlGroup::tSensorOutput<tBuffer>, 
    341             data_ports::tPort<tBuffer >>::type >::type >::type type; 
    342   }; 
     279  /*! Read Port in component's interface */ 
     280  tReadPort read_port; 
     281 
    343282}; 
    344283 
  • tBlackboardClient.h

    r124 r132  
    102102  typedef data_ports::tPortDataPointer<tBuffer> tBufferPointer; 
    103103  typedef data_ports::tPortDataPointer<const tBuffer> tConstBufferPointer; 
     104  typedef typename tServer::tReadLockedBufferPointer tReadLockedBufferPointer; 
    104105  typedef std::vector<tChange<T>> tChangeSet; 
    105106  typedef data_ports::tPortDataPointer<tChangeSet> tChangeSetPointer; 
     
    337338   * \exception rpc_ports::tRPCException is thrown if call fails 
    338339   */ 
    339   inline tConstBufferPointer Read(const rrlib::time::tDuration& timeout = std::chrono::seconds(2)) 
    340   { 
    341     if (read_port && read_port.GetFlag(core::tFrameworkElement::tFlag::PUSH_STRATEGY)) 
    342     { 
    343       return read_port.GetPointer(); 
    344     } 
    345     rpc_ports::tFuture<tConstBufferPointer> future = ReadLock(timeout); 
     340  inline tReadLockedBufferPointer Read(const rrlib::time::tDuration& timeout = std::chrono::seconds(2)) 
     341  { 
     342    rpc_ports::tFuture<tReadLockedBufferPointer> future = ReadLock(timeout); 
    346343    return future.Get(timeout); 
    347344  } 
     
    361358   * \exception rpc_ports::tRPCException is thrown if call fails 
    362359   */ 
    363   rpc_ports::tFuture<tConstBufferPointer> ReadLock(const rrlib::time::tDuration& timeout = std::chrono::seconds(10)); 
     360  rpc_ports::tFuture<tReadLockedBufferPointer> ReadLock(const rrlib::time::tDuration& timeout = std::chrono::seconds(10)); 
    364361 
    365362  /*! 
  • tBlackboardClient.h

    r127 r132  
    5151// Internal includes with "" 
    5252//---------------------------------------------------------------------- 
     53#include "plugins/blackboard/internal/tBlackboardBase.h" 
    5354#include "plugins/blackboard/tChange.h" 
    54 #include "plugins/blackboard/internal/tBlackboardClientBackend.h" 
    5555#include "plugins/blackboard/internal/tBlackboardServer.h" 
    5656 
     
    105105  typedef std::vector<tChange<T>> tChangeSet; 
    106106  typedef data_ports::tPortDataPointer<tChangeSet> tChangeSetPointer; 
     107  typedef typename data_ports::standard::tStandardPort::tBufferPool tChangeSetBufferPool; 
     108 
     109  typedef core::tFrameworkElement::tFlag tFlag; 
     110  typedef core::tFrameworkElement::tFlag tFlags; 
     111  typedef data_ports::tInputPort<tBuffer> tReadPort; 
     112  typedef rpc_ports::tClientPort<tServer> tWritePort; 
     113 
    107114 
    108115  /*! 
     
    113120    read_port(), 
    114121    write_port(), 
    115     backend(NULL), 
    116     outside_write_port1(), 
    117     outside_write_port2(), 
    118     outside_read_port() 
    119   { 
    120   } 
    121  
    122   /*! 
    123    * Creates plain blackboard client (without any additional ports in any interfaces) 
    124    * 
    125    * \param name Name/Uid of blackboard 
    126    * \param parent Parent of blackboard client 
    127    * \param push_updates Use push strategy? (Any blackboard updates will be pushed to read port; required for changed-flag to work properly; disabled by default (network-bandwidth)) 
    128    * \param auto_connect_mode Desired mode of auto-connecting 
    129    * \param read_port Create read port? 
    130    */ 
    131   tBlackboardClient(const std::string& name, core::tFrameworkElement* parent, bool push_updates = false, bool read_port = true); 
    132  
    133   /*! 
    134    * Connects to local blackboard 
    135    * 
    136    * \param server Blackboard server to connect to (in case it is available as object) 
    137    * \param parent Parent of blackboard client 
    138    * \param non_default_name Default name is "<server name> Client". Specifiy non-empty string for other name 
    139    * \param push_updates Use push strategy? (Any blackboard updates will be pushed to read port; required for changed-flag to work properly; disabled by default (network-bandwidth)) 
    140    * \param read_port Create read port? 
    141    */ 
    142   tBlackboardClient(internal::tBlackboardServer<T>& server, core::tFrameworkElement* parent, 
    143                     const std::string& non_default_name = "", bool push_updates = false, bool read_port = true); 
    144  
    145   /*! 
    146    * Constructor for use with tModule and tSenseControlModule. 
    147    * Does NOT connect to global blackboards - but rather uses group's/module's input/output port groups. 
    148    * 
    149    * (per default, full-blackboard-access-ports are created in Output/ControllerOutput. 
    150    *  If this is not desired, the last two constructor parameters can be used to specify alternatives.) 
    151    * 
    152    * \param name Name of blackboard 
    153    * \param parent Parent of blackboard 
    154    * \param push_updates Use push strategy? (Any blackboard updates will be pushed to read port; required for changed-flag to work properly; disabled by default (network-bandwidth)) 
    155    * \param create_read_port Which read ports to create for blackboard 
    156    * \param create_write_port_in If not NULL, creates write port in specified port group instead of Input/ControllerInput 
    157    * \param create_write_port_in2 If not NULL, creates another write port in specified port group 
    158    */ 
    159   tBlackboardClient(const std::string& name, structure::tModuleBase* parent, bool push_updates = false, 
    160                     tReadPorts create_read_port = tReadPorts::EXTERNAL, core::tPortGroup* create_write_port_in = NULL, core::tPortGroup* create_write_port_in2 = NULL); 
     122    change_set_buffer_pool() 
     123  { 
     124  } 
     125 
     126  /*! 
     127   * Creates blackboard client 
     128   * 
     129   * \param name Name/Uid of blackboard (will be name of write port) 
     130   * \param parent Parent component of blackboard client 
     131   * \param push_updates Use push strategy for read port? (Any blackboard updates will be pushed to read port; required for changed-flag to work properly; disabled by default (network-bandwidth)) 
     132   * \param create_read_port_in If not nullptr, creates data port for reading blackboard in specified component interface (possibly relevant for data dependencies -> scheduling order) 
     133   * \param read_port_name Name for read port. If empty, blackboard name will be used. 
     134   */ 
     135  template <typename TParent> 
     136  tBlackboardClient(const std::string& name, TParent* parent, bool push_updates = false, tInterface* create_read_port_in = UseDefaultComponentInterface(), const std::string& read_port_name = "") : 
     137    tBlackboardClient(push_updates, parent->GetServices(), name, create_read_port_in == UseDefaultComponentInterface() ? GetDefaultReadPortInterface(parent, nullptr) : create_read_port_in, read_port_name.length() ? read_port_name : name) 
     138  { 
     139  } 
    161140 
    162141  /*! 
     
    166145   * 
    167146   * \param replicated_bb Blackboard to provide access to 
    168    * \param parent Parent of blackboard 
    169    * \param create_read_port_in_ci In case we have a plain tModule: Create read port in Controller Input (rather than Sensor Input?) 
    170    * \param forward_write_port_in_controller Forward write ports in controller port groups? 
    171    * \param forward_write_port_in_sensor Forward write ports in sensor port groups? 
    172    */ 
    173   tBlackboardClient(const tBlackboardClient& replicated_bb, structure::tSenseControlGroup* parent, 
    174                     bool create_read_port_in_ci = false, bool forward_write_port_in_controller = true, bool forward_write_port_in_sensor = false); 
     147   * \param parent Composite component that replicates blackboard 
     148   * \param create_read_port_in If not nullptr and blackboard has a read port, creates data port for reading blackboard in specified component interface (possibly relevant for data dependencies -> scheduling order) 
     149   * \param blackboard_name Name for blackboard (== name for write port). If empty, replicated blackboard's name will be used. 
     150   * \param read_port_name Name for read port. If empty, replicated blackboard's read port name will be used. 
     151   */ 
     152  template <typename TParent> 
     153  tBlackboardClient(const tBlackboardClient& replicated_bb, TParent* parent, tInterface* create_read_port_in = UseDefaultComponentInterface(), 
     154                    const std::string& blackboard_name = "", const std::string& read_port_name = "") : 
     155    read_port(), 
     156    write_port(), 
     157    change_set_buffer_pool() 
     158  { 
     159    // hack to get rpc port that is actually a proxy into a client port 
     160    static_cast<core::tPortWrapperBase&>(write_port) = core::tPortWrapperBase(parent->GetServices().CreatePort(blackboard_name.length() ? blackboard_name : replicated_bb.write_port.GetName(), replicated_bb.write_port.GetDataType(), 
     161        core::tFrameworkElement::tFlag::ACCEPTS_DATA | core::tFrameworkElement::tFlag::EMITS_DATA | (replicated_bb.write_port.GetFlag(tFlag::OUTPUT_PORT) ? tFlag::OUTPUT_PORT : tFlag::PORT))); 
     162    write_port.ConnectTo(replicated_bb.write_port); 
     163    if (replicated_bb.read_port.GetWrapped() && create_read_port_in) 
     164    { 
     165      create_read_port_in = create_read_port_in == UseDefaultComponentInterface() ? GetDefaultReadPortInterface(parent, replicated_bb.read_port.GetWrapped()) : create_read_port_in; 
     166      read_port = tReadPort(read_port_name.length() ? read_port_name : replicated_bb.read_port.GetName(), create_read_port_in, create_read_port_in->GetDefaultPortFlags() | tFlag::EMITS_DATA | tFlag::ACCEPTS_DATA | tFlag::PUSH_STRATEGY); 
     167      replicated_bb.read_port.GetWrapped()->ConnectTo(*read_port.GetWrapped()); 
     168    } 
     169  } 
    175170 
    176171  /*! move constructor */ 
     
    212207  inline std::string GetName() const 
    213208  { 
    214     return backend->GetName(); 
    215   } 
    216  
    217   /*! 
    218    * \return Port to use, when modules outside of group/module containing blackboard want to connect to this blackboard's read port. May not exist. 
    219    */ 
    220   data_ports::tPort<tBuffer> GetOutsideReadPort() const 
    221   { 
    222     return outside_read_port; 
     209    return write_port.GetName(); 
     210  } 
     211 
     212  /*! 
     213   * \return Port for reading - in case pushing of updates is activated 
     214   */ 
     215  tReadPort GetReadPort() const 
     216  { 
     217    return read_port; 
    223218  } 
    224219 
     
    233228 
    234229  /*! 
    235    * \return Port to use, when modules outside of group/module containing blackboard want to connect to this blackboard's primary write port 
    236    */ 
    237   rpc_ports::tProxyPort<tServer, false> GetOutsideWritePort() const 
    238   { 
    239     return outside_write_port1; 
    240   } 
    241  
    242   /*! 
    243    * \return Port to use, when modules outside of group/module containing blackboard want to connect to this blackboard's secondary write port 
    244    */ 
    245   rpc_ports::tProxyPort<tServer, false> GetOutsideWritePort2() const 
    246   { 
    247     return outside_write_port2; 
    248   } 
    249  
    250   /*! 
    251230   * \return Handle of server that handles calls (can be used to detect whether we're connected to a different blackboard). 0 if not connected to a server. 
    252231   */ 
     
    257236 
    258237  /*! 
     238   * \return Port for full blackboard access 
     239   */ 
     240  tWritePort GetWritePort() const 
     241  { 
     242    return write_port; 
     243  } 
     244 
     245  /*! 
    259246   * \return Unused buffer (may be published/committed directly using Publish()) 
    260247   */ 
    261248  inline tBufferPointer GetUnusedBuffer() 
    262249  { 
    263     return backend->GetUnusedBuffer<tBuffer>(); 
     250    return read_port.GetUnusedBuffer(); 
    264251  } 
    265252 
     
    269256  inline tChangeSetPointer GetUnusedChangeBuffer() 
    270257  { 
    271     return backend->GetUnusedBuffer<tChangeSet>(); 
    272   } 
    273  
    274   /*! 
    275    * \return Wrapped raw blackboard backend 
    276    */ 
    277   inline internal::tBlackboardClientBackend* GetBackend() const 
    278   { 
    279     return backend; 
     258    auto buffer = change_set_buffer_pool->GetUnusedBuffer(rrlib::rtti::tDataType<tChangeSet>()); 
     259    buffer->SetUnused(true); 
     260    return data_ports::api::tPortDataPointerImplementation<tChangeSet, false>(buffer); 
    280261  } 
    281262 
     
    316297  inline void Init() 
    317298  { 
    318     backend->Init(); 
    319   } 
     299    write_port.Init(); 
     300    if (read_port.GetWrapped()) 
     301    { 
     302      read_port.Init(); 
     303    } 
     304  } 
     305 
     306  /*! 
     307   * Deletes this blackboard (its server/client/ports in particular). Object is empty afterwards (equals to a tBlackboard()). 
     308   */ 
     309  void ManagedDelete() 
     310  { 
     311    read_port.ManagedDelete(); 
     312    write_port.ManagedDelete(); 
     313  } 
     314 
    320315 
    321316  /*! 
     
    378373  } 
    379374 
     375  /*! \return Returns constant that indicates that default component interface for read port should be used */ 
     376  static tInterface* UseDefaultComponentInterface() 
     377  { 
     378    return internal::tBlackboardBase::UseDefaultComponentInterface(); 
     379  } 
     380 
     381 
    380382  /*! 
    381383   * Acquire write lock on blackboard. 
     
    396398  operator bool() const 
    397399  { 
    398     return backend != NULL; 
     400    return change_set_buffer_pool.get(); 
    399401  } 
    400402 
     
    404406private: 
    405407 
     408  friend class tBlackboard<T>; 
     409 
    406410  /*! Port for reading - in case pushing of updates is activated */ 
    407   data_ports::tInputPort<tBuffer> read_port; 
     411  tReadPort read_port; 
    408412 
    409413  /*! Port for full blackboard access */ 
    410   rpc_ports::tClientPort<tServer> write_port; 
    411  
    412   /*! Wrapped blackboard backend */ 
    413   internal::tBlackboardClientBackend* backend; 
    414  
    415   /*! Replicated ports in group's/module's tPortGroups */ 
    416   rpc_ports::tProxyPort<tServer, false> outside_write_port1, outside_write_port2; 
    417  
    418   /*! Replicated read port in group's/module's tPortGroups */ 
    419   data_ports::tPort<tBuffer> outside_read_port; 
    420  
    421  
    422   /*! 
    423    * Check whether these ports can be connected - if yes, do so 
    424    * (connecting to blackboard) 
    425    */ 
    426   void CheckConnect(core::tPortWrapperBase p1, core::tPortWrapperBase p2); 
    427  
    428   /*! 
    429    * Check whether these ports can be connected - if yes, do so 
    430    * (connecting to outer blackboard client) 
    431    */ 
    432   void CheckClientConnect(core::tPortWrapperBase p1, core::tPortWrapperBase p2); 
     414  tWritePort write_port; 
     415 
     416  /*! Additional port buffer pool */ 
     417  std::unique_ptr<tChangeSetBufferPool> change_set_buffer_pool; 
     418 
     419 
     420  /*! 
     421   * Creates blackboard client 
     422   * 
     423   * \param push_updates Use push strategy for read port? (Any blackboard updates will be pushed to read port; required for changed-flag to work properly; disabled by default (network-bandwidth)) 
     424   * \param create_write_port_in Interface to create RPC for blackboard access in 
     425   * \param write_port_name Name for write port 
     426   * \param create_read_port_in If not nullptr, creates data port for reading blackboard in specified component interface (possibly relevant for data dependencies -> scheduling order) 
     427   * \param read_port_name Name for read port. If empty, blackboard name will be used. 
     428   */ 
     429  tBlackboardClient(bool push_updates, tInterface& create_write_port_in, const std::string& write_port_name, tInterface* create_read_port_in, const std::string& read_port_name); 
    433430 
    434431  /*! 
     
    437434  inline const core::tFrameworkElement& GetLogDescription() const 
    438435  { 
    439     return *backend; 
    440   } 
    441  
    442   /*! 
    443    * (Helper to make constructors shorter) 
    444    * Creates read port 
    445    * 
    446    * \param create Actually create port? 
    447    * \param push_updates Use push strategy? (Any blackboard updates will be pushed to read port) 
    448    * \return Created read port 
    449    */ 
    450   static data_ports::tInputPort<tBuffer> PossiblyCreateReadPort(bool create, bool push_updates) 
    451   { 
    452     if (create) 
     436    return *write_port.GetWrapped(); 
     437  } 
     438 
     439  /*! Helper function to determine component interface to create read ports in by default */ 
     440  static tInterface* GetDefaultReadPortInterface(structure::tSenseControlGroup* g, core::tAbstractPort* replicated_port) 
     441  { 
     442    if (replicated_port && replicated_port->GetParent()->GetFlag(tFlag::CONTROLLER_DATA)) 
    453443    { 
    454       data_ports::tInputPort<tBuffer> read_port = data_ports::tInputPort<tBuffer>("read"); 
    455       if (!push_updates) 
    456       { 
    457         read_port.SetPushStrategy(false); 
    458       } 
    459       return read_port; 
     444      return &g->GetControllerInputs(); 
    460445    } 
    461     return data_ports::tInputPort<tBuffer>(); 
    462   } 
    463  
    464   /*! 
    465    * Create blackboard write port in specified port group and connect it to 
    466    * (original blackboard client) write port. 
    467    * 
    468    * \param write_port Port to connect newly created port to 
    469    * \param port_group Port group to create port in 
    470    * \param name Name of new port 
    471    * \return Created Port 
    472    */ 
    473   rpc_ports::tProxyPort<tServer, false> ReplicateWritePort(core::tPortWrapperBase& write_port, core::tFrameworkElement* port_group, const std::string& name) 
    474   { 
    475     typename core::tFrameworkElement::tFlags extra_flags; 
    476     if (typeid(*port_group) == typeid(core::tPortGroup)) 
     446    return &g->GetSensorInputs(); 
     447  } 
     448  static tInterface* GetDefaultReadPortInterface(structure::tSenseControlModule* g, core::tAbstractPort* replicated_port) 
     449  { 
     450    if (replicated_port && replicated_port->GetParent()->GetFlag(tFlag::CONTROLLER_DATA)) 
    477451    { 
    478       extra_flags |= static_cast<core::tPortGroup&>(*port_group).GetDefaultPortFlags(); 
     452      return &g->GetControllerInputs(); 
    479453    } 
    480     rpc_ports::tProxyPort<tServer, false> new_port(name, port_group, extra_flags); 
    481     write_port.ConnectTo(new_port); 
    482     return new_port; 
     454    return &g->GetSensorInputs(); 
     455  } 
     456  static tInterface* GetDefaultReadPortInterface(structure::tGroup* g, core::tAbstractPort* replicated_port) 
     457  { 
     458    return &g->GetInputs(); 
     459  } 
     460  static tInterface* GetDefaultReadPortInterface(structure::tModule* g, core::tAbstractPort* replicated_port) 
     461  { 
     462    return &g->GetInputs(); 
     463  } 
     464  static tInterface* GetDefaultReadPortInterface(core::tFrameworkElement* g, core::tAbstractPort* replicated_port) 
     465  { 
     466    return nullptr; 
    483467  } 
    484468}; 
  • tBlackboardClient.hpp

    r124 r132  
    146146 
    147147template<typename T> 
    148 rpc_ports::tFuture<typename tBlackboardClient<T>::tConstBufferPointer> tBlackboardClient<T>::ReadLock(const rrlib::time::tDuration& timeout) 
     148rpc_ports::tFuture<typename tBlackboardClient<T>::tReadLockedBufferPointer> tBlackboardClient<T>::ReadLock(const rrlib::time::tDuration& timeout) 
    149149{ 
    150150  // Possibly obtain value from read_port 
    151151  if (read_port.GetWrapped() && read_port.GetFlag(core::tFrameworkElement::tFlag::PUSH_STRATEGY)) 
    152152  { 
    153     rpc_ports::tPromise<tConstBufferPointer> promise; 
    154     promise.SetValue(read_port.GetPointer()); 
    155     return promise.GetFuture(); 
     153    auto buffer_pointer = read_port.GetPointer(); 
     154    if (buffer_pointer->size())   // TODO: Heuristic: if blackboard does not have read port, blackboard has size zero; so if size is zero, lock via RPC lock which is always appropriate  (this heuristic can break, when read port was connected to multi-buffered blackboard - and is connected to single-buffered blackboard later); why is read port used at all? over the network this is significantly more efficient (push instead of pull) 
     155    { 
     156      rpc_ports::tPromise<tReadLockedBufferPointer> promise; 
     157      promise.SetValue(std::move(buffer_pointer)); 
     158      return promise.GetFuture(); 
     159    } 
    156160  } 
    157161 
  • tBlackboardClient.hpp

    r127 r132  
    6565//---------------------------------------------------------------------- 
    6666 
    67 template<typename T> 
    68 tBlackboardClient<T>::tBlackboardClient(const std::string& name, core::tFrameworkElement* parent, bool push_updates, bool create_read_port) : 
    69   read_port(PossiblyCreateReadPort(create_read_port, push_updates)), 
    70   write_port("write", internal::tBlackboardServer<T>::GetRPCInterfaceType()), 
    71   backend(new internal::tBlackboardClientBackend(name, parent, write_port, read_port)), 
    72   outside_write_port1(), 
    73   outside_write_port2(), 
    74   outside_read_port() 
    75 { 
    76   //backend->SetAutoConnectMode(auto_connect_mode); 
    77 } 
     67 
     68/* 
     69read_port(create_read_port_in ? tReadPort() : tReadPort()), 
     70    write_port(), 
     71    change_set_buffer_pool(new tChangeSetBufferPool(rrlib::rtti::tDataType<tChangeSet>(), 0)) 
     72*/ 
    7873 
    7974template<typename T> 
    80 tBlackboardClient<T>::tBlackboardClient(internal::tBlackboardServer<T>& server, core::tFrameworkElement* parent, const std::string& non_default_name, bool push_updates, bool create_read_port) : 
    81   read_port(PossiblyCreateReadPort(create_read_port, push_updates)), 
    82   write_port("write", internal::tBlackboardServer<T>::GetRPCInterfaceType()), 
    83   backend(new internal::tBlackboardClientBackend(non_default_name.length() > 0 ? non_default_name : (server.GetName() + " Client"), parent, write_port, read_port)), 
    84   outside_write_port1(), 
    85   outside_write_port2(), 
    86   outside_read_port() 
     75tBlackboardClient<T>::tBlackboardClient(bool push_updates, tInterface& create_write_port_in, const std::string& write_port_name, tInterface* create_read_port_in, const std::string& read_port_name) : 
     76  read_port(), 
     77  write_port(write_port_name, &create_write_port_in, internal::tBlackboardServer<T>::GetRPCInterfaceType()), 
     78  change_set_buffer_pool(new tChangeSetBufferPool(rrlib::rtti::tDataType<tChangeSet>(), 0)) 
    8779{ 
    88   if (create_read_port) 
     80  if (create_read_port_in) 
    8981  { 
    90     server.GetReadPort().ConnectTo(read_port); 
    91   } 
    92   server.GetWritePort().ConnectTo(write_port); 
    93 } 
    94  
    95 template<typename T> 
    96 tBlackboardClient<T>::tBlackboardClient(const std::string& name, structure::tModuleBase* parent, bool push_updates, tReadPorts create_read_port, core::tPortGroup* create_write_port_in, core::tPortGroup* create_write_port_in2) : 
    97   read_port(PossiblyCreateReadPort(create_read_port != tReadPorts::NONE, push_updates)), 
    98   write_port("write", internal::tBlackboardServer<T>::GetRPCInterfaceType()), 
    99   backend(new internal::tBlackboardClientBackend(name, parent->GetChild("Blackboards") ? parent->GetChild("Blackboards") : new core::tFrameworkElement(parent, "Blackboards"), write_port, read_port)), 
    100   outside_write_port1(), 
    101   outside_write_port2(), 
    102   outside_read_port() 
    103 { 
    104   structure::tModule* module = dynamic_cast<structure::tModule*>(parent); 
    105   structure::tSenseControlModule* sense_control_module = dynamic_cast<structure::tSenseControlModule*>(parent); 
    106   assert((module == NULL || sense_control_module == NULL) && (module || sense_control_module)); 
    107  
    108   // Possibly create read ports in module 
    109   if (create_read_port == tReadPorts::EXTERNAL) 
    110   { 
    111     if (sense_control_module) 
     82    read_port = tReadPort(read_port_name, create_read_port_in, data_ports::cDEFAULT_INPUT_PORT_FLAGS); 
     83    if (!push_updates) 
    11284    { 
    113       outside_read_port = structure::tSenseControlModule::tSensorInput<tBuffer>(name, parent, core::tFrameworkElement::tFlag::EMITS_DATA); 
     85      read_port.SetPushStrategy(false); 
    11486    } 
    115     else 
    116     { 
    117       outside_read_port = structure::tModule::tInput<tBuffer>(name, parent, core::tFrameworkElement::tFlag::EMITS_DATA); 
    118     } 
    119     read_port.ConnectTo(outside_read_port); 
    120   } 
    121  
    122   // create write/full-access ports 
    123   core::tFrameworkElement& port_group = module ? module->GetOutputs() : sense_control_module->GetControllerOutputs(); 
    124   outside_write_port1 = ReplicateWritePort(write_port, create_write_port_in != NULL ? create_write_port_in : &port_group, name); 
    125   if (create_write_port_in2 != NULL) 
    126   { 
    127     outside_write_port2 = ReplicateWritePort(write_port, create_write_port_in2, name); 
    12887  } 
    12988} 
    13089 
    131 template<typename T> 
    132 tBlackboardClient<T>::tBlackboardClient(const tBlackboardClient& replicated_bb, structure::tSenseControlGroup* parent, bool create_read_port_in_ci, bool forward_write_port_in_controller, bool forward_write_port_in_sensor) : 
    133   read_port(), 
    134   write_port(), 
    135   backend(NULL), 
    136   outside_write_port1(), 
    137   outside_write_port2(), 
    138   outside_read_port() 
    139 { 
    140   // forward read port 
    141   if (replicated_bb.GetOutsideReadPort().GetWrapped()) 
    142   { 
    143     // where do we create port? 
    144     core::tFrameworkElement* port_group = replicated_bb.GetOutsideReadPort().GetParent(); 
    145     if (port_group->NameEquals("Sensor Input")) 
    146     { 
    147       create_read_port_in_ci = false; 
    148     } 
    149     else if (port_group->NameEquals("Controller Input")) 
    150     { 
    151       create_read_port_in_ci = true; 
    152     } 
    153  
    154     // create port 
    155     if (create_read_port_in_ci) 
    156     { 
    157       outside_read_port = structure::tSenseControlGroup::tControllerInput<tBuffer>(replicated_bb.GetOutsideReadPort().GetName(), parent); 
    158     } 
    159     else 
    160     { 
    161       outside_read_port = structure::tSenseControlGroup::tSensorInput<tBuffer>(replicated_bb.GetOutsideReadPort().GetName(), parent); 
    162     } 
    163     replicated_bb.GetOutsideReadPort().ConnectTo(outside_read_port); 
    164   } 
    165  
    166   // forward write ports 
    167   std::vector<rpc_ports::tProxyPort<tServer, false>> new_ports; 
    168   for (int i = 0; i < 2; i++) 
    169   { 
    170     rpc_ports::tProxyPort<tServer, false> port = (i == 0) ? replicated_bb.GetOutsideWritePort() : replicated_bb.GetOutsideWritePort2(); 
    171     if (port.GetWrapped()) 
    172     { 
    173       // where do we create ports? 
    174       core::tFrameworkElement* port_group = port.GetParent(); 
    175       if (port_group->NameEquals("Input")) 
    176       { 
    177         if (forward_write_port_in_sensor) 
    178         { 
    179           new_ports.push_back(ReplicateWritePort(port, &parent->GetSensorInputs(), port.GetName())); 
    180         } 
    181         if (forward_write_port_in_controller) 
    182         { 
    183           new_ports.push_back(ReplicateWritePort(port, &parent->GetControllerInputs(), port.GetName())); 
    184         } 
    185       } 
    186       else if (port_group->NameEquals("Output")) 
    187       { 
    188         if (forward_write_port_in_sensor) 
    189         { 
    190           new_ports.push_back(ReplicateWritePort(port, &parent->GetSensorOutputs(), port.GetName())); 
    191         } 
    192         if (forward_write_port_in_controller) 
    193         { 
    194           new_ports.push_back(ReplicateWritePort(port, &parent->GetControllerOutputs(), port.GetName())); 
    195         } 
    196       } 
    197       else if ((rrlib::util::StartsWith(port_group->GetName(), "Sensor") && forward_write_port_in_sensor) || (rrlib::util::StartsWith(port_group->GetName(), "Controller") && forward_write_port_in_controller)) 
    198       { 
    199         new_ports.push_back(ReplicateWritePort(port, &parent->GetInterface(port_group->GetName()), port.GetName())); 
    200       } 
    201     } 
    202   } 
    203   assert(new_ports.size() <= 2); 
    204   if (new_ports.size() >= 1) 
    205   { 
    206     outside_write_port1 = new_ports[0]; 
    207   } 
    208   if (new_ports.size() >= 2) 
    209   { 
    210     outside_write_port2 = new_ports[1]; 
    211   } 
    212 } 
    21390 
    21491template<typename T> 
     
    21693  read_port(), 
    21794  write_port(), 
    218   backend(NULL), 
    219   outside_write_port1(), 
    220   outside_write_port2(), 
    221   outside_read_port() 
     95  change_set_buffer_pool() 
    22296{ 
    22397  std::swap(read_port, o.read_port); 
    22498  std::swap(write_port, o.write_port); 
    225   std::swap(backend, o.backend); 
    226   std::swap(outside_write_port1, o.outside_write_port1); 
    227   std::swap(outside_write_port2, o.outside_write_port2); 
    228   std::swap(outside_read_port, o.outside_read_port); 
     99  std::swap(change_set_buffer_pool, o.change_set_buffer_pool); 
    229100} 
    230101 
     
    234105  std::swap(read_port, o.read_port); 
    235106  std::swap(write_port, o.write_port); 
    236   std::swap(backend, o.backend); 
    237   std::swap(outside_write_port1, o.outside_write_port1); 
    238   std::swap(outside_write_port2, o.outside_write_port2); 
    239   std::swap(outside_read_port, o.outside_read_port); 
     107  std::swap(change_set_buffer_pool, o.change_set_buffer_pool); 
    240108  return *this; 
    241109} 
     
    243111 
    244112template<typename T> 
    245 void tBlackboardClient<T>::CheckConnect(core::tPortWrapperBase p1, core::tPortWrapperBase p2) 
    246 { 
    247   if (p1.GetWrapped() && p2.GetWrapped()) 
    248   { 
    249     core::tFrameworkElement* parent1 = p1.GetParent(); 
    250     core::tFrameworkElement* parent2 = p2.GetParent(); 
    251     if ((rrlib::util::EndsWith(parent1->GetName(), "Output") && rrlib::util::EndsWith(parent2->GetName(), "Input")) || 
    252         (rrlib::util::EndsWith(parent1->GetName(), "Input") && rrlib::util::EndsWith(parent2->GetName(), "Output"))) 
    253     { 
    254       if (!((rrlib::util::StartsWith(parent1->GetName(), "Sensor") && rrlib::util::StartsWith(parent2->GetName(), "Controller")) || 
    255             (rrlib::util::StartsWith(parent1->GetName(), "Controller") && rrlib::util::StartsWith(parent2->GetName(), "Sensor")))) 
    256       { 
    257         p1.ConnectTo(p2); 
    258       } 
    259     } 
    260   } 
    261 } 
    262  
    263 template<typename T> 
    264 void tBlackboardClient<T>::CheckClientConnect(core::tPortWrapperBase p1, core::tPortWrapperBase p2) 
    265 { 
    266   if (p1.GetWrapped() && p2.GetWrapped()) 
    267   { 
    268     core::tFrameworkElement* parent1 = p1.GetParent(); 
    269     core::tFrameworkElement* parent2 = p2.GetParent(); 
    270     if ((rrlib::util::EndsWith(parent1->GetName(), "Input") && rrlib::util::EndsWith(parent2->GetName(), "Input")) || 
    271         (rrlib::util::EndsWith(parent1->GetName(), "Output") && rrlib::util::EndsWith(parent2->GetName(), "Output"))) 
    272     { 
    273       if (!((rrlib::util::StartsWith(parent1->GetName(), "Sensor") && rrlib::util::StartsWith(parent2->GetName(), "Controller")) || 
    274             (rrlib::util::StartsWith(parent1->GetName(), "Controller") && rrlib::util::StartsWith(parent2->GetName(), "Sensor")))) 
    275       { 
    276         p1.ConnectTo(p2); 
    277       } 
    278     } 
    279   } 
    280 } 
    281  
    282 template<typename T> 
    283113void tBlackboardClient<T>::ConnectTo(const tBlackboard<T>& blackboard) 
    284114{ 
    285   if (blackboard.GetOutsideReadPort().GetWrapped() && GetOutsideReadPort().GetWrapped()) 
     115  if (blackboard.GetReadPort().GetWrapped() && GetReadPort().GetWrapped()) 
    286116  { 
    287     CheckConnect(blackboard.GetOutsideReadPort(), GetOutsideReadPort()); 
     117    blackboard.GetReadPort().ConnectTo(GetReadPort()); 
    288118  } 
    289   CheckConnect(core::tPortWrapperBase(blackboard.GetOutsideWritePort()), GetOutsideWritePort()); 
    290   CheckConnect(core::tPortWrapperBase(blackboard.GetOutsideWritePort2()), GetOutsideWritePort()); 
    291   CheckConnect(core::tPortWrapperBase(blackboard.GetOutsideWritePort()), GetOutsideWritePort2()); 
    292   CheckConnect(core::tPortWrapperBase(blackboard.GetOutsideWritePort2()), GetOutsideWritePort2()); 
     119  GetWritePort().ConnectTo(blackboard.GetWritePort()); 
    293120} 
    294121 
     
    296123void tBlackboardClient<T>::ConnectTo(const tBlackboardClient<T>& client) 
    297124{ 
    298   if (client.GetOutsideReadPort().GetWrapped() && GetOutsideReadPort().GetWrapped()) 
     125  if (client.GetReadPort().GetWrapped() && GetReadPort().GetWrapped()) 
    299126  { 
    300     CheckClientConnect(client.GetOutsideReadPort(), GetOutsideReadPort()); 
     127    client.GetReadPort().ConnectTo(GetReadPort()); 
    301128  } 
    302   CheckClientConnect(client.GetOutsideWritePort(), GetOutsideWritePort()); 
    303   CheckClientConnect(client.GetOutsideWritePort2(), GetOutsideWritePort()); 
    304   CheckClientConnect(client.GetOutsideWritePort(), GetOutsideWritePort2()); 
    305   CheckClientConnect(client.GetOutsideWritePort2(), GetOutsideWritePort2()); 
     129  GetWritePort().ConnectTo(client.GetWritePort()); 
    306130} 
    307131 
  • tests/blackboard_stress_test.cpp

    r130 r132  
    8686  mBlackboardTestServer(tFrameworkElement* parent, const std::string& name = "Server") : 
    8787    tModule(parent, name), 
    88     blackboard("Test Blackboard", this, tBlackboardBufferMode::MULTI_BUFFERED, 20, false, finroc::blackboard::tReadPorts::EXTERNAL), 
    89     blackboard_no_copy("Test Blackboard No Copy", this, tBlackboardBufferMode::SINGLE_BUFFERED, 20, false, finroc::blackboard::tReadPorts::NONE) 
     88    blackboard("Test Blackboard", this, tBlackboardBufferMode::MULTI_BUFFERED, 20, false), 
     89    blackboard_no_copy("Test Blackboard No Copy", this, tBlackboardBufferMode::SINGLE_BUFFERED, 20, false, nullptr) 
    9090  { 
    9191  } 
     
    116116  mBlackboardTestClient(tFrameworkElement* parent, const std::string& name, bool read_ports) : 
    117117    finroc::structure::tThreadContainer<finroc::structure::tModule>(parent, name), 
    118     blackboard_client("Blackboard Client", this, false, read_ports ? finroc::blackboard::tReadPorts::EXTERNAL : finroc::blackboard::tReadPorts::NONE), 
     118    blackboard_client("Blackboard Client", this, false, read_ports ? tBlackboardClient<tBlackboardDataType>::UseDefaultComponentInterface() : nullptr), 
    119119    reader(false), 
    120120    outside_lock_delay_ms(0), 
Note: See TracChangeset for help on using the changeset viewer.