1 // Copyright 2023 The gRPC Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://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, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_CF_ENGINE_CFTYPE_UNIQUE_REF_H 15 #define GRPC_SRC_CORE_LIB_EVENT_ENGINE_CF_ENGINE_CFTYPE_UNIQUE_REF_H 16 #include <grpc/support/port_platform.h> 17 18 #ifdef GPR_APPLE 19 #include <AvailabilityMacros.h> 20 #ifdef AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER 21 22 #include <CoreFoundation/CoreFoundation.h> 23 24 namespace grpc_event_engine { 25 namespace experimental { 26 27 template <typename T> 28 class CFTypeUniqueRef { 29 static_assert(std::is_convertible<T, CFTypeRef>::value, 30 "T should be `CFXxxRef` type"); 31 32 public: 33 /* implicit */ cf_type_ref_(cf_type_ref)34 CFTypeUniqueRef(T cf_type_ref = nullptr) : cf_type_ref_(cf_type_ref) {} ~CFTypeUniqueRef()35 ~CFTypeUniqueRef() { reset(); } 36 37 CFTypeUniqueRef(CFTypeUniqueRef const&) = delete; 38 CFTypeUniqueRef& operator=(CFTypeUniqueRef const&) = delete; 39 CFTypeUniqueRef(CFTypeUniqueRef && other)40 CFTypeUniqueRef(CFTypeUniqueRef&& other) : cf_type_ref_(other.release()) {}; 41 CFTypeUniqueRef& operator=(CFTypeUniqueRef&& other) { 42 reset(other.release()); 43 return *this; 44 } 45 T()46 operator T() { return cf_type_ref_; } 47 48 // Note: this is for passing a CFTypeRef as output parameter to a CF API, the 49 // current ref is released (if any) regardless of whether new value is set 50 T* operator&() { 51 reset(); 52 return &cf_type_ref_; 53 } 54 release()55 T release() { 56 T old = cf_type_ref_; 57 cf_type_ref_ = nullptr; 58 return old; 59 } 60 61 void reset(T other = nullptr) { 62 if (cf_type_ref_ == other) { 63 return; 64 } 65 T old = cf_type_ref_; 66 cf_type_ref_ = other; 67 if (old) { 68 CFRelease(old); 69 } 70 } 71 72 private: 73 T cf_type_ref_; 74 }; 75 76 } // namespace experimental 77 } // namespace grpc_event_engine 78 79 #endif // AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER 80 #endif // GPR_APPLE 81 82 #endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_CF_ENGINE_CFTYPE_UNIQUE_REF_H 83