configuration/src/resource.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2008 by Tomassino Ferrauto                              *
00003  *   t_ferrauto@yahoo.it                                                   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00021 #include "resource.h"
00022 #include "resourcesuser.h"
00023 #include <memory>
00024 
00025 namespace farsa {
00026 
00027 ResourceMutexHolder::ResourceMutexHolder() :
00028     m_shared(NULL)
00029 {
00030     // Creating an instance of ResourceCollection in an exception-safe way
00031     m_shared = new MutexAndRefCounter();
00032     m_shared->referenceCounter++;
00033 }
00034 
00035 ResourceMutexHolder::ResourceMutexHolder(const ResourceMutexHolder& other) throw() :
00036     m_shared(other.m_shared)
00037 {
00038     m_shared->referenceCounter++;
00039 }
00040 
00041 ResourceMutexHolder& ResourceMutexHolder::operator=(const ResourceMutexHolder& other) throw()
00042 {
00043     if (&other == this) {
00044         return *this;
00045     }
00046 
00047     // Sharing with other and decrementing our old one (possibly also deleting)
00048     m_shared->referenceCounter--;
00049     if (m_shared->referenceCounter == 0) {
00050         delete m_shared;
00051     }
00052 
00053     m_shared = other.m_shared;
00054     m_shared->referenceCounter++;
00055 
00056     return *this;
00057 }
00058 
00059 ResourceMutexHolder::~ResourceMutexHolder() throw()
00060 {
00061     // Decrementing the reference counter and possibly deleting the mutex
00062     m_shared->referenceCounter--;
00063     if (m_shared->referenceCounter == 0) {
00064         delete m_shared;
00065     }
00066 }
00067 
00068 ResourceHandler::ResourceHandler(QString name) :
00069     m_name(name),
00070     m_type(t_nonExistent),
00071     m_lock(),
00072     m_notifees()
00073 {
00074 }
00075 
00076 ResourceHandler::~ResourceHandler()
00077 {
00078 }
00079 
00080 void ResourceHandler::shareLockWith(ResourceHandler* other)
00081 {
00082     m_lock = other->m_lock;
00083 }
00084 
00085 void ResourceHandler::set(int* res)
00086 {
00087     const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
00088     m_type = t_int;
00089     m_pointers.intp = res;
00090     notifyAll(changeType);
00091 }
00092 
00093 void ResourceHandler::set(float* res)
00094 {
00095     const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
00096     m_type = t_float;
00097     m_pointers.floatp = res;
00098     notifyAll(changeType);
00099 }
00100 
00101 void ResourceHandler::set(double* res)
00102 {
00103     const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
00104     m_type = t_double;
00105     m_pointers.doublep = res;
00106     notifyAll(changeType);
00107 }
00108 
00109 void ResourceHandler::set(bool* res)
00110 {
00111     const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
00112     m_type = t_bool;
00113     m_pointers.boolp = res;
00114     notifyAll(changeType);
00115 }
00116 
00117 void ResourceHandler::set(Resource* res)
00118 {
00119     const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
00120     m_type = t_resource;
00121     m_pointers.res = res;
00122     notifyAll(changeType);
00123 }
00124 
00125 void ResourceHandler::set(ParameterSettable* res)
00126 {
00127     const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
00128     m_type = t_paramSettable;
00129     m_pointers.par = res;
00130     notifyAll(changeType);
00131 }
00132 
00133 void ResourceHandler::set(QObject* res)
00134 {
00135     const Resource::ResourceChangeType changeType = (m_type == t_nonExistent) ? Resource::Created : Resource::Modified;
00136     m_type = t_qObject;
00137     m_pointers.obj = res;
00138     notifyAll(changeType);
00139 }
00140 
00141 void ResourceHandler::unset()
00142 {
00143     m_type = t_nonExistent;
00144     // Note: if getResource is called in the callback, an exception will be thrown!
00145     notifyAll(Resource::Deleted);
00146 }
00147 
00148 void ResourceHandler::addNotifee(ResourcesUser *n)
00149 {
00150     m_notifees.insert(n);
00151 }
00152 
00153 void ResourceHandler::removeNotifee(ResourcesUser *n)
00154 {
00155     m_notifees.remove(n);
00156 }
00157 
00158 bool ResourceHandler::isNotifee(ResourcesUser *n) const
00159 {
00160     return m_notifees.contains(n);
00161 }
00162 
00163 void ResourceHandler::notifyAll(Resource::ResourceChangeType changeType)
00164 {
00165     foreach (ResourcesUser *n, m_notifees) {
00166         n->notifyResourceChange(this, changeType);
00167     }
00168 }
00169 
00170 ResourceCollection::ResourceCollection() :
00171     m_resources(),
00172     m_lock(QMutex::NonRecursive),
00173     m_referenceCounter(0)
00174 {
00175 }
00176 
00177 ResourceCollection::~ResourceCollection()
00178 {
00179     // Deleting all resources still in the map
00180     foreach (ResourceHandler *r, m_resources) {
00181         delete r;
00182     }
00183 }
00184 
00185 ResourceHandler* ResourceCollection::getResource(QString name, bool create)
00186 {
00187     ResourceHandler *h = NULL;
00188 
00189     if (!m_resources.contains(name)) {
00190         if (create) {
00191             // Adding an non-existant resource (in an exception-safe way)
00192             std::auto_ptr<ResourceHandler> hp(new ResourceHandler(name));
00193             m_resources[name] = hp.get();
00194             h = hp.release();
00195         }
00196     } else {
00197         h = m_resources[name];
00198     }
00199 
00200     return h;
00201 }
00202 
00203 ResourceCollectionHolder::ResourceCollectionHolder() :
00204     m_resourceCollection(NULL),
00205     m_useLocks(false)
00206 {
00207     // Creating an instance of ResourceCollection in an exception-safe way
00208     std::auto_ptr<ResourceCollection> c(new ResourceCollection());
00209     c->incrementReferenceCounter();
00210     m_resourceCollection = c.release();
00211 }
00212 
00213 ResourceCollectionHolder::ResourceCollectionHolder(const ResourceCollectionHolder& other) throw() :
00214     m_resourceCollection(other.m_resourceCollection),
00215     m_useLocks(false)
00216 {
00217     if (other.m_useLocks) {
00218         m_resourceCollection->getLock().lock();
00219     }
00220 
00221     // Incrementing the counter of the ResourceCollection object
00222     m_resourceCollection->incrementReferenceCounter();
00223 
00224     if (other.m_useLocks) {
00225         m_resourceCollection->getLock().unlock();
00226     }
00227 }
00228 
00229 ResourceCollectionHolder& ResourceCollectionHolder::operator=(const ResourceCollectionHolder& other) throw()
00230 {
00231     // Comparing for equality of objects (not pointers) because we must not do anything
00232     // if this and other already point to the same ResourceCollection object
00233     if (other == *this) {
00234         return *this;
00235     }
00236 
00237     // Acquiring locks if we have to
00238     if (m_useLocks) {
00239         m_resourceCollection->getLock().lock();
00240         other.m_resourceCollection->getLock().lock();
00241     }
00242 
00243     // First of all releasing the current resource manager (and destroying it if we have to)
00244     const int refCounter = m_resourceCollection->decrementReferenceCounter();
00245     if (m_useLocks) {
00246         m_resourceCollection->getLock().unlock();
00247     }
00248     if (refCounter == 0) {
00249         delete m_resourceCollection;
00250     }
00251 
00252     // Now we can use the ResourceCollection of other
00253     m_resourceCollection = other.m_resourceCollection;
00254     m_resourceCollection->incrementReferenceCounter();
00255 
00256     if (m_useLocks) {
00257         // m_resourceCollection is now the same as other.m_resourceCollection, so here
00258         // we are unlocking the mutex on the new collection
00259         m_resourceCollection->getLock().unlock();
00260     }
00261 
00262     return *this;
00263 }
00264 
00265 ResourceCollectionHolder::~ResourceCollectionHolder() throw()
00266 {
00267     if (m_useLocks) {
00268         m_resourceCollection->getLock().lock();
00269     }
00270 
00271     const int refCounter = m_resourceCollection->decrementReferenceCounter();
00272 
00273     if (m_useLocks) {
00274         m_resourceCollection->getLock().unlock();
00275     }
00276 
00277     if (refCounter == 0) {
00278         delete m_resourceCollection;
00279     }
00280 }
00281 
00282 } // end namspace farsa