/[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 517 - (hide annotations) (download) (as text)
Sun May 8 00:26:21 2005 UTC (18 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 13007 byte(s)
* implemented progress indicator for loading instruments
  (can be polled with "GET CHANNEL INFO", field "INSTRUMENT_STATUS")

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 53 * *
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 schoenebeck 517
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 schoenebeck 53 };
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 letz 386 virtual ~ResourceManager() {}
100 schoenebeck 53 /**
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 schoenebeck 517 // already create an entry for the resource
114 schoenebeck 53 resource_entry_t entry;
115     entry.key = Key;
116 schoenebeck 517 entry.resource = NULL;
117     entry.consumers.insert(pConsumer);
118     ResourceEntries[Key] = entry;
119     // actually create the resource
120 schoenebeck 53 entry.resource = Create(Key, pConsumer, entry.arg);
121 schoenebeck 517 // now update the entry with the created resource
122     ResourceEntries[Key] = entry;
123 schoenebeck 53 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 schoenebeck 351 if (iter->second.resource == pResource) {
147 schoenebeck 53 resource_entry_t& entry = iter->second;
148     entry.consumers.erase(pConsumer);
149     if (entry.consumers.empty()) {
150     ResourceEntries.erase(iter);
151     Destroy(entry.resource, entry.arg);
152     }
153     return;
154     }
155     }
156     }
157    
158     /**
159     * Request update of a resource.
160     *
161     * @param pResource - resource to be updated
162     * @param pConsumer - consumer who requested the update
163     */
164     void Update(T_res* pResource, ResourceConsumer<T_res>* pConsumer) {
165     typename ResourceMap::iterator iter = ResourceEntries.begin();
166     typename ResourceMap::iterator end = ResourceEntries.end();
167     for (; iter != end; iter++) {
168 schoenebeck 351 if (iter->second.resource == pResource) {
169 schoenebeck 53 resource_entry_t& entry = iter->second;
170     // inform all consumers about pending update
171     std::map<ResourceConsumer<T_res>*,void*> updateargs;
172     typename ConsumerSet::iterator iterCons = entry.consumers.begin();
173     typename ConsumerSet::iterator endCons = entry.consumers.end();
174     for (; iterCons != endCons; iterCons++) {
175     if (*iterCons == pConsumer) continue;
176     void* updatearg = NULL;
177     (*iterCons)->ResourceToBeUpdated(entry.resource, updatearg);
178     if (updatearg) updateargs[*iterCons] = updatearg;
179     }
180     // update resource
181     T_res* pOldResource = entry.resource;
182     Destroy(entry.resource, entry.arg);
183     entry.resource = Create(entry.key, pConsumer, entry.arg);
184     // inform all consumers about update completed
185     iterCons = entry.consumers.begin();
186     endCons = entry.consumers.end();
187     for (; iterCons != endCons; iterCons++) {
188     if (*iterCons == pConsumer) continue;
189     typename std::map<ResourceConsumer<T_res>*,void*>::iterator iterArg = updateargs.find(*iterCons);
190     void* updatearg = (iterArg != updateargs.end()) ? iterArg->second : NULL;
191     (*iterCons)->ResourceUpdated(pOldResource, entry.resource, updatearg);
192     }
193     return;
194     }
195     }
196     }
197    
198     protected:
199     /**
200     * Has to be implemented by the descendant to create (allocate) a
201     * resource identified by \a Key.
202     *
203     * @param Key - identifier of the resource
204     * @param pConsumer - identifier of the consumer who borrows the
205     * resource
206     * @param pArg - pointer the descendant can use to store
207     * informations he might need for destruction of
208     * the resource
209     * @returns pointer to new resource
210     */
211     virtual T_res* Create(T_key Key, ResourceConsumer<T_res>* pConsumer, void*& pArg) = 0;
212    
213     /**
214     * Has to be implemented by the descendant to destroy (free) a
215     * resource pointed by \a pResource.
216     *
217     * @param pResource - pointer to the resource
218     * @param pArg - pointer the descendant might have used when
219     * Create() was called to store informations
220     * about the resource
221     */
222     virtual void Destroy(T_res* pResource, void* pArg) = 0;
223    
224     /**
225     * Has to be implemented by the descendant to react when a consumer
226     * borrows a resource (no matter if freshly created or an already
227     * created one). Of course reacting is optional, but the descendant
228     * at least has to provide a method with empty body.
229     *
230     * @param pResource - pointer to the resource
231     * @param pConsumer - identifier of the consumer who borrows the
232     * resource
233     * @param pArg - pointer the descendant might have used when
234     * Create() was called to store informations
235     * about the resource, this information can be
236     * updated by the descendant here
237     */
238     virtual void OnBorrow(T_res* pResource, ResourceConsumer<T_res>* pConsumer, void*& pArg) = 0;
239 schoenebeck 517
240     /**
241     * Dispatcher method which should be periodically called by the
242     * descendant during update or creation of the resource associated
243     * with \a Key. This method will inform all associated consumers
244     * of the given resource about the current progress.
245     *
246     * @param Key - unique identifier of the resource which is
247     * currently creating or updating
248     * @param fProgress - current progress of that creation / update
249     * process as value between 0.0 and 1.0
250     */
251     void DispatchResourceProgressEvent(T_key Key, float fProgress) {
252     typename ResourceMap::iterator iterEntry = ResourceEntries.find(Key);
253     if (iterEntry != ResourceEntries.end()) {
254     resource_entry_t& entry = iterEntry->second;
255     // inform all consumers of that resource about current progress
256     typename ConsumerSet::iterator iterCons = entry.consumers.begin();
257     typename ConsumerSet::iterator endCons = entry.consumers.end();
258     for (; iterCons != endCons; iterCons++) {
259     (*iterCons)->OnResourceProgress(fProgress);
260     }
261     }
262     }
263 schoenebeck 53 };
264    
265     #endif // __RESOURCE_MANAGER__

  ViewVC Help
Powered by ViewVC