resource.cpp
1 /***************************************************************************
2  * Copyright (C) 2008 by Tomassino Ferrauto *
3  * t_ferrauto@yahoo.it *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
21 #include "resource.h"
22 #include "resourcesuser.h"
23 #include <memory>
24 
25 namespace farsa {
26 
28  m_shared(NULL)
29 {
30  // Creating an instance of ResourceCollection in an exception-safe way
31  m_shared = new MutexAndRefCounter();
32  m_shared->referenceCounter++;
33 }
34 
36  m_shared(other.m_shared)
37 {
38  m_shared->referenceCounter++;
39 }
40 
42 {
43  if (&other == this) {
44  return *this;
45  }
46 
47  // Sharing with other and decrementing our old one (possibly also deleting)
48  m_shared->referenceCounter--;
49  if (m_shared->referenceCounter == 0) {
50  delete m_shared;
51  }
52 
53  m_shared = other.m_shared;
54  m_shared->referenceCounter++;
55 
56  return *this;
57 }
58 
60 {
61  // Decrementing the reference counter and possibly deleting the mutex
62  m_shared->referenceCounter--;
63  if (m_shared->referenceCounter == 0) {
64  delete m_shared;
65  }
66 }
67 
69  m_name(name),
70  m_type(t_nonExistent),
71  m_lock(),
72  m_notifees()
73 {
74 }
75 
77 {
78 }
79 
81 {
82  m_lock = other->m_lock;
83 }
84 
85 void ResourceHandler::set(int* res)
86 {
87  const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
88  m_type = t_int;
89  m_pointers.intp = res;
90  notifyAll(changeType);
91 }
92 
93 void ResourceHandler::set(float* res)
94 {
95  const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
96  m_type = t_float;
97  m_pointers.floatp = res;
98  notifyAll(changeType);
99 }
100 
101 void ResourceHandler::set(double* res)
102 {
103  const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
104  m_type = t_double;
105  m_pointers.doublep = res;
106  notifyAll(changeType);
107 }
108 
109 void ResourceHandler::set(bool* res)
110 {
111  const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
112  m_type = t_bool;
113  m_pointers.boolp = res;
114  notifyAll(changeType);
115 }
116 
118 {
119  const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
120  m_type = t_resource;
121  m_pointers.res = res;
122  notifyAll(changeType);
123 }
124 
126 {
127  const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
128  m_type = t_paramSettable;
129  m_pointers.par = res;
130  notifyAll(changeType);
131 }
132 
133 void ResourceHandler::set(QObject* res)
134 {
135  const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
136  m_type = t_qObject;
137  m_pointers.obj = res;
138  notifyAll(changeType);
139 }
140 
142 {
143  m_type = t_nonExistent;
144  // Note: if getResource is called in the callback, an exception will be thrown!
145  notifyAll(Resource::Deleted);
146 }
147 
149 {
150  m_notifees.insert(n);
151 }
152 
154 {
155  m_notifees.remove(n);
156 }
157 
159 {
160  return m_notifees.contains(n);
161 }
162 
163 void ResourceHandler::notifyAll(Resource::ResourceChangeType changeType)
164 {
165  foreach (ResourcesUser *n, m_notifees) {
166  n->notifyResourceChange(this, changeType);
167  }
168 }
169 
171  m_resources(),
172  m_lock(QMutex::NonRecursive),
173  m_referenceCounter(0)
174 {
175 }
176 
178 {
179  // Deleting all resources still in the map
180  foreach (ResourceHandler *r, m_resources) {
181  delete r;
182  }
183 }
184 
186 {
187  ResourceHandler *h = NULL;
188 
189  if (!m_resources.contains(name)) {
190  if (create) {
191  // Adding an non-existant resource (in an exception-safe way)
192  std::auto_ptr<ResourceHandler> hp(new ResourceHandler(name));
193  m_resources[name] = hp.get();
194  h = hp.release();
195  }
196  } else {
197  h = m_resources[name];
198  }
199 
200  return h;
201 }
202 
204  m_resourceCollection(NULL),
205  m_useLocks(false)
206 {
207  // Creating an instance of ResourceCollection in an exception-safe way
208  std::auto_ptr<ResourceCollection> c(new ResourceCollection());
209  c->incrementReferenceCounter();
210  m_resourceCollection = c.release();
211 }
212 
214  m_resourceCollection(other.m_resourceCollection),
215  m_useLocks(false)
216 {
217  if (other.m_useLocks) {
218  m_resourceCollection->getLock().lock();
219  }
220 
221  // Incrementing the counter of the ResourceCollection object
222  m_resourceCollection->incrementReferenceCounter();
223 
224  if (other.m_useLocks) {
225  m_resourceCollection->getLock().unlock();
226  }
227 }
228 
230 {
231  // Comparing for equality of objects (not pointers) because we must not do anything
232  // if this and other already point to the same ResourceCollection object
233  if (other == *this) {
234  return *this;
235  }
236 
237  // Acquiring locks if we have to
238  if (m_useLocks) {
239  m_resourceCollection->getLock().lock();
240  other.m_resourceCollection->getLock().lock();
241  }
242 
243  // First of all releasing the current resource manager (and destroying it if we have to)
244  const int refCounter = m_resourceCollection->decrementReferenceCounter();
245  if (m_useLocks) {
246  m_resourceCollection->getLock().unlock();
247  }
248  if (refCounter == 0) {
249  delete m_resourceCollection;
250  }
251 
252  // Now we can use the ResourceCollection of other
253  m_resourceCollection = other.m_resourceCollection;
254  m_resourceCollection->incrementReferenceCounter();
255 
256  if (m_useLocks) {
257  // m_resourceCollection is now the same as other.m_resourceCollection, so here
258  // we are unlocking the mutex on the new collection
259  m_resourceCollection->getLock().unlock();
260  }
261 
262  return *this;
263 }
264 
266 {
267  if (m_useLocks) {
268  m_resourceCollection->getLock().lock();
269  }
270 
271  const int refCounter = m_resourceCollection->decrementReferenceCounter();
272 
273  if (m_useLocks) {
274  m_resourceCollection->getLock().unlock();
275  }
276 
277  if (refCounter == 0) {
278  delete m_resourceCollection;
279  }
280 }
281 
282 } // end namspace farsa