//----------------------------------------------------------------------------
//	Copyright (C) 2002-2008 Humboldt-Universitaet zu Berlin
//
//	This library 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 2.1 of the License, or (at your option) any later version.
//
//	This library 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 this library; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//----------------------------------------------------------------------------
/**	\file res/ResT.h

	\author Ronald Kluth

	\date created at 2008/02/18

	\brief Declaration of odemx::synchronization::ResT and observer

	\note This header file is not meant for inclusion, use
	odemx/synchronization/ResTemplate.h instead.

	\sa ResT.cpp

	\since 2.1
*/

#ifndef ODEMX_RES_T_INCLUDED
#define ODEMX_RES_T_INCLUDED

#include <odemx/synchronization/res/ResTBase.h>

namespace odemx {
namespace synchronization {

// forward declaration
template < typename > class ResTObserver;

/** \class ResT

	\author Ronald Kluth

	\brief ResT is a resource holding objects of type Token

	\note ResT supports Observation
	\note ResT supports Trace

	ResT is a resource for synchronizing Process objects. A process is blocked
	in acquire() if the requested number of tokens is greater than the available
	number of tokens. It is reactivated when enough tokens are released to the resource.
	If multiple process	objects are waiting for reactivation, process-priority and
	FIFO-strategy are used to choose the process.

	\since 2.1
*/
template < typename Token >
class ResT:
	public ResTBase< Token >, // is a data producer
	public data::Observable< ResTObserver< Token > >
{
public:

	using data::Producer::trace;
	using data::Producer::debug;
	using data::Producer::info;
	using data::Producer::warning;
	using data::Producer::error;
	using data::Producer::fatal;
	using data::Producer::statistics;
	using data::Producer::log;
	using data::Producer::param;
	using data::Producer::count;
	using data::Producer::update;
	using data::Producer::reset;

	using ResTBase<Token>::getCurrentTime;
	using ResTBase<Token>::getCurrentSched;
	using ResTBase<Token>::getCurrentProcess;

	/**
	 * \copydoc ResTBase(Simulation*,Label,std::vector<Token>&,ResTBaseObserver<Token>*)
	 */
	ResT( base::Simulation& sim, const data::Label& l,
			std::vector< Token >& initialResources,
			ResTObserver< Token >* o = 0 );

	/// Destruction
	virtual ~ResT();

	/**
		\name Token usage

		These functions provide access for resource usage by Processes.
		Tokens can be requested and thus acquired when then are
		available. When the tokens are not needed anymore, the owning
		Process	can release them.

		@{
	*/
	/**
		\brief acquire a token

		If there are no tokens in ResT the current process is blocked.
	*/
	virtual Token* acquire();

	/**
		\brief acquire \p n token

		If there are not enough tokens in ResT the current
		process is blocked.
	*/
	const std::vector< Token* > acquire( std::size_t n );
};

/** \interface ResTObserver

	\author Ronald Kluth

	\brief Observer for ResT specific events

	\sa ResT
	
	\since 2.1
*/
template < typename Token >
class ResTObserver: public ResTBaseObserver< Token > {
public:
	typedef typename ResTBaseObserver< Token >::ResType ResType;

	virtual ~ResTObserver() {}

	/// Failed attempt to acquire n token
	virtual void onAcquireFail(ResType* sender, std::size_t n) {}
	/// Successful attempt to acquire n token
	virtual void onAcquireSucceed(ResType* sender, std::size_t n) {}
};

} } // namespace odemx::synchronization

#endif /* ODEMX_RES_T_INCLUDED */
