diff --git a/dbms/include/DB/Columns/ColumnAggregateFunction.h b/dbms/include/DB/Columns/ColumnAggregateFunction.h index c92c37d1955..d42c72c9ac3 100644 --- a/dbms/include/DB/Columns/ColumnAggregateFunction.h +++ b/dbms/include/DB/Columns/ColumnAggregateFunction.h @@ -12,8 +12,6 @@ #include #include -#include - namespace DB { @@ -49,71 +47,56 @@ namespace ErrorCodes * определяющий, какие отдельные значения надо уничтожать, а какие - нет. * Ясно, что этот метод имел бы существенно ненулевую цену. */ -class ColumnAggregateFunction final : public IColumn +class ColumnAggregateFunction final : public IColumn, public std::enable_shared_from_this { public: using Container_t = PaddedPODArray; private: - Arenas arenas; /// Пулы, в которых выделены состояния агрегатных функций. + /// Пулы, в которых выделены состояния агрегатных функций. + Arenas arenas; - struct Holder - { - using Ptr = Poco::SharedPtr; + /// Используется для уничтожения состояний и для финализации значений. + AggregateFunctionPtr func; - AggregateFunctionPtr func; /// Используется для уничтожения состояний и для финализации значений. - const Ptr src; /// Источник. Используется, если данный столбец создан из другого и использует все или часть его значений. - Container_t data; /// Массив указателей на состояния агрегатных функций, расположенных в пулах. + /// Источник. Используется (удерживает источник от уничтожения), + /// если данный столбец создан из другого и использует все или часть его значений. + const std::shared_ptr src; - Holder(const AggregateFunctionPtr & func_) : func(func_) {} - Holder(const Ptr & src_) : func(src_->func), src(src_) {} - - ~Holder() - { - if (!func->hasTrivialDestructor() && src.isNull()) - for (auto val : data) - func->destroy(val); - } - - void popBack(size_t n) - { - size_t size = data.size(); - size_t new_size = size - n; - - if (src.isNull()) - for (size_t i = new_size; i < size; ++i) - func->destroy(data[i]); - - data.resize_assume_reserved(new_size); - } - }; - - Holder::Ptr holder; /// NOTE Вместо этого можно было бы унаследовать IColumn от enable_shared_from_this. + /// Массив указателей на состояния агрегатных функций, расположенных в пулах. + Container_t data; public: /// Создать столбец на основе другого. - ColumnAggregateFunction(const ColumnAggregateFunction & src) - : arenas(src.arenas), holder(new Holder(src.holder)) + ColumnAggregateFunction(const ColumnAggregateFunction & other) + : arenas(other.arenas), func(other.func), src(other.shared_from_this()) { } ColumnAggregateFunction(const AggregateFunctionPtr & func_) - : holder(new Holder(func_)) + : func(func_) { } ColumnAggregateFunction(const AggregateFunctionPtr & func_, const Arenas & arenas_) - : arenas(arenas_), holder(new Holder(func_)) + : arenas(arenas_), func(func_) { } + ~ColumnAggregateFunction() + { + if (!func->hasTrivialDestructor() && src) + for (auto val : data) + func->destroy(val); + } + void set(const AggregateFunctionPtr & func_) { - holder->func = func_; + func = func_; } - AggregateFunctionPtr getAggregateFunction() { return holder->func; } - AggregateFunctionPtr getAggregateFunction() const { return holder->func; } + AggregateFunctionPtr getAggregateFunction() { return func; } + AggregateFunctionPtr getAggregateFunction() const { return func; } /// Захватить владение ареной. void addArena(ArenaPtr arena_) @@ -136,7 +119,7 @@ public: ColumnPtr cloneEmpty() const override { - return std::make_shared(holder->func, Arenas(1, std::make_shared())); + return std::make_shared(func, Arenas(1, std::make_shared())); }; Field operator[](size_t n) const override @@ -144,7 +127,7 @@ public: Field field = String(); { WriteBufferFromString buffer(field.get()); - holder.get()->func->serialize(getData()[n], buffer); + func->serialize(getData()[n], buffer); } return field; } @@ -154,7 +137,7 @@ public: res = String(); { WriteBufferFromString buffer(res.get()); - holder.get()->func->serialize(getData()[n], buffer); + func->serialize(getData()[n], buffer); } } @@ -176,7 +159,7 @@ public: /// Объединить состояние в последней строке с заданным void insertMergeFrom(const IColumn & src, size_t n) { - holder.get()->func.get()->merge(getData().back(), static_cast(src).getData()[n]); + func->merge(getData().back(), static_cast(src).getData()[n]); } Arena & createOrGetArena() @@ -188,7 +171,7 @@ public: void insert(const Field & x) override { - IAggregateFunction * function = holder.get()->func.get(); + IAggregateFunction * function = func.get(); Arena & arena = createOrGetArena(); @@ -200,7 +183,7 @@ public: void insertDefault() override { - IAggregateFunction * function = holder.get()->func.get(); + IAggregateFunction * function = func.get(); Arena & arena = createOrGetArena(); @@ -247,7 +230,14 @@ public: void popBack(size_t n) override { - holder.get()->popBack(n); + size_t size = data.size(); + size_t new_size = size - n; + + if (!src) + for (size_t i = new_size; i < size; ++i) + func->destroy(data[i]); + + data.resize_assume_reserved(new_size); } ColumnPtr filter(const Filter & filter, ssize_t result_size_hint) const override @@ -324,12 +314,12 @@ public: /** Более эффективные методы манипуляции */ Container_t & getData() { - return holder.get()->data; + return data; } const Container_t & getData() const { - return holder.get()->data; + return data; } }; diff --git a/dbms/include/DB/Functions/FunctionFactory.h b/dbms/include/DB/Functions/FunctionFactory.h index 6a36a3277fa..2962a75cf1a 100644 --- a/dbms/include/DB/Functions/FunctionFactory.h +++ b/dbms/include/DB/Functions/FunctionFactory.h @@ -11,7 +11,7 @@ class Context; /** Позволяет получить функцию по имени. - * Функция при создании также может использовать для инициализации (например, захватить SharedPtr) + * Функция при создании также может использовать для инициализации (например, захватить shared_ptr) * какие-нибудь справочники, находящиеся в Context-е. */ class FunctionFactory : public Singleton diff --git a/dbms/include/DB/Storages/MergeTree/ReplicatedMergeTreeAlterThread.h b/dbms/include/DB/Storages/MergeTree/ReplicatedMergeTreeAlterThread.h index e718b8c4125..ac1f7082254 100644 --- a/dbms/include/DB/Storages/MergeTree/ReplicatedMergeTreeAlterThread.h +++ b/dbms/include/DB/Storages/MergeTree/ReplicatedMergeTreeAlterThread.h @@ -36,7 +36,7 @@ private: StorageReplicatedMergeTree & storage; Logger * log; - zkutil::EventPtr wakeup_event { new Poco::Event }; + zkutil::EventPtr wakeup_event { std::make_shared() }; volatile bool need_stop { false }; std::thread thread; diff --git a/dbms/include/DB/Storages/MergeTree/ReshardingWorker.h b/dbms/include/DB/Storages/MergeTree/ReshardingWorker.h index 478b347b74a..c620666941a 100644 --- a/dbms/include/DB/Storages/MergeTree/ReshardingWorker.h +++ b/dbms/include/DB/Storages/MergeTree/ReshardingWorker.h @@ -387,7 +387,7 @@ private: Context & context; Logger * log = &Logger::get("ReshardingWorker"); - zkutil::EventPtr event = new Poco::Event; + zkutil::EventPtr event = std::make_shared(); zkutil::GetZooKeeper get_zookeeper; std::atomic is_started{false}; diff --git a/dbms/include/DB/Storages/StorageReplicatedMergeTree.h b/dbms/include/DB/Storages/StorageReplicatedMergeTree.h index f08f5334131..8c63f72d43b 100644 --- a/dbms/include/DB/Storages/StorageReplicatedMergeTree.h +++ b/dbms/include/DB/Storages/StorageReplicatedMergeTree.h @@ -275,7 +275,7 @@ private: /// Поток, следящий за обновлениями в логах всех реплик и загружающий их в очередь. std::thread queue_updating_thread; - zkutil::EventPtr queue_updating_event = zkutil::EventPtr(new Poco::Event); + zkutil::EventPtr queue_updating_event = std::make_shared(); /// Задание, выполняющее действия из очереди. BackgroundProcessingPool::TaskHandle queue_task_handle; @@ -298,7 +298,7 @@ private: ReplicatedMergeTreePartCheckThread part_check_thread; /// Событие, пробуждающее метод alter от ожидания завершения запроса ALTER. - zkutil::EventPtr alter_query_event = zkutil::EventPtr(new Poco::Event); + zkutil::EventPtr alter_query_event = std::make_shared(); Logger * log; diff --git a/dbms/src/Columns/ColumnAggregateFunction.cpp b/dbms/src/Columns/ColumnAggregateFunction.cpp index 7b39198f315..beeee79c448 100644 --- a/dbms/src/Columns/ColumnAggregateFunction.cpp +++ b/dbms/src/Columns/ColumnAggregateFunction.cpp @@ -7,7 +7,7 @@ namespace DB ColumnPtr ColumnAggregateFunction::convertToValues() const { - const IAggregateFunction * function = holder->func.get(); + const IAggregateFunction * function = func.get(); ColumnPtr res = function->getReturnType()->createColumn(); /** Если агрегатная функция возвращает нефинализированное состояние, diff --git a/dbms/src/Interpreters/Aggregator.cpp b/dbms/src/Interpreters/Aggregator.cpp index 398d71b20f2..40f78bcd1e9 100644 --- a/dbms/src/Interpreters/Aggregator.cpp +++ b/dbms/src/Interpreters/Aggregator.cpp @@ -2217,7 +2217,7 @@ void NO_INLINE Aggregator::convertBlockToTwoLevelImpl( dst.insert({src_col.column->filter(filter, size_hint), src_col.type, src_col.name}); /** Вставленные в блок столбцы типа ColumnAggregateFunction будут владеть состояниями агрегатных функций - * путём удержания SharedPtr-а на исходный столбец. См. ColumnAggregateFunction.h + * путём удержания shared_ptr-а на исходный столбец. См. ColumnAggregateFunction.h */ } } diff --git a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeBlockOutputStream.cpp b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeBlockOutputStream.cpp index 0f0445b7d70..209bb437279 100644 --- a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeBlockOutputStream.cpp +++ b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeBlockOutputStream.cpp @@ -313,7 +313,7 @@ void ReplicatedMergeTreeBlockOutputStream::write(const Block & block) { while (true) { - zkutil::EventPtr event = new Poco::Event; + zkutil::EventPtr event = std::make_shared(); std::string value; /// get вместо exists, чтобы не утек watch, если ноды уже нет. diff --git a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeRestartingThread.cpp b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeRestartingThread.cpp index 04894424f79..28b129e1db2 100644 --- a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeRestartingThread.cpp +++ b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeRestartingThread.cpp @@ -193,7 +193,7 @@ bool ReplicatedMergeTreeRestartingThread::tryStartup() activateReplica(); updateQuorumIfWeHavePart(); - storage.leader_election = new zkutil::LeaderElection( + storage.leader_election = std::make_shared( storage.zookeeper_path + "/leader_election", *storage.current_zookeeper, /// current_zookeeper живёт в течение времени жизни leader_election, /// так как до изменения current_zookeeper, объект leader_election уничтожается в методе partialShutdown. diff --git a/dbms/src/Storages/MergeTree/ReshardingWorker.cpp b/dbms/src/Storages/MergeTree/ReshardingWorker.cpp index f4692550a16..3ac0d56c29a 100644 --- a/dbms/src/Storages/MergeTree/ReshardingWorker.cpp +++ b/dbms/src/Storages/MergeTree/ReshardingWorker.cpp @@ -2637,7 +2637,7 @@ void ReshardingWorker::AnomalyMonitor::routine() /// We create a new instance of Poco::Event each time we run /// the loop body in order to avoid multiple notifications. - zkutil::EventPtr event = new Poco::Event; + zkutil::EventPtr event = std::make_shared(); /// Monitor both status changes and movements of the performers. (void) zookeeper->get(resharding_worker.getCoordinatorPath(coordinator_id) diff --git a/dbms/src/Storages/StorageReplicatedMergeTree.cpp b/dbms/src/Storages/StorageReplicatedMergeTree.cpp index b665aa62e8e..2d4dc56f542 100644 --- a/dbms/src/Storages/StorageReplicatedMergeTree.cpp +++ b/dbms/src/Storages/StorageReplicatedMergeTree.cpp @@ -697,7 +697,7 @@ void StorageReplicatedMergeTree::createReplica() { LOG_INFO(log, "Waiting for replica " << source_path << " to be fully created"); - zkutil::EventPtr event = new Poco::Event; + zkutil::EventPtr event = std::make_shared(); if (zookeeper->exists(source_path + "/columns", nullptr, event)) { LOG_WARNING(log, "Oops, a watch has leaked"); @@ -2875,7 +2875,7 @@ void StorageReplicatedMergeTree::waitForReplicaToProcessLogEntry(const String & /// Дождемся, пока запись попадет в очередь реплики. while (true) { - zkutil::EventPtr event = new Poco::Event; + zkutil::EventPtr event = std::make_shared(); String log_pointer = zookeeper->get(zookeeper_path + "/replicas/" + replica + "/log_pointer", nullptr, event); if (!log_pointer.empty() && parse(log_pointer) > log_index) @@ -2920,7 +2920,7 @@ void StorageReplicatedMergeTree::waitForReplicaToProcessLogEntry(const String & /// Дождемся, пока запись попадет в очередь реплики. while (true) { - zkutil::EventPtr event = new Poco::Event; + zkutil::EventPtr event = std::make_shared(); String log_pointer = zookeeper->get(zookeeper_path + "/replicas/" + replica + "/log_pointer", nullptr, event); if (!log_pointer.empty() && parse(log_pointer) > log_index) diff --git a/libs/libcommon/include/common/MultiVersion.h b/libs/libcommon/include/common/MultiVersion.h index 94960b3436f..acd93a1035e 100644 --- a/libs/libcommon/include/common/MultiVersion.h +++ b/libs/libcommon/include/common/MultiVersion.h @@ -24,7 +24,7 @@ template > class MultiVersion { public: - /// Конкретная версия объекта для использования. SharedPtr определяет время жизни версии. + /// Конкретная версия объекта для использования. shared_ptr определяет время жизни версии. using Version = Ptr; /// Инициализация по-умолчанию (NULL-ом). @@ -47,10 +47,10 @@ public: set(std::move(value)); } - /// Получить текущую версию для использования. Возвращает SharedPtr, который определяет время жизни версии. + /// Получить текущую версию для использования. Возвращает shared_ptr, который определяет время жизни версии. const Version get() const { - /// TODO: можно ли заменять SharedPtr lock-free? (Можно, если сделать свою реализацию с использованием cmpxchg16b.) + /// TODO: можно ли заменять shared_ptr lock-free? (Можно, если сделать свою реализацию с использованием cmpxchg16b.) std::lock_guard lock(mutex); return current_version; } diff --git a/libs/libmysqlxx/include/mysqlxx/Pool.h b/libs/libmysqlxx/include/mysqlxx/Pool.h index 5d1957e6244..7936dfb9c17 100644 --- a/libs/libmysqlxx/include/mysqlxx/Pool.h +++ b/libs/libmysqlxx/include/mysqlxx/Pool.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff --git a/libs/libmysqlxx/include/mysqlxx/PoolWithFailover.h b/libs/libmysqlxx/include/mysqlxx/PoolWithFailover.h index 41ccd991b51..f5b7d39aa73 100644 --- a/libs/libmysqlxx/include/mysqlxx/PoolWithFailover.h +++ b/libs/libmysqlxx/include/mysqlxx/PoolWithFailover.h @@ -64,7 +64,7 @@ namespace mysqlxx class PoolWithFailover final { private: - using PoolPtr = Poco::SharedPtr; + using PoolPtr = std::shared_ptr; struct Replica { @@ -86,7 +86,7 @@ namespace mysqlxx /// Количество попыток подключения. size_t max_tries; /// Mutex для доступа к списку реплик. - Poco::FastMutex mutex; + std::mutex mutex; public: using Entry = Pool::Entry; diff --git a/libs/libmysqlxx/src/PoolWithFailover.cpp b/libs/libmysqlxx/src/PoolWithFailover.cpp index 5fe4c64dfdf..f7ca6f20cc3 100644 --- a/libs/libmysqlxx/src/PoolWithFailover.cpp +++ b/libs/libmysqlxx/src/PoolWithFailover.cpp @@ -16,7 +16,7 @@ PoolWithFailover::PoolWithFailover(const Poco::Util::AbstractConfiguration & cfg if (*it == "replica") /// На том же уровне могут быть другие параметры. { std::string replica_name = config_name + "." + *it; - Replica replica(new Pool(cfg, replica_name, default_connections, max_connections, config_name.c_str()), + Replica replica(std::make_shared(cfg, replica_name, default_connections, max_connections, config_name.c_str()), cfg.getInt(replica_name + ".priority", 0)); replicas_by_priority[replica.priority].push_back(replica); } @@ -24,7 +24,7 @@ PoolWithFailover::PoolWithFailover(const Poco::Util::AbstractConfiguration & cfg } else { - replicas_by_priority[0].push_back(Replica(new Pool(cfg, config_name, default_connections, max_connections), 0)); + replicas_by_priority[0].push_back(Replica(std::make_shared(cfg, config_name, default_connections, max_connections), 0)); } } @@ -44,14 +44,14 @@ PoolWithFailover::PoolWithFailover(const PoolWithFailover & other) Replicas replicas; replicas.reserve(replica_with_priority.second.size()); for (const auto & replica : replica_with_priority.second) - replicas.emplace_back(new Pool{*replica.pool}, replica.priority); + replicas.emplace_back(std::make_shared(*replica.pool), replica.priority); replicas_by_priority.emplace(replica_with_priority.first, std::move(replicas)); } } PoolWithFailover::Entry PoolWithFailover::Get() { - Poco::ScopedLock locker(mutex); + std::lock_guard locker(mutex); Poco::Util::Application & app = Poco::Util::Application::instance(); /// Если к какой-то реплике не подключились, потому что исчерпан лимит соединений, можно подождать и подключиться к ней. diff --git a/libs/libzkutil/include/zkutil/LeaderElection.h b/libs/libzkutil/include/zkutil/LeaderElection.h index 2f383dcbe05..c92de3c5a6c 100644 --- a/libs/libzkutil/include/zkutil/LeaderElection.h +++ b/libs/libzkutil/include/zkutil/LeaderElection.h @@ -2,6 +2,7 @@ #include #include +#include #include @@ -79,7 +80,7 @@ private: std::thread thread; volatile bool shutdown = false; - zkutil::EventPtr event = new Poco::Event(); + zkutil::EventPtr event = std::make_shared(); State state = WAITING_LEADERSHIP; @@ -122,6 +123,6 @@ private: } }; -using LeaderElectionPtr = Poco::SharedPtr; +using LeaderElectionPtr = std::shared_ptr; } diff --git a/libs/libzkutil/include/zkutil/RWLock.h b/libs/libzkutil/include/zkutil/RWLock.h index 49b910427a2..f79caad44aa 100644 --- a/libs/libzkutil/include/zkutil/RWLock.h +++ b/libs/libzkutil/include/zkutil/RWLock.h @@ -70,7 +70,7 @@ private: private: GetZooKeeper get_zookeeper; - EventPtr event = new Poco::Event; + EventPtr event = std::make_shared(); CancellationHook cancellation_hook; /// Path to the lock request queue. std::string path; diff --git a/libs/libzkutil/include/zkutil/SingleBarrier.h b/libs/libzkutil/include/zkutil/SingleBarrier.h index cf9e9c7025c..9b26efee5d1 100644 --- a/libs/libzkutil/include/zkutil/SingleBarrier.h +++ b/libs/libzkutil/include/zkutil/SingleBarrier.h @@ -33,7 +33,7 @@ private: private: GetZooKeeper get_zookeeper; - EventPtr event = new Poco::Event; + EventPtr event = std::make_shared(); CancellationHook cancellation_hook; std::string path; std::string token; diff --git a/libs/libzkutil/include/zkutil/Types.h b/libs/libzkutil/include/zkutil/Types.h index 1fff66e8c8f..5326dd37ba4 100644 --- a/libs/libzkutil/include/zkutil/Types.h +++ b/libs/libzkutil/include/zkutil/Types.h @@ -2,10 +2,10 @@ #include #include #include +#include #include #include #include -#include #include namespace zkutil @@ -97,6 +97,6 @@ namespace CreateMode extern const int PersistentSequential; } -using EventPtr = Poco::SharedPtr; +using EventPtr = std::shared_ptr; } diff --git a/libs/libzkutil/src/ZooKeeper.cpp b/libs/libzkutil/src/ZooKeeper.cpp index 8e52ad82052..b18f421481c 100644 --- a/libs/libzkutil/src/ZooKeeper.cpp +++ b/libs/libzkutil/src/ZooKeeper.cpp @@ -586,7 +586,7 @@ void ZooKeeper::waitForDisappear(const std::string & path) { while (true) { - zkutil::EventPtr event = new Poco::Event; + zkutil::EventPtr event = std::make_shared(); std::string unused; /// get вместо exists, чтобы не утек watch, если ноды уже нет. diff --git a/libs/libzkutil/src/tests/zkutil_test.cpp b/libs/libzkutil/src/tests/zkutil_test.cpp index 9ea3ddbac12..d24fa4a937f 100644 --- a/libs/libzkutil/src/tests/zkutil_test.cpp +++ b/libs/libzkutil/src/tests/zkutil_test.cpp @@ -94,7 +94,7 @@ int main(int argc, char ** argv) std::string w; ss >> w; bool watch = w == "w"; - zkutil::EventPtr event = watch ? new Poco::Event() : nullptr; + zkutil::EventPtr event = watch ? std::make_shared() : nullptr; std::vector v = zk.getChildren(path, nullptr, event); for (size_t i = 0; i < v.size(); ++i) { @@ -148,7 +148,7 @@ int main(int argc, char ** argv) std::string w; ss >> w; bool watch = w == "w"; - zkutil::EventPtr event = watch ? new Poco::Event() : nullptr; + zkutil::EventPtr event = watch ? std::make_shared() : nullptr; zkutil::Stat stat; bool e = zk.exists(path, &stat, event); if (e) @@ -163,7 +163,7 @@ int main(int argc, char ** argv) std::string w; ss >> w; bool watch = w == "w"; - zkutil::EventPtr event = watch ? new Poco::Event() : nullptr; + zkutil::EventPtr event = watch ? std::make_shared() : nullptr; zkutil::Stat stat; std::string data = zk.get(path, &stat, event); std::cout << "Data: " << data << std::endl; diff --git a/libs/libzkutil/src/tests/zkutil_test_commands.cpp b/libs/libzkutil/src/tests/zkutil_test_commands.cpp index f4f3a48dbaa..2321109ef33 100644 --- a/libs/libzkutil/src/tests/zkutil_test_commands.cpp +++ b/libs/libzkutil/src/tests/zkutil_test_commands.cpp @@ -17,7 +17,7 @@ int main() std::cout << "create path" << std::endl; zk.create("/test", "old", zkutil::CreateMode::Persistent); zkutil::Stat stat; - zkutil::EventPtr watch = new Poco::Event; + zkutil::EventPtr watch = std::make_shared(); std::cout << "get path" << std::endl; zk.get("/test", &stat, watch); diff --git a/utils/iotest/iotest.cpp b/utils/iotest/iotest.cpp index 4c1874d361c..da70ab519c4 100644 --- a/utils/iotest/iotest.cpp +++ b/utils/iotest/iotest.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include diff --git a/utils/iotest/iotest_aio.cpp b/utils/iotest/iotest_aio.cpp index a412d7894b7..6656e839204 100644 --- a/utils/iotest/iotest_aio.cpp +++ b/utils/iotest/iotest_aio.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include diff --git a/utils/iotest/iotest_nonblock.cpp b/utils/iotest/iotest_nonblock.cpp index 51b2a4099ff..6016d7bef78 100644 --- a/utils/iotest/iotest_nonblock.cpp +++ b/utils/iotest/iotest_nonblock.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include