chromium/native_client_sdk/src/libraries/sdk_util/scoped_ref.h

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIBRARIES_SDK_UTIL_SCOPED_REF_H_
#define LIBRARIES_SDK_UTIL_SCOPED_REF_H_

#include <stdlib.h>

#include "sdk_util/macros.h"
#include "sdk_util/ref_object.h"

namespace sdk_util {

class ScopedRefBase {
 protected:
  ScopedRefBase() : ptr_(NULL) {}
  ~ScopedRefBase() { reset(NULL); }

  void reset(RefObject* obj) {
    if (obj) {
      obj->Acquire();
    }
    if (ptr_) {
      ptr_->Release();
    }
    ptr_ = obj;
  }

 protected:
  RefObject* ptr_;
};

template <class T>
class ScopedRef : public ScopedRefBase {
 public:
  ScopedRef() {}
  ScopedRef(const ScopedRef& ptr) { reset(ptr.get()); }
  explicit ScopedRef(T* ptr) { reset(ptr); }

  ScopedRef& operator=(const ScopedRef& ptr) {
    reset(ptr.get());
    return *this;
  }

  template <typename U>
  ScopedRef(const ScopedRef<U>& ptr) {
    reset(ptr.get());
  }

  template <typename U>
  ScopedRef& operator=(const ScopedRef<U>& ptr) {
    reset(ptr.get());
    return *this;
  }

  void reset(T* obj = NULL) { ScopedRefBase::reset(obj); }
  T* get() const { return static_cast<T*>(ptr_); }

  template <typename U>
  bool operator==(const ScopedRef<U>& p) const {
    return get() == p.get();
  }

  template <typename U>
  bool operator!=(const ScopedRef<U>& p) const {
    return get() != p.get();
  }

 public:
  T& operator*() const { return *get(); }
  T* operator->() const { return get(); }

 private:
  typedef void (ScopedRef::*bool_as_func_ptr)() const;
  void bool_as_func_impl() const {}

 public:
  operator bool_as_func_ptr() const {
    return (ptr_ != NULL) ? &ScopedRef::bool_as_func_impl : 0;
  }
};

template <typename U, typename T>
ScopedRef<U> static_scoped_ref_cast(const ScopedRef<T>& ptr) {
  return ScopedRef<U>(static_cast<U*>(ptr.get()));
}

}  // namespace sdk_util

#endif  // LIBRARIES_SDK_UTIL_SCOPED_REF_H_