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