#ifndef PERA_SOFTWARE_SOLUTIONS___THREAD_RESOURCE_LOCK_HPP
#define PERA_SOFTWARE_SOLUTIONS___THREAD_RESOURCE_LOCK_HPP

// Copyright (C) 2010 by P. Most, PERA Software Solutions GmbH under the GNU LGPL

#include <boost/thread/recursive_mutex.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/bind.hpp>

namespace PERASoftwareSolutions
{

template < typename Resource, typename Mutex = boost::recursive_mutex >
	class ThreadResourceLock : private boost::noncopyable {
		public:
			typedef boost::shared_ptr< Resource > Pointer;
			typedef boost::shared_ptr< const Resource > ConstPointer;

			Pointer lock( void )
			{
				my_mutex.lock();

				void ( ThreadResourceLock< Resource >::*unlockMethod )( Resource * ) =
					&ThreadResourceLock< Resource >::unlock;
				Pointer pointer( &my_resource, boost::bind( unlockMethod, this, _1 ));

				return ( pointer );
			}

			void unlock( Resource *resource )
			{
				BOOST_ASSERT( &my_resource == resource );

				my_mutex.unlock();
			}
		
			ConstPointer lock( void ) const
			{
				my_mutex.lock();

				void ( ThreadResourceLock< Resource >::*unlockMethod )( const Resource * ) const =
					&ThreadResourceLock< Resource >::unlock;
				ConstPointer pointer( &my_resource, boost::bind( unlockMethod, this, _1 ));

				return ( pointer );
			}

			void unlock( const Resource *resource ) const
			{
				BOOST_ASSERT( &my_resource == resource );

				my_mutex.unlock();
			}

		private:
			mutable Mutex my_mutex;
			Resource my_resource;
	};

}

#endif


