147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Originally these classes are from Chromium.
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/ref_counted.h?view=markup
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// A smart pointer class for reference counted objects.  Use this class instead
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// of calling AddRef and Release manually on a reference counted object to
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// avoid common memory leaks caused by forgetting to Release an object
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// reference.  Sample usage:
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   class MyFoo : public RefCounted<MyFoo> {
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//    ...
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   };
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   void some_function() {
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     scoped_refptr<MyFoo> foo = new MyFoo();
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     foo->Method(param);
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     // |foo| is released when this function returns
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   }
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   void some_other_function() {
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     scoped_refptr<MyFoo> foo = new MyFoo();
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     ...
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     foo = NULL;  // explicitly releases |foo|
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     ...
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     if (foo)
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//       foo->Method(param);
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   }
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// The above examples show how scoped_refptr<T> acts like a pointer to T.
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Given two scoped_refptr<T> classes, it is also possible to exchange
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// references between the two objects, like so:
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   {
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     scoped_refptr<MyFoo> a = new MyFoo();
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     scoped_refptr<MyFoo> b;
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     b.swap(a);
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     // now, |b| references the MyFoo object, and |a| references NULL.
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   }
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// To make both |a| and |b| in the above example reference the same MyFoo
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// object, simply use the assignment operator:
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   {
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     scoped_refptr<MyFoo> a = new MyFoo();
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     scoped_refptr<MyFoo> b;
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     b = a;
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//     // now, |a| and |b| each own a reference to the same MyFoo object.
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//   }
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifndef WEBRTC_BASE_SCOPED_REF_PTR_H_
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define WEBRTC_BASE_SCOPED_REF_PTR_H_
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <stddef.h>
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtemplate <class T>
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass scoped_refptr {
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_refptr() : ptr_(NULL) {
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_refptr(T* p) : ptr_(p) {
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ptr_)
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ptr_->AddRef();
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ptr_)
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ptr_->AddRef();
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  template <typename U>
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ptr_)
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ptr_->AddRef();
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ~scoped_refptr() {
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ptr_)
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ptr_->Release();
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  T* get() const { return ptr_; }
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  operator T*() const { return ptr_; }
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  T* operator->() const { return ptr_; }
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Release a pointer.
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // The return value is the current pointer held by this object.
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // If this object holds a NULL pointer, the return value is NULL.
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // After this operation, this object will hold a NULL pointer,
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // and will not own the object any more.
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  T* release() {
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    T* retVal = ptr_;
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ptr_ = NULL;
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return retVal;
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_refptr<T>& operator=(T* p) {
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // AddRef first so that self assignment should work
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (p)
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      p->AddRef();
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ptr_ )
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ptr_ ->Release();
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ptr_ = p;
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return *this;
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return *this = r.ptr_;
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  template <typename U>
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return *this = r.get();
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void swap(T** pp) {
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    T* p = ptr_;
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ptr_ = *pp;
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *pp = p;
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void swap(scoped_refptr<T>& r) {
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    swap(&r.ptr_);
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org protected:
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  T* ptr_;
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // WEBRTC_BASE_SCOPED_REF_PTR_H_
148