source: finroc_plugins_blackboard/tBlackboardWriteAccess.h

tip
Last change on this file was 131:3158500c35a3, checked in by Max Reichardt <max.reichardt@…>, 4 years ago

Fixes tBlackboardWriteAccess::SetTimestamp

File size: 8.3 KB
Line 
1//
2// You received this file as part of Finroc
3// A framework for intelligent robot control
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    plugins/blackboard/tBlackboardWriteAccess.h
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2012-12-18
27 *
28 * \brief   Contains tBlackboardWriteAccess
29 *
30 * \b tBlackboardWriteAccess
31 *
32 * Objects of this class are used to acquire write access to blackboards.
33 * The lock is released as soon as the objects goes out of scope.
34 *
35 * This class is derived from tBlackboardReadAccess so that it can also
36 * be used in places where only read access is required.
37 *
38 */
39//----------------------------------------------------------------------
40#ifndef __plugins__blackboard__tBlackboardWriteAccess_h__
41#define __plugins__blackboard__tBlackboardWriteAccess_h__
42
43//----------------------------------------------------------------------
44// External includes (system with <>, local with "")
45//----------------------------------------------------------------------
46
47//----------------------------------------------------------------------
48// Internal includes with ""
49//----------------------------------------------------------------------
50#include "plugins/blackboard/tBlackboardReadAccess.h"
51
52//----------------------------------------------------------------------
53// Namespace declaration
54//----------------------------------------------------------------------
55namespace finroc
56{
57namespace blackboard
58{
59
60//----------------------------------------------------------------------
61// Forward declarations / typedefs / enums
62//----------------------------------------------------------------------
63
64//----------------------------------------------------------------------
65// Class declaration
66//----------------------------------------------------------------------
67//! Object for blackboard write access
68/*!
69 * Objects of this class are used to acquire write access to blackboards.
70 * The lock is released as soon as the objects goes out of scope.
71 *
72 * This class is derived from tBlackboardReadAccess so that it can also
73 * be used in places where only read access is required.
74 */
75template <typename T>
76class tBlackboardWriteAccess : public tBlackboardReadAccess<T>
77{
78  typedef tBlackboardReadAccess<T> tBase;
79
80//----------------------------------------------------------------------
81// Public methods and typedefs
82//----------------------------------------------------------------------
83public:
84
85  /*!
86   * \param blackboard Blackboard to access
87   * \param timeout Timeout for lock (in ms)
88   * \param deferred_lock_check If set to true, this constructor does not check whether lock could be
89   *                            acquired (and does not block). The lock is checked on the first access instead.
90   *
91   * \exception tLockException is thrown if lock fails (and deferred_lock_check is false)
92   */
93  tBlackboardWriteAccess(tBlackboardClient<T>& blackboard, const rrlib::time::tDuration& timeout = std::chrono::seconds(10), bool deferred_lock_check = false) :
94    tBase(blackboard, blackboard),
95    locked_buffer_future(),
96    locked_buffer(),
97    changed(false)
98  {
99    this->timeout = timeout;
100    ConstructorImplementation(deferred_lock_check);
101  }
102
103  /*!
104   * \param blackboard Blackboard to access
105   * \param timeout Timeout for lock (in ms)
106   * \param deferred_lock_check If set to true, this constructor does not check whether lock could be
107   *                            acquired (and does not block). The lock is checked on the first access instead.
108   *
109   * \exception tLockException is thrown if lock fails (and deferred_lock_check is false)
110   */
111  tBlackboardWriteAccess(tBlackboard<T>& blackboard, const rrlib::time::tDuration& timeout = std::chrono::seconds(10), bool deferred_lock_check = false) :
112    tBase(blackboard.GetClient(), blackboard.GetClient()),
113    locked_buffer_future(),
114    locked_buffer(),
115    changed(false)
116  {
117    this->timeout = timeout;
118    ConstructorImplementation(deferred_lock_check);
119  }
120
121  ~tBlackboardWriteAccess()
122  {
123    if (locked_buffer_raw)
124    {
125      FINROC_LOG_PRINT(DEBUG_VERBOSE_1, "Releasing write lock on blackboard '", blackboard.GetName(), "' at ", rrlib::time::Now());
126      if (changed)
127      {
128        locked_buffer.CommitCurrentBuffer();
129      }
130      else
131      {
132        locked_buffer.CommitNoChanges();
133      }
134    }
135  }
136
137  inline T& operator[](size_t index)
138  {
139    return Get(index);
140  }
141
142  /*!
143   * \param index Element index
144   * \return Element at index
145   *
146   * \exception tLockException is thrown if lock fails (can only occur if locking was deferred in constructor)
147   */
148  inline T& Get(size_t index)
149  {
150    CheckLock();
151    if (index >= locked_buffer_raw->size())
152    {
153      throw std::runtime_error("Blackboard write access out of bounds");
154    }
155    changed = true;
156    return (*locked_buffer.Get())[index];
157  }
158
159  /*!
160   * \return Timestamp of locked blackboard data
161   */
162  rrlib::time::tTimestamp GetTimestamp()
163  {
164    CheckLock();
165    return locked_buffer->GetTimestamp();
166  }
167
168  /*!
169   * \param new_size New size (number of elements) in blackboard
170   *
171   * \exception tLockException is thrown if lock fails (can only occur if locking was deferred in constructor)
172   */
173  inline void Resize(size_t new_size)
174  {
175    if (new_size != this->Size())
176    {
177      rrlib::rtti::ResizeVector(*locked_buffer.Get(), new_size);
178      changed = true;
179      locked_buffer_raw = locked_buffer.Get();
180    }
181  }
182
183  /*!
184   * Sets timestamp of locked blackboard data
185   *
186   * \param timestamp Value to set timestamp to
187   */
188  void SetTimestamp(const rrlib::time::tTimestamp& timestamp)
189  {
190    CheckLock();
191    locked_buffer.SetTimestamp(timestamp);
192  }
193
194  /*!
195   * \return Number of elements in blackboard
196   *
197   * \exception tLockException is thrown if lock fails (can only occur if locking was deferred in constructor)
198   */
199  inline size_t Size()
200  {
201    CheckLock();
202    return locked_buffer_raw->size();
203  }
204
205//----------------------------------------------------------------------
206// Private fields and methods
207//----------------------------------------------------------------------
208private:
209
210  typedef typename tBlackboardClient<T>::tBuffer tBuffer;
211
212  using tBase::blackboard;
213  using tBase::locked_buffer_raw;
214  using tBase::timeout;
215
216  /*! Future for locked buffer */
217  rpc_ports::tFuture<internal::tLockedBuffer<tBuffer>> locked_buffer_future;
218
219  /*! Buffer from locked blackboard */
220  internal::tLockedBuffer<tBuffer> locked_buffer;
221
222  /*! True as soon as changes have been made to buffer */
223  bool changed;
224
225
226  /*!
227   * Check whether locked_buffer has already been obtained.
228   * If not, obtain it.
229   */
230  void CheckLock()
231  {
232    if (!locked_buffer_raw)
233    {
234      try
235      {
236        locked_buffer = locked_buffer_future.Get(timeout);
237        locked_buffer_raw = locked_buffer.GetConst();
238      }
239      catch (const rpc_ports::tRPCException& e)
240      {
241        throw tLockException(e.GetType());
242      }
243    }
244  }
245
246  /*!
247   * Code that would be identical in both constructors
248   */
249  void ConstructorImplementation(bool deferred_lock_check)
250  {
251    if (!this->blackboard)
252    {
253      throw tLockException(rpc_ports::tFutureStatus::INVALID_CALL);
254    }
255    FINROC_LOG_PRINT(DEBUG_VERBOSE_1, "Acquiring write lock on blackboard '", blackboard.GetName(), "' at ", rrlib::time::Now());
256    locked_buffer_future = this->blackboard.WriteLock(timeout);
257    if (!deferred_lock_check)
258    {
259      CheckLock();
260    }
261  }
262
263  // no heap allocation permitted
264  void *operator new(size_t);
265  void *operator new[](size_t);
266
267};
268
269//----------------------------------------------------------------------
270// End of namespace declaration
271//----------------------------------------------------------------------
272}
273}
274
275
276#endif
Note: See TracBrowser for help on using the repository browser.