mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-15 10:52:30 +00:00
482 lines
11 KiB
C++
482 lines
11 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 <algorithm>
|
|
#include "Poco/Event.h"
|
|
#include "Poco/Exception.h"
|
|
#include "Poco/Foundation.h"
|
|
#include "Poco/Mutex.h"
|
|
#include "Poco/RefCountedObject.h"
|
|
|
|
|
|
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(false)
|
|
/// 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(false)
|
|
/// 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
|