| // 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_ |