//----------------------------------------------------------------------
// Copyright (C) 2006-2007 Electronic Arts    
//----------------------------------------------------------------------

#include "job_util/for_each_desc.h"

// for memcpy.
#include <string.h>

namespace EA { 
    namespace Jobs {

//----------------------------------------------------------------------
ForEachDesc::ForEachDesc(uint16_t size, uint16_t ident) :
    mSize(size),
    mIdent(ident),
    mForEachDivisionEnum(FOR_EACH_DIVISION_EVEN),
    mDynamicCounter(0),
    mNumJobs(1),
    mRefCounter(0)
{
    EA_ASSERT(size <= sLargeEnoughToHoldAllKnownDescTypes);
}

//----------------------------------------------------------------------
int ForEachDesc::JobCount() const
{
    return mNumJobs;
}

//----------------------------------------------------------------------
void ForEachDesc::InitDynamicCounter()
{
    mDynamicCounter = 0;
}

//----------------------------------------------------------------------
uint32_t * ForEachDesc::GetDynamicCounterEa(uintptr_t batchDescEa)
{
    return &(reinterpret_cast<ForEachDesc *>(batchDescEa)->mDynamicCounter);
}

//----------------------------------------------------------------------
void ForEachDesc::InitRefCounter(uint32_t refCount)
{
    mRefCounter = refCount;
}

//----------------------------------------------------------------------
uint32_t * ForEachDesc::GetRefCounterEa(uintptr_t batchDescEa)
{
    return &(reinterpret_cast<ForEachDesc *>(batchDescEa)->mRefCounter);
}

//----------------------------------------------------------------------
void ForEachDesc::SetDivision(ForEachDivisionEnum batchDivisionEnum, int numJobs)
{
    mForEachDivisionEnum = batchDivisionEnum;
    mNumJobs = numJobs;
}

//----------------------------------------------------------------------
ForEachDivisionEnum ForEachDesc::GetDivision() const
{
    return mForEachDivisionEnum;
}

//----------------------------------------------------------------------
void ForEachDesc::Copy(ForEachDesc const & forEachDesc)
{
    //
    // This method exists so I can manage a group of descriptors that
    // descend from ForEachDesc in an atomic pool.
    //
    // We Copy the real descriptor into *this. *this is allocated
    // in the atomic pool.
    //
    // *this is already claimed when we get called, so its mRefCount
    // must be preserved. (Setting it back to zero would return
    // it to the pool.)
    //
    // I considered splitting the atomic pool state into its own
    // type, but since the descriptor and the atomic pool state are
    // both transfered to the SPU via a DMA it's "easier" to leave
    // it as a base class.  I'm not totally convinced this is the
    // right approach still, and am open to alternative approaches
    // if anyone has one.
    //
    //   -- Cliff
    //

    EA_ASSERT(forEachDesc.mSize <= sLargeEnoughToHoldAllKnownDescTypes);
    EA_ASSERT(forEachDesc.mSize > 0);
    EA_ASSERT(forEachDesc.mIdent > 0);

    // preserve these:
    forEachDesc.mRefCounter = mRefCounter;
    forEachDesc.mNext = mNext;
    forEachDesc.mAtomicAllocator = mAtomicAllocator;

    memcpy(this, &forEachDesc, forEachDesc.mSize);
}

bool ForEachDesc::Verify(uint16_t size, uint16_t ident) const
{
    return mSize == size && mIdent == ident;
}



}}
