2017-10-06 16:53:55 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
/// An atomic variable that is used to block and interrupt certain actions
|
|
|
|
/// If it is not zero then actions related with it should be considered as interrupted
|
|
|
|
struct ActionBlocker
|
|
|
|
{
|
|
|
|
mutable std::atomic<int> counter{0};
|
|
|
|
|
|
|
|
bool isCancelled() const { return counter > 0; }
|
|
|
|
|
2017-10-12 20:15:39 +00:00
|
|
|
/// Temporarily blocks corresponding actions (while the returned object is alive)
|
2017-10-06 16:53:55 +00:00
|
|
|
struct BlockHolder;
|
|
|
|
BlockHolder cancel() const { return BlockHolder(this); }
|
|
|
|
|
|
|
|
// Cancel the actions forever.
|
|
|
|
void cancelForever() const { ++counter; }
|
|
|
|
|
|
|
|
/// Blocks related action while a BlockerHolder instance exists
|
|
|
|
struct BlockHolder
|
|
|
|
{
|
|
|
|
explicit BlockHolder(const ActionBlocker * var_ = nullptr) : var(var_)
|
|
|
|
{
|
|
|
|
if (var)
|
|
|
|
++var->counter;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockHolder(BlockHolder && other) noexcept
|
|
|
|
{
|
2017-10-12 20:16:50 +00:00
|
|
|
*this = std::move(other);
|
2017-10-06 16:53:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BlockHolder & operator=(BlockHolder && other) noexcept
|
|
|
|
{
|
|
|
|
var = other.var;
|
|
|
|
other.var = nullptr;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockHolder(const BlockHolder & other) = delete;
|
|
|
|
BlockHolder & operator=(const BlockHolder & other) = delete;
|
|
|
|
|
|
|
|
~BlockHolder()
|
|
|
|
{
|
|
|
|
if (var)
|
|
|
|
--var->counter;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const ActionBlocker * var = nullptr;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|