Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(640)

Side by Side Diff: include/core/SkRefCnt.h

Issue 1773453002: Add element_type, swap, operators, fix reset on sk_sp. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Clang! You were the chosen one! Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | include/private/SkTLogic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkRefCnt_DEFINED 8 #ifndef SkRefCnt_DEFINED
9 #define SkRefCnt_DEFINED 9 #define SkRefCnt_DEFINED
10 10
11 #include "../private/SkAtomics.h" 11 #include "../private/SkAtomics.h"
12 #include "../private/SkUniquePtr.h" 12 #include "../private/SkUniquePtr.h"
13 #include "SkTypes.h" 13 #include "SkTypes.h"
14 #include <functional>
14 #include <utility> 15 #include <utility>
15 16
16 /** \class SkRefCntBase 17 /** \class SkRefCntBase
17 18
18 SkRefCntBase is the base class for objects that may be shared by multiple 19 SkRefCntBase is the base class for objects that may be shared by multiple
19 objects. When an existing owner wants to share a reference, it calls ref(). 20 objects. When an existing owner wants to share a reference, it calls ref().
20 When an owner wants to release its reference, it calls unref(). When the 21 When an owner wants to release its reference, it calls unref(). When the
21 shared object's reference count goes to zero as the result of an unref() 22 shared object's reference count goes to zero as the result of an unref()
22 call, its (virtual) destructor is called. It is an error for the 23 call, its (virtual) destructor is called. It is an error for the
23 destructor to be called explicitly (or via the object going out of scope on 24 destructor to be called explicitly (or via the object going out of scope on
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 * Shared pointer class to wrap classes that support a ref()/unref() interface. 235 * Shared pointer class to wrap classes that support a ref()/unref() interface.
235 * 236 *
236 * This can be used for classes inheriting from SkRefCnt, but it also works for other 237 * This can be used for classes inheriting from SkRefCnt, but it also works for other
237 * classes that match the interface, but have different internal choices: e.g. the hosted class 238 * classes that match the interface, but have different internal choices: e.g. the hosted class
238 * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk _sp. 239 * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk _sp.
239 */ 240 */
240 template <typename T> class sk_sp { 241 template <typename T> class sk_sp {
241 /** Supports safe bool idiom. Obsolete with explicit operator bool. */ 242 /** Supports safe bool idiom. Obsolete with explicit operator bool. */
242 using unspecified_bool_type = T* sk_sp::*; 243 using unspecified_bool_type = T* sk_sp::*;
243 public: 244 public:
245 using element_type = T;
246
244 sk_sp() : fPtr(nullptr) {} 247 sk_sp() : fPtr(nullptr) {}
245 sk_sp(std::nullptr_t) : fPtr(nullptr) {} 248 sk_sp(std::nullptr_t) : fPtr(nullptr) {}
246 249
247 /** 250 /**
248 * Shares the underlying object by calling ref(), so that both the argument and the newly 251 * Shares the underlying object by calling ref(), so that both the argument and the newly
249 * created sk_sp both have a reference to it. 252 * created sk_sp both have a reference to it.
250 */ 253 */
251 sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {} 254 sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}
252 template <typename U, 255 template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U* , T*>::value>>
253 typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value >>
254 sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {} 256 sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {}
255 257
256 /** 258 /**
257 * Move the underlying object from the argument to the newly created sk_sp. Afterwards only 259 * Move the underlying object from the argument to the newly created sk_sp. Afterwards only
258 * the new sk_sp will have a reference to the object, and the argument will point to null. 260 * the new sk_sp will have a reference to the object, and the argument will point to null.
259 * No call to ref() or unref() will be made. 261 * No call to ref() or unref() will be made.
260 */ 262 */
261 sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {} 263 sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
262 template <typename U, 264 template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U* , T*>::value>>
263 typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value >>
264 sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {} 265 sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}
265 266
266 /** 267 /**
267 * Adopt the bare pointer into the newly created sk_sp. 268 * Adopt the bare pointer into the newly created sk_sp.
268 * No call to ref() or unref() will be made. 269 * No call to ref() or unref() will be made.
269 */ 270 */
270 explicit sk_sp(T* obj) : fPtr(obj) {} 271 explicit sk_sp(T* obj) : fPtr(obj) {}
271 272
272 /** 273 /**
273 * Calls unref() on the underlying object pointer. 274 * Calls unref() on the underlying object pointer.
274 */ 275 */
275 ~sk_sp() { 276 ~sk_sp() {
276 SkSafeUnref(fPtr); 277 SkSafeUnref(fPtr);
278 SkDEBUGCODE(fPtr = nullptr);
277 } 279 }
278 280
279 sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; } 281 sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
280 282
281 /** 283 /**
282 * Shares the underlying object referenced by the argument by calling ref() on it. If this 284 * Shares the underlying object referenced by the argument by calling ref() on it. If this
283 * sk_sp previously had a reference to an object (i.e. not null) it will ca ll unref() on that 285 * sk_sp previously had a reference to an object (i.e. not null) it will ca ll unref() on that
284 * object. 286 * object.
285 */ 287 */
286 sk_sp<T>& operator=(const sk_sp<T>& that) { 288 sk_sp<T>& operator=(const sk_sp<T>& that) {
287 this->reset(SkSafeRef(that.get())); 289 this->reset(SkSafeRef(that.get()));
288 return *this; 290 return *this;
289 } 291 }
290 template <typename U, 292 template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U* , T*>::value>>
291 typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value >>
292 sk_sp<T>& operator=(const sk_sp<U>& that) { 293 sk_sp<T>& operator=(const sk_sp<U>& that) {
293 this->reset(SkSafeRef(that.get())); 294 this->reset(SkSafeRef(that.get()));
294 return *this; 295 return *this;
295 } 296 }
296 297
297 /** 298 /**
298 * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held 299 * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held
299 * a reference to another object, unref() will be called on that object. No call to ref() 300 * a reference to another object, unref() will be called on that object. No call to ref()
300 * will be made. 301 * will be made.
301 */ 302 */
302 sk_sp<T>& operator=(sk_sp<T>&& that) { 303 sk_sp<T>& operator=(sk_sp<T>&& that) {
303 this->reset(that.release()); 304 this->reset(that.release());
304 return *this; 305 return *this;
305 } 306 }
306 template <typename U, 307 template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U* , T*>::value>>
307 typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value >>
308 sk_sp<T>& operator=(sk_sp<U>&& that) { 308 sk_sp<T>& operator=(sk_sp<U>&& that) {
309 this->reset(that.release()); 309 this->reset(that.release());
310 return *this; 310 return *this;
311 } 311 }
312 312
313 bool operator==(std::nullptr_t) const { return this->get() == nullptr; }
314 bool operator!=(std::nullptr_t) const { return this->get() != nullptr; }
315
316 template <typename U>
317 bool operator==(const sk_sp<U>& that) const { return this->get() == that.get (); }
318 template <typename U>
319 bool operator!=(const sk_sp<U>& that) const { return this->get() != that.get (); }
320
321 T& operator*() const { 313 T& operator*() const {
322 SkASSERT(this->get() != nullptr); 314 SkASSERT(this->get() != nullptr);
323 return *this->get(); 315 return *this->get();
324 } 316 }
325 317
326 // MSVC 2013 does not work correctly with explicit operator bool. 318 // MSVC 2013 does not work correctly with explicit operator bool.
327 // https://chromium-cpp.appspot.com/#core-blacklist 319 // https://chromium-cpp.appspot.com/#core-blacklist
328 // When explicit operator bool can be used, remove operator! and operator un specified_bool_type. 320 // When explicit operator bool can be used, remove operator! and operator un specified_bool_type.
329 //explicit operator bool() const { return this->get() != nullptr; } 321 //explicit operator bool() const { return this->get() != nullptr; }
330 operator unspecified_bool_type() const { return this->get() ? &sk_sp::fPtr : nullptr; } 322 operator unspecified_bool_type() const { return this->get() ? &sk_sp::fPtr : nullptr; }
331 bool operator!() const { return this->get() == nullptr; } 323 bool operator!() const { return this->get() == nullptr; }
332 324
333 T* get() const { return fPtr; } 325 T* get() const { return fPtr; }
334 T* operator->() const { return fPtr; } 326 T* operator->() const { return fPtr; }
335 327
336 /** 328 /**
337 * Adopt the new bare pointer, and call unref() on any previously held obje ct (if not null). 329 * Adopt the new bare pointer, and call unref() on any previously held obje ct (if not null).
338 * No call to ref() will be made. 330 * No call to ref() will be made.
339 */ 331 */
340 void reset(T* ptr = nullptr) { 332 void reset(T* ptr = nullptr) {
341 SkSafeUnref(fPtr); 333 // Calling fPtr->unref() may call this->~() or this->reset(T*).
334 // http://wg21.cmeerw.net/lwg/issue998
335 // http://wg21.cmeerw.net/lwg/issue2262
336 T* oldPtr = fPtr;
342 fPtr = ptr; 337 fPtr = ptr;
338 SkSafeUnref(oldPtr);
343 } 339 }
344 340
345 /** 341 /**
346 * Return the bare pointer, and set the internal object pointer to nullptr. 342 * Return the bare pointer, and set the internal object pointer to nullptr.
347 * The caller must assume ownership of the object, and manage its reference count directly. 343 * The caller must assume ownership of the object, and manage its reference count directly.
348 * No call to unref() will be made. 344 * No call to unref() will be made.
349 */ 345 */
350 T* SK_WARN_UNUSED_RESULT release() { 346 T* SK_WARN_UNUSED_RESULT release() {
351 T* ptr = fPtr; 347 T* ptr = fPtr;
352 fPtr = nullptr; 348 fPtr = nullptr;
353 return ptr; 349 return ptr;
354 } 350 }
355 351
352 void swap(sk_sp<T>& that) /*noexcept*/ {
353 using std::swap;
354 swap(fPtr, that.fPtr);
355 }
356
356 private: 357 private:
357 T* fPtr; 358 T* fPtr;
358 }; 359 };
359 360
361 template <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ {
362 a.swap(b);
363 }
364
365 template <typename T, typename U> inline bool operator==(const sk_sp<T>& a, cons t sk_sp<U>& b) {
366 return a.get() == b.get();
367 }
368 template <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
369 return !a;
370 }
371 template <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
372 return !b;
373 }
374
375 template <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, cons t sk_sp<U>& b) {
376 return a.get() != b.get();
377 }
378 template <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
379 return static_cast<bool>(a);
380 }
381 template <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
382 return static_cast<bool>(b);
383 }
384
385 template <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const sk_sp<U>& b) {
386 // Provide defined total order on sk_sp.
387 // http://wg21.cmeerw.net/lwg/issue1297
388 // http://wg21.cmeerw.net/lwg/issue1401 .
389 return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get());
390 }
391 template <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) {
392 return std::less<T*>()(a.get(), nullptr);
393 }
394 template <typename T> inline bool operator<(std::nullptr_t, const sk_sp<T>& b) {
395 return std::less<T*>()(nullptr, b.get());
396 }
397
398 template <typename T, typename U> inline bool operator<=(const sk_sp<T>& a, cons t sk_sp<U>& b) {
399 return !(b < a);
400 }
401 template <typename T> inline bool operator<=(const sk_sp<T>& a, std::nullptr_t) {
402 return !(nullptr < a);
403 }
404 template <typename T> inline bool operator<=(std::nullptr_t, const sk_sp<T>& b) {
405 return !(b < nullptr);
406 }
407
408 template <typename T, typename U> inline bool operator>(const sk_sp<T>& a, const sk_sp<U>& b) {
409 return b < a;
410 }
411 template <typename T> inline bool operator>(const sk_sp<T>& a, std::nullptr_t) {
412 return nullptr < a;
413 }
414 template <typename T> inline bool operator>(std::nullptr_t, const sk_sp<T>& b) {
415 return b < nullptr;
416 }
417
418 template <typename T, typename U> inline bool operator>=(const sk_sp<T>& a, cons t sk_sp<U>& b) {
419 return !(a < b);
420 }
421 template <typename T> inline bool operator>=(const sk_sp<T>& a, std::nullptr_t) {
422 return !(a < nullptr);
423 }
424 template <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b) {
425 return !(nullptr < b);
426 }
427
360 template <typename T, typename... Args> 428 template <typename T, typename... Args>
361 sk_sp<T> sk_make_sp(Args&&... args) { 429 sk_sp<T> sk_make_sp(Args&&... args) {
362 return sk_sp<T>(new T(std::forward<Args>(args)...)); 430 return sk_sp<T>(new T(std::forward<Args>(args)...));
363 } 431 }
364 432
365 #endif 433 #endif
OLDNEW
« no previous file with comments | « no previous file | include/private/SkTLogic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698