summaryrefslogtreecommitdiff
path: root/project2/basics/options/preload.cpp
blob: 5cf42e89469ccd6c0727a119b435c073067ffa1f (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
#include <pch.hpp>
#include <options.h>
#include <library.h>
#include <appInstance.h>
#include <boost/filesystem/path.hpp>
#include <map>
#include <dlfcn.h>
#include <logger.h>

using namespace boost::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 = InstanceSet<Options>::GetAll();

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

			const auto afterOpts = InstanceSet<Options>::GetAll();
			for (const auto & opt : afterOpts) {
				if (std::find(beforeOpts.begin(), beforeOpts.end(), opt) == beforeOpts.end()) {
					opt->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)