mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-10-27 19:10:20 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			498 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			498 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| // ActiveResult.h
 | |
| //
 | |
| // $Id: //poco/1.4/Foundation/include/Poco/ActiveResult.h#1 $
 | |
| //
 | |
| // 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)
 | |
| 	{
 | |
| 		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)
 | |
| 	{
 | |
| 		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
 | 
