2011-11-28 05:48:52 +00:00
|
|
|
#pragma once
|
|
|
|
|
2011-11-28 06:22:25 +00:00
|
|
|
#include <statdaemons/threadpool.hpp>
|
2011-11-28 05:48:52 +00:00
|
|
|
|
2011-11-28 06:22:25 +00:00
|
|
|
#include <DB/DataStreams/IProfilingBlockInputStream.h>
|
2011-11-28 05:48:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
/** Выполняет другой BlockInputStream в отдельном потоке, используя двойную буферизацию.
|
|
|
|
*/
|
2011-11-28 06:22:25 +00:00
|
|
|
class AsynchronousBlockInputStream : public IProfilingBlockInputStream
|
2011-11-28 05:48:52 +00:00
|
|
|
{
|
|
|
|
public:
|
2011-11-28 06:22:25 +00:00
|
|
|
AsynchronousBlockInputStream(BlockInputStreamPtr in_) : in(in_), pool(1), started(false)
|
2011-11-28 05:48:52 +00:00
|
|
|
{
|
|
|
|
children.push_back(in);
|
|
|
|
}
|
|
|
|
|
2011-11-28 06:22:25 +00:00
|
|
|
Block readImpl()
|
2011-11-28 05:48:52 +00:00
|
|
|
{
|
|
|
|
/// Если вычислений ещё не было - вычислим первый блок синхронно
|
2011-11-28 06:22:25 +00:00
|
|
|
if (!started)
|
|
|
|
{
|
2011-11-28 05:48:52 +00:00
|
|
|
calculate();
|
2011-11-28 06:22:25 +00:00
|
|
|
started = true;
|
|
|
|
}
|
2011-11-28 05:48:52 +00:00
|
|
|
else /// Если вычисления уже идут - подождём результата
|
2011-11-28 06:22:25 +00:00
|
|
|
pool.wait();
|
2011-11-28 05:48:52 +00:00
|
|
|
|
|
|
|
if (exception)
|
2011-12-12 06:15:34 +00:00
|
|
|
exception->rethrow();
|
2011-11-28 05:48:52 +00:00
|
|
|
|
|
|
|
Block res = block;
|
|
|
|
if (!res)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
/// Запустим вычисления следующего блока
|
|
|
|
block = Block();
|
2011-11-28 06:22:25 +00:00
|
|
|
pool.schedule(boost::bind(&AsynchronousBlockInputStream::calculate, this));
|
2011-11-28 05:48:52 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
String getName() const { return "AsynchronousBlockInputStream"; }
|
|
|
|
|
|
|
|
BlockInputStreamPtr clone() { return new AsynchronousBlockInputStream(in); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
BlockInputStreamPtr in;
|
2011-11-28 06:22:25 +00:00
|
|
|
boost::threadpool::pool pool;
|
|
|
|
bool started;
|
2011-11-28 05:48:52 +00:00
|
|
|
|
|
|
|
Block block;
|
|
|
|
SharedPtr<Exception> exception;
|
|
|
|
|
|
|
|
/// Вычисления, которые могут выполняться в отдельном потоке
|
|
|
|
void calculate()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
block = in->read();
|
|
|
|
}
|
|
|
|
catch (const Exception & e)
|
|
|
|
{
|
|
|
|
exception = new Exception(e);
|
|
|
|
}
|
|
|
|
catch (const Poco::Exception & e)
|
|
|
|
{
|
|
|
|
exception = new Exception(e.message(), ErrorCodes::POCO_EXCEPTION);
|
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
exception = new Exception(e.what(), ErrorCodes::STD_EXCEPTION);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
exception = new Exception("Unknown exception", ErrorCodes::UNKNOWN_EXCEPTION);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|