source: rrlib_serialization/PublishedRegisters.hpp @ 163:3cfc25edb314

17.03
Last change on this file since 163:3cfc25edb314 was 163:3cfc25edb314, checked in by Max Reichardt <mreichardt@…>, 6 years ago

Adjusts auto-register publishing mechanism to remain compatible with older Finroc versions

File size: 7.0 KB
Line 
1//
2// You received this file as part of RRLib
3// Robotics Research Library
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    rrlib/serialization/PublishedRegisters.hpp
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2017-02-09
27 *
28 */
29//----------------------------------------------------------------------
30
31//----------------------------------------------------------------------
32// External includes (system with <>, local with "")
33//----------------------------------------------------------------------
34#include "rrlib/concurrent_containers/tRegister.h"
35
36//----------------------------------------------------------------------
37// Internal includes with ""
38//----------------------------------------------------------------------
39
40//----------------------------------------------------------------------
41// Debugging
42//----------------------------------------------------------------------
43#include <cassert>
44
45//----------------------------------------------------------------------
46// Namespace declaration
47//----------------------------------------------------------------------
48namespace rrlib
49{
50namespace serialization
51{
52
53//----------------------------------------------------------------------
54// Forward declarations / typedefs / enums
55//----------------------------------------------------------------------
56
57//----------------------------------------------------------------------
58// Const values
59//----------------------------------------------------------------------
60
61//----------------------------------------------------------------------
62// Implementation
63//----------------------------------------------------------------------
64
65template <typename TRemoteType>
66const TRemoteType& PublishedRegisters::DeserializeRemoteRegisterEntry(tInputStream& stream, std::array<std::unique_ptr<tInputStream::tRemoteRegister>, cMAX_PUBLISHED_REGISTERS>& register_array)
67{
68  int register_uid = GetRemoteEntryRegisterUid<TRemoteType>();
69  if (register_uid < 0)
70  {
71    throw std::runtime_error("TRemoteType must be registered ad PublishedRegisters first");
72  }
73  if (!register_array[register_uid])
74  {
75    register_array[register_uid].reset(RegisteredRegisters()[register_uid]->CreateRemoteRegister());
76  }
77  const typename TRemoteType::tHandle cESCAPE = -2;
78  auto handle = stream.ReadNumber<typename TRemoteType::tHandle>();
79  if (handle == cESCAPE)
80  {
81    stream.ReadRegisterUpdatesImplementation();
82    handle = stream.ReadNumber<typename TRemoteType::tHandle>();
83  }
84  return *reinterpret_cast<const TRemoteType*>(static_cast<tRemoteRegisterBase*>(register_array[register_uid].get())->GetRemoteElement(handle));
85}
86
87template <typename TElement>
88static const TElement& EmptyElement()
89{
90  static const TElement cEMPTY_ELEMENT;
91  return cEMPTY_ELEMENT;
92}
93
94template <typename TRemoteEntry, bool Tempty_element>
95void PublishedRegisters::Register(const typename TRemoteEntry::tLocalRegister& r, uint uid)
96{
97  typedef typename TRemoteEntry::tLocalRegister tReg;
98  typedef typename tReg::tHandle tHandle;
99  static_assert(std::is_same<typename TRemoteEntry::tHandle, tHandle>::value, "Handle types must match");
100
101  class tRemoteRegisterInstance : public tRemoteRegister<TRemoteEntry>
102  {
103    typedef tRemoteRegister<TRemoteEntry> tBase;
104
105  public:
106    tRemoteRegisterInstance()
107    {
108      tRemoteRegisterBase::size = &tBase::SizeAtomic();
109    }
110
111  private:
112    virtual void DeserializeEntries(tInputStream& stream) override
113    {
114      TRemoteEntry t;
115      if (stream.GetSourceInfo().revision == 0)
116      {
117        if (tBase::Size() == 0)
118        {
119          stream.ReadShort();
120        }
121
122        // legacy type exchange support
123        short s = stream.ReadShort();
124        while (s != -1)
125        {
126          t.DeserializeRegisterEntry(stream);
127          tBase::SetHandle(t, tBase::Size());
128          tBase::Add(t);
129          s = stream.ReadShort();
130        }
131      }
132      else
133      {
134        size_t count = stream.ReadInt();
135        for (size_t i = 0; i < count; i++)
136        {
137          tBase::SetHandle(t, tBase::Size());
138          t.DeserializeRegisterEntry(stream);
139          tBase::Add(t);
140        }
141      }
142    }
143
144    virtual const void* GetRemoteElement(size_t index) override
145    {
146      tHandle handle = static_cast<tHandle>(index);
147      if (Tempty_element && handle == static_cast<tHandle>(-1))
148      {
149        return &EmptyElement<typename std::conditional<Tempty_element, TRemoteEntry, std::string>::type>();
150      }
151      if (index >= this->Size())
152      {
153        throw std::runtime_error("Read invalid index deserializing remote register entry");
154      }
155      return &((*this)[index]);
156    }
157  };
158
159  struct tInfo : tPerRegisterInfo
160  {
161    virtual tRemoteRegisterBase* CreateRemoteRegister() override
162    {
163      return new tRemoteRegisterInstance();
164    }
165    virtual void AddListener(const std::function<void()>& callback, const void* address) override
166    {
167      reg->AddListener(callback, address);
168    }
169    virtual bool RemoveListener(const void* address) override
170    {
171      return reg->RemoveListener(address);
172    }
173    virtual void SerializeEntries(tOutputStream& stream, uint start_element, uint end_element) override
174    {
175      for (size_t i = start_element; i < end_element; i++)
176      {
177        TRemoteEntry::SerializeRegisterEntry(stream, (*reg)[i]);
178      }
179    }
180    const tReg* reg; // Pointer to register
181  };
182
183  auto& infos = RegisteredRegisters();
184  if (infos[uid] && infos[uid]->raw_register_pointer != &r)
185  {
186    throw std::invalid_argument("Uid already occupied with different register");
187  }
188  r.uid = uid;
189  if (infos[uid])
190  {
191    return;
192  }
193
194  std::unique_ptr<tInfo> info(new tInfo());
195  info->reg = &r;
196  info->raw_register_pointer = info->reg;
197  info->size = &(r.SizeAtomic());
198  infos[uid] = std::move(info);
199  RemoteEntryRegisterUid<TRemoteEntry>::Uid() = uid;
200}
201
202template <typename TRemoteEntry>
203inline const TRemoteEntry& tInputStream::ReadRegisterEntry()
204{
205  if (!shared_serialization_info.remote_registers)
206  {
207    throw std::runtime_error("tInputStream: No shared serialization info set");
208  }
209  return PublishedRegisters::DeserializeRemoteRegisterEntry<TRemoteEntry>(*this, *shared_serialization_info.remote_registers);
210}
211
212//----------------------------------------------------------------------
213// End of namespace declaration
214//----------------------------------------------------------------------
215}
216}
Note: See TracBrowser for help on using the repository browser.