Fix race between killing object and drawing object
[lsnes.git] / include / library / loadlib.hpp
blob6f858dbef71ec21199a7088a3c5e094b8fb7c77e
1 #ifndef _library__loadlib__hpp__included__
2 #define _library__loadlib__hpp__included__
4 #include <string>
5 #include <stdexcept>
6 #include <map>
7 #include <set>
8 #include "threads.hpp"
10 #if defined(_WIN32) || defined(_WIN64)
11 #include <windows.h>
12 #endif
14 namespace loadlib
16 threads::lock& global_mutex();
18 /**
19 * A loaded library.
21 class library
23 public:
24 /**
25 * Construct a NULL library.
27 library()
29 lib = NULL;
31 /**
32 * Load a new library.
34 * Parameter filename: The name of file.
35 * Throws std::bad_alloc: Not enough memory.
36 * Throws std::runtime_error: Error loading shared library.
38 library(const std::string& filename) throw(std::bad_alloc, std::runtime_error)
40 try {
41 set_loading(this);
42 lib = new internal(filename);
43 set_loading(NULL);
44 } catch(...) {
45 set_loading(NULL);
46 throw;
49 /**
50 * Unload a library.
52 ~library() throw()
54 threads::alock h(global_mutex());
55 if(lib && !--lib->refs)
56 delete lib;
58 /**
59 * Look up a symbol.
61 * Parameter symbol: The symbol to look up.
62 * Returns: The symbol value.
63 * Throws std::bad_alloc: Not enough memory.
64 * Throws std::runtime_error: Error looking up the symbol.
66 void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error)
68 threads::alock h(global_mutex());
69 if(!lib) throw std::runtime_error("Symbol '" + symbol + "' not found");
70 return (*lib)[symbol];
72 /**
73 * See what libraries are called on this platform.
75 * Returns: The name of library.
77 static const std::string& name() throw();
78 /**
79 * See what standard library extension is on this platform.
81 * Returns: The extension of library.
83 static const std::string& extension() throw();
84 /**
85 * Copy ctor.
87 library(const library& r)
89 threads::alock h(global_mutex());
90 lib = r.lib;
91 if(lib) ++lib->refs;
93 library& operator=(const library& r)
95 if(lib == r.lib)
96 return *this;
97 threads::alock h(global_mutex());
98 if(lib && !--lib->refs)
99 delete lib;
100 lib = r.lib;
101 if(lib) ++lib->refs;
102 return *this;
104 std::string get_libname() const { return lib->libname; }
105 void mark(const void* obj) const { if(lib) lib->mark(obj); }
106 bool is_marked(const void* obj) const { return lib ? lib->is_marked(obj) : false; }
108 * Get currently loading library, or NULL if nothing is loading.
110 static library* loading() throw();
111 private:
112 void set_loading(library* lib) throw(std::bad_alloc);
113 struct internal
115 internal(const std::string& filename) throw(std::bad_alloc, std::runtime_error);
116 ~internal() throw();
117 void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error);
118 internal(const internal&);
119 internal& operator=(const internal&);
120 #if defined(_WIN32) || defined(_WIN64)
121 HMODULE handle;
122 #elif !defined(NO_DLFCN)
123 void* handle;
124 #endif
125 size_t refs;
126 std::string libname;
127 void mark(const void* obj) { marked.insert(obj); }
128 bool is_marked(const void* obj) { return marked.count(obj); }
129 std::set<const void*> marked;
131 mutable internal* lib;
135 * A program module.
137 class module
139 template<typename T, typename... U> struct fntype { typedef T(*t)(U...); };
140 public:
142 * Symbol definition.
144 struct symbol
146 const char* name;
147 void* address;
150 * Construct a module from list of symbols.
152 module(std::initializer_list<symbol> symbols, std::function<void(const module&)> init_fn);
154 * Construct a module from library.
156 module(library lib);
158 * Copy ctor
160 module(const module& mod);
162 * Dtor.
164 ~module();
166 * Symbol lookup.
168 void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error);
170 * Variable symbol lookup.
172 template<typename T> T* var(const std::string& symbol) const throw(std::bad_alloc, std::runtime_error)
174 return (T*)(*this)[symbol];
177 * Function symbol lookup.
179 template<typename T, typename... U> typename fntype<T, U...>::t fn(const std::string& symbol) const
180 throw(std::bad_alloc, std::runtime_error)
182 return (typename fntype<T, U...>::t)(*this)[symbol];
185 * Get name.
187 std::string get_libname() const { return libname; }
189 * Run all not ran initialization functions.
191 static void run_initializers();
193 * Mark object (only works for libraries).
195 void mark(const void* obj) const { if(dynamic) lib.mark(obj); }
197 * Is object marked (only works for libraries)?
199 bool is_marked(const void* obj) const { return dynamic ? lib.is_marked(obj) : false; }
200 private:
201 bool dynamic;
202 library lib;
203 std::map<std::string, void*> symbols;
204 std::function<void(const module&)> init;
205 std::string libname;
209 #endif