A class to access/declare resources in a thread-safe way. More...

Inheritance diagram for ConcurrentResourcesUser:

Public Member Functions

 ConcurrentResourcesUser ()
 Constructor. More...
 
virtual ~ConcurrentResourcesUser ()
 Destructor. More...
 
void addUsableResource (QString resource)
 Adds a new resource to the list of resources that will be used. More...
 
void addUsableResources (QStringList resources)
 Adds new resources to the list of resources that will be used. More...
 
template<class T >
void declareResource (QString name, T *resource, QString lockBuddy="")
 Declares the name for a resource. More...
 
void deleteResource (QString name)
 Deletes the resource with the specified name. More...
 
template<class T >
T * getResource (QString name, bool *resourceExists=NULL)
 Returns a pointer to the resource declared with the specified name. More...
 
bool hasResource (QString name) const
 Returns true if a resource with name specified has been declared. More...
 
void removeAllUsableResources ()
 Removes all resources from the list of resources that will be used. More...
 
void removeUsableResource (QString resource)
 Removes the resource from the list of resources that will be used. More...
 
void removeUsableResources (QStringList resources)
 Removes resources from the list of resources that will be used. More...
 
virtual void shareResourcesWith (ResourcesUser *buddy)
 Shares resources with the provided instance of ResourcesUser. More...
 
void usableResources (QStringList resources)
 Defines the list of resources that will be used. More...
 
bool usedResourcesExist (QStringList *nonExistingResources=NULL) const
 Returns true if all the resources we use exist. More...
 
- Public Member Functions inherited from Resource
virtual ~Resource ()
 Destructor. More...
 

Protected Member Functions

template<class T >
T * getResource ()
 Returns a pointer to the resource whose change we have been notified of. More...
 
virtual void resourceChanged (QString name, ResourceChangeType changeType)
 The function called when a resource you use is changed. More...
 
- Protected Member Functions inherited from ResourcesUser
 ResourcesUser ()
 Constructor. More...
 
 ResourcesUser (const ResourcesUser &other) throw ()
 Copy constructor. More...
 
virtual ~ResourcesUser ()
 Constructor. More...
 
ResourcesUseroperator= (const ResourcesUser &other) throw ()
 Copy operator. More...
 

Friends

class ResourcesLocker
 The ResourcesLocker class is friend to access the lockAll() and unlockAll() function. More...
 

Additional Inherited Members

- Public Types inherited from ResourcesUser
typedef Resource::ResourceChangeType ResourceChangeType
 The change that happened to a resource. More...
 
- Public Types inherited from Resource
enum  ResourceChangeType { Created, Modified, Deleted }
 The change that happened to a resource. More...
 
- Protected Attributes inherited from ResourcesUser
ResourceCollectionHolder m_resources
 The object holding the shared resources. More...
 

Detailed Description

A class to access/declare resources in a thread-safe way.

A resource is a pointer to a variable of a primitive type or to an object that is associated to a resource name. The resource name is a string that can be used to access the resource. If you want an instance of a class to be used as a resource the class must be a subclass (direct or indirect) of one of the following classes:

When you declare a resource, you give it a name and specify the pointer to an object/variable of a primitive type, using the declareResource() function. When you need to get the resource (i.e the pointer), you can access it calling the getResource() method and passing the resource name. Once you declare a resource, you can change the pointer over time, simply re-declaring a resource with the same resource name. If you instead want to delete a resource, use deleteResource(). An instance of this class does never frees memory for the resource, so this must be managed outside (e.g. by the actual owner of the resource). Accessing resources is thread-safe. This means that you can get a lock on the resources you use to be sure no one else is using them at the same time. It is also possible to be notified when a resource changes (i.e. when a new resource with the same name is declared). More details will be given below.

Before being able to use resources, you have to declare which ones you will use. You can declare the list of resources you need to use with the function usableResources(), passing as argument the list of resource names. You can change completely the list of resources you will be using calling the usableResources() function again or you can add/remove a resource from the list using the functions addUsableResource(), addUsableResources(), removeUsableResource(), removeUsableResources() or removeAllUsableResources(). Note that is possible to pass non-existent resource names to those functions: you will then be able to get the associated resource once it is created.

To actually get the resource you can use the getResource() function. You must, however, acquire the lock on resources before using that function. This way you will be sure to be the only one using that resource. To acquire the lock you have to use the ResourcesLocker class. We do not provide explicit functions to lock and unlock because they would easily lead to code that is not exception safe. In fact if you acquire the lock and then, before releasing it, an exception gets thrown, you won't be able to unlock resources leading to unexpected behaviours. If you instead use an instance of ResourcesLocker, when that instance goes out of scope, its destructor will take care of releasing the lock (i.e. ResourcesLocker implements RAII for resource locks). Of course the ResourcesLocker class has also methods to manage the lock/unlock status of resource (see that class documentation for more information). You should acquire the lock even if you don't plan to use getResource(), for example because you have a direct pointer to the resource. This way you are sure to be the only one to use the resource.

It is possible to share the lock among resources. For example if two different resources A and B act on the same shared data, it is advisable to acquire the lock on both even if a ConcurrentResourcesUser object only declares to need one of them. Instead of forcing a resource user to explicitly acquire the lock on all resources that have to be locked together, it is possible to share the same lock among different resources. To do that you need to specify as the third parameter to declareResource the name of the resource with which the lock of the resource being declared will be shared. This is transitive, so if resources A and B already share the same lock and you declare a resource C to share the lock with A, then A, B and C will all share the same lock.

It is important to know what you can and cannot do while holding the lock for resources, as doing something not allowed will raise an exception. Here is the list of allowed and disallowed calls when holding or not locks:

Using a single instance of this class is not very useful. You should not share it among different objects (because they could need different resources and also because functions of this class are not thread-safe, only accessing resources is) and using it inside a single class could be pointless. The purpouse of the resource mechanism is to allow objects to declare certain resources at runtime and then let other objects use it without the need to know who is the owner of the resource. To be able to do this you have to associate different instances of this class creating a groups of interconnected ResourcesUser objects sharing the same set of resources. Each instance can then declare resources or use a subset of them. To be able to do this you have to use the shareResourcesWith() function. This function takes a pointer to another ResourcesUser class with which resources will be shared. Be aware that when you call shareResourcesWith() all resources declared by the calling instance of ResourcesUser will be lost, that is they will no longer be accessible by that object (as stated above, their memory will not be freed in any case). The list of resources to use, however, is not modified, so the object will be able to access resources with the same name as before (if they exists in the new set). After the call to shareResourcesWith() the calling object will share all resources with the other ResourcesUser object. The sharing of resources is "transitive", that is if you call shareResourcesWith() to associate object A with another ResourcesUser object B that is already associated with a third objects C, then A, B and C will all share the same resource set. So, for example, if you want a certain number of objects to share resources among them you can simply call the shareResourcesWith() function of all of them passing always the same object as parameter. You can call shareResourcesWith() with a NULL parameter to remove the association of the ResourcesUser instance with other instances. Note that the shareResourcesWith() function is NOT thread safe.

Declaring which resources you will use you have the side effect that you will be notified when those resources change: the resourceChanged() function is called with the resource name and the type of change (whether the resource was Created, Modified or Deleted) as parameters. The default implementation of resourceChanged() does nothing, you have to subclass this class and implement that function to add your own code. During the call to resourceChanged() the resource is locked (only the resource being changed!), so you can access it using getResource(). There is an overloaded version of this function taking no parameters that can be used only inside resourceChanged() and that returns the resource you have been notified the change of. The lock is automatically released when you exit from the resourceChanged() function. The notification mechanism works also for resources that didn't exist when you declared you would use them: resourceChanged() is called the first time they are declared. You will be notified also when a resource is deleted. The removal of a resource doesn't influence the list of resources you are using, so when the resource is re-declared, you will be notified again. When you first declare the resources you will use, a notification is sent for each existing resource. So, for example, if a resource named "A" exists and you call usableResources() declaring you need to use resources "A" and "B", the resourceChanged() function will be called for "A" with changeType set to Created (during the call to usableResources()). The same holds if you remove a resource from the list of resources you use: if the resource exists at the time you remove it from the list of used resource, you will be notified that the resource has been Deleted. If you call shareResourcesWith() to share resources with another resource user, you will be notified for all resources you use, depending on their new status: if a resource existed in the old set and not in the new one, changeType will be Deleted, if it existed in the old set and is also present in the new one, changeType will be Modified, if it didn't exist in the old set but is present in the new one, changeType will be Created.

An important notice about changing a resource: it is possible that objects using a given resource keep a pointer to it because they need to so some cleanup with the old resource before start using the new one. Because of this it is important that when you re-declare a resource, you first call declareResource() with the new istance of the resource and only later eventually delete the old one.

Note
A convenient way of using this class is to have your classes that need to access resources inherit from this one, as in the example above.
Functions of this object are not thread-safe per se. This means that while you can share and use resources concurrently, you must never share ConcurrentResourcesUser objects. Use shareResourcesWith() and share resources, instead.
The notification callback can be called concurrently on different resources. This means that inside the handler you should only access data related to the resource being notified and nothing else.

Definition at line 592 of file resourcesuser.h.

Constructor & Destructor Documentation

Destructor.

Definition at line 204 of file resourcesuser.cpp.

Member Function Documentation

void addUsableResource ( QString  resource)

Adds a new resource to the list of resources that will be used.

Before accessing resources using getResource() you have to declare which resource you will be accessing using this function or usableResources(). This function adds the specified resource to the list of resources that will be used. You can specify a non-existent resource: you will then be able to access them once they are declared

Parameters
resourceThe resource to add to the list of resources that will be used. You can specify non-existent resources.
Note
You cannot use this function while holding the lock to resources

Definition at line 369 of file resourcesuser.cpp.

References ResourceHandler::addNotifee(), ResourceHandler::exists(), ResourceCollection::getLock(), ResourceCollection::getResource(), and ResourcesUser::m_resources.

void addUsableResources ( QStringList  resources)

Adds new resources to the list of resources that will be used.

Before accessing resources using getResource() you have to declare which resource you will be accessing using this function, addUsableResource() or usableResources(). This function adds the specified resources to the list of resources that will be used. You can specify non-existent resources: you will then be able to access them once they are declared

Parameters
resourcesThe list resource to add to the list of resources that will be used. You can specify non-existent resources.
Note
You cannot use this function while holding the lock to resources

Definition at line 397 of file resourcesuser.cpp.

References ResourceHandler::addNotifee(), ResourceHandler::exists(), ResourceCollection::getLock(), ResourceCollection::getResource(), and ResourcesUser::m_resources.

void declareResource ( QString  name,
T *  resource,
QString  lockBuddy = "" 
)
inline

Declares the name for a resource.

This method overwrites any previous declaration with the same name. When you declare a resource you are not automatically declaring you will also use it. You have to explicitly call usableResources() or addUsableResource() if you plan to use the resource you have declared. If you call one of these functions before calling declareResource() you will be notified that the resource is being created (even if it is you who are creating the resource); if you call them after calling declareResource(), you could miss some notifications because another thread could call declareResource() on the same resource after you have called declareResource() but before you call usableResources() or addUsableResource(). In this case you should call getResource() after the calls to declareResource() and usableResources() or addUsableResource() to be sure to have the correct pointer (of course this is not necessary if you are sure to be the only one declaring/using that resource at that time)

Parameters
namethe name of the resource to declare
resourcethe pointer to the object/variable resource
lockBuddythe resource with which the new one will share the lock (see class documentation for more details). If set to the empty string the lock will not be shared. If a resource with name lockBuddy does not exist, an exception is thrown
Note
You cannot use this function while holding the lock to resources

Definition at line 727 of file resourcesuser.h.

References ResourceHandler::exists(), ResourceHandler::set(), and ResourceHandler::shareLockWith().

void deleteResource ( QString  name)

Deletes the resource with the specified name.

Parameters
namethe name of the resource to delete
Note
You cannot use this function while holding the lock to resources
Warning
it will raise an exception if the resource doesn't exist

Definition at line 536 of file resourcesuser.cpp.

References ResourceHandler::exists(), ResourceCollection::getLock(), ResourceCollection::getResource(), ResourcesUser::m_resources, and ResourceHandler::unset().

T* getResource ( QString  name,
bool *  resourceExists = NULL 
)
inline

Returns a pointer to the resource declared with the specified name.

Parameters
namethe name of the resource to return.
resourceExistsif not NULL the pointed boolean variable will be set to true if the resource exists, false otherwise. Moreover if this is not NULL no exception will be thrown if the resource doesn't exsists (NULL will be returned)
Returns
the pointer to the resource if it exists or NULL (see the description of the resourceExists parameter)
Note
You cannot use this function while holding the lock to resources
Warning
it will raise an exception if the type does not correspond to what requested or the resource doesn't exist (but see the description of the resourceExists parameter)
Note
You cannot use this function if the lock on resources is not acquired. The only exception is that you can use this inside resourceChanged() but only for the resource that is notified

Definition at line 777 of file resourcesuser.h.

References ResourceHandler::exists(), and ResourceHandler::get().

T* getResource ( )
inlineprotected

Returns a pointer to the resource whose change we have been notified of.

You can use this function only inside a call to resourceChanged (as a shortcut to get the resource being notified). This is why it is protected.

Returns
the pointer to the resource or NULL if not inside the handler
Warning
it will raise an exception if the type does not correspond to what requested

Definition at line 875 of file resourcesuser.h.

bool hasResource ( QString  name) const

Returns true if a resource with name specified has been declared.

This checks among all resources, even if the resource we are checking has not been declared as usable

Parameters
namethe name of the resource
Returns
true if the resource exists and has been declared; false otherwise

Definition at line 559 of file resourcesuser.cpp.

References ResourceCollection::getLock(), ResourceCollection::hasResource(), and ResourcesUser::m_resources.

void removeAllUsableResources ( )

Removes all resources from the list of resources that will be used.

Note
You cannot use this function while holding the lock to resources

Definition at line 503 of file resourcesuser.cpp.

References ResourceHandler::exists(), ResourceCollection::getLock(), ResourcesUser::m_resources, and ResourceHandler::removeNotifee().

void removeUsableResource ( QString  resource)

Removes the resource from the list of resources that will be used.

Parameters
resourceThe resource that will no longer be used. If the resource wasn't in the list of used resources, this function does nothing
Note
You cannot use this function while holding the lock to resources

Definition at line 434 of file resourcesuser.cpp.

References ResourceCollection::getLock(), ResourceCollection::getResource(), ResourcesUser::m_resources, and ResourceHandler::removeNotifee().

void removeUsableResources ( QStringList  resources)

Removes resources from the list of resources that will be used.

Parameters
resourcesThe list of resources that will no longer be used. If any resource wasn't in the list of used resources, this function does nothing for that resource
Note
You cannot use this function while holding the lock to resources

Definition at line 461 of file resourcesuser.cpp.

References ResourceHandler::exists(), ResourceCollection::getLock(), ResourceCollection::getResource(), ResourcesUser::m_resources, and ResourceHandler::removeNotifee().

void resourceChanged ( QString  name,
ResourceChangeType  changeType 
)
protectedvirtual

The function called when a resource you use is changed.

When this function is called, the lock on the resource is acquired, so you can safely call getResource(). Note however that only the resource being changed is locked, a getResource() on other resources will fail because the lock on them is not acquired. Of course no lock is acquired if the resource was deleted. The default implementation of this function does nothing

Parameters
namethe name of the resource that has changed.
chageTypethe type of change the resource has gone through (whether it was created, modified or deleted)
Note
In multithread applications this function could be called from a thread different from the one this object lives in. In fact this function is called from the thread in which the resource has changed

Definition at line 596 of file resourcesuser.cpp.

void shareResourcesWith ( ResourcesUser buddy)
virtual

Shares resources with the provided instance of ResourcesUser.

The calling instance will lose the possibility to access the resources that were previously declared

Parameters
buddythe instance with which resources will be shared
Note
This is NOT thread safe (both this and the other instance should not be being accessed by other threads). Moreover do not call this while holding the lock to resources

Reimplemented from ResourcesUser.

Definition at line 212 of file resourcesuser.cpp.

References ResourceHandler::addNotifee(), ResourceCollection::getLock(), ResourceCollection::getResource(), ResourcesUser::m_resources, ResourceCollectionHolder::setUseLock(), and ResourcesUser::shareResourcesWith().

void usableResources ( QStringList  resources)

Defines the list of resources that will be used.

Before accessing resources using getResource() you have to declare which resource you will be accessing using this function or addUsableResource(). This function overrides the previous list of resources. You can put in the list non-existent resources: you will then be able to access them once they are declared

Parameters
resourcesThe list of resources you want to access. The old list will be removed. You can specify non-existent resources.
Note
You cannot use this function while holding the lock to resources

Definition at line 334 of file resourcesuser.cpp.

References ResourceHandler::addNotifee(), ResourceHandler::exists(), ResourceCollection::getLock(), ResourceCollection::getResource(), and ResourcesUser::m_resources.

bool usedResourcesExist ( QStringList *  nonExistingResources = NULL) const

Returns true if all the resources we use exist.

Parameters
nonExistingResourcesif not NULL, it will be filled with the names of resource we use but that doesn't exist
Returns
true if all the resources we use exist; false otherwise

Definition at line 570 of file resourcesuser.cpp.

References ResourceHandler::exists(), ResourceCollection::getLock(), ResourcesUser::m_resources, and ResourceHandler::name().

Friends And Related Function Documentation

friend class ResourcesLocker
friend

The ResourcesLocker class is friend to access the lockAll() and unlockAll() function.

Definition at line 1063 of file resourcesuser.h.


The documentation for this class was generated from the following files: