/*
 *  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 "api/ref_count.h"
#include "rtc_base/ref_counter.h"

namespace webrtc {

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_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 RefCountedNonVirtual<MyInt>  {
//     int foo_ = 0;
//   };
//
//   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 `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_impl::RefCounter ref_count_{0};
};

}  // namespace webrtc


#endif  // API_REF_COUNTED_BASE_H_
