00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef RESOURCESUSER_H
00025 #define RESOURCESUSER_H
00026
00027 #include "parametersettable.h"
00028 #include "configurationconfig.h"
00029 #include "configurationexceptions.h"
00030 #include "resource.h"
00031 #include <QMap>
00032 #include <QString>
00033 #include <QStringList>
00034 #include <QMutexLocker>
00035 #include <QSet>
00036
00037 class QObject;
00038
00039 namespace farsa {
00040
00041 class ResourcesUser;
00042 class SimpleResourcesUser;
00043 class ConcurrentResourcesUser;
00044 class ResourcesLocker;
00045
00070 class FARSA_CONF_API ResourcesUser : public Resource
00071 {
00072 public:
00084 virtual void shareResourcesWith(ResourcesUser* other);
00085
00086 protected:
00092 ResourcesUser();
00093
00102 ResourcesUser(const ResourcesUser& other) throw();
00103
00112 ResourcesUser& operator=(const ResourcesUser& other) throw();
00113
00119 virtual ~ResourcesUser();
00120
00130 virtual void notifyResourceChange(ResourceHandler* resource, ResourceChangeType changeType) = 0;
00131
00135 ResourceCollectionHolder m_resources;
00136
00141 friend class ResourceHandler;
00142
00147 friend class ConcurrentResourcesUser;
00148 };
00149
00219 class FARSA_CONF_API SimpleResourcesUser : public ResourcesUser
00220 {
00221 public:
00225 SimpleResourcesUser();
00226
00235 SimpleResourcesUser(const SimpleResourcesUser& other);
00236
00245 SimpleResourcesUser& operator=(const SimpleResourcesUser& other);
00246
00250 virtual ~SimpleResourcesUser();
00251
00263 virtual void shareResourcesWith(ResourcesUser* other);
00264
00272 template<class T>
00273 void declareResource(QString name, T* resource)
00274 {
00275
00276 ResourceHandler* h = m_resources->getResource(name, true);
00277
00278
00279
00280
00281 h->set(resource);
00282 }
00283
00293 template<class T>
00294 T* getResource(QString name)
00295 {
00296
00297 ResourceHandler* h = m_resources->getResource(name, false);
00298
00299 if ((h == NULL) || (!h->exists())){
00300 throw ResourceNotDeclaredException(name.toAscii().data());
00301 }
00302
00303 T* resource = h->get<T>();
00304 if (resource == NULL) {
00305 throw ResourceTypeMismatchException(name.toAscii().data(), typeid(T).name());
00306 }
00307
00308 return resource;
00309 }
00310
00317 void deleteResource(QString name);
00318
00326 bool hasResource(QString name) const
00327 {
00328 return m_resources->hasResource(name);
00329 }
00330
00331 protected:
00340 virtual void resourceChanged(QString name, ResourceChangeType changeType);
00341
00354 template<class T>
00355 T* getResource()
00356 {
00357 if (!m_beingNotified) {
00358 return NULL;
00359 }
00360
00361 if (!m_notifiedResourceHandler->exists()) {
00362
00363 throw ResourceNotDeclaredException(m_notifiedResourceHandler->name().toAscii().data());
00364 }
00365 T* resource = m_notifiedResourceHandler->get<T>();
00366 if (resource == NULL) {
00367 throw ResourceTypeMismatchException(m_notifiedResourceHandler->name().toAscii().data(), typeid(T).name());
00368 }
00369
00370 return resource;
00371 }
00372
00373 private:
00383 virtual void notifyResourceChange(ResourceHandler* resource, ResourceChangeType changeType);
00384
00389 void removeAllNotifications();
00390
00394 void forceBeingNotified();
00395
00402 bool m_beingNotified;
00403
00410 ResourceHandler* m_notifiedResourceHandler;
00411
00415 QSet<ResourceHandler*> m_observedResources;
00416 };
00417
00581 class FARSA_CONF_API ConcurrentResourcesUser : public ResourcesUser
00582 {
00583 public:
00587 ConcurrentResourcesUser();
00588
00592 virtual ~ConcurrentResourcesUser();
00593
00604 virtual void shareResourcesWith(ResourcesUser* buddy);
00605
00620 void usableResources(QStringList resources);
00621
00635 void addUsableResource(QString resource);
00636
00652 void addUsableResources(QStringList resources);
00653
00664 void removeUsableResource(QString resource);
00665
00676 void removeUsableResources(QStringList resources);
00677
00685 void removeAllUsableResources();
00686
00715 template<class T>
00716 void declareResource(QString name, T* resource, QString lockBuddy = "")
00717 {
00718 if ((m_lockAcquired > 0) || m_beingNotified) {
00719 throw WrongResourceLockStatusForOperation("declareResource", true);
00720 }
00721
00722
00723 QMutexLocker collectionLocker(&(m_resources->getLock()));
00724
00725
00726 ResourceHandler* h = m_resources->getResource(name, true);
00727 if (!lockBuddy.isEmpty()) {
00728 ResourceHandler* lockBuddyHandler = m_resources->getResource(lockBuddy, false);
00729 if ((lockBuddyHandler == NULL) || (!lockBuddyHandler->exists())) {
00730 throw ResourceNotDeclaredException(lockBuddy.toAscii().data());
00731 }
00732 h->shareLockWith(lockBuddyHandler);
00733 }
00734 ResourcesMutexesLocker resourceLocker(this, h);
00735
00736
00737 collectionLocker.unlock();
00738
00739
00740
00741 h->set(resource);
00742 }
00743
00765 template<class T>
00766 T* getResource(QString name, bool* resourceExists = NULL)
00767 {
00768 if ((m_lockAcquired == 0) && ((!m_beingNotified) || (m_notifiedResourceHandler->name() != name))) {
00769 throw WrongResourceLockStatusForOperation("getResource", false);
00770 }
00771
00772 if (!m_usableResources.contains(name)) {
00773 throw ResourceNotUsableException(name.toAscii().data());
00774 }
00775
00776
00777 if (resourceExists != NULL) {
00778
00779 *resourceExists = true;
00780 }
00781 ResourceHandler* h = m_usableResources[name];
00782 if (!h->exists()) {
00783 if (resourceExists != NULL) {
00784 *resourceExists = false;
00785 } else {
00786 throw ResourceNotDeclaredException(name.toAscii().data());
00787 }
00788 }
00789
00790 T* resource = h->get<T>();
00791 if (resource == NULL) {
00792 throw ResourceTypeMismatchException(name.toAscii().data(), typeid(T).name());
00793 }
00794
00795 return resource;
00796 }
00797
00806 void deleteResource(QString name);
00807
00818 bool hasResource(QString name) const;
00819
00828 bool usedResourcesExist(QStringList* nonExistingResources = NULL) const;
00829
00830 protected:
00846 virtual void resourceChanged(QString name, ResourceChangeType changeType);
00847
00859 template<class T>
00860 T* getResource()
00861 {
00862 if (!m_beingNotified) {
00863 if (m_lockAcquired > 0) {
00864 return NULL;
00865 } else {
00866 throw WrongResourceLockStatusForOperation("getResource (inside resourceChanged())", false);
00867 }
00868 }
00869
00870 if (!m_notifiedResourceHandler->exists()) {
00871
00872 throw ResourceNotDeclaredException(m_notifiedResourceHandler->name().toAscii().data());
00873 }
00874 T* resource = m_notifiedResourceHandler->get<T>();
00875 if (resource == NULL) {
00876 throw ResourceTypeMismatchException(m_notifiedResourceHandler->name().toAscii().data(), typeid(T).name());
00877 }
00878
00879 return resource;
00880 }
00881
00882 private:
00889 void lockAll();
00890
00897 void unlockAll();
00898
00908 virtual void notifyResourceChange(ResourceHandler* resource, ResourceChangeType changeType);
00909
00914 void removeAllNotifications();
00915
00919 void forceBeingNotified();
00920
00929 void lockResources(const QList<ResourceHandler*>& resources);
00930
00939 void unlockResources(const QList<ResourceHandler*>& resources);
00940
00950 class ResourcesMutexesLocker
00951 {
00952 public:
00960 ResourcesMutexesLocker(ConcurrentResourcesUser *resourcesUser, const QList<ResourceHandler *>& resources) :
00961 m_resourcesUser(resourcesUser),
00962 m_resources(resources)
00963 {
00964 m_resourcesUser->lockResources(m_resources);
00965 }
00966
00974 ResourcesMutexesLocker(ConcurrentResourcesUser *resourcesUser, ResourceHandler* resource) :
00975 m_resourcesUser(resourcesUser),
00976 m_resources(QList<ResourceHandler *>() << resource)
00977 {
00978 m_resourcesUser->lockResources(m_resources);
00979 }
00980
00987 ~ResourcesMutexesLocker()
00988 {
00989 m_resourcesUser->unlockResources(m_resources);
00990 }
00991
00992 private:
00996 ConcurrentResourcesUser *const m_resourcesUser;
00997
01001 QList<ResourceHandler *> m_resources;
01002 };
01003
01011 unsigned int m_lockAcquired;
01012
01019 bool m_beingNotified;
01020
01027 ResourceHandler* m_notifiedResourceHandler;
01028
01032 QMap<QString, ResourceHandler*> m_usableResources;
01033
01037 ConcurrentResourcesUser(const ConcurrentResourcesUser& other);
01038
01042 ConcurrentResourcesUser& operator=(const ConcurrentResourcesUser& other);
01043
01048 friend class ResourcesLocker;
01049 };
01050
01083 class FARSA_CONF_API ResourcesLocker
01084 {
01085 public:
01095 ResourcesLocker(ConcurrentResourcesUser *resourcesUser, bool acquireLock = true);
01096
01102 ~ResourcesLocker();
01103
01109 void lock();
01110
01116 void unlock();
01117
01118 private:
01122 ConcurrentResourcesUser *const m_resourcesUser;
01123
01158 bool m_lockedByUs;
01159 };
01160
01161 }
01162
01163 #endif