/*
 *  Copyright 2017 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#ifndef API_REF_COUNTED_BASE_H_
#define API_REF_COUNTED_BASE_H_

#include <type_traits>

#include "rtc_base/ref_counter.h"

namespace rtc {

class RefCountedBase {
 public:
  RefCountedBase() = default;

  RefCountedBase(const RefCountedBase&) = delete;
  RefCountedBase& operator=(const RefCountedBase&) = delete;

  void AddRef() const { ref_count_.IncRef(); }
  RefCountReleaseStatus Release() const {
    const auto status = ref_count_.DecRef();
    if (status == RefCountReleaseStatus::kDroppedLastRef) {
      delete this;
    }
    return status;
  }

 protected:
  // Provided for internal webrtc subclasses for corner cases where it's
  // necessary to know whether or not a reference is exclusively held.
  bool HasOneRef() const { return ref_count_.HasOneRef(); }

  virtual ~RefCountedBase() = default;

 private:
  mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
};

// Template based version of `RefCountedBase` for simple implementations that do
// not need (or want) destruction via virtual destructor or the overhead of a
// vtable.
//
// To use:
//   struct MyInt : public rtc::RefCountedNonVirtual<MyInt>  {
//     int foo_ = 0;
//   };
//
//   rtc::scoped_refptr<MyInt> my_int(new MyInt());
//
// sizeof(MyInt) on a 32 bit system would then be 8, int + refcount and no
// vtable generated.
template <typename T>
class RefCountedNonVirtual {
 public:
  RefCountedNonVirtual() = default;

  RefCountedNonVirtual(const RefCountedNonVirtual&) = delete;
  RefCountedNonVirtual& operator=(const RefCountedNonVirtual&) = delete;

  void AddRef() const { ref_count_.IncRef(); }
  RefCountReleaseStatus Release() const {
    // If you run into this assert, T has virtual methods. There are two
    // options:
    // 1) The class doesn't actually need virtual methods, the type is complete
    //    so the virtual attribute(s) can be removed.
    // 2) The virtual methods are a part of the design of the class. In this
    //    case you can consider using `RefCountedBase` instead or alternatively
    //    use `rtc::RefCountedObject`.
    static_assert(!std::is_polymorphic<T>::value,
                  "T has virtual methods. RefCountedBase is a better fit.");
    const auto status = ref_count_.DecRef();
    if (status == RefCountReleaseStatus::kDroppedLastRef) {
      delete static_cast<const T*>(this);
    }
    return status;
  }

 protected:
  // Provided for internal webrtc subclasses for corner cases where it's
  // necessary to know whether or not a reference is exclusively held.
  bool HasOneRef() const { return ref_count_.HasOneRef(); }

  ~RefCountedNonVirtual() = default;

 private:
  mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
};

}  // namespace rtc

#endif  // API_REF_COUNTED_BASE_H_
