diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /tier0/dynfunction.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'tier0/dynfunction.cpp')
| -rw-r--r-- | tier0/dynfunction.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/tier0/dynfunction.cpp b/tier0/dynfunction.cpp new file mode 100644 index 0000000..e05dcb3 --- /dev/null +++ b/tier0/dynfunction.cpp @@ -0,0 +1,148 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Shared library loading and symbol lookup. +// +// $NoKeywords: $ +//=============================================================================// + +#include "pch_tier0.h" +#include "tier0/dynfunction.h" + +#if defined(WIN32) +typedef HMODULE LibraryHandle; +#define LoadLibraryHandle(libname) LoadLibrary(libname) +#define CloseLibraryHandle(handle) FreeLibrary(handle) +#define LookupInLibraryHandle(handle, fn) GetProcAddress(handle, fn) +#elif defined(POSIX) +#include <dlfcn.h> +typedef void *LibraryHandle; +#define LoadLibraryHandle(libname) dlopen(libname, RTLD_NOW) +#define CloseLibraryHandle(handle) dlclose(handle) +#define LookupInLibraryHandle(handle, fn) dlsym(handle, fn) +#else +#error Please define your platform. +#endif + +#if 1 +static inline void dbgdynfn(const char *fmt, ...) {} +#else +#define dbgdynfn printf +#endif + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + +class CSharedLibraryCache +{ +public: + static CSharedLibraryCache &GetCache() + { + static CSharedLibraryCache Singleton; + return Singleton; + } + + struct CSharedLibraryItem + { + CSharedLibraryItem(LibraryHandle handle, const char *name) + { + m_handle = handle; + m_name = new char[strlen(name) + 1]; + m_next = NULL; + strcpy(m_name, name); + } + + ~CSharedLibraryItem() + { + dbgdynfn("CDynamicFunction: Closing library '%s' (%p)\n", m_name, (void *) m_handle); + CloseLibraryHandle(m_handle); + delete[] m_name; + delete m_next; + } + + char *m_name; + CSharedLibraryItem *m_next; + LibraryHandle m_handle; + }; + + CSharedLibraryCache() : m_pList(NULL) {} + ~CSharedLibraryCache() { CloseAllLibraries(); } + + LibraryHandle GetHandle(const char *name) + { + CSharedLibraryItem *item = GetCacheItem(name); + if (item == NULL) + { + LibraryHandle lib = LoadLibraryHandle(name); + dbgdynfn("CDynamicFunction: Loading library '%s' (%p)\n", name, (void *) lib); + if (lib == NULL) + return NULL; + + item = new CSharedLibraryItem(lib, name); + item->m_next = m_pList; + m_pList = item; + } + return item->m_handle; + } + + void CloseLibrary(const char *name) + { + CSharedLibraryItem *item = GetCacheItem(name); + if (item) + { + assert(item == m_pList); + m_pList = item->m_next; + item->m_next = NULL; + delete item; + } + } + + void CloseAllLibraries() + { + delete m_pList; + } + +private: + CSharedLibraryItem *GetCacheItem(const char *name) + { + CSharedLibraryItem *prev = NULL; + CSharedLibraryItem *item = m_pList; + while (item) + { + if (strcmp(item->m_name, name) == 0) + { + // move this item to the front of the list, since there will + // probably be a big pile of these lookups in a row + // and then none ever again. + if (prev != NULL) + { + prev->m_next = item->m_next; + item->m_next = m_pList; + m_pList = item; + } + return item; + } + + prev = item; + item = item->m_next; + } + return NULL; // not found. + } + + CSharedLibraryItem *m_pList; +}; + +void *VoidFnPtrLookup_Tier0(const char *libname, const char *fn, void *fallback) +{ + LibraryHandle lib = CSharedLibraryCache::GetCache().GetHandle(libname); + void *retval = NULL; + if (lib != NULL) + { + retval = LookupInLibraryHandle(lib, fn); + dbgdynfn("CDynamicFunction: Lookup of '%s' in '%s': %p\n", fn, libname, retval); + } + + if (retval == NULL) + retval = fallback; + return retval; +} + |