code: Add a proper dynamic loader for components
This loader model should have wider compatibility, as it relies on defined C++ behavior instead of undefined preprocessor behavior. We may even be able to implement a simple dependency system that automatically sorts components into the correct order.
This commit is contained in:
parent
65c45c4461
commit
49f763aa44
|
@ -76,6 +76,8 @@
|
||||||
|
|
||||||
#include "warning-disable.hpp"
|
#include "warning-disable.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "warning-enable.hpp"
|
#include "warning-enable.hpp"
|
||||||
|
|
||||||
|
@ -83,11 +85,60 @@ static std::shared_ptr<streamfx::util::threadpool::threadpool> _threadpool;
|
||||||
static std::shared_ptr<streamfx::gfx::opengl> _streamfx_gfx_opengl;
|
static std::shared_ptr<streamfx::gfx::opengl> _streamfx_gfx_opengl;
|
||||||
static std::shared_ptr<streamfx::obs::source_tracker> _source_tracker;
|
static std::shared_ptr<streamfx::obs::source_tracker> _source_tracker;
|
||||||
|
|
||||||
|
namespace streamfx {
|
||||||
|
typedef std::list<loader_function_t> loader_list_t;
|
||||||
|
typedef std::map<loader_priority_t, loader_list_t> loader_map_t;
|
||||||
|
|
||||||
|
loader_map_t& get_initializers()
|
||||||
|
{
|
||||||
|
static loader_map_t initializers;
|
||||||
|
return initializers;
|
||||||
|
}
|
||||||
|
|
||||||
|
loader_map_t& get_finalizers()
|
||||||
|
{
|
||||||
|
static loader_map_t finalizers;
|
||||||
|
return finalizers;
|
||||||
|
}
|
||||||
|
|
||||||
|
loader::loader(loader_function_t initializer, loader_function_t finalizer, loader_priority_t priority)
|
||||||
|
{
|
||||||
|
auto init_kv = get_initializers().find(priority);
|
||||||
|
if (init_kv != get_initializers().end()) {
|
||||||
|
init_kv->second.push_back(initializer);
|
||||||
|
} else {
|
||||||
|
get_initializers().emplace(priority, loader_list_t{initializer});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert the order for finalizers.
|
||||||
|
auto ipriority = priority ^ static_cast<loader_priority_t>(0xFFFFFFFFFFFFFFFF);
|
||||||
|
auto fina_kv = get_finalizers().find(ipriority);
|
||||||
|
if (fina_kv != get_finalizers().end()) {
|
||||||
|
fina_kv->second.push_back(finalizer);
|
||||||
|
} else {
|
||||||
|
get_finalizers().emplace(ipriority, loader_list_t{finalizer});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace streamfx
|
||||||
|
|
||||||
MODULE_EXPORT bool obs_module_load(void)
|
MODULE_EXPORT bool obs_module_load(void)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
DLOG_INFO("Loading Version %s", STREAMFX_VERSION_STRING);
|
DLOG_INFO("Loading Version %s", STREAMFX_VERSION_STRING);
|
||||||
|
|
||||||
|
// Run all initializers.
|
||||||
|
for (auto kv : streamfx::get_initializers()) {
|
||||||
|
for (auto init : kv.second) {
|
||||||
|
try {
|
||||||
|
init();
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
DLOG_ERROR("Initializer threw exception: %s", ex.what());
|
||||||
|
} catch (...) {
|
||||||
|
DLOG_ERROR("Initializer threw unknown exception.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize global configuration.
|
// Initialize global configuration.
|
||||||
streamfx::configuration::initialize();
|
streamfx::configuration::initialize();
|
||||||
|
|
||||||
|
@ -290,6 +341,19 @@ MODULE_EXPORT void obs_module_unload(void)
|
||||||
// Finalize Thread Pool
|
// Finalize Thread Pool
|
||||||
_threadpool.reset();
|
_threadpool.reset();
|
||||||
|
|
||||||
|
// Run all finalizers.
|
||||||
|
for (auto kv : streamfx::get_finalizers()) {
|
||||||
|
for (auto init : kv.second) {
|
||||||
|
try {
|
||||||
|
init();
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
DLOG_ERROR("Finalizer threw exception: %s", ex.what());
|
||||||
|
} catch (...) {
|
||||||
|
DLOG_ERROR("Finalizer threw unknown exception.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DLOG_INFO("Unloaded Version %s", STREAMFX_VERSION_STRING);
|
DLOG_INFO("Unloaded Version %s", STREAMFX_VERSION_STRING);
|
||||||
} catch (std::exception const& ex) {
|
} catch (std::exception const& ex) {
|
||||||
DLOG_ERROR("Unexpected exception in function '%s': %s", __FUNCTION_NAME__, ex.what());
|
DLOG_ERROR("Unexpected exception in function '%s': %s", __FUNCTION_NAME__, ex.what());
|
||||||
|
|
|
@ -5,7 +5,36 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
|
||||||
|
#include "warning-disable.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include "warning-enable.hpp"
|
||||||
|
|
||||||
namespace streamfx {
|
namespace streamfx {
|
||||||
|
/** Simple but efficient loader structure for ordered initia-/finalize.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef int32_t loader_priority_t;
|
||||||
|
typedef std::function<void()> loader_function_t;
|
||||||
|
enum loader_priority : loader_priority_t {
|
||||||
|
HIGHEST = INT32_MIN,
|
||||||
|
HIGHER = INT32_MIN / 4 * 3,
|
||||||
|
HIGH = INT32_MIN / 4 * 2,
|
||||||
|
ABOVE = INT32_MIN / 4,
|
||||||
|
NORMAL = 0,
|
||||||
|
BELOW = INT32_MAX / 4,
|
||||||
|
LOW = INT32_MAX / 4 * 2,
|
||||||
|
LOWER = INT32_MAX / 4 * 3,
|
||||||
|
LOWEST = INT32_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct loader {
|
||||||
|
loader(loader_function_t initializer, loader_function_t finalizer, loader_priority_t priority);
|
||||||
|
|
||||||
|
// Usage:
|
||||||
|
// auto loader = streamfx::loader([]() { ... }, []() { ... }, 0);
|
||||||
|
};
|
||||||
|
|
||||||
// Threadpool
|
// Threadpool
|
||||||
std::shared_ptr<streamfx::util::threadpool::threadpool> threadpool();
|
std::shared_ptr<streamfx::util::threadpool::threadpool> threadpool();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue