Move most functionality from the macro to template.

Have the users of the macro use common functionality.
This commit is contained in:
redpolline 2024-12-14 20:01:17 -05:00
parent 35ff20ebfc
commit c593c3f8b8

139
dll/dll.h
View File

@ -28,67 +28,128 @@
#define GOLDBERG_CALLBACK_INTERNAL(parent, fname, cb_type) \ #define GOLDBERG_CALLBACK_INTERNAL(parent, fname, cb_type) \
struct GB_CCallbackInternal_ ## fname : private GB_CCallbackInterImp< sizeof(cb_type) > { \ struct GB_CCallbackInternal_ ## fname : private GB_CCallbackInterImp< sizeof(cb_type) > { \
public: \ public: \
~GB_CCallbackInternal_ ## fname () { if (m_nCallbackFlags & k_ECallbackFlagsRegistered) { \ GB_CCallbackInternal_ ## fname () { \
bool ready = false; \ PRINT_DEBUG("GB_CCallbackInternal_%s::%s %s 0x%p.\n", \
do { \ #fname, \
if (global_mutex.try_lock() == true) { \ #fname, \
Steam_Client * client = get_steam_client(); \ "Default constructor", \
if (client != NULL) { \ this); \
get_steam_client()->UnregisterCallback(this); \ this->reg_thread_has_run = false; \
ready = true; \ std::thread th = std::thread(GB_CCallbackInterImp::_register, this, cb_type::k_iCallback); \
th.detach(); \
} \ } \
global_mutex.unlock(); \ GB_CCallbackInternal_ ## fname ( const GB_CCallbackInternal_ ## fname & a ) { \
PRINT_DEBUG("GB_CCallbackInternal_%s::%s %s 0x%p.\n", \
#fname, \
#fname, \
"Copy constructor", \
this); \
this->reg_thread_has_run = false; \
std::thread th = std::thread(GB_CCallbackInterImp::_register, this, cb_type::k_iCallback); \
th.detach(); \
} \
GB_CCallbackInternal_ ## fname & operator=(const GB_CCallbackInternal_ ## fname &) { \
PRINT_DEBUG("GB_CCallbackInternal_%s::%s %s 0x%p.\n", \
#fname, \
#fname, \
"Assignment = operator", \
this); \
return *this; \
} \ } \
} while (!ready); \
} }\
GB_CCallbackInternal_ ## fname () {} \
GB_CCallbackInternal_ ## fname ( const GB_CCallbackInternal_ ## fname & ) {} \
GB_CCallbackInternal_ ## fname & operator=(const GB_CCallbackInternal_ ## fname &) { return *this; } \
private: \
virtual void Run(void *callback) { \ virtual void Run(void *callback) { \
if (!(m_nCallbackFlags & k_ECallbackFlagsRegistered)) { \ PRINT_DEBUG("GB_CCallbackInternal_%s::Run 0x%p Callback argument: 0x%p.\n", \
bool ready = false; \ #fname, \
do { \ this, \
if (global_mutex.try_lock() == true) { \ callback); \
Steam_Client * client = get_steam_client(); \
if (client != NULL) { \
client->RegisterCallback(this, cb_type::k_iCallback); \
ready = true; \
} \
global_mutex.unlock(); \
} \
} while (!ready); \
} \
if (m_nCallbackFlags & k_ECallbackFlagsRegistered) { \ if (m_nCallbackFlags & k_ECallbackFlagsRegistered) { \
parent *obj = reinterpret_cast<parent*>(reinterpret_cast<char*>(this) - offsetof(parent, m_steamcallback_ ## fname)); \ parent *obj = reinterpret_cast<parent*>(reinterpret_cast<char*>(this) - offsetof(parent, m_steamcallback_ ## fname)); \
obj->fname(reinterpret_cast<cb_type*>(callback)); \ obj->fname(reinterpret_cast<cb_type*>(callback)); \
} \ } \
} \ } \
} m_steamcallback_ ## fname ; void fname( cb_type *callback ) private: \
} m_steamcallback_ ## fname ; void fname(cb_type *callback )
template<int sizeof_cb_type> template<int sizeof_cb_type>
class GB_CCallbackInterImp : protected CCallbackBase class GB_CCallbackInterImp : protected CCallbackBase
{ {
public: public:
virtual ~GB_CCallbackInterImp() { if (m_nCallbackFlags & k_ECallbackFlagsRegistered) { virtual ~GB_CCallbackInterImp() {
_unregister(this);
return;
}
void SetGameserverFlag() {
m_nCallbackFlags |= k_ECallbackFlagsGameServer;
return;
}
protected:
friend class CCallbackMgr;
std::atomic<bool> reg_thread_has_run;
virtual void Run(void *callback) = 0;
virtual void Run(void *callback, bool io_failure, SteamAPICall_t api_fp) {
Run(callback);
return;
}
virtual int GetCallbackSizeBytes() {
return sizeof_cb_type;
}
static void _register(void * arg, int callback) {
GB_CCallbackInterImp * gb = (GB_CCallbackInterImp *)arg;
if (gb != NULL) {
PRINT_DEBUG("GB_CCallbackInterImp::_register Begin registration thread for 0x%p callback %d.\n",
gb,
callback);
if (!(gb->m_nCallbackFlags & k_ECallbackFlagsRegistered)) {
bool ready = false; bool ready = false;
do { do {
if (global_mutex.try_lock() == true) { if (global_mutex.try_lock() == true) {
Steam_Client * client = get_steam_client(); Steam_Client * client = try_get_steam_client();
if (client != NULL) { if (client != NULL) {
get_steam_client()->UnregisterCallback(this); client->RegisterCallback(gb, callback);
ready = true; ready = true;
gb->reg_thread_has_run = true;
PRINT_DEBUG("GB_CCallbackInterImp::_register Registration complete for 0x%p callback %d.\n",
gb,
callback);
} }
global_mutex.unlock(); global_mutex.unlock();
} }
} while (!ready); } while (!ready);
} } }
void SetGameserverFlag() { m_nCallbackFlags |= k_ECallbackFlagsGameServer; } PRINT_DEBUG("GB_CCallbackInterImp::_register Exiting registration thread for 0x%p callback %d.\n",
protected: gb,
friend class CCallbackMgr; callback);
virtual void Run(void *callback) = 0; }
virtual void Run( void *callback, bool io_failure, SteamAPICall_t api_fp) { Run(callback); } return;
virtual int GetCallbackSizeBytes() { return sizeof_cb_type; } }
static void _unregister(void * arg) {
GB_CCallbackInterImp * gb = (GB_CCallbackInterImp *)arg;
if (gb != NULL) {
PRINT_DEBUG("GB_CCallbackInterImp::_unregister Begin deregistration thread for 0x%p.\n",
gb);
bool can_dereg = false;
do {
can_dereg = gb->reg_thread_has_run;
} while (!can_dereg);
if (gb->m_nCallbackFlags & k_ECallbackFlagsRegistered) {
bool ready = false;
do {
if (global_mutex.try_lock() == true) {
Steam_Client * client = try_get_steam_client();
if (client != NULL) {
client->UnregisterCallback(gb);
ready = true;
PRINT_DEBUG("GB_CCallbackInterImp::_unregister Deregistration complete for 0x%p.\n",
gb);
}
global_mutex.unlock();
}
} while (!ready);
PRINT_DEBUG("GB_CCallbackInterImp::_unregister Exiting deregistration thread for 0x%p.\n",
gb);
}
}
return;
}
}; };
Steam_Client *get_steam_client(); Steam_Client *get_steam_client();