/*
 *
 *    Copyright (c) 2016-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    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.
 */

/**
 *    @file
 *      This file contains declarations of the following classes and
 *      templates:
 *
 *        - class nl::Weave::System::Object
 *        - template<typename ALIGN, size_t SIZE> union nl::Weave::System::ObjectArena
 *        - template<class T, unsigned int N> class nl::Weave::System::ObjectPool
 */

#ifndef SYSTEMOBJECT_H
#define SYSTEMOBJECT_H

// Include configuration headers
#include <SystemLayer/SystemConfig.h>

// Include dependent headers
#include <stddef.h>
#include <stdint.h>

#include <Weave/Support/NLDLLUtil.h>

#include <SystemLayer/SystemError.h>
#include <SystemLayer/SystemStats.h>

namespace nl {
namespace Weave {
namespace System {

// Forward class and class template declarations
class Layer;
template<class T, unsigned int N> class ObjectPool;

/**
 *  @class Object
 *
 *  @brief
 *    This represents a reference-counted object allocated from space contained in an ObjectPool<T, N> object.
 *
 *  @note
 *      Instance of this class may only be constructed using the related ObjectPool class template. The copy constructor and the
 *      assignment operator are deleted. A reference counting system is used to track retentions of instances of this class.
 *      When an object is initially retained, its reference count is one. Additional retentions may increment the reference count.
 *      When the object is released, the reference count is decremented. When the reference count is zero, the object is recycled
 *      back to the pool for reallocation. There is no destructor available. Subclasses must be designed to ensure that all
 *      encapsulated resources are released when the final retention is released and the object is recycled.
 *
 *      While this class is defined as concrete, in conformance with Nest C++ style, it should be regarded as abstract.
 */
class NL_DLL_EXPORT Object
{
    template<class T, unsigned int N> friend class ObjectPool;

public:
    /** Test whether this object is retained by \c aLayer. Concurrency safe. */
    bool IsRetained(const Layer& aLayer) const;

    void Retain(void);
    void Release(void);
    Layer& SystemLayer(void) const;

protected:
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
    /**< What to do when DeferredRelease fails to post a kEvent_ReleaseObj. */
    enum ReleaseDeferralErrorTactic
    {
        kReleaseDeferralErrorTactic_Ignore,     /**< No action. */
        kReleaseDeferralErrorTactic_Release,    /**< Release immediately. */
        kReleaseDeferralErrorTactic_Die,        /**< Die with message. */
    };

    void DeferredRelease(ReleaseDeferralErrorTactic aTactic);
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP

private:
    Object(void);
    ~Object(void);
    Object(const Object&)               /* = delete */;
    Object& operator =(const Object&)   /* = delete */;

    Layer* volatile mSystemLayer;   /**< Pointer to the layer object that owns this object. */
    unsigned int mRefCount;         /**< Count of remaining calls to Release before object is dead. */

    /** If not already retained, attempt initial retention of this object for \c aLayer and zero up to \c aOctets. */
    bool TryCreate(Layer& aLayer, size_t aOctets);

public:
    void* AppState;                 /**< Generic pointer to app-specific data associated with the object. */
};

/**
 *  @brief
 *      Tests whether this object is retained by \c aLayer.
 *
 *  @note
 *      No memory barrier is applied. If this returns \c false in one thread context, then it does not imply that another thread
 *      cannot have previously retained the object for \c aLayer. If it returns \c true, then the logic using \c aLayer is
 *      responsible for ensuring concurrency safety for this object.
 */
inline bool Object::IsRetained(const Layer& aLayer) const
{
    return this->mSystemLayer == &aLayer;
}

/**
 *  @brief
 *      Increments the reference count for the Weave System Layer object. The object is assumed to be live.
 */
inline void Object::Retain(void)
{
    __sync_fetch_and_add(&this->mRefCount, 1);
}

/**
 *  @brief
 *      Returns a reference to the Weave System Layer object provided when the object was initially retained from its corresponding
 *      object pool instance. The object is assumed to be live.
 */
inline Layer& Object::SystemLayer(void) const
{
    return *this->mSystemLayer;
}

/** Deleted. */
inline Object::Object(void)
{
}

/** Deleted. */
inline Object::~Object(void)
{
}

/**
 *  @brief
 *      A union template used for representing a well-aligned block of memory.
 *
 *  @tparam     ALIGN   a typename with the alignment properties for the block.
 *  @tparam     SIZE    a constant size of the block in bytes.
 */
template<typename ALIGN, size_t SIZE>
union ObjectArena {
    uint8_t uMemory[SIZE];
    ALIGN uAlign;
};

/**
 *  @brief
 *      A class template used for allocating Object subclass objects from an ObjectArena<> template union.
 *
 *  @tparam     T   a subclass of Object to be allocated from the arena.
 *  @tparam     N   a positive integer number of objects of class T to allocate from the arena.
 */
template<class T, unsigned int N>
class ObjectPool
{
public:
    static size_t Size(void);

    T* Get(const Layer& aLayer, size_t aIndex);
    T* TryCreate(Layer& aLayer);
    void GetStatistics(nl::Weave::System::Stats::count_t& aNumInUse);

private:
    ObjectArena<void*, N * sizeof(T)> mArena;
};

/**
 *  @brief
 *      Returns the number of objects that can be simultaneously retained from a pool.
 */
template<class T, unsigned int N>
inline size_t ObjectPool<T, N>::Size(void)
{
    return N;
}

/**
 *  @brief
 *      Returns a pointer the object at \c aIndex or \c NULL if the object is not retained by \c aLayer.
 */
template<class T, unsigned int N>
inline T* ObjectPool<T, N>::Get(const Layer& aLayer, size_t aIndex)
{
    T* lReturn = NULL;

    if (aIndex < N)
        lReturn = &reinterpret_cast<T*>(mArena.uMemory)[aIndex];

    (void) static_cast<Object*>(lReturn);   /* In C++-11, this would be a static_assert that T inherits Object. */

    return (lReturn != NULL) && lReturn->IsRetained(aLayer) ? lReturn : NULL;
}

/**
 *  @brief
 *      Tries to initially retain the first object in the pool that is not retained by any layer.
 */
template<class T, unsigned int N>
inline T* ObjectPool<T, N>::TryCreate(Layer& aLayer)
{
    T* lReturn = NULL;

    for (unsigned int lIndex = 0; lIndex < N; ++lIndex)
    {
        T& lObject = reinterpret_cast<T*>(mArena.uMemory)[lIndex];

        if (lObject.TryCreate(aLayer, sizeof(T)))
        {
            lReturn = &lObject;
            break;
        }
    }

    return lReturn;
}

template<class T, unsigned int N>
inline void ObjectPool<T, N>::GetStatistics(nl::Weave::System::Stats::count_t& aNumInUse)
{
    aNumInUse = 0;

    for (size_t lIndex = 0; lIndex < N; ++lIndex)
    {
        T& lObject = reinterpret_cast<T*>(mArena.uMemory)[lIndex];

        if (lObject.mSystemLayer != NULL)
            aNumInUse++;
    }
}

} // namespace System
} // namespace Weave
} // namespace nl

#endif // defined(SYSTEMOBJECT_H)
