// src/backend/scheduler.hh - Copyright 2005, 2006, University
//               of Padova, dept. of Pure and Applied
//               Mathematics
//
// This file is part of SGPEMv2.
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// SGPEMv2 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SGPEMv2; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#ifndef SCHEDULER_HH
#define SCHEDULER_HH 1
namespace sgpem
{
  class Scheduler;
  class CPUPolicy;
}

#include "config.h"

#include <sgpemv2/history.hh>
#include <sgpemv2/cpu_policy.hh>
#include <sgpemv2/resource_policy.hh>
#include <sgpemv2/ready_queue.hh>
#include <sgpemv2/user_interrupt_exception.hh>
#include <sgpemv2/malformed_policy_exception.hh>

// Do not include full template definition here
#include <sgpemv2/templates/singleton.hh>

#include <glibmm/thread.h>

namespace sgpem
{
  class Scheduler;


  /** \brief Manages the DynamicSchedulable objects, implementing a given policy.

  Class Scheduler manages the schedulable entities which are ready to run, 
  ordering them in a queue; it also checks that the current scheduling policy 
  is well-defined and does not disrupt the application inner mechanism. 
  It is also responsible for the creation and the destruction of some of 
  the DynamicSchedulable objects (for further details about this, check 
  class DynamicSchedulable).

  */

  class SG_DLLEXPORT Scheduler : public Singleton<Scheduler>
  {
    friend class Singleton<Scheduler>;
  public:
    /**
        Generates a new ReadyQueue representing the status of the processes
        at the simulation instant next to the current one, and extends the History by
        one instant with it.
       Returning true if next instants will be identical to the last one added.
       
        \return false If the simulation has ended, true otherwise
     */
    bool       step_forward(History& history, CPUPolicy& cpu_policy, ResourcePolicy& resource_policy) throw(UserInterruptException, MalformedPolicyException);

    /**
       \brief Returns the policy that will be used to generate the simulation at the next instant.
       
       \warning This is a callback method: it can only be used in methods of CPUPolicy called
       by step_forward(). Else, a NULL pointer will be returned.
       \return A pointer to the active policy, or NULL if not inside step_forward()
    */
    CPUPolicy*      get_policy();
    
    /**
       \brief Returns a pointer to the queue containing all the ready 
       schedulable objects (for the policy to sort it). 

       \warning This is a callback method: it can only be used in methods of CPUPolicy called
       by step_forward(). Else, a NULL pointer will be returned.
       \return A pointer to the queue, or NULL if not inside step_forward()
    */
    ReadyQueue*     get_ready_queue();

  private:
    Scheduler();     //private constructor.

    ReadyQueue*       _ready_queue;
    CPUPolicy*        _policy;

    Glib::Mutex       _step_mutex;
  };

}//~ namespace sgpem

#endif //SCHEDULER_HH
