ReadyEvent.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file
  11. /// \brief Ready event plugin. This enables a set of systems to create a signal event, set this signal as ready or unready, and to trigger the event when all systems are ready
  12. ///
  13. #include "NativeFeatureIncludes.h"
  14. #if _RAKNET_SUPPORT_ReadyEvent==1
  15. #ifndef __READY_EVENT_H
  16. #define __READY_EVENT_H
  17. #include "PluginInterface2.h"
  18. #include "DS_OrderedList.h"
  19. namespace RakNet {
  20. class RakPeerInterface;
  21. /// \defgroup READY_EVENT_GROUP ReadyEvent
  22. /// \brief Peer to peer synchronized ready and unready events
  23. /// \details
  24. /// \ingroup PLUGINS_GROUP
  25. /// \ingroup READY_EVENT_GROUP
  26. /// Returns the status of a remote system when querying with ReadyEvent::GetReadyStatus
  27. enum ReadyEventSystemStatus
  28. {
  29. /// ----------- Normal states ---------------
  30. /// The remote system is not in the wait list, and we have never gotten a ready or complete message from it.
  31. /// This is the default state for valid events
  32. RES_NOT_WAITING,
  33. /// We are waiting for this remote system to call SetEvent(thisEvent,true).
  34. RES_WAITING,
  35. /// The remote system called SetEvent(thisEvent,true), but it still waiting for other systems before completing the ReadyEvent.
  36. RES_READY,
  37. /// The remote system called SetEvent(thisEvent,true), and is no longer waiting for any other systems.
  38. /// This remote system has completed the ReadyEvent
  39. RES_ALL_READY,
  40. /// Error code, we couldn't look up the system because the event was unknown
  41. RES_UNKNOWN_EVENT,
  42. };
  43. /// \brief Peer to peer synchronized ready and unready events
  44. /// \details For peer to peer networks in a fully connected mesh.<BR>
  45. /// Solves the problem of how to tell if all peers, relative to all other peers, are in a certain ready state.<BR>
  46. /// For example, if A is connected to B and C, A may see that B and C are ready, but does not know if B is ready to C, or vice-versa.<BR>
  47. /// This plugin uses two stages to solve that problem, first, everyone I know about is ready. Second, everyone I know about is ready to everyone they know about.<BR>
  48. /// The user will get ID_READY_EVENT_SET and ID_READY_EVENT_UNSET as the signal flag is set or unset<BR>
  49. /// The user will get ID_READY_EVENT_ALL_SET when all systems are done waiting for all other systems, in which case the event is considered complete, and no longer tracked.<BR>
  50. /// \sa FullyConnectedMesh2
  51. /// \ingroup READY_EVENT_GROUP
  52. class ReadyEvent : public PluginInterface2
  53. {
  54. public:
  55. // GetInstance() and DestroyInstance(instance*)
  56. STATIC_FACTORY_DECLARATIONS(ReadyEvent)
  57. // Constructor
  58. ReadyEvent();
  59. // Destructor
  60. virtual ~ReadyEvent();
  61. // --------------------------------------------------------------------------------------------
  62. // User functions
  63. // --------------------------------------------------------------------------------------------
  64. /// Sets or updates the initial ready state for our local system.
  65. /// If eventId is an unknown event the event is created.
  66. /// If eventId was previously used and you want to reuse it, call DeleteEvent first, or else you will keep the same event signals from before
  67. /// Systems previously or later added through AddToWaitList() with the same \a eventId when isReady=true will get ID_READY_EVENT_SET
  68. /// Systems previously added through AddToWaitList with the same \a eventId will get ID_READY_EVENT_UNSET
  69. /// For both ID_READY_EVENT_SET and ID_READY_EVENT_UNSET, eventId is encoded in bytes 1 through 1+sizeof(int)
  70. /// \param[in] eventId A user-defined identifier to wait on. This can be a sequence counter, an event identifier, or anything else you want.
  71. /// \param[in] isReady True to signal we are ready to proceed with this event, false to unsignal
  72. /// \return False if event status is ID_READY_EVENT_FORCE_ALL_SET, or if we are setting to a status we are already in (no change). Otherwise true
  73. bool SetEvent(int eventId, bool isReady);
  74. /// When systems can call SetEvent() with isReady==false, it is possible for one system to return true from IsEventCompleted() while the other systems return false
  75. /// This can occur if a system SetEvent() with isReady==false while the completion message is still being transmitted.
  76. /// If your game has the situation where some action should be taken on all systems when IsEventCompleted() is true for any system, then call ForceCompletion() when the action begins.
  77. /// This will force all systems to return true from IsEventCompleted().
  78. /// \param[in] eventId A user-defined identifier to immediately set as completed
  79. void ForceCompletion(int eventId);
  80. /// Deletes an event. We will no longer wait for this event, and any systems that we know have set the event will be forgotten.
  81. /// Call this to clear memory when events are completed and you know you will never need them again.
  82. /// \param[in] eventId A user-defined identifier
  83. /// \return True on success. False (failure) on unknown eventId
  84. bool DeleteEvent(int eventId);
  85. /// Returns what was passed to SetEvent()
  86. /// \return The value of isReady passed to SetEvent(). Also returns false on unknown event.
  87. bool IsEventSet(int eventId);
  88. /// Returns if the event is about to be ready and we are negotiating the final packets.
  89. /// This will usually only be true for a very short time, after which IsEventCompleted should return true.
  90. /// While this is true you cannot add to the wait list, or SetEvent() isReady to false anymore.
  91. /// \param[in] eventId A user-defined identifier
  92. /// \return True if any other system has completed processing. Will always be true if IsEventCompleted() is true
  93. bool IsEventCompletionProcessing(int eventId) const;
  94. /// Returns if the wait list is a subset of the completion list.
  95. /// Call this after all systems you want to wait for have been added with AddToWaitList
  96. /// If you are waiting for a specific number of systems (such as players later connecting), also check GetRemoteWaitListSize(eventId) to be equal to 1 less than the total number of participants.
  97. /// \param[in] eventId A user-defined identifier
  98. /// \return True on completion. False (failure) on unknown eventId, or the set is not completed.
  99. bool IsEventCompleted(int eventId) const;
  100. /// Returns if this is a known event.
  101. /// Events may be known even if we never ourselves referenced them with SetEvent, because other systems created them via ID_READY_EVENT_SET.
  102. /// \param[in] eventId A user-defined identifier
  103. /// \return true if we have this event, false otherwise
  104. bool HasEvent(int eventId);
  105. /// Returns the total number of events stored in the system.
  106. /// \return The total number of events stored in the system.
  107. unsigned GetEventListSize(void) const;
  108. /// Returns the event ID stored at a particular index. EventIDs are stored sorted from least to greatest.
  109. /// \param[in] index Index into the array, from 0 to GetEventListSize()
  110. /// \return The event ID stored at a particular index
  111. int GetEventAtIndex(unsigned index) const;
  112. /// Adds a system to wait for to signal an event before considering the event complete and returning ID_READY_EVENT_ALL_SET.
  113. /// As we add systems, if this event was previously set to true with SetEvent, these systems will get ID_READY_EVENT_SET.
  114. /// As these systems disconnect (directly or indirectly through the router) they are removed.
  115. /// \note If the event completion process has already started, you cannot add more systems, as this would cause the completion process to fail
  116. /// \param[in] eventId A user-defined number previously passed to SetEvent that has not yet completed
  117. /// \param[in] guid An address to wait for event replies from. Pass UNASSIGNED_SYSTEM_ADDRESS for all currently connected systems. Until all systems in this list have called SetEvent with this ID and true, and have this system in the list, we won't get ID_READY_EVENT_COMPLETE
  118. /// \return True on success, false on unknown eventId (this should be considered an error)
  119. bool AddToWaitList(int eventId, RakNetGUID guid);
  120. /// Removes systems from the wait list, which should have been previously added with AddToWaitList
  121. /// \note Systems that directly or indirectly disconnect from us are automatically removed from the wait list
  122. /// \param[in] guid The system to remove from the wait list. Pass UNASSIGNED_RAKNET_GUID for all currently connected systems.
  123. /// \return True on success, false on unknown eventId (this should be considered an error)
  124. bool RemoveFromWaitList(int eventId, RakNetGUID guid);
  125. /// Returns if a particular system is waiting on a particular event.
  126. /// \param[in] eventId A user-defined identifier
  127. /// \param[in] guid The system we are checking up on
  128. /// \return True if this system is waiting on this event, false otherwise.
  129. bool IsInWaitList(int eventId, RakNetGUID guid);
  130. /// Returns the total number of systems we are waiting on for this event.
  131. /// Does not include yourself
  132. /// \param[in] eventId A user-defined identifier
  133. /// \return The total number of systems we are waiting on for this event.
  134. unsigned GetRemoteWaitListSize(int eventId) const;
  135. /// Returns the system address of a system at a particular index, for this event.
  136. /// \param[in] eventId A user-defined identifier
  137. /// \param[in] index Index into the array, from 0 to GetWaitListSize()
  138. /// \return The system address of a system at a particular index, for this event.
  139. RakNetGUID GetFromWaitListAtIndex(int eventId, unsigned index) const;
  140. /// For a remote system, find out what their ready status is (waiting, signaled, complete).
  141. /// \param[in] eventId A user-defined identifier
  142. /// \param[in] guid Which system we are checking up on
  143. /// \return The status of this system, for this particular event. \sa ReadyEventSystemStatus
  144. ReadyEventSystemStatus GetReadyStatus(int eventId, RakNetGUID guid);
  145. /// This channel will be used for all RakPeer::Send calls
  146. /// \param[in] newChannel The channel to use for internal RakPeer::Send calls from this system. Defaults to 0.
  147. void SetSendChannel(unsigned char newChannel);
  148. // ---------------------------- ALL INTERNAL AFTER HERE ----------------------------
  149. /// \internal
  150. /// Status of a remote system
  151. struct RemoteSystem
  152. {
  153. MessageID lastSentStatus, lastReceivedStatus;
  154. RakNetGUID rakNetGuid;
  155. };
  156. static int RemoteSystemCompByGuid( const RakNetGUID &key, const RemoteSystem &data );
  157. /// \internal
  158. /// An event, with a set of systems we are waiting for, a set of systems that are signaled, and a set of systems with completed events
  159. struct ReadyEventNode
  160. {
  161. int eventId; // Sorted on this
  162. MessageID eventStatus;
  163. DataStructures::OrderedList<RakNetGUID,RemoteSystem,ReadyEvent::RemoteSystemCompByGuid> systemList;
  164. };
  165. static int ReadyEventNodeComp( const int &key, ReadyEvent::ReadyEventNode * const &data );
  166. protected:
  167. // --------------------------------------------------------------------------------------------
  168. // Packet handling functions
  169. // --------------------------------------------------------------------------------------------
  170. virtual PluginReceiveResult OnReceive(Packet *packet);
  171. virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
  172. virtual void OnRakPeerShutdown(void);
  173. void Clear(void);
  174. /*
  175. bool AnyWaitersCompleted(unsigned eventIndex) const;
  176. bool AllWaitersCompleted(unsigned eventIndex) const;
  177. bool AllWaitersReady(unsigned eventIndex) const;
  178. void SendAllReady(unsigned eventId, RakNetGUID guid);
  179. void BroadcastAllReady(unsigned eventIndex);
  180. void SendReadyStateQuery(unsigned eventId, RakNetGUID guid);
  181. void BroadcastReadyUpdate(unsigned eventIndex);
  182. bool AddToWaitListInternal(unsigned eventIndex, RakNetGUID guid);
  183. bool IsLocked(unsigned eventIndex) const;
  184. bool IsAllReadyByIndex(unsigned eventIndex) const;
  185. */
  186. void SendReadyStateQuery(unsigned eventId, RakNetGUID guid);
  187. void SendReadyUpdate(unsigned eventIndex, unsigned systemIndex, bool forceIfNotDefault);
  188. void BroadcastReadyUpdate(unsigned eventIndex, bool forceIfNotDefault);
  189. void RemoveFromAllLists(RakNetGUID guid);
  190. void OnReadyEventQuery(Packet *packet);
  191. void PushCompletionPacket(unsigned eventId);
  192. bool AddToWaitListInternal(unsigned eventIndex, RakNetGUID guid);
  193. void OnReadyEventForceAllSet(Packet *packet);
  194. void OnReadyEventPacketUpdate(Packet *packet);
  195. void UpdateReadyStatus(unsigned eventIndex);
  196. bool IsEventCompletedByIndex(unsigned eventIndex) const;
  197. unsigned CreateNewEvent(int eventId, bool isReady);
  198. bool SetEventByIndex(int eventIndex, bool isReady);
  199. DataStructures::OrderedList<int, ReadyEventNode*, ReadyEvent::ReadyEventNodeComp> readyEventNodeList;
  200. unsigned char channel;
  201. };
  202. } // namespace RakNet
  203. #endif
  204. #endif // _RAKNET_SUPPORT_*
粤ICP备19079148号