// src/backend/sgpemv2/schedulable.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 3 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, see http://www.gnu.org/licenses/.


#ifndef SCHEDULABLE_HH
#define SCHEDULABLE_HH 1

#include <sgpemv2/sgpemv2-visibility.hh>

#include <glibmm/ustring.h>

namespace sgpem
{
  /// \brief Represents a schedulable entity within the simulated system.
  ///
  /// Represents a schedulable entity within the simulated system.
  /// Real world schedulable entities are, for example: batch jobs, processes
  /// threads, fibers.
  /// This class factors out some of their features.
  ///
  /// This is an abstract class. Known subclasses are ::Process, and ::Thread
  class Schedulable;

  class SerializeVisitor;

  class SG_DLLEXPORT Schedulable
  {
  public:

    /// \brief This flag describes the actual state of the schedulable.
    ///
    /// You can think of this flag as the particular stack in the OS where the
    /// process are placed during their lifetime.  In the OS there are three
    /// main stacks that are Running processes, Read processes, and Blocked
    /// processes. These are emulated in a single list by this flag.
    enum state
    {
      state_running    = 1 << 0,
      state_ready      = 1 << 1,
      state_blocked    = 1 << 2,
      state_future     = 1 << 3,
      state_terminated = 1 << 4
    };

    /// \brief Virtual destructor
    ///
    /// Abstract virtual destructor
    virtual ~Schedulable() = 0;

    /// \brief Redefined operator equals (static equality).
    ///
    /// Redefined operator equals.
    /// By design, a Schedulable entity equals an other schedulable entity
    /// when their static (respect to the simulation) properties are equal.
    /// This means, for example, that the priority push does not count when
    /// determining equality, nor state, last aquisition and last release 
    /// time and elapsed time do count.
    /// \param op2 the Schedulable to compare this with.
    /// \return true if the Schedulable equal, false otherwise.
    virtual bool operator==(const Schedulable& op2) const = 0;


    /// \brief Returns the name of the Schedulable.
    ///
    /// Returns the name of the Schedulable.
    /// \return the name of the Schedulable.
    virtual Glib::ustring get_name() const = 0;

    /// \brief Returns the arrival time of the Schedulable.
    ///
    /// Returns the arrival time of the Schedulable.
    /// The arrival time is the instant of the simulation when
    /// the state of the Schedulable is switched from future to
    /// ready.
    ///
    /// The arrival time is a static (respect to the simulation) property.
    /// \return the arrival time of the Schedulable.
    virtual unsigned int get_arrival_time() const = 0;

    /// \brief Returns the elapsed time of the Schedulable.
    ///
    /// Returns the elapsed time of the Schedulable.
    /// The elapsed time is the amount of time a Schedulable has been running
    /// until the current instant.
    ///
    /// The elapsed time is a dynamic (respect to the simulation) property.
    /// \return the elapsed time of the Schedulable.
    virtual unsigned int get_elapsed_time() const = 0;

    /// \brief Returns the remaining time of the Schedulable.
    ///
    /// Returns the remaining time of the Schedulable.
    /// The remaining time is the remaining amount of time a Schedulable
    /// before its termination.
    ///
    /// It is defined as the difference between the total required CPU time
    /// and the current elapsed CPU time.
    ///
    /// The remaining time is a dynamic (respect to the simulation) property.
    /// \return the remaining time of the Schedulable.
    virtual unsigned int get_remaining_time() const;

    /// \brief Returns the last aquisition instant of the Schedulable.
    ///
    /// Returns the last aquisition instant of the Schedulable.
    /// The last aquisition instant of a Schedulable is the last instant at witch
    /// its state changed from anything but "running" to "running", i.e. when it 
    /// received the cpu.
    ///
    /// Its dual feature is the last release instant.
    ///
    /// The last aquisition instant is a dynamic (respect to the simulation) property.
    /// \return the last aquisition instant of the Schedulable.
    virtual int get_last_acquisition() const = 0;

    /// \brief Returns the last release instant of the Schedulable.
    ///
    /// Returns the last release instant of the Schedulable.
    /// The last release instant of a Schedulable is the last instant at witch
    /// its state changed from "running" to anything but "running", i.e. when it 
    /// abandoned the cpu.
    ///
    /// Its dual feature is the last aquisition instant.
    ///
    /// The last release instant is a dynamic (respect to the simulation) property.
    /// \return the last release instant of the Schedulable.
    virtual int get_last_release() const = 0;

    /// \brief Returns the base priority of the Schedulable.
    ///
    /// Returns the base priority of the Schedulable.
    /// The base priority of a Schedulable is an indicator of the importance of
    /// the Schedulable. Priority-sensitive policies usually give better services
    /// to more important Schedulables.
    ///
    /// Base priority is summed to the priority push to obtain the current priority
    /// of the schedulable, which is the real parameter policies read.
    ///
    /// The base priority is a static (respect to the simulation) property.
    /// \return the base priority of the Schedulable.
    virtual int get_base_priority() const = 0;

    /// \brief Returns the total required CPU time of the Schedulable.
    ///
    /// Returns the total required CPU time of the Schedulable.
    /// The total required CPU time is the time the Schedulable needs to 
    /// complete its work.
    /// 
    /// When a Schedulable's elapsed CPU time equals the total required CPU time
    /// its state is set to "terminated". 
    ///
    /// The total required CPU time is a static (respect to the simulation) property.
    /// \return the total required CPU time of the Schedulable.
    virtual unsigned int get_total_cpu_time() const = 0;

    /// \brief Returns the current priority of the Schedulable.
    ///
    /// Returns the current priority of the Schedulable.
    /// The current priority of a Schedulable is an indicator of the importance of
    /// the Schedulable. Priority-sensitive policies usually give better services
    /// to more important Schedulables.
    ///
    /// Base priority is summed to the priority push to obtain the current priority
    /// of the schedulable, which is the real parameter policies read.
    ///
    /// The current priority is a dynamic (respect to the simulation) property.
    /// \return the dynamic priority of the Schedulable.
    virtual int get_current_priority() const = 0;

    /// \brief Returns the current priority push of the Schedulable.
    ///
    /// Returns the current priority push of the Schedulable.
    /// The current priority push of a Schedulable is an indicator of the local 
    /// importance of the Schedulable. Priority-sensitive policies usually give
    /// better services to more important Schedulables.
    ///
    /// Base priority is summed to the priority push to obtain the current priority
    /// of the schedulable, which is the real parameter policies read.
    ///
    /// The priority push is a dynamic (respect to the simulation) property.
    /// \return the current priority push of the Schedulable.
    virtual int get_priority_push() const;

    /// \brief Sets the priority push of the Schedulable, returning the old one.
    ///
    /// Sets the current priority push of the Schedulable.
    /// The current priority push of a Schedulable is an indicator of the local 
    /// importance of the Schedulable. Priority-sensitive policies usually give
    /// better services to more important Schedulables.
    ///
    /// Base priority is summed to the priority push to obtain the current priority
    /// of the schedulable, which is the real parameter policies read.
    ///
    /// The priority push is a dynamic (respect to the simulation) property.
    /// \param new_value the new push to be set.
    /// \return the old priority push of the Schedulable.
    virtual int set_priority_push(int new_value = 0) = 0;

    /// \brief Returns the current state of the Schedulable.
    ///
    /// Returns the current state of the Schedulable.
    /// The current state of a Schedulable describes the role of the process within
    /// the system at the current instant. See Schedulable::state for the possible
    /// states of a schedulable.
    ///
    /// The current state is a dynamic (respect to the simulation) property.
    /// \return the current state of the Schedulable.
    virtual state get_state() const = 0;

    /// \brief Serializes this entity using a visitor pattern.
    ///
    /// \param translator the visitor used to serialize this entity.
    virtual void serialize(SerializeVisitor& translator) const = 0;
  };
}

#endif
