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