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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1040 - (hide annotations) (download) (as text)
Wed Feb 7 15:41:31 2007 UTC (17 years, 2 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 26709 byte(s)
* bugfix: sampler crashed when trying to persistently map a not existent or
  corrupt .gig file ("MAP MIDI_INSTRUMENT ... PERSISTENT")
* behavior fix: reset FX send levels i.e. when receiving a MIDI "reset all
  controllers" message
* bumped version to 0.4.0.3cvs

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 1040 * Copyright (C) 2005 - 2007 Christian Schoenebeck *
7 schoenebeck 53 * *
8     * This program is free software; you can redistribute it and/or modify *
9     * it under the terms of the GNU General Public License as published by *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13     * This program is distributed in the hope that it will be useful, *
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19     * along with this program; if not, write to the Free Software *
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24     #ifndef __RESOURCE_MANAGER__
25     #define __RESOURCE_MANAGER__
26    
27     #include <set>
28     #include <map>
29 schoenebeck 947 #include <vector>
30 schoenebeck 53
31 schoenebeck 947 #include "Exception.h"
32 schoenebeck 970 #include "Mutex.h"
33 schoenebeck 947
34     namespace LinuxSampler {
35    
36     /** @brief Interface class for Resource Consumers.
37     *
38 schoenebeck 53 * Interface class for consumer classes which use a resource managed
39 schoenebeck 947 * by the ResourceManager class. All classes which use the ResourceManager
40     * to aquire resources have to derive from this interface class and
41     * implement the abstract methods.
42 schoenebeck 53 */
43     template<class T_res>
44     class ResourceConsumer {
45     public:
46     /**
47     * Will be called by the ResourceManager to inform the
48     * consumer that a resource currently used by him is going
49     * to be updated. The consumer can then react by stopping
50     * usage until resource is updated. The ResourceManager will
51     * not update the resource until this method returns. This
52     * method needs to be implemented by the consumer.
53     *
54     * @param pResource - resource going to be updated
55     * @param pUpdateArg - pointer the consumer might use to store
56     * informations he might need when update
57     * process was completed
58     */
59     virtual void ResourceToBeUpdated(T_res* pResource, void*& pUpdateArg) = 0;
60    
61     /**
62     * Will be called by the ResourceManager to inform the
63     * consumer that resource update was completed. This method
64     * needs to be implemented by the consumer.
65     *
66     * @param pOldResource - (now invalid) pointer to the old
67     * resource
68     * @param pNewResource - (valid) pointer to the updated
69     * resource
70     * @param pUpdateArg - pointer the consumer might have used when
71     * ResourceToBeUpdated() was called
72     */
73     virtual void ResourceUpdated(T_res* pOldResource, T_res* pNewResource, void* pUpdateArg) = 0;
74 schoenebeck 517
75     /**
76     * Might be called by the ResourceManager periodically during an
77     * update / creation of a resource to inform the consumer about the
78     * current progress of that process. This method needs to be
79     * implemented by the consumer.
80     *
81     * @param fProgress - current progress as value between 0.0 and 1.0
82     */
83     virtual void OnResourceProgress(float fProgress) = 0;
84 schoenebeck 53 };
85    
86 schoenebeck 947 /** @brief Manager for sharing resources.
87     *
88 schoenebeck 53 * Abstract base class for sharing resources between multiple consumers.
89     * A consumer can borrow a resource from the ResourceManager, if the
90     * resource doesn't exist yet it will be created. Other consumers will
91     * just be given the same pointer to the resource then. When all consumers
92 schoenebeck 947 * gave back their pointer to the resource, the resource will (by default)
93     * be destroyed.
94     *
95 schoenebeck 53 * Descendants of this base class have to implement the (protected)
96     * Create() and Destroy() methods to create and destroy a resource.
97 schoenebeck 958 *
98 schoenebeck 970 * This class is thread safe (by default). Its methods should however not
99     * be called in a realtime context due to this! Alternatively one can
100     * call the respective methods with bLock = false, in that case thread
101     * safety mechanisms will be omitted - use with care !
102 schoenebeck 53 */
103     template<class T_key, class T_res>
104     class ResourceManager {
105 schoenebeck 947 public:
106     /**
107     * Defines life-time strategy for resources.
108     */
109     enum mode_t {
110     ON_DEMAND = 0, ///< Create resource when needed, free it once not needed anymore (default behavior).
111     ON_DEMAND_HOLD = 1, ///< Create resource when needed and keep it even if not needed anymore.
112     PERSISTENT = 2 ///< Immediately create resource and keep it.
113     };
114    
115 schoenebeck 53 private:
116     typedef std::set<ResourceConsumer<T_res>*> ConsumerSet;
117     struct resource_entry_t {
118     T_key key;
119     T_res* resource; ///< pointer to the resource
120 schoenebeck 947 mode_t mode; ///< When should the resource be created? When should it be destroyed?
121 schoenebeck 53 ConsumerSet consumers; ///< list of all consumers who currently use the resource
122 schoenebeck 947 void* lifearg; ///< optional pointer the descendant might use to store informations about a created resource
123     void* entryarg; ///< optional pointer the descendant might use to store informations about an entry
124 schoenebeck 53 };
125     typedef std::map<T_key, resource_entry_t> ResourceMap;
126     ResourceMap ResourceEntries;
127 schoenebeck 970 Mutex ResourceEntriesMutex; // Mutex for protecting the ResourceEntries map
128 schoenebeck 53
129     public:
130     /**
131 schoenebeck 947 * Returns (the keys of) all current entries of this
132     * ResourceManager instance.
133 schoenebeck 970 *
134     * @param bLock - use thread safety mechanisms
135 schoenebeck 947 */
136 schoenebeck 970 std::vector<T_key> Entries(bool bLock = true) {
137 schoenebeck 947 std::vector<T_key> result;
138 schoenebeck 970 if (bLock) ResourceEntriesMutex.Lock();
139 schoenebeck 947 for (typename ResourceMap::iterator iter = ResourceEntries.begin();
140     iter != ResourceEntries.end(); iter++)
141     {
142     result.push_back(iter->first);
143     }
144 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
145 schoenebeck 947 return result;
146     }
147    
148     /**
149 schoenebeck 53 * Borrow a resource identified by \a Key. The ResourceManager will
150     * mark the resource as in usage by the consumer given with
151     * \a pConsumer. If the Resource doesn't exist yet it will be
152     * created.
153     *
154     * @param Key - resource identifier
155     * @param pConsumer - identifier of the consumer who borrows it
156 schoenebeck 970 * @param bLock - use thread safety mechanisms
157 schoenebeck 53 * @returns pointer to resource
158     */
159 schoenebeck 970 T_res* Borrow(T_key Key, ResourceConsumer<T_res>* pConsumer, bool bLock = true) {
160     if (bLock) ResourceEntriesMutex.Lock();
161 schoenebeck 947 // search for an entry for this resource
162 schoenebeck 53 typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
163 schoenebeck 947 if (iterEntry == ResourceEntries.end()) { // entry doesn't exist yet
164 schoenebeck 517 // already create an entry for the resource
165 schoenebeck 53 resource_entry_t entry;
166     entry.key = Key;
167 schoenebeck 517 entry.resource = NULL;
168 schoenebeck 947 entry.mode = ON_DEMAND; // default mode
169     entry.lifearg = NULL;
170     entry.entryarg = NULL;
171 schoenebeck 517 entry.consumers.insert(pConsumer);
172     ResourceEntries[Key] = entry;
173 schoenebeck 925 try {
174     // actually create the resource
175 schoenebeck 947 entry.resource = Create(Key, pConsumer, entry.lifearg);
176 schoenebeck 925 } catch (...) {
177     // creating the resource failed, so remove the entry
178     ResourceEntries.erase(Key);
179 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
180 schoenebeck 925 // rethrow the same exception
181     throw;
182     }
183 schoenebeck 517 // now update the entry with the created resource
184     ResourceEntries[Key] = entry;
185 schoenebeck 947 OnBorrow(entry.resource, pConsumer, entry.lifearg);
186 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
187 schoenebeck 53 return entry.resource;
188 schoenebeck 947 } else { // entry already exists
189     resource_entry_t& entry = iterEntry->second;
190     if (!entry.resource) { // create resource if not created already
191     try {
192     entry.resource = Create(Key, pConsumer, entry.lifearg);
193     } catch (...) {
194     entry.resource = NULL;
195 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
196 schoenebeck 947 throw; // rethrow the same exception
197     }
198     }
199     entry.consumers.insert(pConsumer);
200     OnBorrow(entry.resource, pConsumer, entry.lifearg);
201 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
202 schoenebeck 947 return entry.resource;
203 schoenebeck 53 }
204     }
205    
206     /**
207     * Give back a resource. This tells the ResourceManager that the
208     * consumer given by \a pConsumer doesn't need the resource anymore.
209 schoenebeck 947 * If the resource is not needed by any consumer anymore and the
210     * resource has a life-time strategy of ON_DEMAND (which is the
211     * default setting) then the resource will be destroyed.
212 schoenebeck 53 *
213     * @param pResource - pointer to resource
214     * @param pConsumer - identifier of the consumer who borrowed the
215     * resource
216 schoenebeck 970 * @param bLock - use thread safety mechanisms
217 schoenebeck 53 */
218 schoenebeck 970 void HandBack(T_res* pResource, ResourceConsumer<T_res>* pConsumer, bool bLock = true) {
219     if (bLock) ResourceEntriesMutex.Lock();
220 schoenebeck 947 // search for the entry associated with the given resource
221 schoenebeck 53 typename ResourceMap::iterator iter = ResourceEntries.begin();
222     typename ResourceMap::iterator end = ResourceEntries.end();
223     for (; iter != end; iter++) {
224 schoenebeck 947 if (iter->second.resource == pResource) { // found entry for resource
225 schoenebeck 53 resource_entry_t& entry = iter->second;
226     entry.consumers.erase(pConsumer);
227 schoenebeck 947 // remove entry if necessary
228     if (entry.mode == ON_DEMAND && !entry.entryarg && entry.consumers.empty()) {
229 persson 835 T_res* resource = entry.resource;
230 schoenebeck 947 void* arg = entry.lifearg;
231 schoenebeck 53 ResourceEntries.erase(iter);
232 schoenebeck 947 // destroy resource if necessary
233     if (resource) Destroy(resource, arg);
234 schoenebeck 53 }
235 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
236 schoenebeck 53 return;
237     }
238     }
239 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
240 schoenebeck 53 }
241    
242     /**
243 schoenebeck 947 * Request update of a resource. All consumers will be informed
244     * about the pending update of the resource so they can safely react
245     * by stopping its usage first, then the resource will be recreated
246     * and finally the consumers will be informed once the update was
247     * completed, so they can continue to use the resource.
248 schoenebeck 53 *
249     * @param pResource - resource to be updated
250     * @param pConsumer - consumer who requested the update
251 schoenebeck 970 * @param bLock - use thread safety mechanisms
252 schoenebeck 53 */
253 schoenebeck 970 void Update(T_res* pResource, ResourceConsumer<T_res>* pConsumer, bool bLock = true) {
254     if (bLock) ResourceEntriesMutex.Lock();
255 schoenebeck 53 typename ResourceMap::iterator iter = ResourceEntries.begin();
256     typename ResourceMap::iterator end = ResourceEntries.end();
257     for (; iter != end; iter++) {
258 schoenebeck 351 if (iter->second.resource == pResource) {
259 schoenebeck 53 resource_entry_t& entry = iter->second;
260     // inform all consumers about pending update
261     std::map<ResourceConsumer<T_res>*,void*> updateargs;
262     typename ConsumerSet::iterator iterCons = entry.consumers.begin();
263     typename ConsumerSet::iterator endCons = entry.consumers.end();
264     for (; iterCons != endCons; iterCons++) {
265     if (*iterCons == pConsumer) continue;
266     void* updatearg = NULL;
267     (*iterCons)->ResourceToBeUpdated(entry.resource, updatearg);
268     if (updatearg) updateargs[*iterCons] = updatearg;
269     }
270     // update resource
271     T_res* pOldResource = entry.resource;
272 schoenebeck 947 Destroy(entry.resource, entry.lifearg);
273     entry.resource = Create(entry.key, pConsumer, entry.lifearg);
274 schoenebeck 53 // inform all consumers about update completed
275     iterCons = entry.consumers.begin();
276     endCons = entry.consumers.end();
277     for (; iterCons != endCons; iterCons++) {
278     if (*iterCons == pConsumer) continue;
279     typename std::map<ResourceConsumer<T_res>*,void*>::iterator iterArg = updateargs.find(*iterCons);
280     void* updatearg = (iterArg != updateargs.end()) ? iterArg->second : NULL;
281     (*iterCons)->ResourceUpdated(pOldResource, entry.resource, updatearg);
282     }
283 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
284 schoenebeck 53 return;
285     }
286     }
287 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
288 schoenebeck 53 }
289    
290 schoenebeck 947 /**
291     * Returns the life-time strategy of the given resource.
292     *
293 schoenebeck 970 * @param Key - ID of the resource
294     * @param bLock - use thread safety mechanisms
295 schoenebeck 947 */
296 schoenebeck 970 mode_t AvailabilityMode(T_key Key, bool bLock = true) {
297     if (bLock) ResourceEntriesMutex.Lock();
298 schoenebeck 947 typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
299 schoenebeck 970 if (iterEntry == ResourceEntries.end()) {
300     if (bLock) ResourceEntriesMutex.Unlock();
301 schoenebeck 947 return ON_DEMAND; // resource entry doesn't exist, so we return the default mode
302 schoenebeck 970 }
303 schoenebeck 947 resource_entry_t& entry = iterEntry->second;
304 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
305 schoenebeck 947 return entry.mode;
306     }
307    
308     /**
309     * Change life-time strategy of the given resource. If a life-time
310     * strategy of PERSISTENT was given and the resource was not created
311     * yet, it will immediately be created and this method will block
312     * until the resource creation was completed.
313     *
314     * @param Key - ID of the resource
315     * @param Mode - life-time strategy of resource to be set
316 schoenebeck 970 * @param bLock - use thread safety mechanisms
317 schoenebeck 947 * @throws Exception in case an invalid Mode was given
318     */
319 schoenebeck 1040 void SetAvailabilityMode(T_key Key, mode_t Mode, bool bLock = true) {
320 schoenebeck 947 if (Mode != ON_DEMAND && Mode != ON_DEMAND_HOLD && Mode != PERSISTENT)
321     throw Exception("ResourceManager::SetAvailabilityMode(): invalid mode");
322    
323 schoenebeck 970 if (bLock) ResourceEntriesMutex.Lock();
324 schoenebeck 947 // search for an entry for this resource
325     typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
326     resource_entry_t* pEntry = NULL;
327     if (iterEntry == ResourceEntries.end()) { // resource entry doesn't exist
328 schoenebeck 970 if (Mode == ON_DEMAND) {
329     if (bLock) ResourceEntriesMutex.Unlock();
330     return; // we don't create an entry for the default value
331     }
332 schoenebeck 947 // create an entry for the resource
333     pEntry = &ResourceEntries[Key];
334     pEntry->key = Key;
335     pEntry->resource = NULL;
336     pEntry->mode = Mode;
337     pEntry->lifearg = NULL;
338     pEntry->entryarg = NULL;
339     } else { // resource entry exists
340     pEntry = &iterEntry->second;
341     // remove entry if necessary
342     if (Mode == ON_DEMAND && !pEntry->entryarg && pEntry->consumers.empty()) {
343     T_res* resource = pEntry->resource;
344     void* arg = pEntry->lifearg;
345     ResourceEntries.erase(iterEntry);
346     // destroy resource if necessary
347     if (resource) Destroy(resource, arg);
348 schoenebeck 970 // done
349     if (bLock) ResourceEntriesMutex.Unlock();
350     return;
351 schoenebeck 947 }
352     pEntry->mode = Mode; // apply new mode
353     }
354    
355     // already create the resource if necessary
356     if (pEntry->mode == PERSISTENT && !pEntry->resource) {
357     try {
358     // actually create the resource
359     pEntry->resource = Create(Key, NULL /*no consumer yet*/, pEntry->lifearg);
360     } catch (...) {
361     // creating the resource failed, so skip it for now
362     pEntry->resource = NULL;
363 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
364 schoenebeck 947 // rethrow the same exception
365     throw;
366     }
367     }
368 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
369 schoenebeck 947 }
370    
371     /**
372 schoenebeck 958 * Returns true in case the resource associated with \a Key is
373     * currently created / "alive".
374     *
375     * @param Key - ID of resource
376 schoenebeck 970 * @param bLock - use thread safety mechanisms
377 schoenebeck 958 */
378 schoenebeck 970 bool IsCreated(T_key Key, bool bLock = true) {
379     return Resource(Key, bLock) != NULL;
380 schoenebeck 958 }
381    
382     /**
383 schoenebeck 947 * Returns custom data sticked to the given resource previously by
384     * a SetCustomData() call.
385     *
386     * @param Key - ID of resource
387 schoenebeck 970 * @param bLock - use thread safety mechanisms
388 schoenebeck 947 */
389 schoenebeck 970 void* CustomData(T_key Key, bool bLock = true) {
390     if (bLock) ResourceEntriesMutex.Lock();
391 schoenebeck 947 typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
392 schoenebeck 970 if (iterEntry == ResourceEntries.end()) {
393     if (bLock) ResourceEntriesMutex.Unlock();
394     return NULL; // resource entry doesn't exist, so we return the default mode
395     }
396     resource_entry_t entry = iterEntry->second;
397     void* res = entry.entryarg;
398     if (bLock) ResourceEntriesMutex.Unlock();
399     return res;
400 schoenebeck 947 }
401    
402     /**
403     * This method can be used to stick custom data to an resource
404     * entry. In case the custom data is not needed anymore, you should
405     * call this method again and set \a pData to NULL, so the
406     * ResourceManager might safe space by removing the respective
407     * entry if not needed anymore.
408     *
409     * @param Key - ID of resource
410     * @param pData - pointer to custom data, or NULL if not needed anymore
411 schoenebeck 970 * @param bLock - use thread safety mechanisms
412 schoenebeck 947 */
413 schoenebeck 970 void SetCustomData(T_key Key, void* pData, bool bLock = true) {
414     if (bLock) ResourceEntriesMutex.Lock();
415 schoenebeck 947 typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
416     if (pData) {
417     if (iterEntry == ResourceEntries.end()) { // entry doesnt exist, so create one
418     resource_entry_t* pEntry = &ResourceEntries[Key];
419     pEntry->key = Key;
420     pEntry->resource = NULL;
421     pEntry->mode = ON_DEMAND;
422     pEntry->lifearg = NULL;
423     pEntry->entryarg = pData; // set custom data
424     } else { // entry exists, so just update its custom data
425     iterEntry->second.entryarg = pData;
426     }
427     } else { // !pData
428 schoenebeck 970 if (iterEntry == ResourceEntries.end()) {
429     if (bLock) ResourceEntriesMutex.Unlock();
430     return; // entry doesnt exist, so nothing to do
431     }
432 schoenebeck 947 // entry exists, remove it if necessary
433     resource_entry_t* pEntry = &iterEntry->second;
434     if (pEntry->mode == ON_DEMAND && pEntry->consumers.empty()) {
435     ResourceEntries.erase(iterEntry);
436     } else iterEntry->second.entryarg = NULL;
437     }
438 schoenebeck 970 if (bLock) ResourceEntriesMutex.Unlock();
439 schoenebeck 947 }
440    
441 schoenebeck 970 /**
442     * Prevent this ResourceManager instance to be used by another
443     * thread at the same time. All methods of this class are thread
444     * safe by default. However sometimes you might need atomicity among
445     * a sequence of method calls. In this case you would first call
446     * this Lock() method, call the respective operational methods of
447     * this class (<b>Important:</b> each one by setting bLock = false,
448     * this avoids double locking). And once the required sequence of
449     * atomic method calls is done, you have to call Unlock() to
450     * reenable accessibility of this ResourceManager instance for other
451     * threads.
452     *
453     * @see Mutex::Lock()
454     */
455     void Lock() {
456     ResourceEntriesMutex.Lock();
457     }
458    
459     /**
460     * Has to be called after a Lock() call to reenable this
461     * ResourceManager instance to be accessible by another thread
462     * again.
463     *
464     * @see Mutex::Unlock()
465     */
466     void Unlock() {
467     ResourceEntriesMutex.Unlock();
468     }
469    
470 schoenebeck 947 virtual ~ResourceManager() {} // due to C++'s nature we cannot destroy created resources here
471    
472 schoenebeck 53 protected:
473     /**
474     * Has to be implemented by the descendant to create (allocate) a
475     * resource identified by \a Key.
476     *
477     * @param Key - identifier of the resource
478     * @param pConsumer - identifier of the consumer who borrows the
479     * resource
480     * @param pArg - pointer the descendant can use to store
481     * informations he might need for destruction of
482     * the resource
483     * @returns pointer to new resource
484     */
485     virtual T_res* Create(T_key Key, ResourceConsumer<T_res>* pConsumer, void*& pArg) = 0;
486    
487     /**
488     * Has to be implemented by the descendant to destroy (free) a
489     * resource pointed by \a pResource.
490     *
491     * @param pResource - pointer to the resource
492     * @param pArg - pointer the descendant might have used when
493     * Create() was called to store informations
494     * about the resource
495     */
496     virtual void Destroy(T_res* pResource, void* pArg) = 0;
497    
498     /**
499     * Has to be implemented by the descendant to react when a consumer
500     * borrows a resource (no matter if freshly created or an already
501     * created one). Of course reacting is optional, but the descendant
502     * at least has to provide a method with empty body.
503     *
504     * @param pResource - pointer to the resource
505     * @param pConsumer - identifier of the consumer who borrows the
506     * resource
507     * @param pArg - pointer the descendant might have used when
508     * Create() was called to store informations
509     * about the resource, this information can be
510     * updated by the descendant here
511     */
512     virtual void OnBorrow(T_res* pResource, ResourceConsumer<T_res>* pConsumer, void*& pArg) = 0;
513 schoenebeck 517
514     /**
515     * Dispatcher method which should be periodically called by the
516     * descendant during update or creation of the resource associated
517     * with \a Key. This method will inform all associated consumers
518     * of the given resource about the current progress.
519     *
520     * @param Key - unique identifier of the resource which is
521     * currently creating or updating
522     * @param fProgress - current progress of that creation / update
523     * process as value between 0.0 and 1.0
524     */
525     void DispatchResourceProgressEvent(T_key Key, float fProgress) {
526 schoenebeck 970 // no Mutex here, since Create() is already protected
527 schoenebeck 517 typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
528     if (iterEntry != ResourceEntries.end()) {
529     resource_entry_t& entry = iterEntry->second;
530     // inform all consumers of that resource about current progress
531     typename ConsumerSet::iterator iterCons = entry.consumers.begin();
532     typename ConsumerSet::iterator endCons = entry.consumers.end();
533     for (; iterCons != endCons; iterCons++) {
534     (*iterCons)->OnResourceProgress(fProgress);
535     }
536     }
537     }
538 schoenebeck 958
539     /**
540     * Returns pointer to the resource associated with \a Key if
541     * currently created / "alive", NULL otherwise. This method
542     * should be taken with great care in multi-threaded scenarios,
543     * since the returned resource might be destroyed by a concurrent
544     * HandBack() call.
545     *
546     * @param Key - ID of resource
547 schoenebeck 970 * @param bLock - use thread safety mechanisms
548 schoenebeck 958 */
549 schoenebeck 970 T_res* Resource(T_key Key, bool bLock = true) {
550     if (bLock) ResourceEntriesMutex.Lock();
551 schoenebeck 958 typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
552 schoenebeck 970 T_res* result = (iterEntry == ResourceEntries.end()) ? NULL : iterEntry->second.resource;
553     if (bLock) ResourceEntriesMutex.Unlock();
554     return result;
555 schoenebeck 958 }
556 schoenebeck 53 };
557    
558 schoenebeck 947 } // namespace LinuxSampler
559    
560 schoenebeck 53 #endif // __RESOURCE_MANAGER__

  ViewVC Help
Powered by ViewVC