/[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 925 - (hide annotations) (download) (as text)
Sat Oct 21 14:50:32 2006 UTC (17 years, 6 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 13455 byte(s)
* fixed crash when instrument loading failed previously on the same
  sampler channel (fixes bug #36)

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 925 * Copyright (C) 2005, 2006 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    
30     /**
31     * Interface class for consumer classes which use a resource managed
32     * by the ResourceManager class.
33     */
34     template<class T_res>
35     class ResourceConsumer {
36     public:
37     /**
38     * Will be called by the ResourceManager to inform the
39     * consumer that a resource currently used by him is going
40     * to be updated. The consumer can then react by stopping
41     * usage until resource is updated. The ResourceManager will
42     * not update the resource until this method returns. This
43     * method needs to be implemented by the consumer.
44     *
45     * @param pResource - resource going to be updated
46     * @param pUpdateArg - pointer the consumer might use to store
47     * informations he might need when update
48     * process was completed
49     */
50     virtual void ResourceToBeUpdated(T_res* pResource, void*& pUpdateArg) = 0;
51    
52     /**
53     * Will be called by the ResourceManager to inform the
54     * consumer that resource update was completed. This method
55     * needs to be implemented by the consumer.
56     *
57     * @param pOldResource - (now invalid) pointer to the old
58     * resource
59     * @param pNewResource - (valid) pointer to the updated
60     * resource
61     * @param pUpdateArg - pointer the consumer might have used when
62     * ResourceToBeUpdated() was called
63     */
64     virtual void ResourceUpdated(T_res* pOldResource, T_res* pNewResource, void* pUpdateArg) = 0;
65 schoenebeck 517
66     /**
67     * Might be called by the ResourceManager periodically during an
68     * update / creation of a resource to inform the consumer about the
69     * current progress of that process. This method needs to be
70     * implemented by the consumer.
71     *
72     * @param fProgress - current progress as value between 0.0 and 1.0
73     */
74     virtual void OnResourceProgress(float fProgress) = 0;
75 schoenebeck 53 };
76    
77     /**
78     * Abstract base class for sharing resources between multiple consumers.
79     * A consumer can borrow a resource from the ResourceManager, if the
80     * resource doesn't exist yet it will be created. Other consumers will
81     * just be given the same pointer to the resource then. When all consumers
82     * gave back their pointer to the resource, the resource will be destroyed.
83     * Descendants of this base class have to implement the (protected)
84     * Create() and Destroy() methods to create and destroy a resource.
85     */
86     template<class T_key, class T_res>
87     class ResourceManager {
88     private:
89     typedef std::set<ResourceConsumer<T_res>*> ConsumerSet;
90     struct resource_entry_t {
91     T_key key;
92     T_res* resource; ///< pointer to the resource
93     ConsumerSet consumers; ///< list of all consumers who currently use the resource
94     void* arg; ///< optional pointer the descendant might use to store informations about the resource
95     };
96     typedef std::map<T_key, resource_entry_t> ResourceMap;
97     ResourceMap ResourceEntries;
98    
99     public:
100 letz 386 virtual ~ResourceManager() {}
101 schoenebeck 53 /**
102     * Borrow a resource identified by \a Key. The ResourceManager will
103     * mark the resource as in usage by the consumer given with
104     * \a pConsumer. If the Resource doesn't exist yet it will be
105     * created.
106     *
107     * @param Key - resource identifier
108     * @param pConsumer - identifier of the consumer who borrows it
109     * @returns pointer to resource
110     */
111     T_res* Borrow(T_key Key, ResourceConsumer<T_res>* pConsumer) {
112     typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
113     if (iterEntry == ResourceEntries.end()) {
114 schoenebeck 517 // already create an entry for the resource
115 schoenebeck 53 resource_entry_t entry;
116     entry.key = Key;
117 schoenebeck 517 entry.resource = NULL;
118     entry.consumers.insert(pConsumer);
119     ResourceEntries[Key] = entry;
120 schoenebeck 925 try {
121     // actually create the resource
122     entry.resource = Create(Key, pConsumer, entry.arg);
123     } catch (...) {
124     // creating the resource failed, so remove the entry
125     ResourceEntries.erase(Key);
126     // rethrow the same exception
127     throw;
128     }
129 schoenebeck 517 // now update the entry with the created resource
130     ResourceEntries[Key] = entry;
131 schoenebeck 53 OnBorrow(entry.resource, pConsumer, entry.arg);
132     return entry.resource;
133     }
134     resource_entry_t& entry = iterEntry->second;
135     entry.consumers.insert(pConsumer);
136     OnBorrow(entry.resource, pConsumer, entry.arg);
137     return entry.resource;
138     }
139    
140     /**
141     * Give back a resource. This tells the ResourceManager that the
142     * consumer given by \a pConsumer doesn't need the resource anymore.
143     * If the resource is not needed by any consumer anymore then the
144     * resource will be destroyed.
145     *
146     * @param pResource - pointer to resource
147     * @param pConsumer - identifier of the consumer who borrowed the
148     * resource
149     */
150     void HandBack(T_res* pResource, ResourceConsumer<T_res>* pConsumer) {
151     typename ResourceMap::iterator iter = ResourceEntries.begin();
152     typename ResourceMap::iterator end = ResourceEntries.end();
153     for (; iter != end; iter++) {
154 schoenebeck 351 if (iter->second.resource == pResource) {
155 schoenebeck 53 resource_entry_t& entry = iter->second;
156     entry.consumers.erase(pConsumer);
157     if (entry.consumers.empty()) {
158 persson 835 T_res* resource = entry.resource;
159     void* arg = entry.arg;
160 schoenebeck 53 ResourceEntries.erase(iter);
161 persson 835 Destroy(resource, arg);
162 schoenebeck 53 }
163     return;
164     }
165     }
166     }
167    
168     /**
169     * Request update of a resource.
170     *
171     * @param pResource - resource to be updated
172     * @param pConsumer - consumer who requested the update
173     */
174     void Update(T_res* pResource, ResourceConsumer<T_res>* pConsumer) {
175     typename ResourceMap::iterator iter = ResourceEntries.begin();
176     typename ResourceMap::iterator end = ResourceEntries.end();
177     for (; iter != end; iter++) {
178 schoenebeck 351 if (iter->second.resource == pResource) {
179 schoenebeck 53 resource_entry_t& entry = iter->second;
180     // inform all consumers about pending update
181     std::map<ResourceConsumer<T_res>*,void*> updateargs;
182     typename ConsumerSet::iterator iterCons = entry.consumers.begin();
183     typename ConsumerSet::iterator endCons = entry.consumers.end();
184     for (; iterCons != endCons; iterCons++) {
185     if (*iterCons == pConsumer) continue;
186     void* updatearg = NULL;
187     (*iterCons)->ResourceToBeUpdated(entry.resource, updatearg);
188     if (updatearg) updateargs[*iterCons] = updatearg;
189     }
190     // update resource
191     T_res* pOldResource = entry.resource;
192     Destroy(entry.resource, entry.arg);
193     entry.resource = Create(entry.key, pConsumer, entry.arg);
194     // inform all consumers about update completed
195     iterCons = entry.consumers.begin();
196     endCons = entry.consumers.end();
197     for (; iterCons != endCons; iterCons++) {
198     if (*iterCons == pConsumer) continue;
199     typename std::map<ResourceConsumer<T_res>*,void*>::iterator iterArg = updateargs.find(*iterCons);
200     void* updatearg = (iterArg != updateargs.end()) ? iterArg->second : NULL;
201     (*iterCons)->ResourceUpdated(pOldResource, entry.resource, updatearg);
202     }
203     return;
204     }
205     }
206     }
207    
208     protected:
209     /**
210     * Has to be implemented by the descendant to create (allocate) a
211     * resource identified by \a Key.
212     *
213     * @param Key - identifier of the resource
214     * @param pConsumer - identifier of the consumer who borrows the
215     * resource
216     * @param pArg - pointer the descendant can use to store
217     * informations he might need for destruction of
218     * the resource
219     * @returns pointer to new resource
220     */
221     virtual T_res* Create(T_key Key, ResourceConsumer<T_res>* pConsumer, void*& pArg) = 0;
222    
223     /**
224     * Has to be implemented by the descendant to destroy (free) a
225     * resource pointed by \a pResource.
226     *
227     * @param pResource - pointer to the resource
228     * @param pArg - pointer the descendant might have used when
229     * Create() was called to store informations
230     * about the resource
231     */
232     virtual void Destroy(T_res* pResource, void* pArg) = 0;
233    
234     /**
235     * Has to be implemented by the descendant to react when a consumer
236     * borrows a resource (no matter if freshly created or an already
237     * created one). Of course reacting is optional, but the descendant
238     * at least has to provide a method with empty body.
239     *
240     * @param pResource - pointer to the resource
241     * @param pConsumer - identifier of the consumer who borrows the
242     * resource
243     * @param pArg - pointer the descendant might have used when
244     * Create() was called to store informations
245     * about the resource, this information can be
246     * updated by the descendant here
247     */
248     virtual void OnBorrow(T_res* pResource, ResourceConsumer<T_res>* pConsumer, void*& pArg) = 0;
249 schoenebeck 517
250     /**
251     * Dispatcher method which should be periodically called by the
252     * descendant during update or creation of the resource associated
253     * with \a Key. This method will inform all associated consumers
254     * of the given resource about the current progress.
255     *
256     * @param Key - unique identifier of the resource which is
257     * currently creating or updating
258     * @param fProgress - current progress of that creation / update
259     * process as value between 0.0 and 1.0
260     */
261     void DispatchResourceProgressEvent(T_key Key, float fProgress) {
262     typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
263     if (iterEntry != ResourceEntries.end()) {
264     resource_entry_t& entry = iterEntry->second;
265     // inform all consumers of that resource about current progress
266     typename ConsumerSet::iterator iterCons = entry.consumers.begin();
267     typename ConsumerSet::iterator endCons = entry.consumers.end();
268     for (; iterCons != endCons; iterCons++) {
269     (*iterCons)->OnResourceProgress(fProgress);
270     }
271     }
272     }
273 schoenebeck 53 };
274    
275     #endif // __RESOURCE_MANAGER__

  ViewVC Help
Powered by ViewVC