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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
/*******************************************************************************
* libproxy - A library for proxy configuration
* Copyright (C) 2009 Nathaniel McCallum <nathaniel@natemccallum.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#ifndef MODULEMANAGER_HPP_
#define MODULEMANAGER_HPP_
#include <map>
#include <set>
#include <vector>
#include <typeinfo>
#include <algorithm>
#include "dl_module.hpp"
#include "module.hpp"
#define PX_MODULE_LOAD_NAME px_module_load
#define PX_MODULE_LOAD(type, name, cond) \
extern "C" DLL_PUBLIC bool PX_MODULE_LOAD_NAME(module_manager& mm) { \
if (cond) return mm.register_module<type ## _module>(new name ## _ ## type ## _module); \
return false; \
}
namespace com {
namespace googlecode {
namespace libproxy {
using namespace std;
class DLL_PUBLIC module_manager {
public:
typedef bool (*LOAD_TYPE)(module_manager&);
~module_manager();
template <class T> vector<T*> get_modules() const {
vector<module*> modlist = this->modules.find(&typeid(T))->second;
vector<T*> retlist;
for (size_t i=0 ; i < modlist.size() ; i++)
retlist.push_back(dynamic_cast<T*>(modlist[i]));
return retlist;
}
template <class T> bool register_module(T* module) {
struct pcmp {
static bool cmp(T* x, T* y) { return *x < *y; }
};
// If the class for this module is a singleton...
if (this->singletons.find(&typeid(T)) != this->singletons.end()) {
// ... and we already have an instance of this class ...
if (this->modules[&typeid(T)].size() > 0) {
// ... free the module and return
delete module;
return false;
}
}
// Otherwise we just add the module and sort
vector<T*> modlist = this->get_modules<T>();
modlist.push_back(module);
sort(modlist.begin(), modlist.end(), &pcmp::cmp);
// Insert to our store
this->modules[&typeid(T)].clear();
for (size_t i=0 ; i < modlist.size() ; i++)
this->modules[&typeid(T)].push_back(modlist[i]);
return true;
}
template <class T> bool set_singleton(bool singleton) {
if (singleton)
return this->singletons.insert(&typeid(T)).second;
this->singletons.erase(&typeid(T));
return true;
}
bool load_file(const string filename, const string condsym="");
bool load_dir(const string dirname);
private:
set<dl_module*> dl_modules;
map<const type_info*, vector<module*> > modules;
set<const type_info*> singletons;
bool _load(const string filename, const string initsym);
};
}
}
}
#endif /* MODULEMANAGER_HPP_ */
|