summaryrefslogtreecommitdiff
path: root/project2/basics/options/preload.cpp
blob: 1968023839f6330c1fc24a5bab51139d473de9dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <pch.hpp>
#include <options.h>
#include <library.h>
#include <appInstance.h>
#include <filesystem>
#include <map>
#include <dlfcn.h>
#include <logger.h>

using namespace std::filesystem;

class Preload {
	public:
		INITOPTIONS;

	private:
		typedef boost::shared_ptr<void> Library;
		typedef std::map<path, Library> Libraries;

		static void LoadLibrary(const VariableType & librarypath)
		{
			const auto beforeOpts = AdHoc::PluginManager::getDefault()->getAll<Options>();

			std::string path(librarypath.as<std::string>());
			void * handle = dlopen(path.c_str(), RTLD_GLOBAL | RTLD_NOW); 
			if (handle) {
				Logger()->messagebf(LOG_DEBUG, "Loaded library '%s'", path);
			}
			else {
				const char * dlerr = dlerror();
				Logger()->messagebf(LOG_ERR, "Failed to load library '%s' (%s)", path, dlerr);
				throw LoadLibraryFailed(librarypath, dlerr);
			}
			libs[librarypath.as<std::string>()] = boost::shared_ptr<void>(handle, &dlclose);

			const auto afterOpts = AdHoc::PluginManager::getDefault()->getAll<Options>();
			for (const auto & opt : afterOpts) {
				if (std::find(beforeOpts.begin(), beforeOpts.end(), opt) == beforeOpts.end()) {
					opt->implementation()->reset();
				}
			}
		}

		static void UnloadLibraries()
		{
			AppInstance::current().clearScriptCache();
			libs.clear();
		}

		static Libraries libs;
};

Preload::Libraries Preload::libs;

DECLARE_OPTIONS(Preload, "Library preload options")
("library", Options::functions(Preload::LoadLibrary, Preload::UnloadLibraries), "Libraries to preload")
END_OPTIONS(Preload)