// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef UTIL_SERIAL_DELETE_PTR_H_ #define UTIL_SERIAL_DELETE_PTR_H_ #include #include #include #include "platform/api/task_runner.h" namespace openscreen { // A functor that deletes an object via a task on a specific TaskRunner. This is // used for ensuring an object is deleted after any tasks that reference it have // completed. template class SerialDelete { public: explicit SerialDelete(TaskRunner* task_runner) : task_runner_(task_runner), deleter_() { assert(task_runner); } template SerialDelete(TaskRunner* task_runner, DT&& deleter) : task_runner_(task_runner), deleter_(std::forward
(deleter)) { assert(task_runner); } void operator()(Type* pointer) const { // Deletion of the object depends on the task being run by the task runner. task_runner_->PostTask([pointer, deleter = deleter_] { deleter(pointer); }); } private: TaskRunner* task_runner_; DeleterType deleter_; }; // A wrapper around std::unique_ptr<> that uses SerialDelete<> to schedule the // object's deletion. template > class SerialDeletePtr : public std::unique_ptr> { public: explicit SerialDeletePtr(TaskRunner* task_runner) noexcept : std::unique_ptr>( nullptr, SerialDelete(task_runner)) { assert(task_runner); } SerialDeletePtr(TaskRunner* task_runner, std::nullptr_t) noexcept : std::unique_ptr>( nullptr, SerialDelete(task_runner)) { assert(task_runner); } SerialDeletePtr(TaskRunner* task_runner, Type* pointer) noexcept : std::unique_ptr>( pointer, SerialDelete(task_runner)) { assert(task_runner); } SerialDeletePtr( TaskRunner* task_runner, Type* pointer, typename std::conditional::value, DeleterType, const DeleterType&>::type deleter) noexcept : std::unique_ptr>( pointer, SerialDelete(task_runner, deleter)) { assert(task_runner); } SerialDeletePtr( TaskRunner* task_runner, Type* pointer, typename std::remove_reference::type&& deleter) noexcept : std::unique_ptr>( pointer, SerialDelete(task_runner, std::move(deleter))) { assert(task_runner); } }; template SerialDeletePtr MakeSerialDelete(TaskRunner* task_runner, Args&&... args) { return SerialDeletePtr(task_runner, new Type(std::forward(args)...)); } } // namespace openscreen #endif // UTIL_SERIAL_DELETE_PTR_H_