/**
 * Copyright 2016 Yahoo Inc.
 *
 * 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 LIB_OBJECTPOOL_H_
#define LIB_OBJECTPOOL_H_

#include <algorithm>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread/tss.hpp>

namespace pulsar {

template<typename T, int MaxSize>
class Allocator {
    public:
    // Allocator must be stateless, so put everything in this static
    class Impl {
        public:
        // cheap lock to acquire
        static boost::mutex mutex_;

        // note: use std::forward_list<> when switching to C++11 mode
        struct Node {
            Node* next;
            explicit Node(Node* n) : next(n) {}
        };
        Node *head_;
        int pushSize_;

        struct GlobalPool {
            Node *node_;
            int nodeCount_;
            GlobalPool *next_;
            explicit GlobalPool(GlobalPool* n) : next_(n) {}
        };
        static struct GlobalPool *globalPool_;
        static int globalNodeCount_;

        Impl(const Impl&);
        void operator=(const Impl&);

        void* pop() {
            if (!head_) {
                // size = 0
                boost::lock_guard<boost::mutex> lock(mutex_);

                if (!globalPool_) {
                    return NULL;
                }

                GlobalPool *poolEntry = globalPool_;
                head_ = globalPool_->node_;
                pushSize_ += globalPool_->nodeCount_;
                globalNodeCount_ -= globalPool_->nodeCount_;
                globalPool_ = globalPool_->next_;
                delete poolEntry;

            }
            void* result = head_;
            if (result) {
                head_ = head_->next;
                pushSize_--;
            }
            return result;
        }

        bool push(void* p) {

            // Once thread specific entries reaches 10% of max size, push them to GlobalPool
            if (pushSize_ >= MaxSize*0.1) {

                bool deleteList = true;
                {
                    // Move the entries to global pool
                    boost::lock_guard<boost::mutex> lock(mutex_);

                    // If total node count reached max allowed cache limit,
                    // skip adding to global pool.
                    if ((globalNodeCount_ + pushSize_) <= MaxSize) {

                        deleteList = false;

                        globalPool_ = new GlobalPool(globalPool_);
                        globalPool_->node_ = head_;
                        globalPool_->nodeCount_ = pushSize_;
                        globalNodeCount_ += pushSize_;
                    }

                }
                if (deleteList) {
                    pushSize_ = 0;
                    deleteLinkedList(head_);
                }
                head_ = new(p) Node(0);
                pushSize_ = 1;
                return true;
            }

            head_ = new(p) Node(head_);
            pushSize_++;
            return true;
        }

        static void deleteLinkedList(Node* head) {
            Node* n = head;
            while (n) {
                void* p = n;
                n = n->next;
                ::operator delete(p);
            }
        }
    public:
        Impl() {
            pushSize_ = 0;
            head_ = 0;
        }

        ~Impl() {
            // No need for mutex for pop
            deleteLinkedList(head_);
        }

        void* allocate() {
            void* result = pop();
            if (!result) {
                result = ::operator new(std::max(sizeof(T), sizeof(Node)));
            }
            return result;
        }

        void deallocate(void* p) {
            if (!push(p)) {
                ::operator delete(p);
            }
        }
    };

    static boost::thread_specific_ptr<Impl> implPtr_;
    typedef size_t size_type;
    typedef T* pointer;
    typedef const void* const_pointer;

    Allocator() {
    }

    Allocator(const Allocator& /*other*/) {
    }

    template<typename Other, int OtherSize>
    Allocator(const Allocator<Other, OtherSize>& /*other*/) {
    }

    pointer allocate(size_type n, const void * /*hint*/ = 0) {
        Impl *impl = implPtr_.get();
        if (!impl) {
            implPtr_.reset(new Impl);
            impl = implPtr_.get();
        }
        void* p = (n == 1)
            ? impl->allocate()
            : operator new(n * sizeof(T));
        return static_cast<T*>(p);
    }

    void deallocate(pointer ptr, size_type n) {
        Impl *impl = implPtr_.get();
        if (!impl) {
            implPtr_.reset(new Impl);
            impl = implPtr_.get();
        }
        if (n == 1)
            impl->deallocate(ptr);
        else
            ::operator delete(ptr);
    }

    template<typename Other> struct rebind {
        typedef Allocator<Other, MaxSize> other;
    };
};

// typename Allocator<Type,MaxSize>::Impl is important else the compiler
// doesn't understand that it is a type
template <typename Type, int MaxSize>
boost::thread_specific_ptr<typename Allocator<Type,MaxSize>::Impl> Allocator<Type,MaxSize>::implPtr_;

template <typename Type, int MaxSize>
boost::mutex Allocator<Type,MaxSize>::Impl::mutex_;

template <typename Type, int MaxSize>
struct Allocator<Type,MaxSize>::Impl::GlobalPool *Allocator<Type,MaxSize>::Impl::globalPool_;

template <typename Type, int MaxSize>
int Allocator<Type,MaxSize>::Impl::globalNodeCount_;

template<typename Type, int MaxSize>
class ObjectPool {
    typedef boost::shared_ptr<Type> TypeSharedPtr;

    Allocator<Type, MaxSize> allocator_;

 public:
    ObjectPool() {

    }

    TypeSharedPtr create() {
        return boost::allocate_shared<Type>(allocator_);
    }

    ~ObjectPool() {

        struct Allocator<Type,MaxSize>::Impl::GlobalPool *poolEntry = Allocator<Type,MaxSize>::Impl::globalPool_;
        while(poolEntry) {
            Allocator<Type, MaxSize>::Impl::deleteLinkedList(poolEntry->node_);
            struct Allocator<Type,MaxSize>::Impl::GlobalPool *delEntry = poolEntry;
            poolEntry = poolEntry->next_;
            ::operator delete(delEntry);
        }
    }
 private:
    ObjectPool<Type, MaxSize>(const ObjectPool<Type, MaxSize>&);
    ObjectPool<Type, MaxSize>& operator=(const ObjectPool<Type, MaxSize>&);
};

}
#endif /* LIB_OBJECTPOOL_H_ */
