You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.5 KiB
114 lines
3.5 KiB
// 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 PLATFORM_API_SERIAL_DELETE_PTR_H_
|
|
#define PLATFORM_API_SERIAL_DELETE_PTR_H_
|
|
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#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 <typename Type, typename DeleterType>
|
|
class SerialDelete {
|
|
public:
|
|
SerialDelete() : deleter_() {}
|
|
|
|
explicit SerialDelete(TaskRunner* task_runner)
|
|
: task_runner_(task_runner), deleter_() {
|
|
assert(task_runner);
|
|
}
|
|
|
|
template <typename DT>
|
|
SerialDelete(TaskRunner* task_runner, DT&& deleter)
|
|
: task_runner_(task_runner), deleter_(std::forward<DT>(deleter)) {
|
|
assert(task_runner);
|
|
}
|
|
|
|
void operator()(Type* pointer) const {
|
|
if (task_runner_) {
|
|
// Deletion of the object depends on the task being run by the task
|
|
// runner.
|
|
task_runner_->PostTask(
|
|
[pointer, deleter = std::move(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 <typename Type, typename DeleterType = std::default_delete<Type>>
|
|
class SerialDeletePtr
|
|
: public std::unique_ptr<Type, SerialDelete<Type, DeleterType>> {
|
|
public:
|
|
SerialDeletePtr() noexcept
|
|
: std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
|
|
nullptr,
|
|
SerialDelete<Type, DeleterType>()) {}
|
|
|
|
explicit SerialDeletePtr(TaskRunner* task_runner) noexcept
|
|
: std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
|
|
nullptr,
|
|
SerialDelete<Type, DeleterType>(task_runner)) {
|
|
assert(task_runner);
|
|
}
|
|
|
|
SerialDeletePtr(TaskRunner* task_runner, std::nullptr_t) noexcept
|
|
: std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
|
|
nullptr,
|
|
SerialDelete<Type, DeleterType>(task_runner)) {
|
|
assert(task_runner);
|
|
}
|
|
|
|
SerialDeletePtr(TaskRunner* task_runner, Type* pointer) noexcept
|
|
: std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
|
|
pointer,
|
|
SerialDelete<Type, DeleterType>(task_runner)) {
|
|
assert(task_runner);
|
|
}
|
|
|
|
SerialDeletePtr(
|
|
TaskRunner* task_runner,
|
|
Type* pointer,
|
|
typename std::conditional<std::is_reference<DeleterType>::value,
|
|
DeleterType,
|
|
const DeleterType&>::type deleter) noexcept
|
|
: std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
|
|
pointer,
|
|
SerialDelete<Type, DeleterType>(task_runner, deleter)) {
|
|
assert(task_runner);
|
|
}
|
|
|
|
SerialDeletePtr(
|
|
TaskRunner* task_runner,
|
|
Type* pointer,
|
|
typename std::remove_reference<DeleterType>::type&& deleter) noexcept
|
|
: std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
|
|
pointer,
|
|
SerialDelete<Type, DeleterType>(task_runner, std::move(deleter))) {
|
|
assert(task_runner);
|
|
}
|
|
};
|
|
|
|
template <typename Type, typename... Args>
|
|
SerialDeletePtr<Type> MakeSerialDelete(TaskRunner* task_runner,
|
|
Args&&... args) {
|
|
return SerialDeletePtr<Type>(task_runner,
|
|
new Type(std::forward<Args>(args)...));
|
|
}
|
|
|
|
} // namespace openscreen
|
|
|
|
#endif // PLATFORM_API_SERIAL_DELETE_PTR_H_
|