//----------------------------------------------------------------------------
//	Copyright (C) 2002, 2004 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 CondQ.h

	\author Ralf Gerstenberger

	\date created at 2002/07/11

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

	\sa CondQ.cpp

	\since 1.0
*/

#ifndef ODEMX_CONDQ_INCLUDED
#define ODEMX_CONDQ_INCLUDED

#include <odemx/data/Producer.h>
#include <odemx/synchronization/Queue.h>
#include <odemx/data/Observable.h>

namespace odemx {

// forward declarations
namespace base {
class Process;
class Sched;
}

namespace synchronization {

class CondQObserver;

/** \class CondQ

	\ingroup synch

	\author Ralf Gerstenberger

	\brief %CondQ can be used to make a process wait for an
	arbitrary condition.

	\note CondQ supports Observation
	\note CondQ supports Trace
	\note CondQ supports Report

	\since 1.0
*/
class CondQ
:	public data::Producer
,	public data::Observable< CondQObserver >
{
public:

	/**
		\brief Construction for user-defined Simulation
		\param s
			pointer to Simulation object
		\param l
			label of this object
		\param o
			initial observer
	*/
	CondQ( base::Simulation& sim, const data::Label& label, CondQObserver* obs = 0 );

	/// Destruction
	~CondQ();

	/**
		\name Synchronisation
		@{
	*/
	/**
		\brief Wait for cond

		If the supplied condition \p cond is false the current process
		is blocked until the condition is true and signal() was called.
		If a blocked process is interrupted, it is reactivated and
		the function returns false. (An interrupted process has
		influence on the queue-statistic but not on user and waiting time
		statistics.)
	*/
	bool wait( base::Condition cond );

	/// Trigger condition check
	void signal();
	//@}

	/// Get a list of blocked process objects
	const base::ProcessList& getWaitingProcesses() const;

private:
	/// process management
	Queue processes_;

	/// Helper for quick access to the current simulation time
	base::SimTime getTime() const;
	/// Helper for quick access to the currently running object
	base::Sched* getCurrentSched();
	/// Helper for quick access to the current process
	base::Process* getCurrentProcess();
};

/** \interface CondQObserver

	\author Ralf Gerstenberger

	\brief Observer for CondQ-specific events

	\sa CondQ

	\since 1.0
*/
class CondQObserver
{
public:
	virtual ~CondQObserver() { }

	/// Observe construction
	virtual void onCreate( CondQ* sender ) {}

	/// Observe process entering wait phase
	virtual void onWait( CondQ* sender, base::Process* process ) {}
	/// Observe process continuation
	virtual void onContinue( CondQ* sender, base::Process* process ) {}
	/// Observe triggering of the condition test
	virtual void onSignal( CondQ* sender, base::Process* process ) {}
};

} } // namespace odemx::synchronization

#endif
