CTR Pia  4.11.3
Game Communication Engine
reckoning_ReckoningCloneElement.h
1 /*---------------------------------------------------------------------------*
2  Project: Pia
3  File: reckoning_ReckoningCloneElement.h
4 
5  Copyright Nintendo. All rights reserved.
6 
7  These coded instructions, statements, and computer programs contain
8  proprietary information of Nintendo of America Inc. and/or Nintendo
9  Company Ltd., and are protected by Federal copyright law. They may
10  not be disclosed to third parties or copied or duplicated in any form,
11  in whole or in part, without the prior written consent of Nintendo.
12  *---------------------------------------------------------------------------*/
13 
14 
15 #pragma once
16 
17 #include <pia/reckoning/reckoning_definitions.h>
18 #include <pia/reckoning/reckoning_ReckoningCloneElementBase.h>
19 #include <pia/clone/clone_SerializePolicyDefinition.h>
20 #include <pia/clone/clone_VoidMemberConcealer.h>
21 #include <pia/clone/clone_CloneProtocol.h>
22 
23 
24 namespace nn
25 {
26 namespace pia
27 {
28 namespace reckoning
29 {
30 
31 /*!
32 @brief Manages the sending and receiving of values while using dead reckoning.
33 
34 @tparam ReckoningStrategy_ Specifies the type of class that defines the reckoning algorithm.
35 @tparam SerializePolicy_ Specifies the algorithm to use for serializing <tt>ReckoningStrategy::Sample</tt>.
36 
37 @details Some of the configured values are saved and sent as a sample on which to predict the current value, eliminating the need to send all of the configured values.
38 
39 The following members must be defined in the class specified for <tt>ReckoningStrategy</tt>.
40 
41 Types
42 
43 @li @code Value @endcode
44 Specifies the type of value that is set and retrieved using <tt>SetValue</tt> and <tt>GetValue</tt>.
45 @li @code Sample @endcode
46 Specifies the type of the sample. The value is actually sent and received using this type.
47 @li @code SetValueArg @endcode
48 Specifies the type of value that is set when calling <tt>SetValue</tt>, and is passed to the <tt>ReckoningStrategy::CheckSample</tt> and <tt>ReckoningStrategy::MakeSample</tt> functions.
49 Specify <tt>void</tt> if this is not required.
50 @li @code Work @endcode
51 Specifies the type that stores the pre-calculated result for prediction. Specify <tt>void</tt> if this is not required.
52 
53 Constants
54 
55 @li @code static const size_t BUFFER_SIZE @endcode
56 Specifies the number of samples to retain.
57 
58 Functions
59 
60 @li @code bool Estimate(
61 Value* pValue,
62 const nn::pia::reckoning::ReckoningCloneElementBase::SampleAccessor<Sample>& accessor,
63 nn::pia::clone::ClockValue clock,
64 Work* pWork); @endcode
65 Calculate the prediction.
66 If the prediction could be calculated, set the value in <tt>*pValue</tt> and return <tt>true</tt>.
67 If it could not be calculated, return <tt>false</tt>.
68 @li @code bool CheckSample(
69 bool* pIsReliable,
70 const Value& value,
71 const SetValueArg* cpSetValueArg,
72 const nn::pia::reckoning::ReckoningCloneElementBase::SampleAccessor<Sample>& accessor,
73 nn::pia::clone::ClockValue clock,
74 Work* pWork); @endcode
75 Determine whether to use the <tt>value</tt> set with <tt>SetValue</tt> as a sample.
76 Return <tt>true</tt> to use it as a sample.
77 If you want to use reliable communication when sending the sample, set <tt>*pIsReliable</tt> to <tt>true</tt>.
78 @li @code void MakeSample(
79 Sample* pSample,
80 const Value& value,
81 const SetValueArg* cpSetValueArg,
82 const nn::pia::reckoning::ReckoningCloneElementBase::SampleAccessor<Sample>& accessor,
83 nn::pia::clone::ClockValue clock,
84 Work* pWork); @endcode
85 Calculate the value to save as a sample.
86 This is called when <tt>CheckSample</tt> determines the value is to be used as a sample and the buffer was successfully allocated.
87 Set the sample in <tt>*pSample</tt>.
88 @li @code void OnUpdateSample(
89 const nn::pia::reckoning::ReckoningCloneElementBase::SampleAccessor<Sample>& accessor,
90 int index,
91 Work* pWork); @endcode
92 This is called when a sample is added.
93 Update the <tt>pWork</tt> value as necessary.
94 
95 For more information, see the Programming Manual.
96 
97 @date 2013-10-28 Initial version.
98 
99 */
100 template <
101  typename ReckoningStrategy_,
102  typename SerializePolicy_ = clone::HostByteOrderSerializePolicy<typename ReckoningStrategy_::Sample> >
104 {
105 public:
106 /*!
107 @brief Defines the type of the dead reckoning algorithm.
108 */
109  typedef ReckoningStrategy_ ReckoningStrategy;
110 
111 
112 /*!
113 @brief Specifies the type of value managed by this object.
114 */
115  typedef typename ReckoningStrategy::Value Value;
116 
117 
118 /*!
119 @brief Defines the type of the sample.
120 */
121  typedef typename ReckoningStrategy::Sample Sample;
122 
123 
124 /*!
125 @brief Specifies the type of value that is passed to <tt>ReckoningStrategy::CheckSample</tt> and <tt>ReckoningStrategy::MakeSample</tt> from <tt>SetValue</tt>.
126 */
127  typedef typename ReckoningStrategy::SetValueArg SetValueArg;
128 
129 
130 /*!
131 @brief Defines the type of the working buffer.
132 */
133  typedef typename ReckoningStrategy::Work Work;
134 
135 
136 /*!
137 @brief Specifies the algorithm to use for serializing <tt>Sample</tt>.
138 */
139  typedef SerializePolicy_ SerializePolicy;
140 
141 
142 /*!
143 @brief Specifies the size of the buffer that holds samples.
144 */
145  static const size_t BUFFER_SIZE = ReckoningStrategy::BUFFER_SIZE;
146 
147 
148 /*!
149 @brief Instantiates the object (constructor).
150 @param[in] pReckoningStrategy Specifies an instance of the dead reckoning algorithm.
151 You can skip specifying the algorithm here, but you must set a valid instance using <tt>SetReckoningStrategy</tt> before passing this object to <tt>CloneBase::RegisterElement</tt>.
152 
153 */
154  explicit ReckoningCloneElement(ReckoningStrategy* pReckoningStrategy = NULL);
155 
156 
157 /*!
158 @brief Destroys the object (destructor).
159 */
161  {
162  }
163 
164 
165 /*!
166 @brief Sets an instance of the dead reckoning algorithm.
167 @details This cannot be set when the object is registered to a <tt>@ref clone::CloneBase "CloneBase"</tt>.
168 @param[in] pReckoningStrategy Specifies the dead reckoning algorithm to set.
169 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
170 @retval ResultInvalidState Indicates that the object is registered to a <tt>CloneBase</tt>. Programming error. Fix your program so that this error is not returned.
171 */
172  nn::Result SetReckoningStrategy(ReckoningStrategy* pReckoningStrategy);
173 
174 
175 /*!
176 @brief Resets the currently set instance of the dead reckoning algorithm.
177 @details This cannot be reset when the object is registered to a <tt>@ref clone::CloneBase "CloneBase"</tt>.
178 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
179 @retval ResultInvalidState Indicates that the object is registered to a <tt>CloneBase</tt>. Programming error. Fix your program so that this error is not returned.
180 */
182  {
183  return SetReckoningStrategy(NULL);
184  }
185 
186 
187 /*!
188 @brief Sets values.
189 @param[in] value Specifies the flags to set.
190 @param[in] cpSetValueArg Specifies the value to pass to <tt>ReckoningStrategy::CheckSample</tt> and <tt>ReckoningStrategy::MakeSample</tt>.
191 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
192 @retval ResultInvalidState Indicates that the registered <tt>CloneBase</tt> cannot send in its current state. Programming error. Fix your program so that this error is not returned.
193 */
194  nn::Result SetValue(const Value& value, const SetValueArg* cpSetValueArg = NULL);
195 
196 
197 /*!
198 @brief Gets a value.
199 @return Returns the value managed by this object. This value is undefined when <tt>@ref IsValidValue</tt> returns <tt>false</tt>.
200 */
201  const Value& GetValue()
202  {
203  UpdateValue();
204  return *m_ValueWork.GetT1Ptr();
205  }
206 
207 
208  //! @cond PRIVATE
209 
210 public:
211  virtual bool IsInitialized() const
212  {
213  return PIA_IS_VALID_POINTER(m_pReckoningStrategy);
214  }
215 
216 protected:
217  virtual size_t GetSize() const
218  {
219  return SerializePolicy::GetSize();
220  }
221  virtual void Serialize(void* pBuffer, const ReckoningSendToken* cpToken);
222  virtual void ClearValue()
223  {
224  m_ValueWork = clone::VoidMemberConcealer<Value, Work>();
225  }
226  virtual bool EstimateValue(clone::ClockValue clock);
227 
228  virtual void Deserialize(ReckoningSendToken* pToken, const void* cpData);
229  virtual void OnUpdateSample(int idx);
230 
231 private:
232  ReckoningSendToken* m_apToken[BUFFER_SIZE];
233  SampleReckoningSendToken<Sample> m_aSampleBuffer[BUFFER_SIZE];
234 
235  ReckoningStrategy* m_pReckoningStrategy;
236 
237  clone::VoidMemberConcealer<Value, Work> m_ValueWork;
238 
239  //! @endcond
240 };
241 
242 
243 //! @cond
244 
245 template <typename ReckoningStrategy, typename SerializePolicy>
248  m_pReckoningStrategy(pReckoningStrategy),
249  m_ValueWork()
250 {
251  PIA_COMPILE_ASSERT(BUFFER_SIZE > 0 && BUFFER_SIZE <= LONG_MAX);
252 
253  for (u32 i = 0; i < static_cast<u32>(BUFFER_SIZE); ++i)
254  {
255  m_aSampleBuffer[i].Init(this);
256  m_apToken[i] = &m_aSampleBuffer[i];
257  }
258 }
259 
260 
261 template <typename ReckoningStrategy, typename SerializePolicy>
263 {
265  {
266  PIA_RETURN_RESULT(ResultInvalidState);
267  }
268  m_pReckoningStrategy = pReckoningStrategy;
269  return ResultSuccess();
270 }
271 
272 
273 template <typename ReckoningStrategy, typename SerializePolicy>
275 {
276  bool isSend;
277  nn::Result r = SetValueCore(&isSend);
278 
279  if (isSend)
280  {
281  const clone::ClockValue clock = GetProtocol()->GetClock();
282  const SampleAccessor<Sample> accessor(GetSampleBuffer());
283 
284  bool isReliable = false;
285  bool isSample = m_pReckoningStrategy->CheckSample(&isReliable, value, cpSetValueArg, accessor, clock, m_ValueWork.GetT2Ptr());
286  if (isSample)
287  {
288  int idx;
289  ReckoningSendToken* pToken = AssignTokenForSend(&idx, isReliable);
290  PIA_ASSERT(pToken != NULL && idx == 0);
291 
292  SampleReckoningSendToken<Sample>* pSampleToken = static_cast<SampleReckoningSendToken<Sample>*>(pToken);
293  m_pReckoningStrategy->MakeSample(pSampleToken->GetSamplePtr(), value, cpSetValueArg, accessor, clock, m_ValueWork.GetT2Ptr());
294  m_pReckoningStrategy->OnUpdateSample(accessor, idx, m_ValueWork.GetT2Ptr());
295  }
296  }
297 
298  return r;
299 }
300 
301 
302 template <typename ReckoningStrategy, typename SerializePolicy>
303 void ReckoningCloneElement<ReckoningStrategy, SerializePolicy>::Serialize(void* pBuffer, const ReckoningSendToken* cpToken)
304 {
305  const SampleReckoningSendToken<Sample>* cpSampleToken = static_cast<const SampleReckoningSendToken<Sample>*>(cpToken);
306  SerializePolicy::Serialize(pBuffer, cpSampleToken->GetSample());
307 }
308 
309 
310 template <typename ReckoningStrategy, typename SerializePolicy>
312 {
313  const SampleAccessor<Sample> accessor(GetSampleBuffer());
314  return m_pReckoningStrategy->Estimate(m_ValueWork.GetT1Ptr(), accessor, clock, m_ValueWork.GetT2Ptr());
315 }
316 
317 
318 template <typename ReckoningStrategy, typename SerializePolicy>
319 void ReckoningCloneElement<ReckoningStrategy, SerializePolicy>::Deserialize(ReckoningSendToken* pToken, const void* cpData)
320 {
321  SampleReckoningSendToken<Sample>* pSampleToken = static_cast<SampleReckoningSendToken<Sample>*>(pToken);
322  SerializePolicy::Deserialize(pSampleToken->GetSamplePtr(), cpData);
323 }
324 
325 
326 template <typename ReckoningStrategy, typename SerializePolicy>
328 {
329  const SampleAccessor<Sample> accessor(GetSampleBuffer());
330  m_pReckoningStrategy->OnUpdateSample(accessor, idx, m_ValueWork.GetT2Ptr());
331 }
332 
333 
334 //! @endcond
335 }
336 }
337 } // end of namespace nn::pia::reckoning
ReckoningStrategy_ ReckoningStrategy
Defines the type of the dead reckoning algorithm.
Definition: reckoning_ReckoningCloneElement.h:109
const Value & GetValue()
Gets a value.
Definition: reckoning_ReckoningCloneElement.h:201
nn::Result SetValue(const Value &value, const SetValueArg *cpSetValueArg=NULL)
Sets values.
nn::Result SetReckoningStrategy(ReckoningStrategy *pReckoningStrategy)
Sets an instance of the dead reckoning algorithm.
u32 ClockValue
Defines a type that holds a clock value.
Definition: clone_definitions.h:44
Manages the sending and receiving of values while using dead reckoning.
Definition: reckoning_ReckoningCloneElement.h:103
Definition: assert.h:115
ReckoningCloneElement(ReckoningStrategy *pReckoningStrategy=NULL)
Instantiates the object (constructor).
Contains member functions used to access values in the sample buffer.
Definition: reckoning_ReckoningCloneElementBase.h:261
virtual ~ReckoningCloneElement()
Destroys the object (destructor).
Definition: reckoning_ReckoningCloneElement.h:160
SerializePolicy_ SerializePolicy
Specifies the algorithm to use for serializing Sample.
Definition: reckoning_ReckoningCloneElement.h:139
ReckoningStrategy::SetValueArg SetValueArg
Specifies the type of value that is passed to ReckoningStrategy::CheckSample and ReckoningStrategy::M...
Definition: reckoning_ReckoningCloneElement.h:127
nn::Result ResetReckoningStrategy()
Resets the currently set instance of the dead reckoning algorithm.
Definition: reckoning_ReckoningCloneElement.h:181
static const size_t BUFFER_SIZE
Specifies the size of the buffer that holds samples.
Definition: reckoning_ReckoningCloneElement.h:145
ReckoningStrategy::Value Value
Specifies the type of value managed by this object.
Definition: reckoning_ReckoningCloneElement.h:115
ReckoningStrategy::Sample Sample
Defines the type of the sample.
Definition: reckoning_ReckoningCloneElement.h:121
This is the base class for managing the sending and receiving of data while using dead reckoning...
Definition: reckoning_ReckoningCloneElementBase.h:47
ClockValue GetClock() const
Gets the current clock.
bool IsRegisteredWithCloneBase() const
Determines whether the object is registered with CloneBase.
Definition: clone_CloneElementBase.h:94
Indicates that the API function was called at the wrong time. Indicates that the Pia library was not ...
bool IsInitialized(void)
Gets whether the reckoning module is initialized.
const CloneProtocol * GetProtocol() const
Gets the CloneProtocol of the CloneBase this object is registered to.
ReckoningStrategy::Work Work
Defines the type of the working buffer.
Definition: reckoning_ReckoningCloneElement.h:133