2013-05-04 06:09:23 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <DB/DataStreams/QueueBlockIOStream.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Позволяет из одного источника сделать несколько.
|
|
|
|
|
* Используется для однопроходного выполнения сразу нескольких запросов.
|
2016-05-28 10:15:36 +00:00
|
|
|
|
*
|
2013-05-04 06:09:23 +00:00
|
|
|
|
* Несколько полученных источников должны читаться из разных потоков!
|
|
|
|
|
* Расходует O(1) оперативки (не буферизует все данные).
|
|
|
|
|
* Для этого, чтения из разных полученных источников синхронизируются:
|
|
|
|
|
* чтение следующего блока блокируется, пока все источники не прочитают текущий блок.
|
|
|
|
|
*/
|
|
|
|
|
class ForkBlockInputStreams : private boost::noncopyable
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
ForkBlockInputStreams(BlockInputStreamPtr source_) : source(source_) {}
|
|
|
|
|
|
|
|
|
|
/// Создать источник. Вызывайте функцию столько раз, сколько размноженных источников вам нужно.
|
|
|
|
|
BlockInputStreamPtr createInput()
|
|
|
|
|
{
|
2016-05-28 12:22:22 +00:00
|
|
|
|
destinations.emplace_back(std::make_shared<QueueBlockIOStream>(1));
|
2013-05-04 06:09:23 +00:00
|
|
|
|
return destinations.back();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Перед тем, как из полученных источников можно будет читать, необходимо "запустить" эту конструкцию.
|
|
|
|
|
void run()
|
|
|
|
|
{
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
if (destinations.empty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Block block = source->read();
|
|
|
|
|
|
|
|
|
|
for (Destinations::iterator it = destinations.begin(); it != destinations.end();)
|
|
|
|
|
{
|
|
|
|
|
if ((*it)->isCancelled())
|
|
|
|
|
{
|
|
|
|
|
destinations.erase(it++);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
(*it)->write(block);
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!block)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
/// Откуда читать.
|
|
|
|
|
BlockInputStreamPtr source;
|
|
|
|
|
|
|
|
|
|
/** Размноженные источники.
|
|
|
|
|
* Сделаны на основе очереди небольшой длины.
|
|
|
|
|
* Блок из source кладётся в каждую очередь.
|
|
|
|
|
*/
|
2016-05-28 12:22:22 +00:00
|
|
|
|
using Destination = std::shared_ptr<QueueBlockIOStream>;
|
2016-05-28 10:15:36 +00:00
|
|
|
|
using Destinations = std::list<Destination>;
|
2013-05-04 06:09:23 +00:00
|
|
|
|
Destinations destinations;
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-28 10:15:36 +00:00
|
|
|
|
using ForkPtr = std::shared_ptr<ForkBlockInputStreams>;
|
|
|
|
|
using Forks = std::vector<ForkPtr>;
|
2013-05-04 06:09:23 +00:00
|
|
|
|
|
|
|
|
|
}
|