15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef BASE_MAC_SCOPED_TYPEREF_H_ 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define BASE_MAC_SCOPED_TYPEREF_H_ 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/compiler_specific.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_policy.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace base { 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ScopedTypeRef<> is patterned after scoped_ptr<>, but maintains a ownership 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// of a reference to any type that is maintained by Retain and Release methods. 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The Traits structure must provide the Retain and Release methods for type T. 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A default ScopedTypeRefTraits is used but not defined, and should be defined 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// for each type to use this interface. For example, an appropriate definition 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// of ScopedTypeRefTraits for CGLContextObj would be: 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// template<> 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// struct ScopedTypeRefTraits<CGLContextObj> { 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// void Retain(CGLContextObj object) { CGLContextRetain(object); } 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// void Release(CGLContextObj object) { CGLContextRelease(object); } 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// }; 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// For the many types that have pass-by-pointer create functions, the function 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// InitializeInto() is provided to allow direct initialization and assumption 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// of ownership of the object. For example, continuing to use the above 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// CGLContextObj specialization: 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// base::ScopedTypeRef<CGLContextObj> context; 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// CGLCreateContext(pixel_format, share_group, context.InitializeInto()); 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// For initialization with an existing object, the caller may specify whether 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the ScopedTypeRef<> being initialized is assuming the caller's existing 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ownership of the object (and should not call Retain in initialization) or if 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// it should not assume this ownership and must create its own (by calling 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Retain in initialization). This behavior is based on the |policy| parameter, 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// with |ASSUME| for the former and |RETAIN| for the latter. The default policy 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// is to |ASSUME|. 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename T> 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct ScopedTypeRefTraits; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename T, typename Traits = ScopedTypeRefTraits<T>> 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ScopedTypeRef { 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typedef T element_type; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedTypeRef( 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) T object = NULL, 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : object_(object) { 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (object_ && policy == base::scoped_policy::RETAIN) 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Traits::Retain(object_); 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedTypeRef(const ScopedTypeRef<T, Traits>& that) 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : object_(that.object_) { 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (object_) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Traits::Retain(object_); 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~ScopedTypeRef() { 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (object_) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Traits::Release(object_); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedTypeRef& operator=(const ScopedTypeRef<T, Traits>& that) { 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reset(that.get(), base::scoped_policy::RETAIN); 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return *this; 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This is to be used only to take ownership of objects that are created 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // by pass-by-pointer create functions. To enforce this, require that the 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // object be reset to NULL before this may be used. 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) T* InitializeInto() WARN_UNUSED_RESULT { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!object_); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return &object_; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void reset(T object = NULL, 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::scoped_policy::OwnershipPolicy policy = 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::scoped_policy::ASSUME) { 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (object && policy == base::scoped_policy::RETAIN) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Traits::Retain(object); 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (object_) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Traits::Release(object_); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) object_ = object; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool operator==(T that) const { 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return object_ == that; 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool operator!=(T that) const { 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return object_ != that; 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) operator T() const { 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return object_; 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) T get() const { 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return object_; 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void swap(ScopedTypeRef& that) { 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) T temp = that.object_; 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) that.object_ = object_; 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) object_ = temp; 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // ScopedTypeRef<>::release() is like scoped_ptr<>::release. It is NOT 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // a wrapper for Release(). To force a ScopedTypeRef<> object to call 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Release(), use ScopedTypeRef<>::reset(). 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) T release() WARN_UNUSED_RESULT { 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) T temp = object_; 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) object_ = NULL; 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return temp; 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) T object_; 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace base 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // BASE_MAC_SCOPED_TYPEREF_H_ 133