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
162 lines
5.1 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
#ifndef _TF_GC_SHARED_H |
|
#define _TF_GC_SHARED_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#include "gcsdk/msgprotobuf.h" |
|
|
|
using namespace GCSDK; |
|
|
|
#define MMLog(...) do { Log( __VA_ARGS__ ); } while(false) |
|
|
|
//----------------------------------------------------------------------------- |
|
// ReliableMessage - A message/job class that retry until confirmed, and be sent |
|
// In order with other such messages. |
|
//----------------------------------------------------------------------------- |
|
|
|
//----------------------------------------------------------------------------- |
|
// Check for pending messages |
|
//----------------------------------------------------------------------------- |
|
static bool BPendingReliableMessages(); |
|
|
|
//----------------------------------------------------------------------------- |
|
GCSDK::CGCClientJob *s_pCurrentConfirmJob = NULL; |
|
CUtlQueue< GCSDK::CGCClientJob * > s_queuePendingConfirmJobs; |
|
|
|
template < typename RELIABLE_MSG_CLASS, typename MSG_TYPE, ETFGCMsg E_MSG_TYPE, typename REPLY_TYPE, ETFGCMsg E_REPLY_TYPE> |
|
class CJobReliableMessageBase : public GCSDK::CGCClientJob |
|
{ |
|
public: |
|
typedef CProtoBufMsg< MSG_TYPE > Msg_t; |
|
typedef CProtoBufMsg< REPLY_TYPE > Reply_t; |
|
|
|
CJobReliableMessageBase() |
|
: GCSDK::CGCClientJob( GCClientSystem()->GetGCClient() ) |
|
, m_msg( E_MSG_TYPE ) |
|
, m_msgReply() |
|
{} |
|
|
|
Msg_t &Msg() { return m_msg; } |
|
void Enqueue() |
|
{ |
|
static_cast<RELIABLE_MSG_CLASS *>(this)->InitDebugString( m_strDebug ); |
|
MMLog( "[SendMsgUntilConfirmed] %s queued for %s\n", GetMsgName(), DebugString() ); |
|
|
|
if ( !s_pCurrentConfirmJob ) |
|
{ |
|
s_pCurrentConfirmJob = this; |
|
this->StartJobDelayed( NULL ); |
|
} |
|
else |
|
{ |
|
// Queue, confirm jobs will kick next in queue as necessary |
|
s_queuePendingConfirmJobs.Insert( this ); |
|
} |
|
} |
|
|
|
virtual bool BYieldingRunJob( void *pvStartParam ) |
|
{ |
|
Assert( s_pCurrentConfirmJob == this ); |
|
bool bRet = BYieldingRunJobInternal(); |
|
|
|
if ( s_queuePendingConfirmJobs.Count() ) |
|
{ |
|
// Kick off next job |
|
s_pCurrentConfirmJob = s_queuePendingConfirmJobs.RemoveAtHead(); |
|
s_pCurrentConfirmJob->StartJob( NULL ); |
|
} |
|
else |
|
{ |
|
s_pCurrentConfirmJob = NULL; |
|
} |
|
|
|
return bRet; |
|
} |
|
|
|
bool BYieldingRunJobInternal() |
|
{ |
|
MMLog( "[SendMsgUntilConfirmed] %s started for %s\n", GetMsgName(), DebugString() ); |
|
|
|
// Trigger OnPrepare |
|
static_cast<RELIABLE_MSG_CLASS *>(this)->OnPrepare(); |
|
|
|
for ( ;; ) |
|
{ |
|
BYieldingWaitOneFrame(); |
|
|
|
// Create and load the message |
|
// continuously attempt to send the message to the GC |
|
BYldSendMessageAndGetReply_t result = BYldSendMessageAndGetReplyEx( m_msg, 30, &m_msgReply, E_REPLY_TYPE ); |
|
|
|
switch ( result ) |
|
{ |
|
case BYLDREPLY_SUCCESS: |
|
MMLog( "[SendMsgUntilConfirmed] %s successfully sent for %s\n", |
|
GetMsgName(), DebugString() ); |
|
// Trigger OnReply |
|
static_cast<RELIABLE_MSG_CLASS *>(this)->OnReply( m_msgReply ); |
|
return true; |
|
case BYLDREPLY_SEND_FAILED: |
|
MMLog( "[SendMsgUntilConfirmed] %s send FAILED for %s -- retrying\n", |
|
GetMsgName(), DebugString() ); |
|
break; |
|
case BYLDREPLY_TIMEOUT: |
|
MMLog( "[SendMsgUntilConfirmed] %s send TIMEOUT for %s -- retrying\n", |
|
GetMsgName(), DebugString() ); |
|
break; |
|
case BYLDREPLY_MSG_TYPE_MISMATCH: |
|
MMLog( "[SendMsgUntilConfirmed] %s send TYPE MISMATCH for %s\n", |
|
GetMsgName(), DebugString() ); |
|
Assert( !"Mismatched response type in reliable message" ); |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
protected: |
|
// Overrides |
|
|
|
// Must be overridden by reliable message implementers. Debug string is e.g. "Match 12345, Lobby 4" |
|
void InitDebugString( CUtlString &debugStr ) {} |
|
const char *MsgName() { return "<unknown>"; } |
|
|
|
// Optionally overridden |
|
void OnReply( Reply_t &msgReply ) {} |
|
// Called before sending, after previous messages in queue have flushed |
|
void OnPrepare() {} |
|
|
|
private: |
|
const char *DebugString() { return m_strDebug.Get(); } |
|
|
|
// Forward to override |
|
const char *GetMsgName() { return static_cast<RELIABLE_MSG_CLASS *>(this)->MsgName(); } |
|
|
|
Msg_t m_msg; |
|
Reply_t m_msgReply; |
|
CUtlString m_strDebug; |
|
|
|
void _static_asserts() { |
|
// Ensure we passed an override and provided provided these |
|
#if __cplusplus >= 201103L && !defined ( OSX ) // (Don't have time to figure out what criteria the OS X toolchain has to not blow this) |
|
static_assert( std::is_base_of< decltype( *this ), RELIABLE_MSG_CLASS >::value, |
|
"RELIABLE_MSG_CLASS Must be an override of this base" ); |
|
static_assert( !std::is_same< decltype( &(decltype( *this )::InitDebugString) ), |
|
decltype( &RELIABLE_MSG_CLASS::InitDebugString ) >::value && \ |
|
!std::is_same< decltype( &(decltype( *this )::MsgName) ), |
|
decltype( &RELIABLE_MSG_CLASS::MsgName ) >::value, |
|
"RELIABLE_MSG_CLASS class must override DebugString and MsgName" ); |
|
#endif // __cplusplus >= 201103L && !defined ( OSX ) |
|
} |
|
}; |
|
|
|
static bool BPendingReliableMessages() |
|
{ |
|
Assert( !s_queuePendingConfirmJobs.Count() || s_pCurrentConfirmJob ); |
|
return !!s_pCurrentConfirmJob || s_queuePendingConfirmJobs.Count(); |
|
} |
|
|
|
|
|
#endif // _TF_GC_SHARED_H |
|
|
|
|