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