// src/backend/dynamic_thread.cc - 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

#include "dynamic_thread.hh"
#include "static_thread.hh"
#include "dynamic_request.hh"
#include <sgpemv2/serialize_visitor.hh>

#include <algorithm>
#include <functional>
#include <cassert>

#include <sgpemv2/templates/deletor.tcc>
#include <sgpemv2/templates/smartp.tcc>

using namespace sgpem;
using namespace std;


DynamicThread::DynamicThread(StaticThread* core, DynamicProcess* parent)
    : DynamicSchedulable(), _core(core), _state(state_future), _parent(parent),
    _ran_for(0), _last_acquisition(-1), _last_release(-1)
{
  assert(core != NULL);
  assert(parent != NULL);

  // Leave this line: it helps us with a compiler warning if
  // the get_dynamic* method signature changes:
  std::vector<DynamicThread*>& siblings = parent->get_dynamic_threads();
  siblings.push_back(this);
}

DynamicThread::DynamicThread(const DynamicThread &other, DynamicProcess* parent) :
    Schedulable(), DynamicSchedulable(other), Thread(),
    _core(other._core), _state(other._state), _parent(parent),
    _ran_for(other._ran_for), _last_acquisition(other._last_acquisition),
    _last_release(other._last_release)
{
  typedef vector<DynamicRequest*>::const_iterator ReqIt;

  assert(parent != NULL);

  const vector<DynamicRequest*>& other_req = other._dynamic_requests;

  for (ReqIt it = other_req.begin(); it != other_req.end(); ++it)
    new DynamicRequest(*(*it), this);

  // Leave this line: it helps us with a compiler warning if
  // the get_dynamic* method signature changes:
  std::vector<DynamicThread*>& siblings = parent->get_dynamic_threads();
  siblings.push_back(this);
}

DynamicThread::~DynamicThread()
{
  for_each(_dynamic_requests.begin(), _dynamic_requests.end(),
           memory::deletor<DynamicRequest>());
}


DynamicProcess&
DynamicThread::get_process()
{
  return *_parent;
}

Schedulable::state
DynamicThread::get_state() const
{
  return _state;
}

Schedulable::state
DynamicThread::set_state(state new_state)
{
  state old_state = _state;
  _state = new_state;

  return old_state;
}

vector<Request*>
DynamicThread::get_requests()
{
  return vector<Request*>(_dynamic_requests.begin(), _dynamic_requests.end());
}

void
DynamicThread::serialize(SerializeVisitor& translator) const
{
  //translator.from_thread(*_core);
  translator.from_thread(*this);
}

StaticThread&
DynamicThread::get_core()
{
  return *_core;
}

const StaticThread&
DynamicThread::get_core() const
{
  return *_core;
}


std::vector<DynamicRequest*>&
DynamicThread::get_dynamic_requests()
{
  return _dynamic_requests;
}


unsigned int
DynamicThread::get_elapsed_time() const
{
  return _ran_for;
}

void
DynamicThread::decrease_remaining_time()
{
  // strict check for us to better debug scheduler
  assert(_ran_for < get_total_cpu_time());
  if (_ran_for < get_total_cpu_time())
    _ran_for++;
}

int
DynamicThread::get_last_acquisition() const
{
  return _last_acquisition;
}

void
DynamicThread::set_last_acquisition(int instant)
{
  _last_acquisition = instant;
}

int
DynamicThread::get_last_release() const
{
  return _last_release;
}

void
DynamicThread::set_last_release(int instant)
{
  _last_release = instant;
}

