// src/backend/dynamic_sub_request.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_sub_request.hh"
#include "dynamic_request.hh"
#include <sgpemv2/request.hh>
#include <sgpemv2/serialize_visitor.hh>

#include <sgpemv2/templates/smartp.tcc>

#include <algorithm>
#include <cassert>

using namespace sgpem;

DynamicSubRequest::DynamicSubRequest(StaticSubRequest* core,
                                     DynamicRequest* owner) :
    _static_subrequest(core), _owner(owner),
    _queue_position(-1), _ran_for(0), _state(Request::state_future)
{
  assert(core != NULL);
  assert(owner != NULL);
// Leave this line: it helps us with a compiler warning if
// the get_dynamic* method signature changes:
  std::vector<DynamicSubRequest*>& siblings = owner->get_dynamic_subrequests();
  siblings.push_back(this);
}

DynamicSubRequest::DynamicSubRequest(const DynamicSubRequest& other,
                                     DynamicRequest* owner) :
    _static_subrequest(other._static_subrequest), _owner(owner),
    _queue_position(other._queue_position), _ran_for(other._ran_for),
    _state(other._state)
{
  assert(owner != NULL);

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

DynamicSubRequest::~DynamicSubRequest()
{}


bool
DynamicSubRequest::operator==(const SubRequest& op2) const
{
  assert(dynamic_cast<const DynamicSubRequest*>(&op2) != NULL);
  return _static_subrequest == dynamic_cast<const DynamicSubRequest&>(op2)._static_subrequest;
}


SubRequest::resource_key_t
DynamicSubRequest::get_resource_key() const
{
  return _static_subrequest->get_resource_key();
}


unsigned int
DynamicSubRequest::get_length() const
{
  return _static_subrequest->get_length();
}

int
DynamicSubRequest::get_queue_position() const
{
  return _queue_position;
}

void
DynamicSubRequest::set_queue_position(int position)
{
  _queue_position = position;
}


DynamicRequest&
DynamicSubRequest::get_request()
{
  return *_owner;
}


DynamicSubRequest::state
DynamicSubRequest::get_state() const
{
  return _state;
}


DynamicSubRequest::state
DynamicSubRequest::set_state(state new_state)
{
  state temp = _state;
  _state = new_state;
  return temp;
}


unsigned int
DynamicSubRequest::get_remaining_time() const
{
  return _static_subrequest->get_length() - _ran_for;
}


unsigned int
DynamicSubRequest::decrease_remaining_time()
{
  assert(_state == Request::state_allocated);
  unsigned int temp = get_remaining_time();
  if (temp > 0)
    _ran_for++;

  return temp;
}


void
DynamicSubRequest::serialize(SerializeVisitor& translator) const
{
  translator.from_subrequest(*this);
}


StaticSubRequest&
DynamicSubRequest::get_core()
{
  return *_static_subrequest;
}


const StaticSubRequest&
DynamicSubRequest::get_core() const
{
  return *_static_subrequest;
}
