mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-11-03 19:40:37 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			496 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			496 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//
 | 
						|
// ActiveResult.h
 | 
						|
//
 | 
						|
// Library: Foundation
 | 
						|
// Package: Threading
 | 
						|
// Module:  ActiveObjects
 | 
						|
//
 | 
						|
// Definition of the ActiveResult class.
 | 
						|
//
 | 
						|
// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
 | 
						|
// and Contributors.
 | 
						|
//
 | 
						|
// SPDX-License-Identifier:	BSL-1.0
 | 
						|
//
 | 
						|
 | 
						|
 | 
						|
#ifndef Foundation_ActiveResult_INCLUDED
 | 
						|
#define Foundation_ActiveResult_INCLUDED
 | 
						|
 | 
						|
 | 
						|
#include "Poco/Foundation.h"
 | 
						|
#include "Poco/Mutex.h"
 | 
						|
#include "Poco/Event.h"
 | 
						|
#include "Poco/RefCountedObject.h"
 | 
						|
#include "Poco/Exception.h"
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
 | 
						|
namespace Poco {
 | 
						|
 | 
						|
 | 
						|
template <class ResultType>
 | 
						|
class ActiveResultHolder: public RefCountedObject
 | 
						|
	/// This class holds the result of an asynchronous method
 | 
						|
	/// invocation. It is used to pass the result from the
 | 
						|
	/// execution thread back to the invocation thread.
 | 
						|
	/// The class uses reference counting for memory management.
 | 
						|
	/// Do not use this class directly, use ActiveResult instead.
 | 
						|
{
 | 
						|
public:
 | 
						|
	ActiveResultHolder():
 | 
						|
		_pData(0),
 | 
						|
		_pExc(0),
 | 
						|
		_event(Event::EVENT_MANUALRESET)
 | 
						|
		/// Creates an ActiveResultHolder.
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	ResultType& data()
 | 
						|
		/// Returns a reference to the actual result.
 | 
						|
	{
 | 
						|
		poco_check_ptr(_pData);
 | 
						|
		return *_pData;
 | 
						|
	}
 | 
						|
 | 
						|
	void data(ResultType* pData)
 | 
						|
	{
 | 
						|
		delete _pData;
 | 
						|
		_pData = pData;
 | 
						|
	}
 | 
						|
 | 
						|
	void wait()
 | 
						|
		/// Pauses the caller until the result becomes available.
 | 
						|
	{
 | 
						|
		_event.wait();
 | 
						|
	}
 | 
						|
 | 
						|
	bool tryWait(long milliseconds)
 | 
						|
		/// Waits up to the specified interval for the result to
 | 
						|
		/// become available. Returns true if the result became
 | 
						|
		/// available, false otherwise.
 | 
						|
	{
 | 
						|
		return _event.tryWait(milliseconds);
 | 
						|
	}
 | 
						|
 | 
						|
	void wait(long milliseconds)
 | 
						|
		/// Waits up to the specified interval for the result to
 | 
						|
		/// become available. Throws a TimeoutException if the
 | 
						|
		/// result did not became available.
 | 
						|
	{
 | 
						|
		_event.wait(milliseconds);
 | 
						|
	}
 | 
						|
 | 
						|
	void notify()
 | 
						|
		/// Notifies the invoking thread that the result became available.
 | 
						|
	{
 | 
						|
		_event.set();
 | 
						|
	}
 | 
						|
 | 
						|
	bool failed() const
 | 
						|
		/// Returns true if the active method failed (and threw an exception).
 | 
						|
		/// Information about the exception can be obtained by calling error().
 | 
						|
	{
 | 
						|
		return _pExc != 0;
 | 
						|
	}
 | 
						|
 | 
						|
	std::string error() const
 | 
						|
		/// If the active method threw an exception, a textual representation
 | 
						|
		/// of the exception is returned. An empty string is returned if the
 | 
						|
		/// active method completed successfully.
 | 
						|
	{
 | 
						|
		if (_pExc)
 | 
						|
			return _pExc->message();
 | 
						|
		else
 | 
						|
			return std::string();
 | 
						|
	}
 | 
						|
 | 
						|
	Exception* exception() const
 | 
						|
		/// If the active method threw an exception, a clone of the exception
 | 
						|
		/// object is returned, otherwise null.
 | 
						|
	{
 | 
						|
		return _pExc;
 | 
						|
	}
 | 
						|
 | 
						|
	void error(const Exception& exc)
 | 
						|
		/// Sets the exception.
 | 
						|
	{
 | 
						|
		delete _pExc;
 | 
						|
		_pExc = exc.clone();
 | 
						|
	}
 | 
						|
 | 
						|
	void error(const std::string& msg)
 | 
						|
		/// Sets the exception.
 | 
						|
	{
 | 
						|
		delete _pExc;
 | 
						|
		_pExc = new UnhandledException(msg);
 | 
						|
	}
 | 
						|
 | 
						|
protected:
 | 
						|
	~ActiveResultHolder()
 | 
						|
	{
 | 
						|
		delete _pData;
 | 
						|
		delete _pExc;
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	ResultType* _pData;
 | 
						|
	Exception*  _pExc;
 | 
						|
	Event       _event;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
template <>
 | 
						|
class ActiveResultHolder<void>: public RefCountedObject
 | 
						|
{
 | 
						|
public:
 | 
						|
	ActiveResultHolder():
 | 
						|
		_pExc(0),
 | 
						|
		_event(Event::EVENT_MANUALRESET)
 | 
						|
		/// Creates an ActiveResultHolder.
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	void wait()
 | 
						|
		/// Pauses the caller until the result becomes available.
 | 
						|
	{
 | 
						|
		_event.wait();
 | 
						|
	}
 | 
						|
 | 
						|
	bool tryWait(long milliseconds)
 | 
						|
		/// Waits up to the specified interval for the result to
 | 
						|
		/// become available. Returns true if the result became
 | 
						|
		/// available, false otherwise.
 | 
						|
	{
 | 
						|
		return _event.tryWait(milliseconds);
 | 
						|
	}
 | 
						|
 | 
						|
	void wait(long milliseconds)
 | 
						|
		/// Waits up to the specified interval for the result to
 | 
						|
		/// become available. Throws a TimeoutException if the
 | 
						|
		/// result did not became available.
 | 
						|
	{
 | 
						|
		_event.wait(milliseconds);
 | 
						|
	}
 | 
						|
 | 
						|
	void notify()
 | 
						|
		/// Notifies the invoking thread that the result became available.
 | 
						|
	{
 | 
						|
		_event.set();
 | 
						|
	}
 | 
						|
 | 
						|
	bool failed() const
 | 
						|
		/// Returns true if the active method failed (and threw an exception).
 | 
						|
		/// Information about the exception can be obtained by calling error().
 | 
						|
	{
 | 
						|
		return _pExc != 0;
 | 
						|
	}
 | 
						|
 | 
						|
	std::string error() const
 | 
						|
		/// If the active method threw an exception, a textual representation
 | 
						|
		/// of the exception is returned. An empty string is returned if the
 | 
						|
		/// active method completed successfully.
 | 
						|
	{
 | 
						|
		if (_pExc)
 | 
						|
			return _pExc->message();
 | 
						|
		else
 | 
						|
			return std::string();
 | 
						|
	}
 | 
						|
 | 
						|
	Exception* exception() const
 | 
						|
		/// If the active method threw an exception, a clone of the exception
 | 
						|
		/// object is returned, otherwise null.
 | 
						|
	{
 | 
						|
		return _pExc;
 | 
						|
	}
 | 
						|
 | 
						|
	void error(const Exception& exc)
 | 
						|
		/// Sets the exception.
 | 
						|
	{
 | 
						|
		delete _pExc;
 | 
						|
		_pExc = exc.clone();
 | 
						|
	}
 | 
						|
 | 
						|
	void error(const std::string& msg)
 | 
						|
		/// Sets the exception.
 | 
						|
	{
 | 
						|
		delete _pExc;
 | 
						|
		_pExc = new UnhandledException(msg);
 | 
						|
	}
 | 
						|
 | 
						|
protected:
 | 
						|
	~ActiveResultHolder()
 | 
						|
	{
 | 
						|
		delete _pExc;
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	Exception*  _pExc;
 | 
						|
	Event       _event;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
template <class RT>
 | 
						|
class ActiveResult
 | 
						|
	/// This class holds the result of an asynchronous method
 | 
						|
	/// invocation (see class ActiveMethod). It is used to pass the
 | 
						|
	/// result from the execution thread back to the invocation thread.
 | 
						|
{
 | 
						|
public:
 | 
						|
	typedef RT ResultType;
 | 
						|
	typedef ActiveResultHolder<ResultType> ActiveResultHolderType;
 | 
						|
 | 
						|
	ActiveResult(ActiveResultHolderType* pHolder):
 | 
						|
		_pHolder(pHolder)
 | 
						|
		/// Creates the active result. For internal use only.
 | 
						|
	{
 | 
						|
		poco_check_ptr (pHolder);
 | 
						|
	}
 | 
						|
 | 
						|
	ActiveResult(const ActiveResult& result)
 | 
						|
		/// Copy constructor.
 | 
						|
	{
 | 
						|
		_pHolder = result._pHolder;
 | 
						|
		_pHolder->duplicate();
 | 
						|
	}
 | 
						|
 | 
						|
	~ActiveResult()
 | 
						|
		/// Destroys the result.
 | 
						|
	{
 | 
						|
		_pHolder->release();
 | 
						|
	}
 | 
						|
 | 
						|
	ActiveResult& operator = (const ActiveResult& result)
 | 
						|
		/// Assignment operator.
 | 
						|
	{
 | 
						|
		ActiveResult tmp(result);
 | 
						|
		swap(tmp);
 | 
						|
		return *this;
 | 
						|
	}
 | 
						|
 | 
						|
	void swap(ActiveResult& result) noexcept
 | 
						|
	{
 | 
						|
		using std::swap;
 | 
						|
		swap(_pHolder, result._pHolder);
 | 
						|
	}
 | 
						|
 | 
						|
	ResultType& data() const
 | 
						|
		/// Returns a reference to the result data.
 | 
						|
	{
 | 
						|
		return _pHolder->data();
 | 
						|
	}
 | 
						|
 | 
						|
	void data(ResultType* pValue)
 | 
						|
	{
 | 
						|
		_pHolder->data(pValue);
 | 
						|
	}
 | 
						|
 | 
						|
	void wait()
 | 
						|
		/// Pauses the caller until the result becomes available.
 | 
						|
	{
 | 
						|
		_pHolder->wait();
 | 
						|
	}
 | 
						|
 | 
						|
	bool tryWait(long milliseconds)
 | 
						|
		/// Waits up to the specified interval for the result to
 | 
						|
		/// become available. Returns true if the result became
 | 
						|
		/// available, false otherwise.
 | 
						|
	{
 | 
						|
		return _pHolder->tryWait(milliseconds);
 | 
						|
	}
 | 
						|
 | 
						|
	void wait(long milliseconds)
 | 
						|
		/// Waits up to the specified interval for the result to
 | 
						|
		/// become available. Throws a TimeoutException if the
 | 
						|
		/// result did not became available.
 | 
						|
	{
 | 
						|
		_pHolder->wait(milliseconds);
 | 
						|
	}
 | 
						|
 | 
						|
	bool available() const
 | 
						|
		/// Returns true if a result is available.
 | 
						|
	{
 | 
						|
		return _pHolder->tryWait(0);
 | 
						|
	}
 | 
						|
 | 
						|
	bool failed() const
 | 
						|
		/// Returns true if the active method failed (and threw an exception).
 | 
						|
		/// Information about the exception can be obtained by calling error().
 | 
						|
	{
 | 
						|
		return _pHolder->failed();
 | 
						|
	}
 | 
						|
 | 
						|
	std::string error() const
 | 
						|
		/// If the active method threw an exception, a textual representation
 | 
						|
		/// of the exception is returned. An empty string is returned if the
 | 
						|
		/// active method completed successfully.
 | 
						|
	{
 | 
						|
		return _pHolder->error();
 | 
						|
	}
 | 
						|
 | 
						|
	Exception* exception() const
 | 
						|
		/// If the active method threw an exception, a clone of the exception
 | 
						|
		/// object is returned, otherwise null.
 | 
						|
	{
 | 
						|
		return _pHolder->exception();
 | 
						|
	}
 | 
						|
 | 
						|
	void notify()
 | 
						|
		/// Notifies the invoking thread that the result became available.
 | 
						|
		/// For internal use only.
 | 
						|
	{
 | 
						|
		_pHolder->notify();
 | 
						|
	}
 | 
						|
 | 
						|
	ResultType& data()
 | 
						|
		/// Returns a non-const reference to the result data. For internal
 | 
						|
		/// use only.
 | 
						|
	{
 | 
						|
		return _pHolder->data();
 | 
						|
	}
 | 
						|
 | 
						|
	void error(const std::string& msg)
 | 
						|
		/// Sets the failed flag and the exception message.
 | 
						|
	{
 | 
						|
		_pHolder->error(msg);
 | 
						|
	}
 | 
						|
 | 
						|
	void error(const Exception& exc)
 | 
						|
		/// Sets the failed flag and the exception message.
 | 
						|
	{
 | 
						|
		_pHolder->error(exc);
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	ActiveResult();
 | 
						|
 | 
						|
	ActiveResultHolderType* _pHolder;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
template <>
 | 
						|
class ActiveResult<void>
 | 
						|
	/// This class holds the result of an asynchronous method
 | 
						|
	/// invocation (see class ActiveMethod). It is used to pass the
 | 
						|
	/// result from the execution thread back to the invocation thread.
 | 
						|
{
 | 
						|
public:
 | 
						|
	typedef ActiveResultHolder<void> ActiveResultHolderType;
 | 
						|
 | 
						|
	ActiveResult(ActiveResultHolderType* pHolder):
 | 
						|
		_pHolder(pHolder)
 | 
						|
		/// Creates the active result. For internal use only.
 | 
						|
	{
 | 
						|
		poco_check_ptr (pHolder);
 | 
						|
	}
 | 
						|
 | 
						|
	ActiveResult(const ActiveResult& result)
 | 
						|
		/// Copy constructor.
 | 
						|
	{
 | 
						|
		_pHolder = result._pHolder;
 | 
						|
		_pHolder->duplicate();
 | 
						|
	}
 | 
						|
 | 
						|
	~ActiveResult()
 | 
						|
		/// Destroys the result.
 | 
						|
	{
 | 
						|
		_pHolder->release();
 | 
						|
	}
 | 
						|
 | 
						|
	ActiveResult& operator = (const ActiveResult& result)
 | 
						|
		/// Assignment operator.
 | 
						|
	{
 | 
						|
		ActiveResult tmp(result);
 | 
						|
		swap(tmp);
 | 
						|
		return *this;
 | 
						|
	}
 | 
						|
 | 
						|
	void swap(ActiveResult& result) noexcept
 | 
						|
	{
 | 
						|
		using std::swap;
 | 
						|
		swap(_pHolder, result._pHolder);
 | 
						|
	}
 | 
						|
 | 
						|
	void wait()
 | 
						|
		/// Pauses the caller until the result becomes available.
 | 
						|
	{
 | 
						|
		_pHolder->wait();
 | 
						|
	}
 | 
						|
 | 
						|
	bool tryWait(long milliseconds)
 | 
						|
		/// Waits up to the specified interval for the result to
 | 
						|
		/// become available. Returns true if the result became
 | 
						|
		/// available, false otherwise.
 | 
						|
	{
 | 
						|
		return _pHolder->tryWait(milliseconds);
 | 
						|
	}
 | 
						|
 | 
						|
	void wait(long milliseconds)
 | 
						|
		/// Waits up to the specified interval for the result to
 | 
						|
		/// become available. Throws a TimeoutException if the
 | 
						|
		/// result did not became available.
 | 
						|
	{
 | 
						|
		_pHolder->wait(milliseconds);
 | 
						|
	}
 | 
						|
 | 
						|
	bool available() const
 | 
						|
		/// Returns true if a result is available.
 | 
						|
	{
 | 
						|
		return _pHolder->tryWait(0);
 | 
						|
	}
 | 
						|
 | 
						|
	bool failed() const
 | 
						|
		/// Returns true if the active method failed (and threw an exception).
 | 
						|
		/// Information about the exception can be obtained by calling error().
 | 
						|
	{
 | 
						|
		return _pHolder->failed();
 | 
						|
	}
 | 
						|
 | 
						|
	std::string error() const
 | 
						|
		/// If the active method threw an exception, a textual representation
 | 
						|
		/// of the exception is returned. An empty string is returned if the
 | 
						|
		/// active method completed successfully.
 | 
						|
	{
 | 
						|
		return _pHolder->error();
 | 
						|
	}
 | 
						|
 | 
						|
	Exception* exception() const
 | 
						|
		/// If the active method threw an exception, a clone of the exception
 | 
						|
		/// object is returned, otherwise null.
 | 
						|
	{
 | 
						|
		return _pHolder->exception();
 | 
						|
	}
 | 
						|
 | 
						|
	void notify()
 | 
						|
		/// Notifies the invoking thread that the result became available.
 | 
						|
		/// For internal use only.
 | 
						|
	{
 | 
						|
		_pHolder->notify();
 | 
						|
	}
 | 
						|
 | 
						|
	void error(const std::string& msg)
 | 
						|
		/// Sets the failed flag and the exception message.
 | 
						|
	{
 | 
						|
		_pHolder->error(msg);
 | 
						|
	}
 | 
						|
 | 
						|
	void error(const Exception& exc)
 | 
						|
		/// Sets the failed flag and the exception message.
 | 
						|
	{
 | 
						|
		_pHolder->error(exc);
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	ActiveResult();
 | 
						|
 | 
						|
	ActiveResultHolderType* _pHolder;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
} // namespace Poco
 | 
						|
 | 
						|
 | 
						|
#endif // Foundation_ActiveResult_INCLUDED
 |