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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 969 by schoenebeck, Wed Nov 29 19:48:38 2006 UTC revision 970 by schoenebeck, Wed Dec 6 22:28:17 2006 UTC
# Line 29  Line 29 
29  #include <vector>  #include <vector>
30    
31  #include "Exception.h"  #include "Exception.h"
32    #include "Mutex.h"
33    
34  namespace LinuxSampler {  namespace LinuxSampler {
35    
# Line 94  class ResourceConsumer { Line 95  class ResourceConsumer {
95   * Descendants of this base class have to implement the (protected)   * Descendants of this base class have to implement the (protected)
96   * Create() and Destroy() methods to create and destroy a resource.   * Create() and Destroy() methods to create and destroy a resource.
97   *   *
98   * Note: this template class is not thread safe, so if thread safety is   * This class is thread safe (by default). Its methods should however not
99   * needed the descendant has to add synchronization methods on its own.   * 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   */   */
103  template<class T_key, class T_res>  template<class T_key, class T_res>
104  class ResourceManager {  class ResourceManager {
# Line 121  class ResourceManager { Line 124  class ResourceManager {
124          };          };
125          typedef std::map<T_key, resource_entry_t> ResourceMap;          typedef std::map<T_key, resource_entry_t> ResourceMap;
126          ResourceMap ResourceEntries;          ResourceMap ResourceEntries;
127            Mutex       ResourceEntriesMutex; // Mutex for protecting the ResourceEntries map
128    
129      public:      public:
130          /**          /**
131           * Returns (the keys of) all current entries of this           * Returns (the keys of) all current entries of this
132           * ResourceManager instance.           * ResourceManager instance.
133             *
134             * @param bLock - use thread safety mechanisms
135           */           */
136          std::vector<T_key> Entries() {          std::vector<T_key> Entries(bool bLock = true) {
137              std::vector<T_key> result;              std::vector<T_key> result;
138                if (bLock) ResourceEntriesMutex.Lock();
139              for (typename ResourceMap::iterator iter = ResourceEntries.begin();              for (typename ResourceMap::iterator iter = ResourceEntries.begin();
140                   iter != ResourceEntries.end(); iter++)                   iter != ResourceEntries.end(); iter++)
141              {              {
142                  result.push_back(iter->first);                  result.push_back(iter->first);
143              }              }
144                if (bLock) ResourceEntriesMutex.Unlock();
145              return result;              return result;
146          }          }
147    
# Line 145  class ResourceManager { Line 153  class ResourceManager {
153           *           *
154           * @param Key       - resource identifier           * @param Key       - resource identifier
155           * @param pConsumer - identifier of the consumer who borrows it           * @param pConsumer - identifier of the consumer who borrows it
156             * @param bLock     - use thread safety mechanisms
157           * @returns  pointer to resource           * @returns  pointer to resource
158           */           */
159          T_res* Borrow(T_key Key, ResourceConsumer<T_res>* pConsumer) {          T_res* Borrow(T_key Key, ResourceConsumer<T_res>* pConsumer, bool bLock = true) {
160                if (bLock) ResourceEntriesMutex.Lock();
161              // search for an entry for this resource              // search for an entry for this resource
162              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
163              if (iterEntry == ResourceEntries.end()) { // entry doesn't exist yet              if (iterEntry == ResourceEntries.end()) { // entry doesn't exist yet
# Line 166  class ResourceManager { Line 176  class ResourceManager {
176                  } catch (...) {                  } catch (...) {
177                      // creating the resource failed, so remove the entry                      // creating the resource failed, so remove the entry
178                      ResourceEntries.erase(Key);                      ResourceEntries.erase(Key);
179                        if (bLock) ResourceEntriesMutex.Unlock();
180                      // rethrow the same exception                      // rethrow the same exception
181                      throw;                      throw;
182                  }                  }
183                  // now update the entry with the created resource                  // now update the entry with the created resource
184                  ResourceEntries[Key] = entry;                  ResourceEntries[Key] = entry;
185                  OnBorrow(entry.resource, pConsumer, entry.lifearg);                  OnBorrow(entry.resource, pConsumer, entry.lifearg);
186                    if (bLock) ResourceEntriesMutex.Unlock();
187                  return entry.resource;                  return entry.resource;
188              } else { // entry already exists              } else { // entry already exists
189                  resource_entry_t& entry = iterEntry->second;                  resource_entry_t& entry = iterEntry->second;
# Line 180  class ResourceManager { Line 192  class ResourceManager {
192                          entry.resource = Create(Key, pConsumer, entry.lifearg);                          entry.resource = Create(Key, pConsumer, entry.lifearg);
193                      } catch (...) {                      } catch (...) {
194                          entry.resource = NULL;                          entry.resource = NULL;
195                            if (bLock) ResourceEntriesMutex.Unlock();
196                          throw; // rethrow the same exception                          throw; // rethrow the same exception
197                      }                      }
198                  }                  }
199                  entry.consumers.insert(pConsumer);                  entry.consumers.insert(pConsumer);
200                  OnBorrow(entry.resource, pConsumer, entry.lifearg);                  OnBorrow(entry.resource, pConsumer, entry.lifearg);
201                    if (bLock) ResourceEntriesMutex.Unlock();
202                  return entry.resource;                  return entry.resource;
203              }              }
204          }          }
# Line 199  class ResourceManager { Line 213  class ResourceManager {
213           * @param pResource - pointer to resource           * @param pResource - pointer to resource
214           * @param pConsumer - identifier of the consumer who borrowed the           * @param pConsumer - identifier of the consumer who borrowed the
215           *                    resource           *                    resource
216             * @param bLock     - use thread safety mechanisms
217           */           */
218          void HandBack(T_res* pResource, ResourceConsumer<T_res>* pConsumer) {          void HandBack(T_res* pResource, ResourceConsumer<T_res>* pConsumer, bool bLock = true) {
219                if (bLock) ResourceEntriesMutex.Lock();
220              // search for the entry associated with the given resource              // search for the entry associated with the given resource
221              typename ResourceMap::iterator iter = ResourceEntries.begin();              typename ResourceMap::iterator iter = ResourceEntries.begin();
222              typename ResourceMap::iterator end  = ResourceEntries.end();              typename ResourceMap::iterator end  = ResourceEntries.end();
# Line 216  class ResourceManager { Line 232  class ResourceManager {
232                          // destroy resource if necessary                          // destroy resource if necessary
233                          if (resource) Destroy(resource, arg);                          if (resource) Destroy(resource, arg);
234                      }                      }
235                        if (bLock) ResourceEntriesMutex.Unlock();
236                      return;                      return;
237                  }                  }
238              }              }
239                if (bLock) ResourceEntriesMutex.Unlock();
240          }          }
241    
242          /**          /**
# Line 230  class ResourceManager { Line 248  class ResourceManager {
248           *           *
249           * @param pResource - resource to be updated           * @param pResource - resource to be updated
250           * @param pConsumer - consumer who requested the update           * @param pConsumer - consumer who requested the update
251             * @param bLock     - use thread safety mechanisms
252           */           */
253          void Update(T_res* pResource, ResourceConsumer<T_res>* pConsumer) {          void Update(T_res* pResource, ResourceConsumer<T_res>* pConsumer, bool bLock = true) {
254                if (bLock) ResourceEntriesMutex.Lock();
255              typename ResourceMap::iterator iter = ResourceEntries.begin();              typename ResourceMap::iterator iter = ResourceEntries.begin();
256              typename ResourceMap::iterator end  = ResourceEntries.end();              typename ResourceMap::iterator end  = ResourceEntries.end();
257              for (; iter != end; iter++) {              for (; iter != end; iter++) {
# Line 260  class ResourceManager { Line 280  class ResourceManager {
280                          void* updatearg = (iterArg != updateargs.end()) ? iterArg->second : NULL;                          void* updatearg = (iterArg != updateargs.end()) ? iterArg->second : NULL;
281                          (*iterCons)->ResourceUpdated(pOldResource, entry.resource, updatearg);                          (*iterCons)->ResourceUpdated(pOldResource, entry.resource, updatearg);
282                      }                      }
283                        if (bLock) ResourceEntriesMutex.Unlock();
284                      return;                      return;
285                  }                  }
286              }              }
287                if (bLock) ResourceEntriesMutex.Unlock();
288          }          }
289    
290          /**          /**
291           * Returns the life-time strategy of the given resource.           * Returns the life-time strategy of the given resource.
292           *           *
293           * @param Key - ID of the resource           * @param Key   - ID of the resource
294             * @param bLock - use thread safety mechanisms
295           */           */
296          mode_t AvailabilityMode(T_key Key) {          mode_t AvailabilityMode(T_key Key, bool bLock = true) {
297                if (bLock) ResourceEntriesMutex.Lock();
298              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
299              if (iterEntry == ResourceEntries.end())              if (iterEntry == ResourceEntries.end()) {
300                    if (bLock) ResourceEntriesMutex.Unlock();
301                  return ON_DEMAND; // resource entry doesn't exist, so we return the default mode                  return ON_DEMAND; // resource entry doesn't exist, so we return the default mode
302                }
303              resource_entry_t& entry = iterEntry->second;              resource_entry_t& entry = iterEntry->second;
304                if (bLock) ResourceEntriesMutex.Unlock();
305              return entry.mode;              return entry.mode;
306          }          }
307    
# Line 286  class ResourceManager { Line 313  class ResourceManager {
313           *           *
314           * @param Key - ID of the resource           * @param Key - ID of the resource
315           * @param Mode - life-time strategy of resource to be set           * @param Mode - life-time strategy of resource to be set
316             * @param bLock - use thread safety mechanisms
317           * @throws Exception in case an invalid Mode was given           * @throws Exception in case an invalid Mode was given
318           */           */
319          void SetAvailabilityMode(T_key Key, mode_t Mode) throw (Exception) {          void SetAvailabilityMode(T_key Key, mode_t Mode, bool bLock = true) throw (Exception) {
320              if (Mode != ON_DEMAND && Mode != ON_DEMAND_HOLD && Mode != PERSISTENT)              if (Mode != ON_DEMAND && Mode != ON_DEMAND_HOLD && Mode != PERSISTENT)
321                  throw Exception("ResourceManager::SetAvailabilityMode(): invalid mode");                  throw Exception("ResourceManager::SetAvailabilityMode(): invalid mode");
322    
323                if (bLock) ResourceEntriesMutex.Lock();
324              // search for an entry for this resource              // search for an entry for this resource
325              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
326              resource_entry_t* pEntry = NULL;              resource_entry_t* pEntry = NULL;
327              if (iterEntry == ResourceEntries.end()) { // resource entry doesn't exist              if (iterEntry == ResourceEntries.end()) { // resource entry doesn't exist
328                  if (Mode == ON_DEMAND) return; // we don't create an entry for the default value                  if (Mode == ON_DEMAND) {
329                        if (bLock) ResourceEntriesMutex.Unlock();
330                        return; // we don't create an entry for the default value
331                    }
332                  // create an entry for the resource                  // create an entry for the resource
333                  pEntry = &ResourceEntries[Key];                  pEntry = &ResourceEntries[Key];
334                  pEntry->key      = Key;                  pEntry->key      = Key;
# Line 313  class ResourceManager { Line 345  class ResourceManager {
345                      ResourceEntries.erase(iterEntry);                      ResourceEntries.erase(iterEntry);
346                      // destroy resource if necessary                      // destroy resource if necessary
347                      if (resource) Destroy(resource, arg);                      if (resource) Destroy(resource, arg);
348                      return; // done                      // done
349                        if (bLock) ResourceEntriesMutex.Unlock();
350                        return;
351                  }                  }
352                  pEntry->mode = Mode; // apply new mode                  pEntry->mode = Mode; // apply new mode
353              }              }
# Line 326  class ResourceManager { Line 360  class ResourceManager {
360                  } catch (...) {                  } catch (...) {
361                      // creating the resource failed, so skip it for now                      // creating the resource failed, so skip it for now
362                      pEntry->resource = NULL;                      pEntry->resource = NULL;
363                        if (bLock) ResourceEntriesMutex.Unlock();
364                      // rethrow the same exception                      // rethrow the same exception
365                      throw;                      throw;
366                  }                  }
367              }              }
368                if (bLock) ResourceEntriesMutex.Unlock();
369          }          }
370    
371          /**          /**
# Line 337  class ResourceManager { Line 373  class ResourceManager {
373           * currently created / "alive".           * currently created / "alive".
374           *           *
375           * @param Key - ID of resource           * @param Key - ID of resource
376             * @param bLock - use thread safety mechanisms
377           */           */
378          bool IsCreated(T_key Key) {          bool IsCreated(T_key Key, bool bLock = true) {
379              return Resource(Key) != NULL;              return Resource(Key, bLock) != NULL;
380          }          }
381    
382          /**          /**
# Line 347  class ResourceManager { Line 384  class ResourceManager {
384           * a SetCustomData() call.           * a SetCustomData() call.
385           *           *
386           * @param Key - ID of resource           * @param Key - ID of resource
387             * @param bLock - use thread safety mechanisms
388           */           */
389          void* CustomData(T_key Key) {          void* CustomData(T_key Key, bool bLock = true) {
390                if (bLock) ResourceEntriesMutex.Lock();
391              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
392              if (iterEntry == ResourceEntries.end()) return NULL; // resource entry doesn't exist, so we return the default mode              if (iterEntry == ResourceEntries.end()) {
393              resource_entry_t& entry = iterEntry->second;                  if (bLock) ResourceEntriesMutex.Unlock();
394              return entry.entryarg;                  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          }          }
401    
402          /**          /**
# Line 364  class ResourceManager { Line 408  class ResourceManager {
408           *           *
409           * @param Key - ID of resource           * @param Key - ID of resource
410           * @param pData - pointer to custom data, or NULL if not needed anymore           * @param pData - pointer to custom data, or NULL if not needed anymore
411             * @param bLock - use thread safety mechanisms
412           */           */
413          void SetCustomData(T_key Key, void* pData) {          void SetCustomData(T_key Key, void* pData, bool bLock = true) {
414                if (bLock) ResourceEntriesMutex.Lock();
415              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
416              if (pData) {              if (pData) {
417                  if (iterEntry == ResourceEntries.end()) { // entry doesnt exist, so create one                  if (iterEntry == ResourceEntries.end()) { // entry doesnt exist, so create one
# Line 379  class ResourceManager { Line 425  class ResourceManager {
425                      iterEntry->second.entryarg = pData;                      iterEntry->second.entryarg = pData;
426                  }                  }
427              } else { // !pData              } else { // !pData
428                  if (iterEntry == ResourceEntries.end()) return; // entry doesnt exist, so nothing to do                  if (iterEntry == ResourceEntries.end()) {
429                        if (bLock) ResourceEntriesMutex.Unlock();
430                        return; // entry doesnt exist, so nothing to do
431                    }
432                  // entry exists, remove it if necessary                  // entry exists, remove it if necessary
433                  resource_entry_t* pEntry = &iterEntry->second;                  resource_entry_t* pEntry = &iterEntry->second;
434                  if (pEntry->mode == ON_DEMAND && pEntry->consumers.empty()) {                  if (pEntry->mode == ON_DEMAND && pEntry->consumers.empty()) {
435                      ResourceEntries.erase(iterEntry);                      ResourceEntries.erase(iterEntry);
436                  } else iterEntry->second.entryarg = NULL;                  } else iterEntry->second.entryarg = NULL;
437              }              }
438                if (bLock) ResourceEntriesMutex.Unlock();
439            }
440    
441            /**
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          virtual ~ResourceManager() {} // due to C++'s nature we cannot destroy created resources here          virtual ~ResourceManager() {} // due to C++'s nature we cannot destroy created resources here
# Line 444  class ResourceManager { Line 523  class ResourceManager {
523           *                    process as value between 0.0 and 1.0           *                    process as value between 0.0 and 1.0
524           */           */
525          void DispatchResourceProgressEvent(T_key Key, float fProgress) {          void DispatchResourceProgressEvent(T_key Key, float fProgress) {
526                // no Mutex here, since Create() is already protected
527              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
528              if (iterEntry != ResourceEntries.end()) {              if (iterEntry != ResourceEntries.end()) {
529                  resource_entry_t& entry = iterEntry->second;                  resource_entry_t& entry = iterEntry->second;
# Line 464  class ResourceManager { Line 544  class ResourceManager {
544           * HandBack() call.           * HandBack() call.
545           *           *
546           * @param Key - ID of resource           * @param Key - ID of resource
547             * @param bLock - use thread safety mechanisms
548           */           */
549          T_res* Resource(T_key Key) {          T_res* Resource(T_key Key, bool bLock = true) {
550                if (bLock) ResourceEntriesMutex.Lock();
551              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);              typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
552              return (iterEntry == ResourceEntries.end()) ? NULL : iterEntry->second.resource;              T_res* result = (iterEntry == ResourceEntries.end()) ? NULL : iterEntry->second.resource;
553                if (bLock) ResourceEntriesMutex.Unlock();
554                return result;
555          }          }
556  };  };
557    

Legend:
Removed from v.969  
changed lines
  Added in v.970

  ViewVC Help
Powered by ViewVC