summaryrefslogtreecommitdiffstats
path: root/xbmc/SectionLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/SectionLoader.cpp')
-rw-r--r--xbmc/SectionLoader.cpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/xbmc/SectionLoader.cpp b/xbmc/SectionLoader.cpp
new file mode 100644
index 0000000..5612512
--- /dev/null
+++ b/xbmc/SectionLoader.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "SectionLoader.h"
+
+#include "cores/DllLoader/DllLoaderContainer.h"
+#include "utils/GlobalsHandling.h"
+#include "utils/StringUtils.h"
+#include "utils/log.h"
+
+#include <mutex>
+
+#define g_sectionLoader XBMC_GLOBAL_USE(CSectionLoader)
+
+// delay for unloading dll's
+#define UNLOAD_DELAY 30*1000 // 30 sec.
+
+//Define this to get logging on all calls to load/unload sections/dlls
+//#define LOGALL
+
+CSectionLoader::CSectionLoader(void) = default;
+
+CSectionLoader::~CSectionLoader(void)
+{
+ UnloadAll();
+}
+
+LibraryLoader *CSectionLoader::LoadDLL(const std::string &dllname, bool bDelayUnload /*=true*/, bool bLoadSymbols /*=false*/)
+{
+ std::unique_lock<CCriticalSection> lock(g_sectionLoader.m_critSection);
+
+ if (dllname.empty()) return NULL;
+ // check if it's already loaded, and increase the reference count if so
+ for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
+ {
+ CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
+ if (StringUtils::EqualsNoCase(dll.m_strDllName, dllname))
+ {
+ dll.m_lReferenceCount++;
+ return dll.m_pDll;
+ }
+ }
+
+ // ok, now load the dll
+ CLog::Log(LOGDEBUG, "SECTION:LoadDLL({})", dllname);
+ LibraryLoader* pDll = DllLoaderContainer::LoadModule(dllname.c_str(), NULL, bLoadSymbols);
+ if (!pDll)
+ return NULL;
+
+ CDll newDLL;
+ newDLL.m_strDllName = dllname;
+ newDLL.m_lReferenceCount = 1;
+ newDLL.m_bDelayUnload=bDelayUnload;
+ newDLL.m_pDll=pDll;
+ g_sectionLoader.m_vecLoadedDLLs.push_back(newDLL);
+
+ return newDLL.m_pDll;
+}
+
+void CSectionLoader::UnloadDLL(const std::string &dllname)
+{
+ std::unique_lock<CCriticalSection> lock(g_sectionLoader.m_critSection);
+
+ if (dllname.empty()) return;
+ // check if it's already loaded, and decrease the reference count if so
+ for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
+ {
+ CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
+ if (StringUtils::EqualsNoCase(dll.m_strDllName, dllname))
+ {
+ dll.m_lReferenceCount--;
+ if (0 == dll.m_lReferenceCount)
+ {
+ if (dll.m_bDelayUnload)
+ dll.m_unloadDelayStartTick = std::chrono::steady_clock::now();
+ else
+ {
+ CLog::Log(LOGDEBUG, "SECTION:UnloadDll({})", dllname);
+ if (dll.m_pDll)
+ DllLoaderContainer::ReleaseModule(dll.m_pDll);
+ g_sectionLoader.m_vecLoadedDLLs.erase(g_sectionLoader.m_vecLoadedDLLs.begin() + i);
+ }
+
+ return;
+ }
+ }
+ }
+}
+
+void CSectionLoader::UnloadDelayed()
+{
+ std::unique_lock<CCriticalSection> lock(g_sectionLoader.m_critSection);
+
+ // check if we can unload any unreferenced dlls
+ for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
+ {
+ CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
+ auto now = std::chrono::steady_clock::now();
+ auto duration =
+ std::chrono::duration_cast<std::chrono::milliseconds>(now - dll.m_unloadDelayStartTick);
+ if (dll.m_lReferenceCount == 0 && duration.count() > UNLOAD_DELAY)
+ {
+ CLog::Log(LOGDEBUG, "SECTION:UnloadDelayed(DLL: {})", dll.m_strDllName);
+
+ if (dll.m_pDll)
+ DllLoaderContainer::ReleaseModule(dll.m_pDll);
+ g_sectionLoader.m_vecLoadedDLLs.erase(g_sectionLoader.m_vecLoadedDLLs.begin() + i);
+ return;
+ }
+ }
+}
+
+void CSectionLoader::UnloadAll()
+{
+ // delete the dll's
+ std::unique_lock<CCriticalSection> lock(g_sectionLoader.m_critSection);
+ std::vector<CDll>::iterator it = g_sectionLoader.m_vecLoadedDLLs.begin();
+ while (it != g_sectionLoader.m_vecLoadedDLLs.end())
+ {
+ CDll& dll = *it;
+ if (dll.m_pDll)
+ DllLoaderContainer::ReleaseModule(dll.m_pDll);
+ it = g_sectionLoader.m_vecLoadedDLLs.erase(it);
+ }
+}