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

#ifndef JOB_UTIL_PARALLEL_FOR_EACH_H
#define JOB_UTIL_PARALLEL_FOR_EACH_H

#include "EABase/eabase.h"

#if ! defined EA_PLATFORM_PS3_SPU
    #include "job_util/for_each_desc.h"
    #include "job_manager/job_scheduler.h"
    #include "job_manager/entry_point.h"
    #include "job_manager/job_instance_handle.h"

#if defined(EA_PLATFORM_PS3) && defined(EA_COMPILER_SN)
#pragma diag_push
#pragma diag_suppress=1788
#endif

namespace EA {
    namespace Jobs {

//----------------------------------------------------------------------
class ParallelForEach
{
public:

    ParallelForEach
    (
        JobScheduler& jobScheduler,
        const EntryPoint& entryPoint,
        const ForEachDesc& ForEachDesc,
        int numJobs,
        ForEachDivisionEnum forEachDivisionEnum = FOR_EACH_DIVISION_DYNAMIC
    );

    ParallelForEach();

    void SetJobScheduler(JobScheduler & jobScheduler);
    JobScheduler & GetJobScheduler() const;

    void SetEntryPoint(EntryPoint const& entryPoint);
    EntryPoint GetEntryPoint() const;

    void SetDesc(ForEachDesc const& forEachDesc);

    // directly uses forEachDesc past in.
    //   must be allocated 16-byte aligned
    //   must remain valid during the execution of the FE jobs using it.
    void SetDescUnmanaged(ForEachDesc * forEachDesc);

    void SetNumJobs(int numJobs);
    int GetNumJobs() const;

    void SetDivision(ForEachDivisionEnum forEachDivisionEnum);
    ForEachDivisionEnum GetDivision() const;

    void SetParam2(Param param2);
    Param GetParam2() const;

    void SetParam3(Param param3);
    Param GetParam3() const;

    void SetAllowSleepOn(bool b);
    bool GetAllowSleepOn() const;

    void Run();
    void AddJobInstances();

    void WaitOn(WaitOnCallback* waitOnCallback = 0, void* callbackContext = 0, int sleepInMs = -1) const;
    void SleepOn() const;

    bool IsDone() const;

    JobInstanceHandle GetBeginJobInstanceHandle() const;
    JobInstanceHandle GetEndJobInstanceHandle() const;

    static size_t UsedDescriptors();
    static void Setup();
    static void Teardown();

private:

    JobScheduler      * mJobScheduler;
    EntryPoint          mEntryPoint;

    ForEachDesc       * mDesc;

    ForEachDivisionEnum mForEachDivisionEnum;
    int                 mNumJobs;
    Param               mParam2;
    Param               mParam3;
    bool                mAllowSleepOn;

    JobInstanceHandle mBeginJobInstanceHandle;
    JobInstanceHandle mEndJobInstanceHandle;

    void InitDyanmicCounter();

    ParallelForEach& operator = (const ParallelForEach&);
    ParallelForEach(const ParallelForEach&);
};

}}

#if defined(EA_PLATFORM_PS3) && defined(EA_COMPILER_SN)
#pragma diag_pop
#endif

#endif
#endif
