#pragma once #ifndef BP_NOINC #include "../Common.h" #include "CritSect.h" #endif #include "Dictionary.h" #include "TLSingleton.h" #ifdef BF_PLATFORM_WINDOWS #include #else #include /* See NOTES */ #include typedef int SOCKET; #endif enum BpConnectState { BpConnectState_NotConnected, BpConnectState_Connecting, BpConnectState_Connected, BpConnectState_Failed }; #ifndef BP_DISABLED NS_BF_BEGIN class Buffer { public: uint8* mPtr; int mBufSize; int mDataSize; public: Buffer(); ~Buffer(); uint8* Alloc(int size); void Free(); void Clear(); }; class CircularBuffer { public: // Either points to an internal segment of the CircularBuffer, or if the range is discontinuous then // it presents a temporary pointer that is later committed class View { public: uint8* mPtr; int mSrcIdx; int mSrcSize; uint8* mTempBuf; int mTempBufSize; CircularBuffer* mCircularBuffer; public: View(); ~View(); void Commit(int size = -1); }; public: uint8* mBuffer; int mTail; int mDataSize; int mBufSize; public: CircularBuffer(); ~CircularBuffer(); void Clear(); void Resize(int newSize); void GrowReserve(int addSize); void Grow(int addSize); void GrowFront(int addSize); int GetSize(); void MapView(int idx, int len, View& view); void Read(void* ptr, int idx, int len); void Write(void* ptr, int idx, int len); void RemoveFront(int len); }; class BpContext { }; enum BpResult { BpResult_Ok = 0, BpResult_InternalError, BpResult_AlreadyInitialized }; #define BP_CHUNKSIZE 4096 #define BP_NUMCHUNKS 8 #define BP_CLIENT_VERSION 2 enum BpCmd { BpCmd_Init, BpCmd_Enter, BpCmd_EnterDyn, BpCmd_Leave, BpCmd_LODSmallEntry, BpCmd_StrEntry, BpCmd_ThreadAdd, BpCmd_ThreadRemove, BpCmd_SetThread, BpCmd_ThreadName, BpCmd_Tick, BpCmd_PrevTick, BpCmd_KeepAlive, BpCmd_ClockInfo, BpCmd_StreamSplitInfo, BpCmd_Event, BpCmd_LODEvent, BpCmd_Cmd }; class BpCmdTarget { public: CritSect mCritSect; Buffer mOutBuffer; char* mThreadName; int mCurDynStrIdx; const char* mDynStrs[64]; int mCurDepth; public: BpCmdTarget(); void Disable(); // Note: returned "const char*" is actually an index into a temporary string table const char* DynamicString(const char* str); const char* ToStrPtr(const char* str); void Enter(const char* name); void Enter(const char* name, va_list vargs); void EnterF(const char* name, ...); void Leave(); void Event(const char* name, const char* details); }; class BpRootCmdTarget : public BpCmdTarget { public: void Init(); void Tick(); void KeepAlive(); void AddThread(int threadId, BfpThreadId nativeThreadId); }; class BpThreadInfo : public BpCmdTarget { public: BfpThreadId mNativeThreadId; int mThreadId; bool mReadyToSend; bool mHasTerminated; public: BpThreadInfo(); ~BpThreadInfo(); void SetThreadName(const char* name); void RemoveThread(); }; struct BpZoneName { public: int mIdx; int mSize; }; class BpManager { public: #ifdef BF_PLATFORM_WINDOWS HANDLE mMutex; HANDLE mSharedMemoryFile; #endif SOCKET mSocket; BfpThread* mThread; BfpThreadId mThreadId; String mServerName; String mSessionName; String mSessionID; BpRootCmdTarget mRootCmdTarget; BpConnectState mConnectState; SyncEvent mShutdownEvent; CritSect mCritSect; Array mThreadInfos; String mClientName; TLSDtor mTLSDtor; bool mCollectData; bool mThreadRunning; int64 mInitTimeStamp; uint mInitTickCount; int mPauseCount; int mInitCount; CircularBuffer mOutBuffer; int mOutBlockSizeLeft; int mCurThreadId; Dictionary mZoneNameMap; BF_TLS_DECLSPEC static BpThreadInfo* sBpThreadInfo; static BpManager* sBpManager; int64 mCurTick; protected: bool Connect(); void FinishWorkThread(); void ThreadProc(); static void BFP_CALLTYPE ThreadProcThunk(void* ptr); uint8* StartCmd(uint8 cmd, CircularBuffer::View& view, int maxLen); void EndCmd(CircularBuffer::View& view, uint8* ptr); void TrySendData(); void LostConnection(); virtual BpThreadInfo* SlowGetCurThreadInfo(); public: virtual void* AllocBytes(int size); virtual void FreeBytes(void*); public: BpManager(); ~BpManager(); void Clear(); void SetClientName(const StringImpl& clientName); BpResult Init(const char* serverName, const char* sessionName); void RetryConnect(); void Pause(); void Unpause(); void Shutdown(); bool IsDisconnected(); BpContext* CreateContext(const char* name); void CloseContext(); void Tick(); static BpThreadInfo* GetCurThreadInfo(); static BpManager* Get(); }; NS_BF_END class BpAutoZone { public: BpAutoZone(const char* name) { Beefy::BpManager::GetCurThreadInfo()->Enter(name); } ~BpAutoZone() { Beefy::BpManager::sBpThreadInfo->Leave(); } }; class BpAutoZoneF { public: BpAutoZoneF(const char* name, ...) { va_list args; va_start(args, name); Beefy::BpManager::GetCurThreadInfo()->Enter(name, args); } ~BpAutoZoneF() { Beefy::BpManager::sBpThreadInfo->Leave(); } }; #define BP_ENTER(zoneName) BpEnter(name) #define BP_DYN_STR(str) BpDynStr(str) // We purposely 'incorrectly' define BP_ZONE as a variadic macro so compilation will fail rather than warn if we attempt to add params #define BP_TOKENPASTE(x, y) x ## y #define BP_TOKENPASTE2(x, y) BP_TOKENPASTE(x, y) #define BP_ZONE(zoneName, ...) BpAutoZone BP_TOKENPASTE2(bpZone_, __COUNTER__)(zoneName, ##__VA_ARGS__) #define BP_ZONE_F(zoneName, ...) BpAutoZoneF BP_TOKENPASTE2(bpZone_, __COUNTER__)(zoneName, ##__VA_ARGS__) #define BP_SHUTDOWN() BpShutdown() #else #define BP_ENTER(zoneName) do { } while (0) #define BP_DYN_STR(str) str #define BP_ZONE(zoneName, ...) do { } while (0) #define BP_ZONE_F(zoneName, ...) do { } while (0) #define BP_SHUTDOWN() do { } while (0) #endif #if (defined BP_DYNAMIC) || (!defined BF_PLATFORM_WINDOWS) #define BP_EXPORT BF_EXPORT #define BP_CALLTYPE BF_CALLTYPE #else #define BP_EXPORT #define BP_CALLTYPE #endif BP_EXPORT void BP_CALLTYPE BpInit(const char* serverName, const char* sessionName); BP_EXPORT void BP_CALLTYPE BpShutdown(); BP_EXPORT BpConnectState BP_CALLTYPE BpGetConnectState(); BP_EXPORT void BP_CALLTYPE BpRetryConnect(); BP_EXPORT void BP_CALLTYPE BpPause(); BP_EXPORT void BP_CALLTYPE BpUnpause(); BP_EXPORT void BP_CALLTYPE BpSetClientName(const char* clientName); BP_EXPORT void BP_CALLTYPE BpSetThreadName(const char* threadName); BP_EXPORT void BP_CALLTYPE BpEnter(const char* zoneName); BP_EXPORT void BP_CALLTYPE BpEnterF(const char* zoneName, ...); BP_EXPORT void BP_CALLTYPE BpLeave(); BP_EXPORT void BP_CALLTYPE BpFrameTick(); BP_EXPORT void BP_CALLTYPE BpEvent(const char* name, const char* details); BP_EXPORT const char* BP_CALLTYPE BpDynStr(const char* str);