Commit dc9edba1 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[ADD] - added class for generic thread safe access to arbitrary objects

parent 5e782d3e
......@@ -22,61 +22,5 @@
//
//---------------------------------------------------------------------------
#ifndef WSTLCONTAINER_H
#define WSTLCONTAINER_H
#include <boost/thread.hpp>
/**
* Wrapper around the STL sequence container providing thread safe iterator access.
*/
template < typename T >
class WSTLContainer
{
public:
/**
* Default constructor.
*/
WSTLContainer();
/**
* Destructor.
*/
virtual ~WSTLContainer();
protected:
/**
* The lock to ensure thread safe access.
*/
boost::shared_mutex m_lock;
/**
* The write lock used for write access.
*/
boost::unique_lock< boost::shared_mutex > m_wLock;
/**
* The read lock used for write access.
*/
boost::shared_lock< boost::shared_mutex > m_rLock;
private:
};
template < typename T >
WSTLContainer< T >::WSTLContainer()
{
// init members
}
template < typename T >
WSTLContainer< T >::~WSTLContainer()
{
// clean up
}
#endif // WSTLCONTAINER_H
#include "WSharedObject.h"
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WSHAREDOBJECT_H
#define WSHAREDOBJECT_H
#include <boost/thread.hpp>
/**
* Wrapper around an object/type for thread safe sharing of objects among multiple threads.
*/
template < typename T >
class WSharedObject
{
public:
/**
* Default constructor.
*/
WSharedObject();
/**
* Destructor.
*/
virtual ~WSharedObject();
/**
* Class allowing thread-safe access to an object. It provides some convenience methods to read and write lock the access.
*/
class WSharedObjectAccess
{
public:
/**
* Constructor. It uses the specified mutex which is shared among all access objects of the same WSharedObject.
*
* \param mutex the mutex used to lock the access.
*/
explicit WSharedObjectAccess( T& object, boost::shared_ptr< boost::shared_mutex > mutex );
/**
* Desctructor.
*/
~WSharedObjectAccess();
/**
* Gets the contained, and protected object.
*
* \return the contained object
*/
T& get();
/**
* Acquires a read lock to the protected object for easy access. Use this EVERYTIME you want to read from the object. Use
* endRead() to free the lock.
*/
void beginRead();
/**
* Frees the lock to the object. If you do not free the lock, no write access will be granted in the future. To nobody!
* So always free the lock.
*/
void endRead();
/**
* Acquires a write lock to the object
*/
void beginWrite();
/**
* Frees the lock to the object. If you do not free the lock, no read or write access will be granted in the future. To nobody!
* So always free the lock.
*/
void endWrite();
protected:
/**
* The write lock. Used by beginWrite and endWrite.
*/
boost::unique_lock< boost::shared_mutex > m_writeLock;
/**
* The write lock. Used by beginWrite and endWrite.
*/
boost::shared_lock< boost::shared_mutex > m_readLock;
/**
* The lock to ensure thread safe access. It is the lock provided by WSharedObject.
*/
boost::shared_ptr< boost::shared_mutex > m_lock;
/**
* the object protected.
*/
T& m_object;
};
/**
* Use a shared_ptr since the shared and unique locks from boost are non-copyable.
*/
typedef boost::shared_ptr< WSharedObjectAccess > WSharedAccess;
/**
* This method distributes access objects. These objects are able to read/write lock the object and grant access to it, in
* a thread-safe manner.
*
* \return the access object which allows thread safe access to the object.
*/
WSharedAccess getAccessObject();
protected:
/**
* The object wrapped by this class.
*/
T m_object;
/**
* The lock to ensure thread safe access.
*/
boost::shared_ptr< boost::shared_mutex > m_lock;
private:
};
template < typename T >
WSharedObject< T >::WSharedObject():
m_lock( new boost::shared_mutex )
{
// init members
}
template < typename T >
WSharedObject< T >::~WSharedObject()
{
// clean up
}
template < typename T >
typename WSharedObject< T >::WSharedAccess WSharedObject< T >::getAccessObject()
{
return WSharedObject< T >::WSharedAccess( new WSharedObject< T>::WSharedObjectAccess( m_object, m_lock ) );
}
template < typename T >
WSharedObject< T >::WSharedObjectAccess::WSharedObjectAccess( T& object, boost::shared_ptr< boost::shared_mutex > mutex ):
m_lock( mutex ),
m_object( object )
{
}
template < typename T >
WSharedObject< T >::WSharedObjectAccess::~WSharedObjectAccess()
{
// this shouldn't be necessary as the locks automatically unlock if the get destroyed
// m_readLock.unlock();
// m_writeLock.unlock();
}
template < typename T >
void WSharedObject< T >::WSharedObjectAccess::beginRead()
{
m_readLock = boost::shared_lock< boost::shared_mutex >( *m_lock );
}
template < typename T >
void WSharedObject< T >::WSharedObjectAccess::endRead()
{
m_readLock.unlock();
}
template < typename T >
void WSharedObject< T >::WSharedObjectAccess::beginWrite()
{
m_writeLock = boost::unique_lock< boost::shared_mutex >( *m_lock );
}
template < typename T >
void WSharedObject< T >::WSharedObjectAccess::endWrite()
{
m_writeLock.unlock();
}
template < typename T >
T& WSharedObject< T >::WSharedObjectAccess::get()
{
return m_object;
}
#endif // WSHAREDOBJECT_H
......@@ -29,15 +29,25 @@
#include "WSubject.h"
#include "exceptions/WDHNoSuchDataSet.h"
WDataHandler::WDataHandler()
WDataHandler::WDataHandler():
m_subjects(),
m_subjectAccess( m_subjects.getAccessObject() )
{
}
void WDataHandler::addSubject( boost::shared_ptr< WSubject > newSubject )
void WDataHandler::addSubject( boost::shared_ptr< WSubject > subject )
{
// add the subject to the list ( ensure mutual exclusive write )
boost::unique_lock< boost::shared_mutex > lock = boost::unique_lock< boost::shared_mutex >( m_subjectsLock );
//m_subjects.push_back( newSubject );
lock.unlock();
// simply add the new subject
m_subjectAccess->beginWrite();
m_subjectAccess->get().insert( subject );
m_subjectAccess->endWrite();
}
void WDataHandler::removeSubject( boost::shared_ptr< WSubject > subject )
{
// simply add the new subject
m_subjectAccess->beginWrite();
m_subjectAccess->get().erase( subject );
m_subjectAccess->endWrite();
}
......@@ -26,13 +26,13 @@
#define WDATAHANDLER_H
#include <string>
#include <vector>
#include <set>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "../common/WSTLContainer.h"
#include "../common/WSharedObject.h"
#include "WDataSet.h"
......@@ -45,7 +45,7 @@ class WSubject;
*
* \ingroup dataHandler
*/
class WDataHandler : public boost::enable_shared_from_this< WDataHandler >
class WDataHandler
{
/**
* Only UnitTests may be friends.
......@@ -54,6 +54,11 @@ friend class WDataHandlerTest;
public:
/**
* For shortening: a type defining a shared vector of WSubject pointers.
*/
typedef std::set< boost::shared_ptr< WSubject > > SubjectContainerType;
/**
* Empty standard constructor.
*/
......@@ -62,16 +67,28 @@ public:
/**
* Insert a new subject referenced by a pointer.
*
* \param newSubject a pointer to the subject that will be added
* \param subject a pointer to the subject that will be added
*/
void addSubject( boost::shared_ptr< WSubject > subject );
/**
* Removes the specified subject if it is in the set.
*
* \param subject the subject to remove.
*/
void addSubject( boost::shared_ptr< WSubject > newSubject );
void removeSubject( boost::shared_ptr< WSubject > subject );
protected:
/**
* A container for all WSubjects.
*/
WSTLContainer< std::vector< boost::shared_ptr< WSubject > > > m_subjects;
WSharedObject< SubjectContainerType > m_subjects;
/**
* The access object used for thread safe access.
*/
WSharedObject< SubjectContainerType >::WSharedAccess m_subjectAccess;
/**
* The lock used for avoiding mutual write to the subjects list
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment