summaryrefslogtreecommitdiff
path: root/tier0/dynfunction.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /tier0/dynfunction.cpp
downloadarchived-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.cpp148
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;
+}
+