/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef LIBMEMUNREACHABLE_ALLOCATOR_H_
#define LIBMEMUNREACHABLE_ALLOCATOR_H_

#include <atomic>
#include <cstddef>
#include <functional>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <unordered_set>
#include <vector>
extern std::atomic<int> heap_count;

class HeapImpl;

template<typename T>
class Allocator;


// Non-templated class that implements wraps HeapImpl to keep
// implementation out of the header file
class Heap {
public:
  Heap();
  ~Heap();

  // Copy constructor that does not take ownership of impl_
  Heap(const Heap& other) : impl_(other.impl_), owns_impl_(false) {}

  // Assignment disabled
  Heap& operator=(const Heap&) = delete;

  // Allocate size bytes
  void* allocate(size_t size);

  // Deallocate allocation returned by allocate
  void deallocate(void*);

  bool empty();

  static void deallocate(HeapImpl* impl, void* ptr);

  // Allocate a class of type T
  template<class T>
  T* allocate() {
    return reinterpret_cast<T*>(allocate(sizeof(T)));
  }

  // Comparators, copied objects will be equal
  bool operator ==(const Heap& other) const {
    return impl_ == other.impl_;
  }
  bool operator !=(const Heap& other) const {
    return !(*this == other);
  }

  // std::unique_ptr wrapper that allocates using allocate and deletes using
  // deallocate
  template<class T>
  using unique_ptr = std::unique_ptr<T, std::function<void(void*)>>;

  template<class T, class... Args>
  unique_ptr<T> make_unique(Args&&... args) {
    HeapImpl* impl = impl_;
    return unique_ptr<T>(new (allocate<T>()) T(std::forward<Args>(args)...),
        [impl](void* ptr) {
          reinterpret_cast<T*>(ptr)->~T();
          deallocate(impl, ptr);
        });
  }

  // std::unique_ptr wrapper that allocates using allocate and deletes using
  // deallocate
  template<class T>
  using shared_ptr = std::shared_ptr<T>;

  template<class T, class... Args>
  shared_ptr<T> make_shared(Args&&... args);

protected:
  HeapImpl* impl_;
  bool owns_impl_;
};

// STLAllocator implements the std allocator interface on top of a Heap
template<typename T>
class STLAllocator {
public:
  using value_type = T;
  ~STLAllocator() {
  }

  // Construct an STLAllocator on top of a Heap
  STLAllocator(const Heap& heap) :
      heap_(heap) {
  }

  // Rebind an STLAllocator from an another STLAllocator
  template<typename U>
  STLAllocator(const STLAllocator<U>& other) :
      heap_(other.heap_) {
  }

  STLAllocator(const STLAllocator&) = default;
  STLAllocator<T>& operator=(const STLAllocator<T>&) = default;

  T* allocate(std::size_t n) {
    return reinterpret_cast<T*>(heap_.allocate(n * sizeof(T)));
  }

  void deallocate(T* ptr, std::size_t) {
    heap_.deallocate(ptr);
  }

  template<typename U>
  bool operator ==(const STLAllocator<U>& other) const {
    return heap_ == other.heap_;
  }
  template<typename U>
  inline bool operator !=(const STLAllocator<U>& other) const {
    return !(this == other);
  }

  template<typename U>
  friend class STLAllocator;

protected:
  Heap heap_;
};


// Allocator extends STLAllocator with some convenience methods for allocating
// a single object and for constructing unique_ptr and shared_ptr objects with
// appropriate deleters.
template<class T>
class Allocator : public STLAllocator<T> {
 public:
  ~Allocator() {}

  Allocator(const Heap& other) :
      STLAllocator<T>(other) {
  }

  template<typename U>
  Allocator(const STLAllocator<U>& other) :
      STLAllocator<T>(other) {
  }

  Allocator(const Allocator&) = default;
  Allocator<T>& operator=(const Allocator<T>&) = default;

  using STLAllocator<T>::allocate;
  using STLAllocator<T>::deallocate;
  using STLAllocator<T>::heap_;

  T* allocate() {
    return STLAllocator<T>::allocate(1);
  }
  void deallocate(void* ptr) {
    heap_.deallocate(ptr);
  }

  using shared_ptr = Heap::shared_ptr<T>;

  template<class... Args>
  shared_ptr make_shared(Args&& ...args) {
    return heap_.template make_shared<T>(std::forward<Args>(args)...);
  }

  using unique_ptr = Heap::unique_ptr<T>;

  template<class... Args>
  unique_ptr make_unique(Args&& ...args) {
    return heap_.template make_unique<T>(std::forward<Args>(args)...);
  }
};

// std::unique_ptr wrapper that allocates using allocate and deletes using
// deallocate.  Implemented outside class definition in order to pass
// Allocator<T> to shared_ptr.
template<class T, class... Args>
inline Heap::shared_ptr<T> Heap::make_shared(Args&&... args) {
  return std::allocate_shared<T, Allocator<T>, Args...>(Allocator<T>(*this),
      std::forward<Args>(args)...);
}

namespace allocator {

template<class T>
using vector = std::vector<T, Allocator<T>>;

template<class T>
using list = std::list<T, Allocator<T>>;

template<class T, class Key, class Compare = std::less<Key>>
using map = std::map<Key, T, Compare, Allocator<std::pair<const Key, T>>>;

template<class Key, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
using unordered_set = std::unordered_set<Key, Hash, KeyEqual, Allocator<Key>>;

template<class Key, class Compare = std::less<Key>>
using set = std::set<Key, Compare, Allocator<Key>>;

using string = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
}

#endif
