// plugins/pyloader/src/sgpem.i - 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/.



%module sgpem
%{
#include <sgpemv2/cpu_policy.hh>
#include <sgpemv2/cpu_policies_gatekeeper.hh>
#include <sgpemv2/history.hh>
#include <sgpemv2/policy_parameters.hh>
#include <sgpemv2/process.hh>
#include <sgpemv2/ready_queue.hh>
#include <sgpemv2/schedulable.hh>
#include <sgpemv2/scheduler.hh>
#include <sgpemv2/simulation.hh>
#include <sgpemv2/thread.hh>
using namespace sgpem;
%}

/* NOTE : passing Unicode strings to C++ methods calling them 
 * from Python results in a SIGSEGV. You've been warned!
 * (Investigate if this can be fixed, else please report it in 
 * the sgpem user manual)
 */

/* Due to the relatively new support for namespaces in SWIG,
 * make sure to include the full visibility signature when
 * returning / passing parameters from / to functions with
 * objects different to the one you're declaring.
 */



// ------------- EXCEPTIONS -------------------------------

%include "exception.i"
%exception 
{
  try	{
		$action
	} catch (const std::exception& e) {
		SWIG_exception(SWIG_RuntimeError, e.what());
		throw;
	}
}


// ------------- TEMPLATES -------------------------------

// Instantiate a Thread* vector for usage with sgpem::Process
// std::out_of_range should be automatically defined,
// see Swig manual at the STL Vector .
%include "std_vector.i"
namespace std
{
	%template(ThreadVector) vector<sgpem::Thread*>;
}

// (See last comment): Wrap the above exceptions in the SWIG way.



// ------------- DECLARATIONS -------------------------------

namespace sgpem {
  
	class CPUPolicy {
	public:
		virtual ~CPUPolicy() = 0;
		sgpem::PolicyParameters& get_parameters();

    static CPUPolicy* callback_get_policy();
	};
  
  // --------------------------------------------
	class PolicyParameters 
	{
	public:
		//methods to CREATE PARAMETERS
		// (rewrapped correctly for SWIG usage)
		%ignore register_int(const Glib::ustring&, const int&,
												 const int&, const bool&, const int&);
		%ignore register_float(const Glib::ustring&, const float&,
													 const float&, const bool&, const float&);
		%ignore register_string(const Glib::ustring&, const bool&, 
														const char*);
		
	%extend {
		void register_int(const char* name,
											const int& lower_bound, 
											const int& upper_bound, 
											const bool& required, 
											const int& default_value = 0) 
		{ 
			self->register_int(name, lower_bound, upper_bound,
												 required, default_value); 
		}
		
		void register_float(const char* name,
												const float& lower_bound, 
												const float& upper_bound, 
												const bool& required, 
												const float& default_value = 0.0f)
		{ 
			self->register_float(name, lower_bound, upper_bound,
													 required, default_value); 
		}
		
		void register_string(const char* name, 
												 const bool& required, 
												 const char* default_value = "")
		{ 
			self->register_string(name, required, default_value);
		}
	}
		
		//methods to SET the VALUE of PARAMETERS
		// (rewrapped correctly for SWIG usage)
		%ignore set_int(const Glib::ustring&, const int&);
		%ignore set_float(const Glib::ustring&, const float&);
		%ignore set_string(const Glib::ustring&, const Glib::ustring&);
		
		%extend {
	    bool set_int(const char* name, const int& value)
			{ return self->set_int(name, value); }
	    bool set_float(const char* name, const float& value)
			{ return self->set_float(name, value); }
	    bool set_string(const char* name, const char* value)
			{ return self->set_string(name, value); }
		}
		
		//methods to GET the VALUE of PARAMETERS
		// (rewrapped correctly for SWIG usage)
		%ignore get_int(const Glib::ustring&) const;
		%ignore get_float(const Glib::ustring&) const;
		%ignore get_string(const Glib::ustring&) const;
		
		%extend {
	    int get_int(const char* name) const 
			{ return self->get_int(name); }
	    float get_float(const char* name) const 
			{ return self->get_float(name); }
	    const char* get_string(const char* name) const
			{ return self->get_string(name).c_str(); }
		}
		
	}; //~ class PolicyParameters
	
	// --------------------------------------------
	class Schedulable
	{
	public:
		virtual ~Schedulable() = 0;
		
		virtual unsigned int  get_arrival_time() const = 0;
		virtual unsigned int  get_elapsed_time() const = 0;
    virtual int           get_last_acquisition() const = 0;
    virtual int           get_last_release() const = 0;
		virtual int           get_base_priority() const = 0;
		virtual int           get_current_priority() const = 0;
    virtual int           set_priority_push(int new_value = 0) = 0;
		virtual unsigned int  get_total_cpu_time() const = 0;

    %ignore Schedulable::get_state() const;
    %extend {
      const char* get_state() const
      {
        switch(self->get_state())
          {
          case Schedulable::state_future:
            return "future";
          case Schedulable::state_terminated:
            return "terminated";
          case Schedulable::state_running:
            return "running";
          case Schedulable::state_ready:
            return "ready";
          case Schedulable::state_blocked:
            return "blocked";
          default:
            // should never get here
            return "undefined";
          }
      }
    }
    
		
		%ignore Schedulable::get_name() const;
		%extend {
			const char* get_name() const 
			{ return self->get_name().c_str(); }
		}
	}; //~ class Schedulable
	
	// --------------------------------------------
		
	class Process : public virtual Schedulable
	{
	public:
		virtual std::vector<Thread*> get_threads();
		virtual ~Process() = 0;
	}; //~ class Process
	
	class Thread : public virtual Schedulable
	{
	public:
		virtual Process& get_process();
		virtual ~Thread() = 0;
	}; //~ class Thread
		
	
	// --------------------------------------------
	class ReadyQueue 
    {
    public:
			typedef unsigned int position;
			typedef unsigned int size_t;
			
			size_t  size() const;
			
			sgpem::Thread& get_item_at(position index);
			
			void swap(position a, position b);
      void bubble_to_front(position x);
			
    private:
			// Avoid instantiation and copy
			ReadyQueue();
			ReadyQueue(const ReadyQueue&);
			ReadyQueue& operator=(const ReadyQueue&);
			~ReadyQueue();
    }; //~ class ReadyQueue

	// ---------------------------------------------

	class Scheduler {
	public:
		static sgpem::Scheduler&   get_instance();
		sgpem::ReadyQueue*         get_ready_queue();
	private:
		Scheduler();
		~Scheduler();
	};

} //~ namespace sgpem
