mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 18:20:26 +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
|