source: finroc_plugins_rpc_ports/tRPCInterfaceType.h @ 23:edbda752ab7b

Last change on this file since 23:edbda752ab7b was 23:edbda752ab7b, checked in by Max Reichardt <mreichardt@…>, 6 years ago

Adapted to changes in rrlib_rtti

File size: 8.0 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/rpc_ports/tRPCInterfaceType.h
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2012-12-01
27 *
28 * \brief   Contains tRPCInterfaceType
29 *
30 * \b tRPCInterfaceType
31 *
32 * RPC interface type.
33 * Need to be initialized once so that rrlib::rtti knows it
34 * (similar to rrlib::rtti::tDataType).
35 *
36 */
37//----------------------------------------------------------------------
38#ifndef __plugins__rpc_ports__tRPCInterfaceType_h__
39#define __plugins__rpc_ports__tRPCInterfaceType_h__
40
41//----------------------------------------------------------------------
42// External includes (system with <>, local with "")
43//----------------------------------------------------------------------
44
45//----------------------------------------------------------------------
46// Internal includes with ""
47//----------------------------------------------------------------------
48#include "plugins/rpc_ports/tClientPort.h"
49#include "plugins/rpc_ports/internal/tRPCInterfaceTypeInfo.h"
50#include "plugins/rpc_ports/internal/tRPCMessage.h"
51#include "plugins/rpc_ports/internal/tRPCRequest.h"
52#include "plugins/rpc_ports/internal/tRPCResponse.h"
53
54//----------------------------------------------------------------------
55// Namespace declaration
56//----------------------------------------------------------------------
57namespace finroc
58{
59namespace rpc_ports
60{
61
62//----------------------------------------------------------------------
63// Forward declarations / typedefs / enums
64//----------------------------------------------------------------------
65
66//----------------------------------------------------------------------
67// Class declaration
68//----------------------------------------------------------------------
69//! RPC interface type
70/*!
71 * RPC interface type.
72 * Need to be initialized once so that rrlib::rtti knows this interface type
73 * (similar to rrlib::rtti::tDataType).
74 */
75template <typename T>
76class tRPCInterfaceType : public rrlib::rtti::tType
77{
78
79//----------------------------------------------------------------------
80// Public methods and typedefs
81//----------------------------------------------------------------------
82public:
83
84  tRPCInterfaceType() :
85    rrlib::rtti::tType(GetTypeInfo())
86  {
87    if (GetName().length() == 0)
88    {
89      FINROC_LOG_PRINT(ERROR, "RPC type needs to be instantiated with name and function once first.");
90      abort();
91    }
92  }
93
94
95  template <typename ... TFunctions>
96  tRPCInterfaceType(const std::string& name, TFunctions ... functions) :
97    rrlib::rtti::tType(GetTypeInfo(name))
98  {
99    internal::tRPCInterfaceTypeInfo* type_info = this->GetAnnotation<internal::tRPCInterfaceTypeInfo>();
100    if (!type_info)
101    {
102      type_info = new internal::tRPCInterfaceTypeInfo();
103      this->AddAnnotation(type_info);
104      RegisterFunctions<TFunctions...>(*type_info, functions...);
105    }
106    else
107    {
108      FINROC_LOG_PRINT(ERROR, "Attempt to initialize RPC type twice.");
109    }
110  }
111
112  /*!
113   * \function_id Id of function
114   * \return Returns function with specified id
115   */
116  template <typename TFunction>
117  static TFunction GetFunction(uint8_t function_id)
118  {
119    std::vector<std::pair<TFunction, uint8_t>>& lookup = GetFunctionIDLookup<TFunction>();
120    for (auto it = lookup.begin(); it != lookup.end(); ++it)
121    {
122      if (it->second == function_id)
123      {
124        return it->first;
125      }
126    }
127    throw std::runtime_error("Function lookup failed: no such function");
128  }
129
130  /*!
131   * Looks up function id for specified function
132   *
133   * \param function Function whose id is to be looked up
134   * \return Function id in this RPC interface type
135   */
136  template <typename TFunction>
137  static uint8_t GetFunctionID(TFunction function)
138  {
139    std::vector<std::pair<TFunction, uint8_t>>& lookup = GetFunctionIDLookup<TFunction>();
140    for (auto it = lookup.begin(); it != lookup.end(); ++it)
141    {
142      if (it->first == function)
143      {
144        return it->second;
145      }
146    }
147    throw std::runtime_error("Function is not part of tRPCInterfaceType<T>");
148  }
149
150//----------------------------------------------------------------------
151// Private fields and methods
152//----------------------------------------------------------------------
153private:
154
155  typedef typename internal::tRPCInterfaceTypeInfo::tEntry tEntry;
156
157  class tTypeInfo : public rrlib::rtti::tType::tInfo
158  {
159  public:
160    tTypeInfo(const std::string& name) : tInfo(rrlib::rtti::tType::tClassification::OTHER, typeid(T).name(), name)
161    {
162      binary = rrlib::rtti::GetBinaryCurrentlyPerformingStaticInitialization();
163      if (binary.length() > 0)
164      {
165        RRLIB_LOG_PRINT_STATIC(DEBUG_VERBOSE_1, "RPC type ", name, " is statically loaded in '", binary, "'.");
166      }
167    }
168  };
169
170  /*!
171   * \return Function ids for specified function type.
172   * List contains all registered functions of this type - together with their id
173   */
174  template <typename TFunction>
175  static std::vector<std::pair<TFunction, uint8_t>>& GetFunctionIDLookup()
176  {
177    static std::vector<std::pair<TFunction, uint8_t>> lookup;
178    return lookup;
179  }
180
181  static tTypeInfo* GetTypeInfo(const std::string& name = "")
182  {
183    static tTypeInfo type_info(name);
184    return &type_info;
185  }
186
187  void RegisterFunctions(internal::tRPCInterfaceTypeInfo& type_info) {}
188
189  template <typename TFunction, typename ... TFunctions>
190  void RegisterFunctions(internal::tRPCInterfaceTypeInfo& type_info, TFunction function, TFunctions ... functions)
191  {
192    RegisterFunction<TFunction>(type_info, function);
193    RegisterFunctions(type_info, functions...);
194  }
195
196  template <typename TFunction>
197  void RegisterFunction(internal::tRPCInterfaceTypeInfo& type_info, TFunction function)
198  {
199    GetFunctionIDLookup<TFunction>().push_back(std::pair<TFunction, uint8_t>(function, static_cast<uint8_t>(type_info.methods.size())));
200    tEntry entry =
201    {
202      GetDeserializeMessageFunction(function),
203      GetDeserializeRequestFunction(function),
204      GetDeserializeResponseFunction(function)
205    };
206    type_info.methods.emplace_back(entry);
207  }
208
209  template <typename TReturn, typename ... TArgs>
210  internal::tDeserializeMessage GetDeserializeMessageFunction(TReturn(T::*function_pointer)(TArgs...))
211  {
212    return &internal::tRPCMessage<TArgs...>::template DeserializeAndExecuteCallImplementation<TReturn, T>;
213  }
214
215  template <typename TReturn, typename ... TArgs>
216  internal::tDeserializeRequest GetDeserializeRequestFunction(TReturn(T::*function_pointer)(TArgs...))
217  {
218    typedef typename std::conditional<std::is_same<TReturn, void>::value, internal::tNoRPCRequest, internal::tRPCRequest<TReturn, TArgs...>>::type tRequest;
219    return &tRequest::template DeserializeAndExecuteCallImplementation<T>;
220  }
221
222  template <typename TReturn, typename ... TArgs>
223  internal::tDeserializeResponse GetDeserializeResponseFunction(TReturn(T::*function_pointer)(TArgs...))
224  {
225    typedef typename std::conditional<std::is_same<TReturn, void>::value, internal::tNoRPCResponse, internal::tRPCResponse<TReturn>>::type tResponse;
226    return &tResponse::DeserializeAndExecuteCallImplementation;
227  }
228
229
230};
231
232//----------------------------------------------------------------------
233// End of namespace declaration
234//----------------------------------------------------------------------
235}
236}
237
238
239#endif
Note: See TracBrowser for help on using the repository browser.