implemented module manager template
Stefan Schuermans

Stefan Schuermans commited on 2011-10-24 20:11:00
Showing 2 changed files, with 195 additions and 2 deletions.

... ...
@@ -0,0 +1,188 @@
1
+/* Blinker
2
+   Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef MODULEMGR_H
7
+#define MODULEMGR_H
8
+
9
+#include <list>
10
+
11
+#include "CallMgr.h"
12
+#include "Directory.h"
13
+#include "Module.h"
14
+#include "StreamMgr.h"
15
+
16
+namespace Blinker {
17
+
18
+/// manager for modules of one type
19
+template<typename MODULE>
20
+class ModuleMgr
21
+{
22
+protected:
23
+  /// module list entry
24
+  struct Entry {
25
+    std::string m_name;     ///< name of module
26
+    MODULE      *m_pModule; ///< module object
27
+    Entry(const std::string &name); ///< constructor
28
+    void createModule(ModuleMgr &mgr); ///< create module
29
+    void destroyModule(); ///< destroy module
30
+  };
31
+
32
+  /// module list
33
+  typedef std::list<Entry> ModuleList;
34
+
35
+public:
36
+  /**
37
+   * @brief constructor
38
+   * @param[in] callMgr callback manager
39
+   * @param[in] streamMgr stream manager
40
+   * @param[in] dirBase base directory
41
+   */
42
+  ModuleMgr(CallMgr &callMgr, StreamMgr &streamMgr, const Directory &dirBase);
43
+
44
+  /// destructor
45
+  ~ModuleMgr();
46
+
47
+private:
48
+  /// copy constructor disabled
49
+  ModuleMgr(const ModuleMgr & that);
50
+
51
+  /// assignment operator disabled
52
+  const ModuleMgr & operator=(const ModuleMgr &that);
53
+
54
+public:
55
+  /// check for update of configuration
56
+  void updateConfig();
57
+
58
+protected:
59
+  /// update module list
60
+  void updateModuleList();
61
+
62
+protected:
63
+  CallMgr     &m_callMgr;   ///< callback manager
64
+  StreamMgr   &m_streamMgr; ///< stream manager
65
+  Directory   m_dirBase;    ///< base directory
66
+  ModuleList  m_moduleList; ///< module list
67
+}; // class ModuleMgr
68
+
69
+/* #############
70
+   # ModuleMgr #
71
+   ############# */
72
+
73
+/**
74
+ * @brief constructor
75
+ * @param[in] callMgr callback manager
76
+ * @param[in] streamMgr stream manager
77
+ * @param[in] dirBase base directory
78
+ */
79
+template<typename MODULE>
80
+ModuleMgr<MODULE>::ModuleMgr(CallMgr &callMgr, StreamMgr &streamMgr,
81
+                             const Directory &dirBase):
82
+  m_callMgr(callMgr),
83
+  m_streamMgr(streamMgr),
84
+  m_dirBase(dirBase)
85
+{
86
+  updateModuleList();
87
+}
88
+
89
+/// destructor
90
+template<typename MODULE>
91
+ModuleMgr<MODULE>::~ModuleMgr()
92
+{
93
+  // free all modules
94
+  while (!m_moduleList.empty()) {
95
+    m_moduleList.back().destroyModule();
96
+    m_moduleList.pop_back();
97
+  }
98
+}
99
+
100
+/// check for update of configuration
101
+template<typename MODULE>
102
+void ModuleMgr<MODULE>::updateConfig()
103
+{
104
+  // base directory was modified -> update module list
105
+  if (m_dirBase.checkModified())
106
+    updateModuleList();
107
+}
108
+
109
+/// update module list
110
+template<typename MODULE>
111
+void ModuleMgr<MODULE>::updateModuleList()
112
+{
113
+  // get list of subdirectories in base directory
114
+  typedef std::list<std::string> Subdirlist;
115
+  Subdirlist curSubdirs;
116
+  m_dirBase.getEntries(Directory::TypeSubdir, curSubdirs);
117
+
118
+  // walk through current module list and subdir list simultaneously
119
+  Subdirlist::const_iterator    itSubdir  = curSubdirs.begin();
120
+  typename ModuleList::iterator itEntry   = m_moduleList.begin();
121
+  while (itSubdir != curSubdirs.end() || itEntry != m_moduleList.end()) {
122
+
123
+    // new module inserted
124
+    if (itEntry == m_moduleList.end() || *itSubdir < itEntry->m_name) {
125
+      // create module
126
+      Entry entry(*itSubdir);
127
+      entry.createModule(*this);
128
+      // insert module list entry
129
+      m_moduleList.insert(itEntry, entry);
130
+      // advance to next subdir
131
+      ++itSubdir;
132
+    }
133
+
134
+    // module removed
135
+    else if (itSubdir == curSubdirs.end() || *itSubdir > itEntry->m_name) {
136
+      // remove entry
137
+      itEntry->destroyModule();
138
+      itEntry = m_moduleList.erase(itEntry);
139
+      // do not advance to next subdir
140
+    }
141
+
142
+    // module stayed in list
143
+    else {
144
+      // call module to check for changes
145
+      itEntry->m_pModule->updateConfig();
146
+      // advance to next subdir and next entry
147
+      ++itSubdir;
148
+      ++itEntry;
149
+    }
150
+
151
+  } // while itSubdir itEntry
152
+}
153
+
154
+/* ####################
155
+   # ModuleMgr::Entry #
156
+   #################### */
157
+
158
+/// constructor
159
+template<typename MODULE>
160
+ModuleMgr<MODULE>::Entry::Entry(const std::string &name):
161
+  m_name(name),
162
+  m_pModule(NULL)
163
+{
164
+}
165
+
166
+/// create module
167
+template<typename MODULE>
168
+void ModuleMgr<MODULE>::Entry::createModule(ModuleMgr &mgr)
169
+{
170
+  destroyModule();
171
+  m_pModule = new MODULE(mgr.m_callMgr, mgr.m_streamMgr,
172
+                         mgr.m_dirBase.getSubdir(m_name));
173
+}
174
+
175
+/// destroy module
176
+template<typename MODULE>
177
+void ModuleMgr<MODULE>::Entry::destroyModule()
178
+{
179
+  if (m_pModule) {
180
+    delete m_pModule;
181
+    m_pModule = NULL;
182
+  }
183
+}
184
+
185
+} // namespace Blinker
186
+
187
+#endif // #ifndef MODULEMGR_H
188
+
... ...
@@ -1,5 +1,6 @@
1 1
 #include "CallMgr.h"
2 2
 #include "Directory.h"
3
+#include "ModuleMgr.h"
3 4
 #include "Player.h"
4 5
 #include "Printer.h"
5 6
 #include "StreamMgr.h"
... ...
@@ -8,11 +9,15 @@ using namespace Blinker;
8 9
 
9 10
 int main()
10 11
 {
12
+  Directory dirCfg("../example.cfg");
13
+
11 14
   CallMgr callMgr;
12 15
   StreamMgr streamMgr;
13 16
 
14
-  Player player(callMgr, streamMgr, Directory("../example.cfg/players/hdl"));
15
-  Printer printer(streamMgr, Directory("../example.cfg/printers/hdl"));
17
+  ModuleMgr<Player> playerMgr(callMgr, streamMgr,
18
+                              dirCfg.getSubdir("players"));
19
+  ModuleMgr<Printer> printerMgr(callMgr, streamMgr,
20
+                                dirCfg.getSubdir("printers"));
16 21
 
17 22
   callMgr.run();
18 23
 
19 24