/[svn]/linuxsampler/trunk/src/common/ResourceManager.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/common/ResourceManager.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 835 - (show annotations) (download) (as text)
Mon Feb 6 18:07:17 2006 UTC (18 years, 2 months ago) by persson
File MIME type: text/x-c++hdr
File size: 13100 byte(s)
* fixed some memory management errors

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #ifndef __RESOURCE_MANAGER__
24 #define __RESOURCE_MANAGER__
25
26 #include <set>
27 #include <map>
28
29 /**
30 * Interface class for consumer classes which use a resource managed
31 * by the ResourceManager class.
32 */
33 template<class T_res>
34 class ResourceConsumer {
35 public:
36 /**
37 * Will be called by the ResourceManager to inform the
38 * consumer that a resource currently used by him is going
39 * to be updated. The consumer can then react by stopping
40 * usage until resource is updated. The ResourceManager will
41 * not update the resource until this method returns. This
42 * method needs to be implemented by the consumer.
43 *
44 * @param pResource - resource going to be updated
45 * @param pUpdateArg - pointer the consumer might use to store
46 * informations he might need when update
47 * process was completed
48 */
49 virtual void ResourceToBeUpdated(T_res* pResource, void*& pUpdateArg) = 0;
50
51 /**
52 * Will be called by the ResourceManager to inform the
53 * consumer that resource update was completed. This method
54 * needs to be implemented by the consumer.
55 *
56 * @param pOldResource - (now invalid) pointer to the old
57 * resource
58 * @param pNewResource - (valid) pointer to the updated
59 * resource
60 * @param pUpdateArg - pointer the consumer might have used when
61 * ResourceToBeUpdated() was called
62 */
63 virtual void ResourceUpdated(T_res* pOldResource, T_res* pNewResource, void* pUpdateArg) = 0;
64
65 /**
66 * Might be called by the ResourceManager periodically during an
67 * update / creation of a resource to inform the consumer about the
68 * current progress of that process. This method needs to be
69 * implemented by the consumer.
70 *
71 * @param fProgress - current progress as value between 0.0 and 1.0
72 */
73 virtual void OnResourceProgress(float fProgress) = 0;
74 };
75
76 /**
77 * Abstract base class for sharing resources between multiple consumers.
78 * A consumer can borrow a resource from the ResourceManager, if the
79 * resource doesn't exist yet it will be created. Other consumers will
80 * just be given the same pointer to the resource then. When all consumers
81 * gave back their pointer to the resource, the resource will be destroyed.
82 * Descendants of this base class have to implement the (protected)
83 * Create() and Destroy() methods to create and destroy a resource.
84 */
85 template<class T_key, class T_res>
86 class ResourceManager {
87 private:
88 typedef std::set<ResourceConsumer<T_res>*> ConsumerSet;
89 struct resource_entry_t {
90 T_key key;
91 T_res* resource; ///< pointer to the resource
92 ConsumerSet consumers; ///< list of all consumers who currently use the resource
93 void* arg; ///< optional pointer the descendant might use to store informations about the resource
94 };
95 typedef std::map<T_key, resource_entry_t> ResourceMap;
96 ResourceMap ResourceEntries;
97
98 public:
99 virtual ~ResourceManager() {}
100 /**
101 * Borrow a resource identified by \a Key. The ResourceManager will
102 * mark the resource as in usage by the consumer given with
103 * \a pConsumer. If the Resource doesn't exist yet it will be
104 * created.
105 *
106 * @param Key - resource identifier
107 * @param pConsumer - identifier of the consumer who borrows it
108 * @returns pointer to resource
109 */
110 T_res* Borrow(T_key Key, ResourceConsumer<T_res>* pConsumer) {
111 typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
112 if (iterEntry == ResourceEntries.end()) {
113 // already create an entry for the resource
114 resource_entry_t entry;
115 entry.key = Key;
116 entry.resource = NULL;
117 entry.consumers.insert(pConsumer);
118 ResourceEntries[Key] = entry;
119 // actually create the resource
120 entry.resource = Create(Key, pConsumer, entry.arg);
121 // now update the entry with the created resource
122 ResourceEntries[Key] = entry;
123 OnBorrow(entry.resource, pConsumer, entry.arg);
124 return entry.resource;
125 }
126 resource_entry_t& entry = iterEntry->second;
127 entry.consumers.insert(pConsumer);
128 OnBorrow(entry.resource, pConsumer, entry.arg);
129 return entry.resource;
130 }
131
132 /**
133 * Give back a resource. This tells the ResourceManager that the
134 * consumer given by \a pConsumer doesn't need the resource anymore.
135 * If the resource is not needed by any consumer anymore then the
136 * resource will be destroyed.
137 *
138 * @param pResource - pointer to resource
139 * @param pConsumer - identifier of the consumer who borrowed the
140 * resource
141 */
142 void HandBack(T_res* pResource, ResourceConsumer<T_res>* pConsumer) {
143 typename ResourceMap::iterator iter = ResourceEntries.begin();
144 typename ResourceMap::iterator end = ResourceEntries.end();
145 for (; iter != end; iter++) {
146 if (iter->second.resource == pResource) {
147 resource_entry_t& entry = iter->second;
148 entry.consumers.erase(pConsumer);
149 if (entry.consumers.empty()) {
150 T_res* resource = entry.resource;
151 void* arg = entry.arg;
152 ResourceEntries.erase(iter);
153 Destroy(resource, arg);
154 }
155 return;
156 }
157 }
158 }
159
160 /**
161 * Request update of a resource.
162 *
163 * @param pResource - resource to be updated
164 * @param pConsumer - consumer who requested the update
165 */
166 void Update(T_res* pResource, ResourceConsumer<T_res>* pConsumer) {
167 typename ResourceMap::iterator iter = ResourceEntries.begin();
168 typename ResourceMap::iterator end = ResourceEntries.end();
169 for (; iter != end; iter++) {
170 if (iter->second.resource == pResource) {
171 resource_entry_t& entry = iter->second;
172 // inform all consumers about pending update
173 std::map<ResourceConsumer<T_res>*,void*> updateargs;
174 typename ConsumerSet::iterator iterCons = entry.consumers.begin();
175 typename ConsumerSet::iterator endCons = entry.consumers.end();
176 for (; iterCons != endCons; iterCons++) {
177 if (*iterCons == pConsumer) continue;
178 void* updatearg = NULL;
179 (*iterCons)->ResourceToBeUpdated(entry.resource, updatearg);
180 if (updatearg) updateargs[*iterCons] = updatearg;
181 }
182 // update resource
183 T_res* pOldResource = entry.resource;
184 Destroy(entry.resource, entry.arg);
185 entry.resource = Create(entry.key, pConsumer, entry.arg);
186 // inform all consumers about update completed
187 iterCons = entry.consumers.begin();
188 endCons = entry.consumers.end();
189 for (; iterCons != endCons; iterCons++) {
190 if (*iterCons == pConsumer) continue;
191 typename std::map<ResourceConsumer<T_res>*,void*>::iterator iterArg = updateargs.find(*iterCons);
192 void* updatearg = (iterArg != updateargs.end()) ? iterArg->second : NULL;
193 (*iterCons)->ResourceUpdated(pOldResource, entry.resource, updatearg);
194 }
195 return;
196 }
197 }
198 }
199
200 protected:
201 /**
202 * Has to be implemented by the descendant to create (allocate) a
203 * resource identified by \a Key.
204 *
205 * @param Key - identifier of the resource
206 * @param pConsumer - identifier of the consumer who borrows the
207 * resource
208 * @param pArg - pointer the descendant can use to store
209 * informations he might need for destruction of
210 * the resource
211 * @returns pointer to new resource
212 */
213 virtual T_res* Create(T_key Key, ResourceConsumer<T_res>* pConsumer, void*& pArg) = 0;
214
215 /**
216 * Has to be implemented by the descendant to destroy (free) a
217 * resource pointed by \a pResource.
218 *
219 * @param pResource - pointer to the resource
220 * @param pArg - pointer the descendant might have used when
221 * Create() was called to store informations
222 * about the resource
223 */
224 virtual void Destroy(T_res* pResource, void* pArg) = 0;
225
226 /**
227 * Has to be implemented by the descendant to react when a consumer
228 * borrows a resource (no matter if freshly created or an already
229 * created one). Of course reacting is optional, but the descendant
230 * at least has to provide a method with empty body.
231 *
232 * @param pResource - pointer to the resource
233 * @param pConsumer - identifier of the consumer who borrows the
234 * resource
235 * @param pArg - pointer the descendant might have used when
236 * Create() was called to store informations
237 * about the resource, this information can be
238 * updated by the descendant here
239 */
240 virtual void OnBorrow(T_res* pResource, ResourceConsumer<T_res>* pConsumer, void*& pArg) = 0;
241
242 /**
243 * Dispatcher method which should be periodically called by the
244 * descendant during update or creation of the resource associated
245 * with \a Key. This method will inform all associated consumers
246 * of the given resource about the current progress.
247 *
248 * @param Key - unique identifier of the resource which is
249 * currently creating or updating
250 * @param fProgress - current progress of that creation / update
251 * process as value between 0.0 and 1.0
252 */
253 void DispatchResourceProgressEvent(T_key Key, float fProgress) {
254 typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
255 if (iterEntry != ResourceEntries.end()) {
256 resource_entry_t& entry = iterEntry->second;
257 // inform all consumers of that resource about current progress
258 typename ConsumerSet::iterator iterCons = entry.consumers.begin();
259 typename ConsumerSet::iterator endCons = entry.consumers.end();
260 for (; iterCons != endCons; iterCons++) {
261 (*iterCons)->OnResourceProgress(fProgress);
262 }
263 }
264 }
265 };
266
267 #endif // __RESOURCE_MANAGER__

  ViewVC Help
Powered by ViewVC