1 // Copyright 2022 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <memory> 17 #include <type_traits> 18 19 namespace pw::bluetooth::internal { 20 21 // Helper deleter struct to call the OnDestroy template parameter method when 22 // RaiiPtr<Api, OnDestroy> is destroyed. 23 template <class Api, void (Api::*OnDestroy)()> 24 struct RaiiPtrDeleter { operatorRaiiPtrDeleter25 void operator()(Api* api) { (api->*OnDestroy)(); } 26 }; 27 28 // Smart pointer class to expose an API with RAII semantics that calls a 29 // specific method of the API implementation when it is destroyed, instead of 30 // calling delete on the API object like the default std::unique_ptr deleter 31 // behavior. This allows to be used like if it was a std::unique_ptr<API> but 32 // leaving the memory management implementation details up to the backend 33 // implementing the API. 34 // 35 // Example usage: 36 // class SomeApi { 37 // public: 38 // virtual ~SomeApi() = default; 39 // 40 // virtual void MethodOne() = 0; 41 // virtual void MethodTwo(int) = 0; 42 // 43 // private: 44 // // Method used to release the resource in the backend. 45 // virtual void DeleteResource() = 0; 46 // 47 // public: 48 // using Ptr = RaiiPtr<SomeApi, &SomeApi::DeleteResource>; 49 // }; 50 // 51 // // The concrete backend implementation. 52 // class BackendImplementation final : public SomeApi { 53 // public: 54 // void MethodOne() override { ... } 55 // void MethodTwo(int) override { ... } 56 // void DeleteResource() override { ... } 57 // }; 58 // 59 // // Example using a static global resource object. GetResource should check 60 // // whether the global resource is in use. 61 // BackendImplementation backend_impl; 62 // SomeApi::Ptr GetResource() { ...; return &backend_impl; } 63 // 64 template <class Api, void (Api::*OnDestroy)()> 65 using RaiiPtr = std::unique_ptr<Api, RaiiPtrDeleter<Api, OnDestroy>>; 66 67 } // namespace pw::bluetooth::internal 68