/*
 * MVKObjectPool.h
 *
 * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
 *
 * 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.
 */


#pragma once

#include "MVKBaseObject.h"
#include <mutex>


#pragma mark -
#pragma mark MVKObjectPool

/**
 * Manages a pool of instances of a particular object type.
 *
 * The objects managed by this pool must have public member variable named "_next", 
 * of the same object type, which is used by this pool to create a linked list of objects.
 *
 * When this pool is destroyed, any objects contained in the pool are also destroyed.
 *
 * This pool includes member functions for managing resources in either a thread-safe,
 * or somewhat faster, but not-thread-safe manner.
 *
 * An instance of this pool can be configured to either manage a pool of objects,
 * or simply allocate a new object instance on each request and destroy the object
 * when it is released back to the pool.
 */
template <class T>
class MVKObjectPool : public MVKBaseObject {

public:

	/**
	 * Acquires and returns the next available object from the pool, creating it if necessary.
	 *
	 * If this instance was configured to use pooling, the object is removed from the pool
	 * until it is returned back to the pool. If this instance was configured NOT to use
	 * pooling, the object is created anew on each request, and will be deleted when
	 * returned back to the pool.
     *
     * This method is not thread-safe. For a particular pool instance, all calls to
     * aquireObject() and returnObject() must be made from the same thread.
	 */
	T* acquireObject() {
		T* obj = VK_NULL_HANDLE;
		if (_isPooling) { obj = nextObject(); }
		if ( !obj ) { obj = newObject(); }

		return obj;
	}

	/**
	 * Returns the specified object back to the pool.
	 *
	 * If this instance was configured to use pooling, the returned object is added back
	 * into the pool. If this instance was configured NOT to use pooling, the returned
	 * object is simply deleted.
     *
     * This method is not thread-safe. For a particular pool instance, all calls to 
     * aquireObject() and returnObject() must be made from the same thread.
	 */
	void returnObject(T* obj) {
		if (_isPooling) {
			if (_tail) { _tail->_next = obj; }
			obj->_next = VK_NULL_HANDLE;
			_tail = obj;
			if ( !_head ) { _head = obj; }
		} else {
			obj->destroy();
		}
	}

	/** A thread-safe version of the acquireObject() function. */
	T* acquireObjectSafely() {
		std::lock_guard<std::mutex> lock(_lock);
		return acquireObject();
	}

	/** A thread-safe version of the returnObject() function. */
	void returnObjectSafely(T* obj) {
		std::lock_guard<std::mutex> lock(_lock);
		returnObject(obj);
	}

	/** Clears all the objects from this pool, deleting each one. This method is thread-safe. */
	void clear() {
        std::lock_guard<std::mutex> lock(_lock);
		while ( T* obj = nextObject() ) { obj->destroy(); }
	}

	/**
	 * Configures this instance to either use pooling, or not, depending on the
	 * value of isPooling, which defaults to true if not indicated explicitly.
	 */
    MVKObjectPool(bool isPooling = true) : _isPooling(isPooling) {}

	~MVKObjectPool() override { clear(); }

protected:

    /**
     * Removes and returns the first object in this pool, or returns null if this pool
     * contains no objects. This differs from the acquireObject() function, which creates
     * and return a new instance if this pool is empty. This method is not thread-safe.
     */
    T* nextObject() {
        T* obj = _head;
        if (obj) {
            _head = (T*)obj->_next;						// Will be null for last object in pool
            if ( !_head ) { _tail = VK_NULL_HANDLE; }	// If last, also clear tail
            obj->_next = VK_NULL_HANDLE;				// Objects in the wild should never think they are still part of this pool
        }
        return obj;
    }

    /** Returns a new instance of the type of object managed by this pool. */
    virtual T* newObject() = 0;

    std::mutex _lock;
	T* _head = nullptr;
	T* _tail = nullptr;
	bool _isPooling;
};

