Ocean
MessageHandler.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_PLATFORM_META_QUEST_PLATFORMSDK_MESSAGE_HANDLER_H
9 #define META_OCEAN_PLATFORM_META_QUEST_PLATFORMSDK_MESSAGE_HANDLER_H
10 
12 
14 
15 #include <OVR_Platform.h>
16 
17 #include <future>
18 
19 namespace Ocean
20 {
21 
22 namespace Platform
23 {
24 
25 namespace Meta
26 {
27 
28 namespace Quest
29 {
30 
31 namespace PlatformSDK
32 {
33 
34 /**
35  * This class is the base class for all objects needing to handle with messages.
36  * The class is mainly forwarding all calls of invokeRequest() to Manager::get().invokeRequest().
37  * @ingroup platformmetaquestplatformsdk
38  */
39 class OCEAN_PLATFORM_META_QUEST_PLATFORMSDK_EXPORT MessageHandler
40 {
41  friend class Manager;
42 
43  public:
44 
45  /**
46  * This class implements a scoped handle for options.
47  * The class is a helper class to ensure that options are always destroyed after usage.
48  * @tparam T The data type of the option
49  */
50  template <typename T>
52  {
53  public:
54 
55  /**
56  * Definition of a function pointer to a function destroying the object.
57  */
58  using DestroyFunction = void(*)(T object);
59 
60  public:
61 
62  /**
63  * Creates a new scoped options object.
64  * @param options The actual options which will be destroyed once this object is disposed, must be valid
65  * @param destoryFunction The destroy function for the given options, must be valid
66  */
67  inline ScopedOptions(const T& options, const DestroyFunction& destoryFunction);
68 
69  /**
70  * Destructs the object and destroys the options.
71  */
72  inline ~ScopedOptions();
73 
74  /**
75  * Returns the actual options.
76  * @return The options of this object
77  */
78  inline operator T() const;
79 
80  protected:
81 
82  /**
83  * Disabled copy constructor.
84  */
85  ScopedOptions(const ScopedOptions&) = delete;
86 
87  /**
88  * Disabled move constructor.
89  */
91 
92  /**
93  * Disabled assign operator.
94  */
96 
97  /**
98  * Disabled move operator.
99  */
101 
102  protected:
103 
104  /// The actual options.
105  T options_ = nullptr;
106 
107  /// The destroy function.
108  DestroyFunction destroyFunction_ = nullptr;
109  };
110 
111  /**
112  * This class implements a helper object allowing to store responses for requests.
113  * @tparam T the data type of the response
114  */
115  template <typename T>
117  {
118  public:
119 
120  /**
121  * Default constructor creating a new object without response.
122  */
123  RequestObject() = default;
124 
125  /**
126  * Sets the latest response.
127  * @param response The response to set
128  */
129  void setResponse(T&& response);
130 
131  /**
132  * Sets the latest response.
133  * @param response The response to set
134  */
135  void setResponse(const T& response);
136 
137  /**
138  * Returns whether this object holds a latest response.
139  * In case a latest response was available, the object is reset so that no latest response is available anymore.
140  * @param response The resulting latest response, if any
141  * @return True, if a latest response was available
142  */
143  bool latestResponse(T& response);
144 
145  protected:
146 
147  /// The latest response.
149 
150  /// True, if this object holds a latest response.
151  bool hasLatestResponse_ = false;
152 
153  /// The object's lock.
154  mutable Lock lock_;
155  };
156 
157  /**
158  * This class implements a helper object allowing to queue responses of requests.
159  */
160  template <typename T>
161  class RequestQueue : public RequestObject<T>
162  {
163  public:
164 
165  /**
166  * Default constructor.
167  */
168  RequestQueue() = default;
169 
170  /**
171  * Adds a new request and returns the corresponding future.
172  * @return The future of the new request
173  */
174  std::future<T> addRequest();
175 
176  /**
177  * Sets the latest response.
178  * The response will be forwarded to the oldest queued future as well.
179  * @param response The response to set
180  */
181  void setResponse(T&& response);
182 
183  /**
184  * Sets the latest response.
185  * The response will be forwarded to the oldest queued future as well.
186  * @param response The response to set
187  */
188  void setResponse(const T& response);
189 
190  protected:
191 
192  /// The queue holding all active promises for the futures of all requests.
193  std::queue<std::promise<T>> promises_;
194  };
195 
196  /**
197  * Definition of a callback function for message responses.
198  * @param message The response message, must be valid
199  * @param succeeded True, if the message succeeded; False, if an error happened
200  */
201  using ResponseCallback = std::function<void(ovrMessage* message, bool succeeded)>;
202 
203  /**
204  * Definition of a member callback function for message responses.
205  * @param message The response message, must be valid
206  * @param succeeded True, if the message succeeded; False, if an error happened
207  * @tparam T The data type of the class of the callback function
208  */
209  template <typename T>
210  using ResponseCallbackFunctionT = void (T::*)(ovrMessage* message, const bool succeeded);
211 
212  /**
213  * Definition of a scoped subscription object for messages.
214  */
216 
217  /**
218  * Definition of a vector holding MessageScopedSubscription objects.
219  */
220  using MessageScopedSubscriptions = std::vector<MessageScopedSubscription>;
221 
222  public:
223 
224  /**
225  * Invokes a new request.
226  * @param requestId The id of the new request
227  * @param responseCallback The callback member function which will be called once the response has arrived
228  * @return True, if succeeded
229  * @tparam T The data type of the class of the callback function
230  */
231  template <typename T>
232  bool invokeRequest(const ovrRequest requestId, const ResponseCallbackFunctionT<T>& responseCallback);
233 
234  /**
235  * Subscribes a callback function for response messages with specific type.
236  * @param messageType The type of the message for wich the callback function will be subscibed, ovrMessage_Unknown to subscribe to all messages
237  * @param responseCallback The callback member function which will be called whenever a response message with the specified type arrives
238  * @return The subscription object, the subscription is active as long as the subscription object exists
239  * @see unsubscribeForMessageResponse().
240  */
241  template <typename T>
242  [[nodiscard]] MessageScopedSubscription subscribeForMessageResponse(const ovrMessageType& messageType, const ResponseCallbackFunctionT<T>& responseCallback);
243 
244  /**
245  * Invokes a new request.
246  * @param requestId The id of the new request
247  * @param responseCallback The callback function which will be called once the response has arrived
248  * @return True, if succeeded
249  */
250  static bool invokeRequest(const ovrRequest requestId, ResponseCallback responseCallback);
251 
252  /**
253  * Subscribes a callback function for response messages with specific type.
254  * @param messageType The type of the message for wich the callback function will be subscibed, ovrMessage_Unknown to subscribe to all messages
255  * @param responseCallback The callback function which will be called whenever a response message with the specified type arrives
256  * @return The subscription object, the subscription is active as long as the subscription object exists
257  * @see unsubscribeForMessageResponse().
258  */
259  [[nodiscard]] static MessageScopedSubscription subscribeForMessageResponse(const ovrMessageType& messageType, ResponseCallback responseCallback);
260 
261  /**
262  * Converts a string with exactly four characters to a unique tag value.
263  * @param tagString The string with four characters to be converted
264  * @return The resulting tag value
265  */
266  static constexpr uint32_t string2tag(const char tagString[4]);
267 
268  protected:
269 
270  /**
271  * Creates a new subscription object for a given subscription id.
272  * @param subscriptionId The subscription id, must be valid
273  * @return The resulting subscription object
274  */
275  [[nodiscard]] static MessageScopedSubscription createMessageScopedSubscription(const unsigned int subscriptionId);
276 
277  /**
278  * Removes a subscription for response messages with specific message type.
279  * @param subscriptionId The subscription id to unsubscribe, must be valid
280  * @see subscribeForMessageResponse().
281  */
282  static void unsubscribeForMessageResponse(const unsigned int& subscriptionId);
283 };
284 
285 template <typename T>
286 bool MessageHandler::invokeRequest(const ovrRequest requestId, const ResponseCallbackFunctionT<T>& responseCallback)
287 {
288  return invokeRequest(requestId, std::bind(responseCallback, (T*)(this), std::placeholders::_1, std::placeholders::_2));
289 }
290 
291 template <typename T>
293 {
294  return subscribeForMessageResponse(messageType, std::bind(responseCallback, (T*)(this), std::placeholders::_1, std::placeholders::_2));
295 }
296 
297 template <typename T>
298 inline MessageHandler::ScopedOptions<T>::ScopedOptions(const T& options, const DestroyFunction& destroyFunction) :
299  options_(options),
300  destroyFunction_(destroyFunction)
301 {
302  ocean_assert(options_ != nullptr);
303  ocean_assert(destroyFunction_ != nullptr);
304 }
305 
306 template <typename T>
308 {
309  ocean_assert(options_ != nullptr);
310  ocean_assert(destroyFunction_ != nullptr);
311 
312  destroyFunction_(options_);
313 }
314 
315 template <typename T>
317 {
318  return options_;
319 }
320 
321 template <typename T>
323 {
324  const ScopedLock scopedLock(lock_);
325 
326  latestResponse_ = std::move(response);
327  hasLatestResponse_ = true;
328 }
329 
330 template <typename T>
332 {
333  const ScopedLock scopedLock(lock_);
334 
335  latestResponse_ = response;
336  hasLatestResponse_ = true;
337 }
338 
339 template <typename T>
341 {
342  const ScopedLock scopedLock(lock_);
343 
344  if (hasLatestResponse_)
345  {
346  value = std::move(latestResponse_);
347  hasLatestResponse_ = false;
348 
349  return true;
350  }
351 
352  return false;
353 }
354 
355 template <typename T>
357 {
358  const ScopedLock scopedLock(this->lock_);
359 
360  std::promise<T> promise;
361  std::future future = promise.get_future();
362 
363  promises_.push(std::move(promise));
364 
365  return future;
366 }
367 
368 template <typename T>
370 {
371  const ScopedLock scopedLock(this->lock_);
372 
373  ocean_assert(!promises_.empty());
374 
375  std::promise<T>& promise = promises_.front();
376  promise.set_value(response);
377 
378  RequestObject<T>::setResponse(std::move(response));
379 
380  promises_.pop();
381 }
382 
383 template <typename T>
385 {
386  const ScopedLock scopedLock(this->lock_);
387 
388  ocean_assert(!promises_.empty());
389 
390  std::promise<T>& promise = promises_.front();
391  promise.set_value(response);
392 
394 
395  promises_.pop();
396 }
397 
398 constexpr uint32_t MessageHandler::string2tag(const char tagString[4])
399 {
400  ocean_assert(tagString[0] != 0 && tagString[1] != 0 && tagString[2] != 0 && tagString[3] != 0);
401 
402  return (uint32_t(tagString[0]) << 0ull)
403  | (uint32_t(tagString[1]) << 8ull)
404  | (uint32_t(tagString[2]) << 16ull)
405  | (uint32_t(tagString[3]) << 24ull);
406 }
407 
408 }
409 
410 }
411 
412 }
413 
414 }
415 
416 }
417 
418 #endif // META_OCEAN_PLATFORM_META_QUEST_PLATFORMSDK_MESSAGE_HANDLER_H
This class implements a recursive lock object.
Definition: Lock.h:31
This class implements a manager that handles the central PlatformSDK functionalities.
Definition: platform/meta/quest/platformsdk/Manager.h:41
This class implements a helper object allowing to store responses for requests.
Definition: MessageHandler.h:117
Lock lock_
The object's lock.
Definition: MessageHandler.h:154
bool latestResponse(T &response)
Returns whether this object holds a latest response.
Definition: MessageHandler.h:340
void setResponse(T &&response)
Sets the latest response.
Definition: MessageHandler.h:322
T latestResponse_
The latest response.
Definition: MessageHandler.h:148
RequestObject()=default
Default constructor creating a new object without response.
This class implements a helper object allowing to queue responses of requests.
Definition: MessageHandler.h:162
void setResponse(T &&response)
Sets the latest response.
Definition: MessageHandler.h:369
std::queue< std::promise< T > > promises_
The queue holding all active promises for the futures of all requests.
Definition: MessageHandler.h:193
std::future< T > addRequest()
Adds a new request and returns the corresponding future.
Definition: MessageHandler.h:356
This class implements a scoped handle for options.
Definition: MessageHandler.h:52
ScopedOptions(const T &options, const DestroyFunction &destoryFunction)
Creates a new scoped options object.
Definition: MessageHandler.h:298
T options_
The actual options.
Definition: MessageHandler.h:105
ScopedOptions & operator=(const ScopedOptions &)=delete
Disabled assign operator.
void(*)(T object) DestroyFunction
Definition of a function pointer to a function destroying the object.
Definition: MessageHandler.h:58
ScopedOptions(const ScopedOptions &)=delete
Disabled copy constructor.
DestroyFunction destroyFunction_
The destroy function.
Definition: MessageHandler.h:108
ScopedOptions & operator=(ScopedOptions &&)=delete
Disabled move operator.
ScopedOptions(ScopedOptions &&)=delete
Disabled move constructor.
This class is the base class for all objects needing to handle with messages.
Definition: MessageHandler.h:40
static MessageScopedSubscription subscribeForMessageResponse(const ovrMessageType &messageType, ResponseCallback responseCallback)
Subscribes a callback function for response messages with specific type.
std::function< void(ovrMessage *message, bool succeeded)> ResponseCallback
Definition of a callback function for message responses.
Definition: MessageHandler.h:201
static MessageScopedSubscription createMessageScopedSubscription(const unsigned int subscriptionId)
Creates a new subscription object for a given subscription id.
static bool invokeRequest(const ovrRequest requestId, ResponseCallback responseCallback)
Invokes a new request.
std::vector< MessageScopedSubscription > MessageScopedSubscriptions
Definition of a vector holding MessageScopedSubscription objects.
Definition: MessageHandler.h:220
static constexpr uint32_t string2tag(const char tagString[4])
Converts a string with exactly four characters to a unique tag value.
Definition: MessageHandler.h:398
static void unsubscribeForMessageResponse(const unsigned int &subscriptionId)
Removes a subscription for response messages with specific message type.
MessageScopedSubscription subscribeForMessageResponse(const ovrMessageType &messageType, const ResponseCallbackFunctionT< T > &responseCallback)
Subscribes a callback function for response messages with specific type.
Definition: MessageHandler.h:292
bool invokeRequest(const ovrRequest requestId, const ResponseCallbackFunctionT< T > &responseCallback)
Invokes a new request.
Definition: MessageHandler.h:286
void(T::*)(ovrMessage *message, const bool succeeded) ResponseCallbackFunctionT
Definition of a member callback function for message responses.
Definition: MessageHandler.h:210
This class implements a scoped lock object for recursive lock objects.
Definition: Lock.h:135
This class implements a subscription object which can be used unique subscriptions to e....
Definition: ScopedSubscription.h:28
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15