resourcesuser.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 "resourcesuser.h"
22 #include <memory>
23 
24 namespace farsa {
25 
26 namespace {
27  // This class is needed so that the status of m_beingNotified is exception safe (i.e. it is reset
28  // to false if an exception gets thrown inside the handler for resource change). This is used both
29  // by SimpleResourcesUser and ConcurrentResourcesUser
30  class BeingNotifiedRAII
31  {
32  public:
33  BeingNotifiedRAII(bool* beingNotified) :
34  m_beingNotified(beingNotified)
35  {
36  *m_beingNotified = true;
37  }
38 
39  ~BeingNotifiedRAII()
40  {
41  *m_beingNotified = false;
42  }
43 
44  private:
45  bool* const m_beingNotified;
46  };
47 }
48 
50 {
51  if (other != NULL) {
52  m_resources = other->m_resources;
53  } else {
54  // This is exception safe (the assignment operator doesn't throw and if the constructor
55  // throws m_resources doesn't change)
57  }
58 }
59 
61  m_resources()
62 {
63 }
64 
66  m_resources(other.m_resources)
67 {
68 }
69 
71 {
72  if (&other == this) {
73  return *this;
74  }
75 
76  m_resources = other.m_resources;
77 
78  return *this;
79 }
80 
82 {
83  // Nothing to do here
84 }
85 
87  ResourcesUser(),
88  m_beingNotified(false),
89  m_notifiedResourceHandler(NULL),
90  m_observedResources()
91 {
92 }
93 
95  ResourcesUser(other),
96  m_beingNotified(false), // When we are created we can't be in the resource change handler
97  m_notifiedResourceHandler(NULL),
98  m_observedResources(other.m_observedResources)
99 {
100  // This is not exception safe. It is difficult to make this exception safe because QT aren't (and here we
101  // have to deal with QT containers)
102 
103  // We have to be notified of changes in the same set of resources as other.
104  forceBeingNotified();
105 }
106 
108 {
109  // This is not exception safe. It is difficult to make this exception safe because QT aren't (and here we
110  // have to deal with QT containers)
111 
112  if (&other == this) {
113  return *this;
114  }
115 
116  // First of all we have to stop being notified for old resources
117  removeAllNotifications();
118 
119  // Calling parent function
121 
122  // Now we can copy the set of resources for which notification is reuested. m_beingNotified and
123  // m_notifiedResourceHandler are not changed as we could be inside the notification handler
124  // (that would be weird, though)
125  m_observedResources = other.m_observedResources;
126 
127  // We have to be notified of changes in the same same set of resources as other
128  forceBeingNotified();
129 
130  return *this;
131 }
132 
134 {
135  removeAllNotifications();
136 }
137 
139 {
140  // Now we have to stop being notified for old resources
141  removeAllNotifications();
142 
143  // Calling parent function
145 }
146 
148 {
149  // Trying to retrieve the resource
150  ResourceHandler* h = m_resources->getResource(name, false);
151 
152  if ((h == NULL) || (!h->exists())){
153  throw ResourceNotDeclaredException(name.toLatin1().data());
154  }
155 
156  // Removing the resource
157  h->unset();
158 }
159 
161 {
162  // The default implementation does nothing
163 }
164 
165 void SimpleResourcesUser::notifyResourceChange(ResourceHandler* resource, ResourceChangeType changeType)
166 {
167  BeingNotifiedRAII beingNotifiedRAII(&m_beingNotified);
168  m_notifiedResourceHandler = resource;
169 
170  resourceChanged(m_notifiedResourceHandler->name(), changeType);
171 }
172 
173 void SimpleResourcesUser::removeAllNotifications()
174 {
175  // Functions using this are not exception safe and its hard to make them exception-safe
176  // because QT aren't...
177  foreach (ResourceHandler* h, m_observedResources) {
178  h->removeNotifee(this);
179  }
180 
181  m_observedResources.clear();
182 }
183 
184 void SimpleResourcesUser::forceBeingNotified()
185 {
186  // Functions using this are not exception safe and its hard to make them exception-safe
187  // because QT aren't...
188  foreach (ResourceHandler* h, m_observedResources) {
189  h->addNotifee(this);
190  }
191 }
192 
194  ResourcesUser(),
195  m_lockAcquired(0),
196  m_beingNotified(false),
197  m_notifiedResourceHandler(NULL),
198  m_usableResources()
199 {
200  // Here we need the ResourceCollectionHolder object to use locks
201  m_resources.setUseLock(true);
202 }
203 
205 {
206  // Removing from the notification list of all resources we were observing
207  removeAllNotifications();
208 
209  m_usableResources.clear();
210 }
211 
213 {
214  if ((m_lockAcquired > 0) || m_beingNotified) {
215  throw WrongResourceLockStatusForOperation("shareResourcesWith", true);
216  }
217 
218  // If other is NULL we do not get any lock on other resources, otherwise we have to. The two
219  // parts of the if are similar but trying to merge them creates quite some problems (with locks and
220  // exception safety), so I leave them separated
221  if (other == NULL) {
222  // Acquiring the lock on old resources to remove notifications, then we can release it. I'm doing
223  // it like this because I'm not sure deleting the mutex before destroying the QMutexLocker is
224  // ok (even if the mutex is unlocked). The mutex could be destroyed together with the corresponding
225  // ResourceCollection in ResourcesUser::shareResourcesWith(). Here we also get the list of name of
226  // existing resource that we use
227  QSet<QString> m_existingResourcesInOldCollection;
228  {
229  QMutexLocker oldCollectionLocker(&(m_resources->getLock()));
230 
231  // Removing all notifications on old resources
232  removeAllNotifications();
233 
234  for (QMap<QString, ResourceHandler*>::const_iterator it = m_usableResources.constBegin(); it != m_usableResources.constEnd(); ++it) {
235  if (it.value()->exists()) {
236  m_existingResourcesInOldCollection.insert(it.key());
237  }
238  }
239  }
240 
241  // Calling parent function.
243 
244  // Taking the lock on the newly created resource collection
245  QMutexLocker newCollectionLocker(&(m_resources->getLock()));
246 
247  // Now we have to update the m_usableResources map to point the the new resource handlers. No resource
248  // still esists, we create empty resourced here
249  for (QMap<QString, ResourceHandler*>::iterator it = m_usableResources.begin(); it != m_usableResources.end(); ++it) {
250  it.value() = m_resources->getResource(it.key(), true);
251  it.value()->addNotifee(this);
252  }
253 
254  // Before sending notifications, we have to get the lock on all resources and to release the lock on the
255  // resource collection
256  ResourcesMutexesLocker resourcesLocker(this, m_usableResources.values());
257 
258  // Now we can unlock the mutex on the Resource Manager
259  newCollectionLocker.unlock();
260 
261  // Now we can send all notifications. All previously existing resources have been deleted
262  foreach (QString name, m_existingResourcesInOldCollection) {
263  notifyResourceChange(m_usableResources[name], Deleted);
264  }
265  } else {
266  // Acquiring lock on new resources
267  QMutexLocker newCollectionLocker(&(other->m_resources->getLock()));
268 
269  // Acquiring the lock on old resources to remove notifications, then we can release it. I'm doing
270  // it like this because I'm not sure deleting the mutex before destroying the QMutexLocker is
271  // ok (even if the mutex is unlocked). The mutex could be destroyed together with the corresponding
272  // ResourceCollection in ResourcesUser::shareResourcesWith(). Here we also get the list of name of
273  // existing resource that we use
274  QSet<QString> m_existingResourcesInOldCollection;
275  {
276  QMutexLocker oldCollectionLocker(&(m_resources->getLock()));
277 
278  // Removing all notifications on old resources
279  removeAllNotifications();
280 
281  for (QMap<QString, ResourceHandler*>::const_iterator it = m_usableResources.constBegin(); it != m_usableResources.constEnd(); ++it) {
282  if (it.value()->exists()) {
283  m_existingResourcesInOldCollection.insert(it.key());
284  }
285  }
286  }
287 
288  // Calling parent function to actually share resources. Here the lock on new resources would be taken
289  // again (but the mutex is not recursive), so we have to temporarly prevent m_resources from locking
290  m_resources.setUseLock(false);
292  m_resources.setUseLock(true);
293 
294  // Now we have to update the m_usableResources map to point the the new resource handlers. We also create
295  // the set of names of resources that exists in the new collection
296  QSet<QString> m_existingResourcesInNewCollection;
297  for (QMap<QString, ResourceHandler*>::iterator it = m_usableResources.begin(); it != m_usableResources.end(); ++it) {
298  it.value() = m_resources->getResource(it.key(), true);
299  it.value()->addNotifee(this);
300 
301  if (it.value()->exists()) {
302  m_existingResourcesInNewCollection.insert(it.key());
303  }
304  }
305 
306  // Before sending notifications, we have to get the lock on all resources and to release the lock on the
307  // resource collection
308  ResourcesMutexesLocker resourcesLocker(this, m_usableResources.values());
309 
310  // Now we can unlock the mutex on the Resource Manager
311  newCollectionLocker.unlock();
312 
313  // Now we can send all notifications. The changeType to use depends on the status of the resource with a given
314  // name in the new and old set: if a resource existed in the old set and not in the new one, changeType will be
315  // Deleted, if it existed in the old set and is also present in the new one, changeType will be Modified, if it
316  // didn't exist in the old set but is present in the new one, changeType will be Created.
317  const QSet<QString> deletedResources = m_existingResourcesInOldCollection - m_existingResourcesInNewCollection;
318  const QSet<QString> modifiedResources = m_existingResourcesInOldCollection & m_existingResourcesInNewCollection;
319  const QSet<QString> createdResources = m_existingResourcesInNewCollection - m_existingResourcesInOldCollection;
320 
321  // Actually sending all notifications
322  foreach (QString name, deletedResources) {
323  notifyResourceChange(m_usableResources[name], Deleted);
324  }
325  foreach (QString name, modifiedResources) {
326  notifyResourceChange(m_usableResources[name], Modified);
327  }
328  foreach (QString name, createdResources) {
329  notifyResourceChange(m_usableResources[name], Created);
330  }
331  }
332 }
333 
334 void ConcurrentResourcesUser::usableResources(QStringList resources)
335 {
336  if ((m_lockAcquired > 0) || m_beingNotified) {
337  throw WrongResourceLockStatusForOperation("usableResources", true);
338  }
339 
340  // First of all we have to acquire the lock on the Resource Manager (because we need to call getResource)
341  QMutexLocker collectionLocker(&(m_resources->getLock()));
342 
343  // Removing old resources
344  m_usableResources.clear();
345 
346  foreach (QString resource, resources) {
347  // Here we create a Resource Handler if the resource doesn't exists
348  ResourceHandler* h = m_resources->getResource(resource, true);
349 
350  h->addNotifee(this);
351  m_usableResources[resource] = h;
352  }
353 
354  // Getting the lock on all new resources to send notifications. There is a little overhead, here,
355  // because we get the lock also for non-existing resources (that are not notified, though)
356  ResourcesMutexesLocker resourcesLocker(this, m_usableResources.values());
357 
358  // Now we can unlock the mutex on the Resource Manager
359  collectionLocker.unlock();
360 
361  // Notifying that all the new resources exist
362  foreach (ResourceHandler* h, m_usableResources) {
363  if (h->exists()) {
364  notifyResourceChange(h, Created);
365  }
366  }
367 }
368 
370 {
371  if ((m_lockAcquired > 0) || m_beingNotified) {
372  throw WrongResourceLockStatusForOperation("addUsableResource", true);
373  }
374 
375  // First of all we have to acquire the lock on the Resource Manager (because we need to call getResource)
376  QMutexLocker collectionLocker(&(m_resources->getLock()));
377 
378  // Here we create a Resource Handler if the resource doesn't exists
379  ResourceHandler* h = m_resources->getResource(resource, true);
380 
381  h->addNotifee(this);
382  m_usableResources[resource] = h;
383 
384  // If the resource exists, sending notification
385  if (h->exists()) {
386  // Taking the lock on the resource because we have to send a notification
387  ResourcesMutexesLocker resourceLocker(this, h);
388 
389  // Now we can unlock the mutex on the Resource Manager
390  collectionLocker.unlock();
391 
392  // Notifying that the resource exists
393  notifyResourceChange(h, Created);
394  }
395 }
396 
398 {
399  if ((m_lockAcquired > 0) || m_beingNotified) {
400  throw WrongResourceLockStatusForOperation("addUsableResources", true);
401  }
402 
403  // First of all we have to acquire the lock on the Resource Manager (because we need to call getResource)
404  QMutexLocker collectionLocker(&(m_resources->getLock()));
405 
406  // Adding all new resources
407  QList<ResourceHandler *> newResources;
408  foreach (QString resource, resources) {
409  // Here we create a Resource Handler if the resource doesn't exists
410  ResourceHandler* h = m_resources->getResource(resource, true);
411 
412  h->addNotifee(this);
413  m_usableResources[resource] = h;
414 
415  // Saving the list of the new resources handlers for notifications
416  newResources.append(h);
417  }
418 
419  // Getting the lock on all new resources to send notifications. There is a little overhead, here,
420  // because we get the lock also for non-existing resources (that are not notified, though)
421  ResourcesMutexesLocker resourcesLocker(this, newResources);
422 
423  // Now we can unlock the mutex on the Resource Manager
424  collectionLocker.unlock();
425 
426  // Notifying that all the new resources exist
427  foreach (ResourceHandler* h, newResources) {
428  if (h->exists()) {
429  notifyResourceChange(h, Created);
430  }
431  }
432 }
433 
435 {
436  if ((m_lockAcquired > 0) || m_beingNotified) {
437  throw WrongResourceLockStatusForOperation("removeUsableResource", true);
438  }
439 
440  if (m_usableResources.contains(resource)) {
441  // First of all we have to acquire the lock on the Resource Manager (because we need to call getResource)
442  QMutexLocker collectionLocker(&(m_resources->getLock()));
443 
444  // The ResourceHandler should exist, if not there is a bug and this function will crash
445  ResourceHandler* h = m_resources->getResource(resource, false);
446  h->removeNotifee(this);
447 
448  m_usableResources.remove(resource);
449 
450  // Now notifying the resource is no longer available. First taking the lock on the resource
451  ResourcesMutexesLocker resourceLocker(this, h);
452 
453  // Now we can unlock the mutex on the Resource Manager
454  collectionLocker.unlock();
455 
456  // Notifying that the resource exists
457  notifyResourceChange(h, Deleted);
458  }
459 }
460 
462 {
463  if ((m_lockAcquired > 0) || m_beingNotified) {
464  throw WrongResourceLockStatusForOperation("removeUsableResources", true);
465  }
466 
467  // First of all we have to acquire the lock on the Resource Manager (because we need to call getResource)
468  QMutexLocker collectionLocker(&(m_resources->getLock()));
469 
470  // Deleting all resources
471  QList<ResourceHandler *> deletedResources;
472  foreach (QString resource, resources) {
473  if (!m_usableResources.contains(resource)) {
474  continue;
475  }
476 
477  // Taking the resource handler and then removing the resource (the resource must exist, otherwise there is a
478  // bug and this will crash)
479  ResourceHandler* h = m_resources->getResource(resource, false);
480  h->removeNotifee(this);
481 
482  m_usableResources.remove(resource);
483 
484  // Saving the list of the deleted resources handlers for notifications
485  deletedResources.append(h);
486  }
487 
488  // Getting the lock on all deleted resources to send notifications. There is a little overhead, here,
489  // because we get the lock also for non-existing resources (that are not notified, though)
490  ResourcesMutexesLocker resourcesLocker(this, deletedResources);
491 
492  // Now we can unlock the mutex on the Resource Manager
493  collectionLocker.unlock();
494 
495  // Notifying that all the resources that exist
496  foreach (ResourceHandler* h, deletedResources) {
497  if (h->exists()) {
498  notifyResourceChange(h, Deleted);
499  }
500  }
501 }
502 
504 {
505  if ((m_lockAcquired > 0) || m_beingNotified) {
506  throw WrongResourceLockStatusForOperation("removeAllUsableResources", true);
507  }
508 
509  // First of all we have to acquire the lock on the Resource Manager (because we need to call getResource)
510  QMutexLocker collectionLocker(&(m_resources->getLock()));
511 
512  // Deleting all resources
513  foreach (ResourceHandler* h, m_usableResources) {
514  h->removeNotifee(this);
515  }
516 
517  QList<ResourceHandler *> deletedResources = m_usableResources.values();
518  // Clearing the list of resources we use
519  m_usableResources.clear();
520 
521  // Getting the lock on all deleted resources to send notifications. There is a little overhead, here,
522  // because we get the lock also for non-existing resources (that are not notified, though)
523  ResourcesMutexesLocker resourcesLocker(this, deletedResources);
524 
525  // Now we can unlock the mutex on the Resource Manager
526  collectionLocker.unlock();
527 
528  // Notifying that all the resources that exist
529  foreach (ResourceHandler* h, deletedResources) {
530  if (h->exists()) {
531  notifyResourceChange(h, Deleted);
532  }
533  }
534 }
535 
537 {
538  if ((m_lockAcquired > 0) || m_beingNotified) {
539  throw WrongResourceLockStatusForOperation("deleteResource", true);
540  }
541 
542  // Getting the lock on the resource collection
543  QMutexLocker collectionLocker(&(m_resources->getLock()));
544 
545  // Now we have to get the resource and then acquire the lock on the resource if it exists
546  ResourceHandler* h = m_resources->getResource(name, false);
547  if ((h == NULL) || (!h->exists())) {
548  throw ResourceNotDeclaredException(name.toLatin1().data());
549  }
550  ResourcesMutexesLocker resourceLocker(this, h);
551 
552  // Before setting the resource, we can release the lock on Resource Manager
553  collectionLocker.unlock();
554 
555  // Now removing the resource
556  h->unset();
557 }
558 
559 bool ConcurrentResourcesUser::hasResource(QString name) const
560 {
561  if ((m_lockAcquired > 0) || m_beingNotified) {
562  throw WrongResourceLockStatusForOperation("hasResource", true);
563  }
564 
565  QMutexLocker locker(&(m_resources->getLock()));
566 
567  return m_resources->hasResource(name);
568 }
569 
570 bool ConcurrentResourcesUser::usedResourcesExist(QStringList* nonExistingResources) const
571 {
572  if ((m_lockAcquired > 0) || m_beingNotified) {
573  throw WrongResourceLockStatusForOperation("usedResourcesExist", true);
574  }
575 
576  QMutexLocker locker(&(m_resources->getLock()));
577 
578  bool allExist = true;
579 
580  foreach (ResourceHandler* h, m_usableResources) {
581  if (!h->exists()) {
582  allExist = false;
583  if (nonExistingResources != NULL) {
584  nonExistingResources->append(h->name());
585  } else {
586  // If we don't have to return the list of non-existing resource, we can exit
587  // from the cicle as soon as we find a resource that doesn't exists
588  break;
589  }
590  }
591  }
592 
593  return allExist;
594 }
595 
597 {
598  // The default implementation of this function does nothing
599 }
600 
601 void ConcurrentResourcesUser::lockAll()
602 {
603  // Locking all resources. To avoid deadlocks here we first acquire the lock on the Resource Manager
604  QMutexLocker locker(&(m_resources->getLock()));
605 
606  // Locking all resources
607  lockResources(m_usableResources.values());
608 
609  ++m_lockAcquired;
610 }
611 
612 void ConcurrentResourcesUser::unlockAll()
613 {
614  // Unlocking all resources. Here we have to take the mutex because the unlock of resources must be
615  // atomic (otherwise a lockAll() call can find a resource locked even if we are here because we haven't
616  // unlocked a certain resource yet and he could then miss the wake of the wait condition)
617  QMutexLocker locker(&(m_resources->getLock()));
618 
619  // Unlocking all resources and signalling threads on the wait condition
620  unlockResources(m_usableResources.values());
621 
622  --m_lockAcquired;
623 
624  // The mutex will be unlocked here
625 }
626 
627 void ConcurrentResourcesUser::notifyResourceChange(ResourceHandler* resource, ResourceChangeType changeType)
628 {
629  BeingNotifiedRAII beingNotifiedRAII(&m_beingNotified);
630  m_notifiedResourceHandler = resource;
631 
632  resourceChanged(m_notifiedResourceHandler->name(), changeType);
633 }
634 
635 void ConcurrentResourcesUser::removeAllNotifications()
636 {
637  // Functions using this are not exception safe and its hard to make them exception-safe
638  // because QT aren't...
639  foreach (ResourceHandler* h, m_usableResources) {
640  h->removeNotifee(this);
641  }
642 }
643 
644 void ConcurrentResourcesUser::forceBeingNotified()
645 {
646  // Functions using this are not exception safe and its hard to make them exception-safe
647  // because QT aren't...
648  foreach (ResourceHandler* h, m_usableResources) {
649  h->addNotifee(this);
650  }
651 }
652 
653 void ConcurrentResourcesUser::lockResources(const QList<ResourceHandler*>& resources)
654 {
655  // We have to cycle until getting resources is successful
656  bool oneLockFailed;
657  do {
658  // Resetting the status of the flag for failed locks
659  oneLockFailed = false;
660 
661  // Now locking all our resources. The mutexes for resources are recursive, so they will not fail
662  // if this function is called recursively. Here I assume that locking a mutex never throws... If
663  // this is not the case, an exception during the lock of one mutex will leave some mutex locked
664  // indefinitely and some other unlocked.
665  QList<ResourceHandler*> lockedResources;
666  foreach (ResourceHandler* resource, resources) {
667  const bool locked = resource->getLock().tryLock();
668  if (!locked) {
669  oneLockFailed = true;
670  break;
671  } else {
672  lockedResources.append(resource);
673  }
674  }
675 
676  // If one lock failed, we can't acquire all resources here, so we unlock what we have
677  // locked and wait
678  if (oneLockFailed) {
679  foreach (ResourceHandler* resource, lockedResources) {
680  resource->getLock().unlock();
681  }
682 
683  // Waiting
685  }
686  } while (oneLockFailed);
687 }
688 
689 void ConcurrentResourcesUser::unlockResources(const QList<ResourceHandler*>& resources)
690 {
691  // Unlocking all resources. Here I assume that unlocking a mutex never throws... If
692  // this is not the case, an exception during the unlock of one mutex will leave some
693  // mutex locked indefinitely and some other unlocked.
694  foreach (ResourceHandler* resource, resources) {
695  resource->getLock().unlock();
696  }
697 
698  // Waking threads that are waiting
699  m_resources->getWaitCondition().wakeAll();
700 }
701 
703  m_resourcesUser(resourcesUser),
704  m_lockedByUs(false)
705 {
706  if (acquireLock) {
707  lock();
708  }
709 }
710 
712 {
713  unlock();
714 }
715 
717 {
718  if (m_lockedByUs) {
719  return;
720  }
721 
722  m_resourcesUser->lockAll();
723 
724  m_lockedByUs = true;
725 }
726 
728 {
729  if (!m_lockedByUs) {
730  return;
731  }
732 
733  m_resourcesUser->unlockAll();
734 
735  m_lockedByUs = false;
736 }
737 
738 } // end namspace farsa
739 
void usableResources(QStringList resources)
Defines the list of resources that will be used.
A simple class to access/declare resources (not thread-safe)
A class to access/declare resources in a thread-safe way.
void removeUsableResources(QStringList resources)
Removes resources from the list of resources that will be used.
void unset()
Marks this resource as non-existing.
Definition: resource.cpp:141
bool exists() const
Returns true if this holds an existing resource.
Definition: resource.h:327
virtual void shareResourcesWith(ResourcesUser *other)
The function to share resources.
void addUsableResource(QString resource)
Adds a new resource to the list of resources that will be used.
virtual void resourceChanged(QString name, ResourceChangeType changeType)
The function called when a resource you use is changed.
virtual ~ConcurrentResourcesUser()
Destructor.
QString name() const
Returns the name of the resource.
Definition: resource.h:211
virtual ~SimpleResourcesUser()
Constructor.
void deleteResource(QString name)
Deletes the resource with the specified name.
ResourceCollectionHolder m_resources
The object holding the shared resources.
virtual void shareResourcesWith(ResourcesUser *buddy)
Shares resources with the provided instance of ResourcesUser.
void removeNotifee(ResourcesUser *n)
Removes an observer.
Definition: resource.cpp:153
void addNotifee(ResourcesUser *n)
Adds a new observer.
Definition: resource.cpp:148
virtual void resourceChanged(QString name, ResourceChangeType changeType)
The function called when a resource you use is changed.
QWaitCondition & getWaitCondition()
Returns the wait condition on the global resource lock.
Definition: resource.h:501
bool hasResource(QString name) const
Returns true if a resource with name specified has been declared.
Definition: resource.h:555
The exception thrown when requesting a resource never declared.
void addUsableResources(QStringList resources)
Adds new resources to the list of resources that will be used.
bool hasResource(QString name) const
Returns true if a resource with name specified has been declared.
virtual ~ResourcesUser()
Constructor.
QMutex & getLock()
Returns the global resource lock for this instance.
Definition: resource.h:491
bool usedResourcesExist(QStringList *nonExistingResources=NULL) const
Returns true if all the resources we use exist.
The exception thrown when an operation is performed on a ConcurrentResourcesUser object but the lock ...
The parent of classes managing resources.
Definition: resourcesuser.h:70
SimpleResourcesUser & operator=(const SimpleResourcesUser &other)
Copy operator.
ResourcesLocker(ConcurrentResourcesUser *resourcesUser, bool acquireLock=true)
Constructor.
ResourcesUser & operator=(const ResourcesUser &other)
Copy operator.
friend class ResourceHandler
The ResourceHandler class is friend to access the notifyResourceChange() function.
virtual void shareResourcesWith(ResourcesUser *other)
The function to share resources.
void unlock()
Releases the lock.
ResourceHandler * getResource(QString name, bool create=false)
Returns a pointer to the resource handler for the resource with the specified name.
Definition: resource.cpp:185
void lock()
Acquires the lock.
void deleteResource(QString name)
Deletes the resource with the specified name.
~ResourcesLocker()
Destructor.
void removeUsableResource(QString resource)
Removes the resource from the list of resources that will be used.
ResourcesUser()
Constructor.
SimpleResourcesUser()
Constructor.
void setUseLock(bool useLock)
Sets whether locks should be used or not.
Definition: resource.h:650
The class for representing a resource.
Definition: resource.h:189
This keeps an instance of ResourceCollection eventually sharing it.
Definition: resource.h:612
ResourceChangeType
The change that happened to a resource.
Definition: resource.h:62
void removeAllUsableResources()
Removes all resources from the list of resources that will be used.