/*
 * 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_map>
#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 Key, class T, class Compare = std::less<Key>>
using map = std::map<Key, T, Compare, Allocator<std::pair<const Key, T>>>;

template<class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
using unordered_map = std::unordered_map<Key, T, Hash, KeyEqual, 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
