configuration/include/resource.h

00001 /********************************************************************************
00002  *  FARSA Experiments Library                                                   *
00003  *  Copyright (C) 2007-2012                                                     *
00004  *  Gianluca Massera <emmegian@yahoo.it>                                        *
00005  *  Stefano Nolfi <stefano.nolfi@istc.cnr.it>                                   *
00006  *  Onofrio Gigliotta <onofrio.gigliotta@istc.cnr.it>                           *
00007  *  Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it>                         *
00008  *                                                                              *
00009  *  This program is free software; you can redistribute it and/or modify        *
00010  *  it under the terms of the GNU General Public License as published by        *
00011  *  the Free Software Foundation; either version 2 of the License, or           *
00012  *  (at your option) any later version.                                         *
00013  *                                                                              *
00014  *  This program is distributed in the hope that it will be useful,             *
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00017  *  GNU General Public License for more details.                                *
00018  *                                                                              *
00019  *  You should have received a copy of the GNU General Public License           *
00020  *  along with this program; if not, write to the Free Software                 *
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00022  ********************************************************************************/
00023 
00024 #ifndef RESOURCE_H
00025 #define RESOURCE_H
00026 
00027 #include "parametersettable.h"
00028 #include "configurationconfig.h"
00029 #include "configurationexceptions.h"
00030 #include <QMap>
00031 #include <QString>
00032 #include <QMutex>
00033 #include <QSet>
00034 
00035 class QObject;
00036 
00037 namespace farsa {
00038 
00039 class ResourceHandler;
00040 class ResourceCollection;
00041 class ResourcesUser;
00042 
00056 class FARSA_CONF_TEMPLATE Resource
00057 {
00058 public:
00062     enum ResourceChangeType {
00063         Created,
00064         Modified,
00065         Deleted
00066     };
00067 
00068 public:
00072     virtual ~Resource()
00073     {
00074     }
00075 };
00076 
00084 class FARSA_CONF_API ResourceMutexHolder
00085 {
00086 public:
00090     ResourceMutexHolder();
00091 
00098     ResourceMutexHolder(const ResourceMutexHolder& other) throw();
00099 
00106     ResourceMutexHolder& operator=(const ResourceMutexHolder& other) throw();
00107 
00111     ~ResourceMutexHolder() throw();
00112 
00121     bool operator==(const ResourceMutexHolder& other) const throw()
00122     {
00123         return (m_shared == other.m_shared);
00124     }
00125 
00131     QMutex& operator*() const throw()
00132     {
00133         return m_shared->resourceLock;
00134     }
00135 
00142     QMutex* operator->() const throw()
00143     {
00144         return &(m_shared->resourceLock);
00145     }
00146 
00147 private:
00152     struct MutexAndRefCounter
00153     {
00157         MutexAndRefCounter() :
00158             resourceLock(QMutex::Recursive),
00159             referenceCounter(0)
00160         {
00161         }
00162 
00166         QMutex resourceLock;
00167 
00171         int referenceCounter;
00172     };
00173 
00177     MutexAndRefCounter* m_shared;
00178 };
00179 
00189 class FARSA_CONF_API ResourceHandler
00190 {
00191 public:
00199     ResourceHandler(QString name);
00200 
00204     ~ResourceHandler();
00205 
00211     QString name() const
00212     {
00213         return m_name;
00214     }
00215 
00225     void shareLockWith(ResourceHandler* other);
00226 
00233     void set(int* res);
00234 
00241     void set(float* res);
00242 
00249     void set(double* res);
00250 
00257     void set(bool* res);
00258 
00265     void set(Resource* res);
00266 
00273     void set(ParameterSettable* res);
00274 
00281     void set(QObject* res);
00282 
00288     void unset();
00289 
00297     template<class T>
00298     T* get() const
00299     {
00300         switch(m_type) {
00301             case t_resource:
00302                 return dynamic_cast<T*>(m_pointers.res);
00303             case t_paramSettable:
00304                 return dynamic_cast<T*>(m_pointers.par);
00305             case t_qObject:
00306                 return dynamic_cast<T*>(m_pointers.obj);
00307             default:
00308                 return NULL;
00309         }
00310     }
00311 
00317     QMutex& getLock()
00318     {
00319         return *m_lock;
00320     }
00321 
00327     bool exists() const
00328     {
00329         return (m_type != t_nonExistent);
00330     }
00331 
00337     void addNotifee(ResourcesUser *n);
00338 
00345     void removeNotifee(ResourcesUser *n);
00346 
00353     bool isNotifee(ResourcesUser *n) const;
00354 
00355 private:
00361     void notifyAll(Resource::ResourceChangeType changeType);
00362 
00366     const QString m_name;
00367 
00373     enum Type
00374     {
00375         t_resource,
00376         t_paramSettable,
00377         t_qObject,
00378         t_int,
00379         t_float,
00380         t_double,
00381         t_bool,
00382         t_nonExistent
00383     } m_type;
00384 
00388     union Pointers
00389     {
00390         Resource* res;
00391         ParameterSettable* par;
00392         QObject* obj;
00393         int* intp;
00394         float* floatp;
00395         double* doublep;
00396         bool* boolp;
00397     } m_pointers;
00398 
00405     ResourceMutexHolder m_lock;
00406 
00411     QSet<ResourcesUser *> m_notifees;
00412 
00416     ResourceHandler(const ResourceHandler&);
00417 
00421     ResourceHandler& operator=(const ResourceHandler&);
00422 };
00423 
00424 template<>
00425 inline int* ResourceHandler::get<int>() const
00426 {
00427     if (m_type == t_int) {
00428         return m_pointers.intp;
00429     } else {
00430         return NULL;
00431     }
00432 }
00433 
00434 template<>
00435 inline float* ResourceHandler::get<float>() const
00436 {
00437     if (m_type == t_float) {
00438         return m_pointers.floatp;
00439     } else {
00440         return NULL;
00441     }
00442 }
00443 
00444 template<>
00445 inline double* ResourceHandler::get<double>() const
00446 {
00447     if (m_type == t_double) {
00448         return m_pointers.doublep;
00449     } else {
00450         return NULL;
00451     }
00452 }
00453 
00454 template<>
00455 inline bool* ResourceHandler::get<bool>() const
00456 {
00457     if (m_type == t_bool) {
00458         return m_pointers.boolp;
00459     } else {
00460         return NULL;
00461     }
00462 }
00463 
00464 
00473 class FARSA_CONF_API ResourceCollection
00474 {
00475 public:
00479     ResourceCollection();
00480 
00484     ~ResourceCollection();
00485 
00491     QMutex& getLock()
00492     {
00493         return m_lock;
00494     }
00495 
00501     QWaitCondition& getWaitCondition()
00502     {
00503         return m_waitCondition;
00504     }
00505 
00511     int incrementReferenceCounter() throw()
00512     {
00513         return ++m_referenceCounter;
00514     }
00515 
00521     int decrementReferenceCounter() throw()
00522     {
00523         return --m_referenceCounter;
00524     }
00525 
00531     int getReferenceCounter() throw()
00532     {
00533         return m_referenceCounter;
00534     }
00535 
00546     ResourceHandler* getResource(QString name, bool create = false);
00547 
00555     bool hasResource(QString name) const
00556     {
00557         return (m_resources.contains(name) && m_resources[name]->exists());
00558     }
00559 
00560 private:
00566     QMap<QString, ResourceHandler*> m_resources;
00567 
00574     QMutex m_lock;
00575 
00585     QWaitCondition m_waitCondition;
00586 
00590     int m_referenceCounter;
00591 
00595     ResourceCollection(const ResourceCollection&);
00596 
00600     ResourceCollection& operator=(const ResourceCollection&);
00601 };
00602 
00612 class FARSA_CONF_API ResourceCollectionHolder
00613 {
00614 public:
00618     ResourceCollectionHolder();
00619 
00627     ResourceCollectionHolder(const ResourceCollectionHolder& other) throw();
00628 
00637     ResourceCollectionHolder& operator=(const ResourceCollectionHolder& other) throw();
00638 
00642     ~ResourceCollectionHolder() throw();
00643 
00650     void setUseLock(bool useLock) throw()
00651     {
00652         m_useLocks = useLock;
00653     }
00654 
00663     bool operator==(const ResourceCollectionHolder& other) const throw()
00664     {
00665         return (m_resourceCollection == other.m_resourceCollection);
00666     }
00667 
00673     ResourceCollection& operator*() const throw()
00674     {
00675         return *m_resourceCollection;
00676     }
00677 
00684     ResourceCollection* operator->() const throw()
00685     {
00686         return m_resourceCollection;
00687     }
00688 
00689 private:
00693     ResourceCollection* m_resourceCollection;
00694 
00699     bool m_useLocks;
00700 };
00701 
00702 } // end namespace farsa
00703 
00704 #endif