• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef PLATFORM_API_SERIAL_DELETE_PTR_H_
6 #define PLATFORM_API_SERIAL_DELETE_PTR_H_
7 
8 #include <cassert>
9 #include <memory>
10 #include <utility>
11 
12 #include "platform/api/task_runner.h"
13 
14 namespace openscreen {
15 
16 // A functor that deletes an object via a task on a specific TaskRunner. This is
17 // used for ensuring an object is deleted after any tasks that reference it have
18 // completed.
19 template <typename Type, typename DeleterType>
20 class SerialDelete {
21  public:
SerialDelete()22   SerialDelete() : deleter_() {}
23 
SerialDelete(TaskRunner * task_runner)24   explicit SerialDelete(TaskRunner* task_runner)
25       : task_runner_(task_runner), deleter_() {
26     assert(task_runner);
27   }
28 
29   template <typename DT>
SerialDelete(TaskRunner * task_runner,DT && deleter)30   SerialDelete(TaskRunner* task_runner, DT&& deleter)
31       : task_runner_(task_runner), deleter_(std::forward<DT>(deleter)) {
32     assert(task_runner);
33   }
34 
operator()35   void operator()(Type* pointer) const {
36     if (task_runner_) {
37       // Deletion of the object depends on the task being run by the task
38       // runner.
39       task_runner_->PostTask(
40           [pointer, deleter = std::move(deleter_)] { deleter(pointer); });
41     }
42   }
43 
44  private:
45   TaskRunner* task_runner_;
46   DeleterType deleter_;
47 };
48 
49 // A wrapper around std::unique_ptr<> that uses SerialDelete<> to schedule the
50 // object's deletion.
51 template <typename Type, typename DeleterType = std::default_delete<Type>>
52 class SerialDeletePtr
53     : public std::unique_ptr<Type, SerialDelete<Type, DeleterType>> {
54  public:
SerialDeletePtr()55   SerialDeletePtr() noexcept
56       : std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
57             nullptr,
58             SerialDelete<Type, DeleterType>()) {}
59 
SerialDeletePtr(TaskRunner * task_runner)60   explicit SerialDeletePtr(TaskRunner* task_runner) noexcept
61       : std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
62             nullptr,
63             SerialDelete<Type, DeleterType>(task_runner)) {
64     assert(task_runner);
65   }
66 
SerialDeletePtr(TaskRunner * task_runner,std::nullptr_t)67   SerialDeletePtr(TaskRunner* task_runner, std::nullptr_t) noexcept
68       : std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
69             nullptr,
70             SerialDelete<Type, DeleterType>(task_runner)) {
71     assert(task_runner);
72   }
73 
SerialDeletePtr(TaskRunner * task_runner,Type * pointer)74   SerialDeletePtr(TaskRunner* task_runner, Type* pointer) noexcept
75       : std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
76             pointer,
77             SerialDelete<Type, DeleterType>(task_runner)) {
78     assert(task_runner);
79   }
80 
SerialDeletePtr(TaskRunner * task_runner,Type * pointer,typename std::conditional<std::is_reference<DeleterType>::value,DeleterType,const DeleterType &>::type deleter)81   SerialDeletePtr(
82       TaskRunner* task_runner,
83       Type* pointer,
84       typename std::conditional<std::is_reference<DeleterType>::value,
85                                 DeleterType,
86                                 const DeleterType&>::type deleter) noexcept
87       : std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
88             pointer,
89             SerialDelete<Type, DeleterType>(task_runner, deleter)) {
90     assert(task_runner);
91   }
92 
SerialDeletePtr(TaskRunner * task_runner,Type * pointer,typename std::remove_reference<DeleterType>::type && deleter)93   SerialDeletePtr(
94       TaskRunner* task_runner,
95       Type* pointer,
96       typename std::remove_reference<DeleterType>::type&& deleter) noexcept
97       : std::unique_ptr<Type, SerialDelete<Type, DeleterType>>(
98             pointer,
99             SerialDelete<Type, DeleterType>(task_runner, std::move(deleter))) {
100     assert(task_runner);
101   }
102 };
103 
104 template <typename Type, typename... Args>
MakeSerialDelete(TaskRunner * task_runner,Args &&...args)105 SerialDeletePtr<Type> MakeSerialDelete(TaskRunner* task_runner,
106                                        Args&&... args) {
107   return SerialDeletePtr<Type>(task_runner,
108                                new Type(std::forward<Args>(args)...));
109 }
110 
111 }  // namespace openscreen
112 
113 #endif  // PLATFORM_API_SERIAL_DELETE_PTR_H_
114