xref: /aosp_15_r20/external/executorch/runtime/core/freeable_buffer.h (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #pragma once
10 
11 #include <cstddef>
12 
13 namespace executorch {
14 namespace runtime {
15 
16 /**
17  * A read-only buffer than can be freed.
18  */
19 class FreeableBuffer final {
20  public:
21   // Callback signature for the function that does the freeing.
22   using FreeFn = void (*)(void* context, void* data, size_t size);
23 
24   /**
25    * Creates an empty FreeableBuffer with size zero and a null data pointer.
26    */
FreeableBuffer()27   FreeableBuffer()
28       : free_fn_(nullptr),
29         free_fn_context_(nullptr),
30         data_(nullptr),
31         size_(0) {}
32 
33   /**
34    * Creates a FreeableBuffer with an optional free function.
35    *
36    * @param[in] data The data of the segment.
37    * @param[in] size The size of the segment data, in bytes.
38    * @param[in] free_fn Optional function to free the data. Guaranteed to be
39    *     called exactly once before the FreeableBuffer is destroyed. May be
40    *     nullptr. NOTE: This function must be thread-safe. If it modifies common
41    *     state, the function must do its own locking.
42    * @param[in] free_fn_context Opaque pointer to pass as the `context`
43    *     parameter of `free_fn`. May be nullptr.
44    */
45   FreeableBuffer(
46       const void* data,
47       size_t size,
48       FreeFn free_fn,
49       void* free_fn_context = nullptr)
free_fn_(free_fn)50       : free_fn_(free_fn),
51         free_fn_context_(free_fn_context),
52         data_(data),
53         size_(size) {}
54 
55   /**
56    * Move ctor. Takes the ownership of the data previously owned by `rhs`,
57    * leaving `rhs` pointing to nullptr.
58    */
FreeableBuffer(FreeableBuffer && rhs)59   FreeableBuffer(FreeableBuffer&& rhs) noexcept
60       : free_fn_(rhs.free_fn_),
61         free_fn_context_(rhs.free_fn_context_),
62         data_(rhs.data_),
63         size_(rhs.size_) {
64     rhs.free_fn_ = nullptr;
65     rhs.free_fn_context_ = nullptr;
66     rhs.data_ = nullptr;
67     rhs.size_ = 0;
68   }
69 
~FreeableBuffer()70   ~FreeableBuffer() {
71     Free();
72   }
73 
74   /**
75    * Frees the data if not already free. Safe to call multiple times.
76    */
Free()77   void Free() {
78     if (data_ != nullptr) {
79       if (free_fn_ != nullptr) {
80         free_fn_(free_fn_context_, const_cast<void*>(data_), size_);
81       }
82       data_ = nullptr;
83       size_ = 0;
84     }
85   }
86 
87   /**
88    * Size of the data in bytes. Returns 0 if the data has been freed.
89    */
size()90   size_t size() const {
91     return size_;
92   }
93 
94   /**
95    * Pointer to the data. Returns nullptr if the data has been freed.
96    */
data()97   const void* data() const {
98     return data_;
99   }
100 
101  private:
102   // Delete other rule-of-five methods.
103   FreeableBuffer(const FreeableBuffer& rhs) = delete;
104   FreeableBuffer& operator=(FreeableBuffer&& rhs) noexcept = delete;
105   FreeableBuffer& operator=(const FreeableBuffer& rhs) = delete;
106 
107   FreeFn free_fn_;
108   void* free_fn_context_;
109   const void* data_;
110   size_t size_;
111 };
112 
113 } // namespace runtime
114 } // namespace executorch
115 
116 namespace torch {
117 namespace executor {
118 // TODO(T197294990): Remove these deprecated aliases once all users have moved
119 // to the new `::executorch` namespaces.
120 using ::executorch::runtime::FreeableBuffer;
121 } // namespace executor
122 } // namespace torch
123