dbms: fixed race condition (still messy) [#METR-11765].

This commit is contained in:
Alexey Milovidov 2014-07-16 05:36:18 +04:00
parent 71935f7916
commit cdbff6e120

View File

@ -2,6 +2,7 @@
#include <list>
#include <queue>
#include <atomic>
#include <Poco/Thread.h>
@ -37,8 +38,7 @@ class UnionBlockInputStream : public IProfilingBlockInputStream
public:
UnionBlockInputStream(BlockInputStreams inputs_, unsigned max_threads_ = 1)
: max_threads(std::min(inputs_.size(), static_cast<size_t>(max_threads_))),
output_queue(max_threads), exhausted_inputs(0), finish(false),
pushed_end_of_output_queue(false), all_read(false), log(&Logger::get("UnionBlockInputStream"))
output_queue(max_threads)
{
children.insert(children.end(), inputs_.begin(), inputs_.end());
@ -223,6 +223,9 @@ private:
if (exception)
{
/// Отдаём эксепшен в основной поток.
parent.output_queue.push(exception);
try
{
parent.cancel();
@ -234,9 +237,6 @@ private:
* - то пофиг.
*/
}
/// Отдаём эксепшен в основной поток.
parent.output_queue.push(exception);
}
}
@ -292,14 +292,9 @@ private:
if (parent.finish)
{
Poco::ScopedLock<Poco::FastMutex> lock(parent.mutex);
/// Отдаём в основной поток пустой блок, что означает, что данных больше нет.
if (!parent.pushed_end_of_output_queue)
{
parent.pushed_end_of_output_queue = true;
/// Отдаём в основной поток пустой блок, что означает, что данных больше нет; только один раз.
if (false == parent.pushed_end_of_output_queue.exchange(true))
parent.output_queue.push(OutputData());
}
}
}
@ -334,19 +329,20 @@ private:
typedef ConcurrentBoundedQueue<OutputData> OutputQueue;
OutputQueue output_queue;
/// Для операций с очередями.
/// Для операций с input_queue.
Poco::FastMutex mutex;
/// Сколько источников иссякло.
size_t exhausted_inputs;
size_t exhausted_inputs = 0;
/// Завершить работу потоков (раньше, чем иссякнут источники).
volatile bool finish;
std::atomic<bool> finish { false };
/// Положили ли в output_queue пустой блок.
volatile bool pushed_end_of_output_queue;
bool all_read;
std::atomic<bool> pushed_end_of_output_queue { false };
Logger * log;
bool all_read { false };
Logger * log = &Logger::get("UnionBlockInputStream");
};
}