scoped_cftyperef.h revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_MAC_SCOPED_CFTYPEREF_H_
6#define BASE_MAC_SCOPED_CFTYPEREF_H_
7
8#include <CoreFoundation/CoreFoundation.h>
9
10#include "base/basictypes.h"
11#include "base/compiler_specific.h"
12#include "base/memory/scoped_policy.h"
13
14namespace base {
15
16// ScopedCFTypeRef<> is patterned after scoped_ptr<>, but maintains ownership
17// of a CoreFoundation object: any object that can be represented as a
18// CFTypeRef.  Style deviations here are solely for compatibility with
19// scoped_ptr<>'s interface, with which everyone is already familiar.
20//
21// By default, ScopedCFTypeRef<> takes ownership of an object (in the
22// constructor or in reset()) by taking over the caller's existing ownership
23// claim.  The caller must own the object it gives to ScopedCFTypeRef<>, and
24// relinquishes an ownership claim to that object.  ScopedCFTypeRef<> does not
25// call CFRetain(). This behavior is parameterized by the |OwnershipPolicy|
26// enum. If the value |RETAIN| is passed (in the constructor or in reset()),
27// then ScopedCFTypeRef<> will call CFRetain() on the object, and the initial
28// ownership is not changed.
29
30template<typename CFT>
31class ScopedCFTypeRef {
32 public:
33  typedef CFT element_type;
34
35  explicit ScopedCFTypeRef(
36      CFT object = NULL,
37      base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME)
38      : object_(object) {
39    if (object_ && policy == base::scoped_policy::RETAIN)
40      CFRetain(object_);
41  }
42
43  ScopedCFTypeRef(const ScopedCFTypeRef<CFT>& that)
44      : object_(that.object_) {
45    if (object_)
46      CFRetain(object_);
47  }
48
49  ~ScopedCFTypeRef() {
50    if (object_)
51      CFRelease(object_);
52  }
53
54  ScopedCFTypeRef& operator=(const ScopedCFTypeRef<CFT>& that) {
55    reset(that.get(), base::scoped_policy::RETAIN);
56    return *this;
57  }
58
59  void reset(CFT object = NULL,
60             base::scoped_policy::OwnershipPolicy policy =
61                base::scoped_policy::ASSUME) {
62    if (object && policy == base::scoped_policy::RETAIN)
63      CFRetain(object);
64    if (object_)
65      CFRelease(object_);
66    object_ = object;
67  }
68
69  bool operator==(CFT that) const {
70    return object_ == that;
71  }
72
73  bool operator!=(CFT that) const {
74    return object_ != that;
75  }
76
77  operator CFT() const {
78    return object_;
79  }
80
81  CFT get() const {
82    return object_;
83  }
84
85  void swap(ScopedCFTypeRef& that) {
86    CFT temp = that.object_;
87    that.object_ = object_;
88    object_ = temp;
89  }
90
91  // ScopedCFTypeRef<>::release() is like scoped_ptr<>::release.  It is NOT
92  // a wrapper for CFRelease().  To force a ScopedCFTypeRef<> object to call
93  // CFRelease(), use ScopedCFTypeRef<>::reset().
94  CFT release() WARN_UNUSED_RESULT {
95    CFT temp = object_;
96    object_ = NULL;
97    return temp;
98  }
99
100 private:
101  CFT object_;
102};
103
104}  // namespace base
105
106#endif  // BASE_MAC_SCOPED_CFTYPEREF_H_
107