|  | // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_MAC_SCOPED_BLOCK_H_ | 
|  | #define BASE_MAC_SCOPED_BLOCK_H_ | 
|  |  | 
|  | #include <Block.h> | 
|  |  | 
|  | #include "base/mac/scoped_typeref.h" | 
|  |  | 
|  | #if defined(__has_feature) && __has_feature(objc_arc) | 
|  | #define BASE_MAC_BRIDGE_CAST(TYPE, VALUE) (__bridge TYPE)(VALUE) | 
|  | #else | 
|  | #define BASE_MAC_BRIDGE_CAST(TYPE, VALUE) VALUE | 
|  | #endif | 
|  |  | 
|  | namespace base { | 
|  | namespace mac { | 
|  |  | 
|  | namespace internal { | 
|  |  | 
|  | template <typename B> | 
|  | struct ScopedBlockTraits { | 
|  | static B InvalidValue() { return nullptr; } | 
|  | static B Retain(B block) { | 
|  | return BASE_MAC_BRIDGE_CAST( | 
|  | B, Block_copy(BASE_MAC_BRIDGE_CAST(const void*, block))); | 
|  | } | 
|  | static void Release(B block) { | 
|  | Block_release(BASE_MAC_BRIDGE_CAST(const void*, block)); | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace internal | 
|  |  | 
|  | // ScopedBlock<> is patterned after ScopedCFTypeRef<>, but uses Block_copy() and | 
|  | // Block_release() instead of CFRetain() and CFRelease(). | 
|  | template <typename B> | 
|  | class ScopedBlock : public ScopedTypeRef<B, internal::ScopedBlockTraits<B>> { | 
|  | public: | 
|  | using Traits = internal::ScopedBlockTraits<B>; | 
|  |  | 
|  | #if !defined(__has_feature) || !__has_feature(objc_arc) | 
|  | explicit ScopedBlock( | 
|  | B block = Traits::InvalidValue(), | 
|  | base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) | 
|  | : ScopedTypeRef<B, Traits>(block, policy) {} | 
|  | #else | 
|  | explicit ScopedBlock(B block = Traits::InvalidValue()) | 
|  | : ScopedTypeRef<B, Traits>(block, base::scoped_policy::RETAIN) {} | 
|  | #endif | 
|  |  | 
|  | #if !defined(__has_feature) || !__has_feature(objc_arc) | 
|  | void reset(B block = Traits::InvalidValue(), | 
|  | base::scoped_policy::OwnershipPolicy policy = | 
|  | base::scoped_policy::ASSUME) { | 
|  | ScopedTypeRef<B, Traits>::reset(block, policy); | 
|  | } | 
|  | #else | 
|  | void reset(B block = Traits::InvalidValue()) { | 
|  | ScopedTypeRef<B, Traits>::reset(block, base::scoped_policy::RETAIN); | 
|  | } | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | }  // namespace mac | 
|  | }  // namespace base | 
|  |  | 
|  | #undef BASE_MAC_BRIDGE_CAST | 
|  |  | 
|  | #endif  // BASE_MAC_SCOPED_BLOCK_H_ |