|
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_WIN_SCOPED_HANDLE_H_ |
|
6 #define BASE_WIN_SCOPED_HANDLE_H_ |
|
7 |
|
8 #include <windows.h> |
|
9 |
|
10 #include "base/base_export.h" |
|
11 #include "base/basictypes.h" |
|
12 #include "base/location.h" |
|
13 #include "base/logging.h" |
|
14 #include "base/move.h" |
|
15 |
|
16 namespace base { |
|
17 namespace win { |
|
18 |
|
19 // TODO(rvargas): remove this with the rest of the verifier. |
|
20 #if defined(COMPILER_MSVC) |
|
21 // MSDN says to #include <intrin.h>, but that breaks the VS2005 build. |
|
22 extern "C" { |
|
23 void* _ReturnAddress(); |
|
24 } |
|
25 #define BASE_WIN_GET_CALLER _ReturnAddress() |
|
26 #elif defined(COMPILER_GCC) |
|
27 #define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\ |
|
28 __builtin_return_address(0)) |
|
29 #endif |
|
30 |
|
31 // Generic wrapper for raw handles that takes care of closing handles |
|
32 // automatically. The class interface follows the style of |
|
33 // the ScopedStdioHandle class with a few additions: |
|
34 // - IsValid() method can tolerate multiple invalid handle values such as NULL |
|
35 // and INVALID_HANDLE_VALUE (-1) for Win32 handles. |
|
36 // - Receive() method allows to receive a handle value from a function that |
|
37 // takes a raw handle pointer only. |
|
38 template <class Traits, class Verifier> |
|
39 class GenericScopedHandle { |
|
40 MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue) |
|
41 |
|
42 public: |
|
43 typedef typename Traits::Handle Handle; |
|
44 |
|
45 // Helper object to contain the effect of Receive() to the function that needs |
|
46 // a pointer, and allow proper tracking of the handle. |
|
47 class Receiver { |
|
48 public: |
|
49 explicit Receiver(GenericScopedHandle* owner) |
|
50 : handle_(Traits::NullHandle()), |
|
51 owner_(owner) {} |
|
52 ~Receiver() { owner_->Set(handle_); } |
|
53 |
|
54 operator Handle*() { return &handle_; } |
|
55 |
|
56 private: |
|
57 Handle handle_; |
|
58 GenericScopedHandle* owner_; |
|
59 }; |
|
60 |
|
61 GenericScopedHandle() : handle_(Traits::NullHandle()) {} |
|
62 |
|
63 explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { |
|
64 Set(handle); |
|
65 } |
|
66 |
|
67 // Move constructor for C++03 move emulation of this type. |
|
68 GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) { |
|
69 Set(other.object->Take()); |
|
70 } |
|
71 |
|
72 ~GenericScopedHandle() { |
|
73 Close(); |
|
74 } |
|
75 |
|
76 bool IsValid() const { |
|
77 return Traits::IsHandleValid(handle_); |
|
78 } |
|
79 |
|
80 // Move operator= for C++03 move emulation of this type. |
|
81 GenericScopedHandle& operator=(RValue other) { |
|
82 if (this != other.object) { |
|
83 Set(other.object->Take()); |
|
84 } |
|
85 return *this; |
|
86 } |
|
87 |
|
88 void Set(Handle handle) { |
|
89 if (handle_ != handle) { |
|
90 Close(); |
|
91 |
|
92 if (Traits::IsHandleValid(handle)) { |
|
93 handle_ = handle; |
|
94 Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER, |
|
95 tracked_objects::GetProgramCounter()); |
|
96 } |
|
97 } |
|
98 } |
|
99 |
|
100 Handle Get() const { |
|
101 return handle_; |
|
102 } |
|
103 |
|
104 operator Handle() const { |
|
105 return handle_; |
|
106 } |
|
107 |
|
108 // This method is intended to be used with functions that require a pointer to |
|
109 // a destination handle, like so: |
|
110 // void CreateRequiredHandle(Handle* out_handle); |
|
111 // ScopedHandle a; |
|
112 // CreateRequiredHandle(a.Receive()); |
|
113 Receiver Receive() { |
|
114 DCHECK(!Traits::IsHandleValid(handle_)) << "Handle must be NULL"; |
|
115 return Receiver(this); |
|
116 } |
|
117 |
|
118 // Transfers ownership away from this object. |
|
119 Handle Take() { |
|
120 Handle temp = handle_; |
|
121 handle_ = Traits::NullHandle(); |
|
122 if (Traits::IsHandleValid(temp)) { |
|
123 Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER, |
|
124 tracked_objects::GetProgramCounter()); |
|
125 } |
|
126 return temp; |
|
127 } |
|
128 |
|
129 // Explicitly closes the owned handle. |
|
130 void Close() { |
|
131 if (Traits::IsHandleValid(handle_)) { |
|
132 Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER, |
|
133 tracked_objects::GetProgramCounter()); |
|
134 |
|
135 if (!Traits::CloseHandle(handle_)) |
|
136 CHECK(false); |
|
137 |
|
138 handle_ = Traits::NullHandle(); |
|
139 } |
|
140 } |
|
141 |
|
142 private: |
|
143 Handle handle_; |
|
144 }; |
|
145 |
|
146 #undef BASE_WIN_GET_CALLER |
|
147 |
|
148 // The traits class for Win32 handles that can be closed via CloseHandle() API. |
|
149 class HandleTraits { |
|
150 public: |
|
151 typedef HANDLE Handle; |
|
152 |
|
153 // Closes the handle. |
|
154 static bool CloseHandle(HANDLE handle) { |
|
155 return ::CloseHandle(handle) != FALSE; |
|
156 } |
|
157 |
|
158 // Returns true if the handle value is valid. |
|
159 static bool IsHandleValid(HANDLE handle) { |
|
160 return handle != NULL && handle != INVALID_HANDLE_VALUE; |
|
161 } |
|
162 |
|
163 // Returns NULL handle value. |
|
164 static HANDLE NullHandle() { |
|
165 return NULL; |
|
166 } |
|
167 |
|
168 private: |
|
169 DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits); |
|
170 }; |
|
171 |
|
172 // Do-nothing verifier. |
|
173 class DummyVerifierTraits { |
|
174 public: |
|
175 typedef HANDLE Handle; |
|
176 |
|
177 static void StartTracking(HANDLE handle, const void* owner, |
|
178 const void* pc1, const void* pc2) {} |
|
179 static void StopTracking(HANDLE handle, const void* owner, |
|
180 const void* pc1, const void* pc2) {} |
|
181 |
|
182 private: |
|
183 DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits); |
|
184 }; |
|
185 |
|
186 // Performs actual run-time tracking. |
|
187 class BASE_EXPORT VerifierTraits { |
|
188 public: |
|
189 typedef HANDLE Handle; |
|
190 |
|
191 static void StartTracking(HANDLE handle, const void* owner, |
|
192 const void* pc1, const void* pc2); |
|
193 static void StopTracking(HANDLE handle, const void* owner, |
|
194 const void* pc1, const void* pc2); |
|
195 |
|
196 private: |
|
197 DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits); |
|
198 }; |
|
199 |
|
200 typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle; |
|
201 |
|
202 } // namespace win |
|
203 } // namespace base |
|
204 |
|
205 #endif // BASE_SCOPED_HANDLE_WIN_H_ |