Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
5.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. #ifndef _TF_GC_SHARED_H
  3. #define _TF_GC_SHARED_H
  4. #ifdef _WIN32
  5. #pragma once
  6. #endif
  7. #include "gcsdk/msgprotobuf.h"
  8. using namespace GCSDK;
  9. #define MMLog(...) do { Log( __VA_ARGS__ ); } while(false)
  10. //-----------------------------------------------------------------------------
  11. // ReliableMessage - A message/job class that retry until confirmed, and be sent
  12. // In order with other such messages.
  13. //-----------------------------------------------------------------------------
  14. //-----------------------------------------------------------------------------
  15. // Check for pending messages
  16. //-----------------------------------------------------------------------------
  17. static bool BPendingReliableMessages();
  18. //-----------------------------------------------------------------------------
  19. GCSDK::CGCClientJob *s_pCurrentConfirmJob = NULL;
  20. CUtlQueue< GCSDK::CGCClientJob * > s_queuePendingConfirmJobs;
  21. template < typename RELIABLE_MSG_CLASS, typename MSG_TYPE, ETFGCMsg E_MSG_TYPE, typename REPLY_TYPE, ETFGCMsg E_REPLY_TYPE>
  22. class CJobReliableMessageBase : public GCSDK::CGCClientJob
  23. {
  24. public:
  25. typedef CProtoBufMsg< MSG_TYPE > Msg_t;
  26. typedef CProtoBufMsg< REPLY_TYPE > Reply_t;
  27. CJobReliableMessageBase()
  28. : GCSDK::CGCClientJob( GCClientSystem()->GetGCClient() )
  29. , m_msg( E_MSG_TYPE )
  30. , m_msgReply()
  31. {}
  32. Msg_t &Msg() { return m_msg; }
  33. void Enqueue()
  34. {
  35. static_cast<RELIABLE_MSG_CLASS *>(this)->InitDebugString( m_strDebug );
  36. MMLog( "[SendMsgUntilConfirmed] %s queued for %s\n", GetMsgName(), DebugString() );
  37. if ( !s_pCurrentConfirmJob )
  38. {
  39. s_pCurrentConfirmJob = this;
  40. this->StartJobDelayed( NULL );
  41. }
  42. else
  43. {
  44. // Queue, confirm jobs will kick next in queue as necessary
  45. s_queuePendingConfirmJobs.Insert( this );
  46. }
  47. }
  48. virtual bool BYieldingRunJob( void *pvStartParam )
  49. {
  50. Assert( s_pCurrentConfirmJob == this );
  51. bool bRet = BYieldingRunJobInternal();
  52. if ( s_queuePendingConfirmJobs.Count() )
  53. {
  54. // Kick off next job
  55. s_pCurrentConfirmJob = s_queuePendingConfirmJobs.RemoveAtHead();
  56. s_pCurrentConfirmJob->StartJob( NULL );
  57. }
  58. else
  59. {
  60. s_pCurrentConfirmJob = NULL;
  61. }
  62. return bRet;
  63. }
  64. bool BYieldingRunJobInternal()
  65. {
  66. MMLog( "[SendMsgUntilConfirmed] %s started for %s\n", GetMsgName(), DebugString() );
  67. // Trigger OnPrepare
  68. static_cast<RELIABLE_MSG_CLASS *>(this)->OnPrepare();
  69. for ( ;; )
  70. {
  71. BYieldingWaitOneFrame();
  72. // Create and load the message
  73. // continuously attempt to send the message to the GC
  74. BYldSendMessageAndGetReply_t result = BYldSendMessageAndGetReplyEx( m_msg, 30, &m_msgReply, E_REPLY_TYPE );
  75. switch ( result )
  76. {
  77. case BYLDREPLY_SUCCESS:
  78. MMLog( "[SendMsgUntilConfirmed] %s successfully sent for %s\n",
  79. GetMsgName(), DebugString() );
  80. // Trigger OnReply
  81. static_cast<RELIABLE_MSG_CLASS *>(this)->OnReply( m_msgReply );
  82. return true;
  83. case BYLDREPLY_SEND_FAILED:
  84. MMLog( "[SendMsgUntilConfirmed] %s send FAILED for %s -- retrying\n",
  85. GetMsgName(), DebugString() );
  86. break;
  87. case BYLDREPLY_TIMEOUT:
  88. MMLog( "[SendMsgUntilConfirmed] %s send TIMEOUT for %s -- retrying\n",
  89. GetMsgName(), DebugString() );
  90. break;
  91. case BYLDREPLY_MSG_TYPE_MISMATCH:
  92. MMLog( "[SendMsgUntilConfirmed] %s send TYPE MISMATCH for %s\n",
  93. GetMsgName(), DebugString() );
  94. Assert( !"Mismatched response type in reliable message" );
  95. return true;
  96. }
  97. }
  98. }
  99. protected:
  100. // Overrides
  101. // Must be overridden by reliable message implementers. Debug string is e.g. "Match 12345, Lobby 4"
  102. void InitDebugString( CUtlString &debugStr ) {}
  103. const char *MsgName() { return "<unknown>"; }
  104. // Optionally overridden
  105. void OnReply( Reply_t &msgReply ) {}
  106. // Called before sending, after previous messages in queue have flushed
  107. void OnPrepare() {}
  108. private:
  109. const char *DebugString() { return m_strDebug.Get(); }
  110. // Forward to override
  111. const char *GetMsgName() { return static_cast<RELIABLE_MSG_CLASS *>(this)->MsgName(); }
  112. Msg_t m_msg;
  113. Reply_t m_msgReply;
  114. CUtlString m_strDebug;
  115. void _static_asserts() {
  116. // Ensure we passed an override and provided provided these
  117. #if __cplusplus >= 201103L && !defined ( OSX ) // (Don't have time to figure out what criteria the OS X toolchain has to not blow this)
  118. static_assert( std::is_base_of< decltype( *this ), RELIABLE_MSG_CLASS >::value,
  119. "RELIABLE_MSG_CLASS Must be an override of this base" );
  120. static_assert( !std::is_same< decltype( &(decltype( *this )::InitDebugString) ),
  121. decltype( &RELIABLE_MSG_CLASS::InitDebugString ) >::value && \
  122. !std::is_same< decltype( &(decltype( *this )::MsgName) ),
  123. decltype( &RELIABLE_MSG_CLASS::MsgName ) >::value,
  124. "RELIABLE_MSG_CLASS class must override DebugString and MsgName" );
  125. #endif // __cplusplus >= 201103L && !defined ( OSX )
  126. }
  127. };
  128. static bool BPendingReliableMessages()
  129. {
  130. Assert( !s_queuePendingConfirmJobs.Count() || s_pCurrentConfirmJob );
  131. return !!s_pCurrentConfirmJob || s_queuePendingConfirmJobs.Count();
  132. }
  133. #endif // _TF_GC_SHARED_H