<commit_before>///
/// @file  LoadBalancer.cpp
/// @brief The LoadBalancer assigns work to the individual
///        threads in the computation of the special leaves
///        in the Lagarias-Miller-Odlyzko and
///        Deleglise-Rivat prime counting algorithms.
///
/// Simply parallelizing the computation of the special leaves in the
/// Lagarias-Miller-Odlyzko and Deleglise-Rivat algorithms by
/// subdividing the sieve interval by the number of threads into
/// equally sized subintervals does not scale because the distribution
/// of the special leaves is highly skewed and most special leaves are
/// in the first few segments whereas later on there are very few
/// special leaves.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <S2Status.hpp>
#include <imath.hpp>
#include <int128_t.hpp>
#include <min.hpp>
#include <calculator.hpp>
#include <json.hpp>

#include <stdint.h>
#include <cmath>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace nlohmann;

namespace primecount {

int LoadBalancer::resume_threads() const
{
  auto j = load_backup();

  if (is_resume(j, "S2_hard", x_, y_, z_))
    return j["S2_hard"]["threads"];

  return 0;
}

void LoadBalancer::backup(int threads,
                          int thread_id,
                          int64_t low,
                          int64_t segments,
                          int64_t segment_size) const
{
  auto j = load_backup();

  double percent = status_.getPercent(low_, z_, s2_total_, s2_approx_);

  j["S2_hard"]["x"] = to_string(x_);
  j["S2_hard"]["y"] = y_;
  j["S2_hard"]["z"] = z_;
  j["S2_hard"]["threads"] = threads;
  j["S2_hard"]["low"] = low_;
  j["S2_hard"]["segments"] = segments_;
  j["S2_hard"]["segment_size"] = segment_size_;
  j["S2_hard"]["s2_hard"] = to_string(s2_total_);
  j["S2_hard"]["percent"] = percent;
  j["S2_hard"]["seconds"] = get_wtime() - time_;

  j["S2_hard"]["thread" + to_string(thread_id)]["low"] = low;
  j["S2_hard"]["thread" + to_string(thread_id)]["segments"] = segments;
  j["S2_hard"]["thread" + to_string(thread_id)]["segment_size"] = segment_size;

  store_backup(j);
}

void LoadBalancer::backup(int thread_id,
                          int64_t low,
                          int64_t segments,
                          int64_t segment_size,
                          maxint_t s2,
                          Runtime& runtime)
{
  #pragma omp critical (LoadBalancer)
  {
    s2_total_ += s2;

    update(&low, &segments, runtime);

    double percent = status_.getPercent(low_, z_, s2_total_, s2_approx_);
    auto j = load_backup();

    j["S2_hard"]["segments"] = segments_;
    j["S2_hard"]["segment_size"] = segment_size_;
    j["S2_hard"]["s2_hard"] = to_string(s2_total_);
    j["S2_hard"]["percent"] = percent;
    j["S2_hard"]["seconds"] = get_wtime() - time_;
    j["S2_hard"].erase("thread" + to_string(thread_id));

    store_backup(j);

    if (is_print())
      status_.print(s2_total_, s2_approx_);
  }
}

void LoadBalancer::backup_result() const
{
  auto j = load_backup();

  if (is_resume(j, "S2_hard", x_, y_, z_))
  {
    j.erase("S2_hard");

    j["S2_hard"]["x"] = to_string(x_);
    j["S2_hard"]["y"] = y_;
    j["S2_hard"]["z"] = z_;
    j["S2_hard"]["low"] = low_;
    j["S2_hard"]["s2_hard"] = to_string(s2_total_);
    j["S2_hard"]["percent"] = 100;
    j["S2_hard"]["seconds"] = get_wtime() - time_;

    store_backup(j);
  }
}

template <typename T>
void print_resume(int thread_id,
                  T low,
                  T segments,
                  T segment_size)
{
  print_log("=== Resuming from primecount.backup ===");
  print_log("thread", thread_id);
  print_log("low", low);
  print_log("segments", segments);
  print_log("segment_size", segment_size);
  print_log("");
}

template <typename T>
void print_resume(T s2_hard, double seconds)
{
  if (!print_variables())
    print_log("");

  print_log("=== Resuming from primecount.backup ===");
  print_log("s2_hard", s2_hard);
  print_log_seconds(seconds);
}

bool LoadBalancer::resume(int thread_id,
                          int64_t& low,
                          int64_t& segments,
                          int64_t& segment_size)
{
  bool resumed = false;

  #pragma omp critical (LoadBalancer)
  {
    auto j = load_backup();

    if (is_resume(j, "S2_hard", thread_id, x_, y_, z_))
    {
      double seconds = j["S2_hard"]["seconds"];
      s2_total_ = calculator::eval<maxint_t>(j["S2_hard"]["s2_hard"]);
      low_ = j["S2_hard"]["low"];
      segments_ = j["S2_hard"]["segments"];
      segment_size_ = j["S2_hard"]["segment_size"];
      time_ = get_wtime() - seconds;
      low = j["S2_hard"]["thread" + to_string(thread_id)]["low"];
      segments = j["S2_hard"]["thread" + to_string(thread_id)]["segments"];
      segment_size = j["S2_hard"]["thread" + to_string(thread_id)]["segment_size"];

      print_resume(thread_id, low, segments, segment_size);

      resumed = true;
    }
  }

  return resumed;
}

bool LoadBalancer::resume(maxint_t& s2_hard, double& time) const
{
  auto j = load_backup();

  if (is_resume(j, "S2_hard", x_, y_, z_) &&
      j["S2_hard"]["low"] >= j["S2_hard"]["z"])
  {
    double seconds = j["S2_hard"]["seconds"];
    s2_hard = calculator::eval<maxint_t>(j["S2_hard"]["s2_hard"]);
    time = get_wtime() - seconds;
    print_resume(s2_hard, seconds);

    return true;
  }

  return false;
}

LoadBalancer::LoadBalancer(maxint_t x,
                           int64_t y,
                           int64_t z,
                           double alpha,
                           maxint_t s2_approx) :
  low_(1),
  max_low_(1),
  x_(x),
  y_(y),
  z_(z),
  sqrtz_(isqrt(z)),
  segments_(1),
  s2_total_(0),
  s2_approx_(s2_approx),
  time_(get_wtime()),
  status_(x)
{
  init_size();
  maxint_t x16 = iroot<6>(x);
  smallest_hard_leaf_ = (int64_t) (x / (y * sqrt(alpha) * x16));
}

void LoadBalancer::init_size()
{
  int64_t log = ilog(sqrtz_);
  log = max(log, 1);
  segment_size_ = sqrtz_ / log;

  int64_t min = 1 << 9;
  segment_size_ = max(segment_size_, min);
  segment_size_ = next_power_of_2(segment_size_);
}

maxint_t LoadBalancer::get_result() const
{
  return s2_total_;
}

double LoadBalancer::get_time() const
{
  return time_;
}

bool LoadBalancer::get_work(int threads,
                            int thread_id,
                            int64_t* low,
                            int64_t* segments,
                            int64_t* segment_size,
                            maxint_t s2,
                            Runtime& runtime)
{
  #pragma omp critical (LoadBalancer)
  {
    s2_total_ += s2;

    update(low, segments, runtime);

    *low = low_;
    *segments = segments_;
    *segment_size = segment_size_;

    low_ += segments_ * segment_size_;

    backup(threads, thread_id, *low, *segments, *segment_size);

    if (is_print())
      status_.print(s2_total_, s2_approx_);
  }

  return *low <= z_;
}

void LoadBalancer::update(int64_t* low,
                          int64_t* segments,
                          Runtime& runtime)
{
  if (*low > max_low_)
  {
    max_low_ = *low;
    segments_ = *segments;

    if (segment_size_ < sqrtz_)
      segment_size_ *= 2;
    else
    {
      double next = get_next(runtime);
      next = in_between(0.25, next, 2.0);
      next *= segments_;
      next = max(1.0, next);
      segments_ = (int64_t) next;
    }
  }

  auto high = low_ + segments_ * segment_size_;

  // Most hard special leaves are located just past
  // smallest_hard_leaf_. In order to prevent assigning
  // the bulk of work to a single thread we reduce
  // the number of segments to a minimum.
  //
  if (smallest_hard_leaf_ >= low_ &&
      smallest_hard_leaf_ <= high)
  {
    segments_ = 1;
  }
}

double LoadBalancer::get_next(Runtime& runtime) const
{
  double min_secs = runtime.init * 10;
  double run_secs = runtime.secs;

  min_secs = max(min_secs, 0.01);
  run_secs = max(run_secs, min_secs / 10);

  double rem = remaining_secs();
  double threshold = rem / 4;
  threshold = max(threshold, min_secs);

  return threshold / run_secs;
}

/// Remaining seconds till finished
double LoadBalancer::remaining_secs() const
{
  double percent = status_.getPercent(low_, z_, s2_total_, s2_approx_);
  percent = in_between(20, percent, 100);

  double total_secs = get_wtime() - time_;
  double secs = total_secs * (100 / percent) - total_secs;
  return secs;
}

} // namespace
<commit_msg>Fix resume bug near finish<commit_after>///
/// @file  LoadBalancer.cpp
/// @brief The LoadBalancer assigns work to the individual
///        threads in the computation of the special leaves
///        in the Lagarias-Miller-Odlyzko and
///        Deleglise-Rivat prime counting algorithms.
///
/// Simply parallelizing the computation of the special leaves in the
/// Lagarias-Miller-Odlyzko and Deleglise-Rivat algorithms by
/// subdividing the sieve interval by the number of threads into
/// equally sized subintervals does not scale because the distribution
/// of the special leaves is highly skewed and most special leaves are
/// in the first few segments whereas later on there are very few
/// special leaves.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <S2Status.hpp>
#include <imath.hpp>
#include <int128_t.hpp>
#include <min.hpp>
#include <calculator.hpp>
#include <json.hpp>

#include <stdint.h>
#include <cmath>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace nlohmann;

namespace primecount {

int LoadBalancer::resume_threads() const
{
  auto j = load_backup();

  if (is_resume(j, "S2_hard", x_, y_, z_))
    return j["S2_hard"]["threads"];

  return 0;
}

void LoadBalancer::backup(int threads,
                          int thread_id,
                          int64_t low,
                          int64_t segments,
                          int64_t segment_size) const
{
  auto j = load_backup();

  double percent = status_.getPercent(low_, z_, s2_total_, s2_approx_);

  j["S2_hard"]["x"] = to_string(x_);
  j["S2_hard"]["y"] = y_;
  j["S2_hard"]["z"] = z_;
  j["S2_hard"]["threads"] = threads;
  j["S2_hard"]["low"] = low_;
  j["S2_hard"]["segments"] = segments_;
  j["S2_hard"]["segment_size"] = segment_size_;
  j["S2_hard"]["s2_hard"] = to_string(s2_total_);
  j["S2_hard"]["percent"] = percent;
  j["S2_hard"]["seconds"] = get_wtime() - time_;

  j["S2_hard"]["thread" + to_string(thread_id)]["low"] = low;
  j["S2_hard"]["thread" + to_string(thread_id)]["segments"] = segments;
  j["S2_hard"]["thread" + to_string(thread_id)]["segment_size"] = segment_size;

  store_backup(j);
}

void LoadBalancer::backup(int thread_id,
                          int64_t low,
                          int64_t segments,
                          int64_t segment_size,
                          maxint_t s2,
                          Runtime& runtime)
{
  #pragma omp critical (LoadBalancer)
  {
    s2_total_ += s2;

    update(&low, &segments, runtime);

    double percent = status_.getPercent(low_, z_, s2_total_, s2_approx_);
    auto j = load_backup();

    j["S2_hard"]["segments"] = segments_;
    j["S2_hard"]["segment_size"] = segment_size_;
    j["S2_hard"]["s2_hard"] = to_string(s2_total_);
    j["S2_hard"]["percent"] = percent;
    j["S2_hard"]["seconds"] = get_wtime() - time_;
    j["S2_hard"].erase("thread" + to_string(thread_id));

    store_backup(j);

    if (is_print())
      status_.print(s2_total_, s2_approx_);
  }
}

void LoadBalancer::backup_result() const
{
  auto j = load_backup();

  if (is_resume(j, "S2_hard", x_, y_, z_))
  {
    j.erase("S2_hard");

    j["S2_hard"]["x"] = to_string(x_);
    j["S2_hard"]["y"] = y_;
    j["S2_hard"]["z"] = z_;
    j["S2_hard"]["low"] = low_;
    j["S2_hard"]["s2_hard"] = to_string(s2_total_);
    j["S2_hard"]["percent"] = 100;
    j["S2_hard"]["seconds"] = get_wtime() - time_;

    store_backup(j);
  }
}

template <typename T>
void print_resume(int thread_id,
                  T low,
                  T segments,
                  T segment_size)
{
  print_log("=== Resuming from primecount.backup ===");
  print_log("thread", thread_id);
  print_log("low", low);
  print_log("segments", segments);
  print_log("segment_size", segment_size);
  print_log("");
}

template <typename T>
void print_resume(T s2_hard, double seconds)
{
  if (!print_variables())
    print_log("");

  print_log("=== Resuming from primecount.backup ===");
  print_log("s2_hard", s2_hard);
  print_log_seconds(seconds);
}

bool LoadBalancer::resume(int thread_id,
                          int64_t& low,
                          int64_t& segments,
                          int64_t& segment_size)
{
  bool resumed = false;

  #pragma omp critical (LoadBalancer)
  {
    auto j = load_backup();

    if (is_resume(j, "S2_hard", thread_id, x_, y_, z_))
    {
      double seconds = j["S2_hard"]["seconds"];
      s2_total_ = calculator::eval<maxint_t>(j["S2_hard"]["s2_hard"]);
      low_ = j["S2_hard"]["low"];
      segments_ = j["S2_hard"]["segments"];
      segment_size_ = j["S2_hard"]["segment_size"];
      time_ = get_wtime() - seconds;
      low = j["S2_hard"]["thread" + to_string(thread_id)]["low"];
      segments = j["S2_hard"]["thread" + to_string(thread_id)]["segments"];
      segment_size = j["S2_hard"]["thread" + to_string(thread_id)]["segment_size"];

      print_resume(thread_id, low, segments, segment_size);

      resumed = true;
    }
  }

  return resumed;
}

bool LoadBalancer::resume(maxint_t& s2_hard, double& time) const
{
  auto j = load_backup();

  if (is_resume(j, "S2_hard", x_, y_, z_) &&
      j["S2_hard"]["low"] >= j["S2_hard"]["z"] &&
      j["S2_hard"].count("threads") == 0)
  {
    double seconds = j["S2_hard"]["seconds"];
    s2_hard = calculator::eval<maxint_t>(j["S2_hard"]["s2_hard"]);
    time = get_wtime() - seconds;
    print_resume(s2_hard, seconds);

    return true;
  }

  return false;
}

LoadBalancer::LoadBalancer(maxint_t x,
                           int64_t y,
                           int64_t z,
                           double alpha,
                           maxint_t s2_approx) :
  low_(1),
  max_low_(1),
  x_(x),
  y_(y),
  z_(z),
  sqrtz_(isqrt(z)),
  segments_(1),
  s2_total_(0),
  s2_approx_(s2_approx),
  time_(get_wtime()),
  status_(x)
{
  init_size();
  maxint_t x16 = iroot<6>(x);
  smallest_hard_leaf_ = (int64_t) (x / (y * sqrt(alpha) * x16));
}

void LoadBalancer::init_size()
{
  int64_t log = ilog(sqrtz_);
  log = max(log, 1);
  segment_size_ = sqrtz_ / log;

  int64_t min = 1 << 9;
  segment_size_ = max(segment_size_, min);
  segment_size_ = next_power_of_2(segment_size_);
}

maxint_t LoadBalancer::get_result() const
{
  return s2_total_;
}

double LoadBalancer::get_time() const
{
  return time_;
}

bool LoadBalancer::get_work(int threads,
                            int thread_id,
                            int64_t* low,
                            int64_t* segments,
                            int64_t* segment_size,
                            maxint_t s2,
                            Runtime& runtime)
{
  #pragma omp critical (LoadBalancer)
  {
    s2_total_ += s2;

    update(low, segments, runtime);

    *low = low_;
    *segments = segments_;
    *segment_size = segment_size_;

    low_ += segments_ * segment_size_;

    backup(threads, thread_id, *low, *segments, *segment_size);

    if (is_print())
      status_.print(s2_total_, s2_approx_);
  }

  return *low <= z_;
}

void LoadBalancer::update(int64_t* low,
                          int64_t* segments,
                          Runtime& runtime)
{
  if (*low > max_low_)
  {
    max_low_ = *low;
    segments_ = *segments;

    if (segment_size_ < sqrtz_)
      segment_size_ *= 2;
    else
    {
      double next = get_next(runtime);
      next = in_between(0.25, next, 2.0);
      next *= segments_;
      next = max(1.0, next);
      segments_ = (int64_t) next;
    }
  }

  auto high = low_ + segments_ * segment_size_;

  // Most hard special leaves are located just past
  // smallest_hard_leaf_. In order to prevent assigning
  // the bulk of work to a single thread we reduce
  // the number of segments to a minimum.
  //
  if (smallest_hard_leaf_ >= low_ &&
      smallest_hard_leaf_ <= high)
  {
    segments_ = 1;
  }
}

double LoadBalancer::get_next(Runtime& runtime) const
{
  double min_secs = runtime.init * 10;
  double run_secs = runtime.secs;

  min_secs = max(min_secs, 0.01);
  run_secs = max(run_secs, min_secs / 10);

  double rem = remaining_secs();
  double threshold = rem / 4;
  threshold = max(threshold, min_secs);

  return threshold / run_secs;
}

/// Remaining seconds till finished
double LoadBalancer::remaining_secs() const
{
  double percent = status_.getPercent(low_, z_, s2_total_, s2_approx_);
  percent = in_between(20, percent, 100);

  double total_secs = get_wtime() - time_;
  double secs = total_secs * (100 / percent) - total_secs;
  return secs;
}

} // namespace
<|endoftext|>


<commit_before>#include <stdio.h>
#include <iostream>
#include <vector>
// glm additional header to generate transformation matrices directly.
#include <glm/gtc/matrix_transform.hpp>
#include <cstring> // For memcopy depending on the platform.

#include "helpers/ProgramUtilities.h"
#include "Renderer.h"

Renderer::~Renderer(){}

Renderer::Renderer(int width, int height){

	// Initialize the timer.
	_timer = glfwGetTime();
	// Initialize random generator;
	Random::seed();
	// Setup projection matrix.
	_camera.screen(width, height);

	_gbuffer = std::make_shared<Gbuffer>(_camera._renderSize[0],_camera._renderSize[1]);
	_ssaoFramebuffer = std::make_shared<Framebuffer>(_camera._renderSize[0],_camera._renderSize[1], GL_RED, GL_UNSIGNED_BYTE, GL_LINEAR, GL_CLAMP_TO_EDGE);

	_sceneFramebuffer = std::make_shared<Framebuffer>(_camera._renderSize[0],_camera._renderSize[1], GL_RGBA,GL_UNSIGNED_BYTE,GL_LINEAR,GL_CLAMP_TO_EDGE);
	_fxaaFramebuffer = std::make_shared<Framebuffer>(_camera._renderSize[0],_camera._renderSize[1], GL_RGBA,GL_UNSIGNED_BYTE,GL_LINEAR,GL_CLAMP_TO_EDGE);

	// Create directional light.
	_directionalLights.emplace_back(glm::vec3(0.0f), glm::vec3(0.7f), glm::ortho(-0.75f,0.75f,-0.75f,0.75f,2.0f,6.0f));

	// Create point lights.
	const float lI = 6.0; // Light intensity.
	std::vector<glm::vec3> colors = { glm::vec3(lI,0.0,0.0), glm::vec3(0.0,lI,0.0), glm::vec3(0.0,0.0,lI), glm::vec3(lI,lI,0.0), glm::vec3(lI,0.0,lI), glm::vec3(0.0,lI,lI), glm::vec3(lI,lI,lI), glm::vec3(lI,lI/2.0,lI/3.0), glm::vec3(lI/3.0,lI,lI/2.0), glm::vec3(lI/2.0,lI/3.0,lI)};

	for(size_t i = 0; i < 64; ++i){
		// 8 by 8 grid, from -2 to 2 on both axis.
		float radius = Random::Float(0.3f, 0.6f);
		glm::vec3 position = glm::vec3(-2.0f + 4.0*float(i%9)/8.0f, Random::Float(-0.25f, 0.0f), -2.0f + 4.0*float(i/9)/8.0f );
		_pointLights.emplace_back(position, colors[Random::Int(0, 9)], radius);
	}

	PointLight::loadProgramAndGeometry();

	// Query the renderer identifier, and the supported OpenGL version.
	const GLubyte* renderer = glGetString(GL_RENDERER);
	const GLubyte* version = glGetString(GL_VERSION);
	std::cout << "Renderer: " << renderer << std::endl;
	std::cout << "OpenGL version supported: " << version << std::endl;
	checkGLError();

	// GL options
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CCW);
	glCullFace(GL_BACK);
	glBlendEquation (GL_FUNC_ADD);
	glBlendFunc(GL_ONE, GL_ONE);
	checkGLError();

	// Initialize objects.
	_suzanne.init( "ressources/suzanne.obj", {"ressources/suzanne_texture_color.png", "ressources/suzanne_texture_normal.png", "ressources/suzanne_texture_ao_specular_reflection.png"}, 1, true);

	_dragon.init("ressources/dragon.obj", {"ressources/dragon_texture_color.png", "ressources/dragon_texture_normal.png", "ressources/dragon_texture_ao_specular_reflection.png" },  1, true);

	_plane.init("ressources/plane.obj", { "ressources/plane_texture_color.png", "ressources/plane_texture_normal.png", "ressources/plane_texture_depthmap.png" },  2);

	_skybox.init();

	std::map<std::string, GLuint> ambientTextures = _gbuffer->textureIds({ TextureType::Albedo, TextureType::Normal, TextureType::Depth });
	ambientTextures["ssaoTexture"] = _ssaoFramebuffer->textureId();
	_ambientScreen.init(ambientTextures);

	const std::vector<TextureType> includedTextures = { TextureType::Albedo, TextureType::Depth, TextureType::Normal, TextureType::Effects };
	for(auto& dirLight : _directionalLights){
		dirLight.init(_gbuffer->textureIds(includedTextures));
	}

	for(auto& pointLight : _pointLights){
		pointLight.init(_gbuffer->textureIds(includedTextures));
	}

	_fxaaScreen.init(_sceneFramebuffer->textureId(), "ressources/shaders/screens/fxaa");
	_finalScreen.init(_fxaaFramebuffer->textureId(), "ressources/shaders/screens/final_screenquad");
	checkGLError();

	// Position fixed objects.
	const glm::mat4 dragonModel = glm::scale(glm::translate(glm::mat4(1.0f), glm::vec3(-0.1,-0.05,-0.25)),glm::vec3(0.5f));
	const glm::mat4 planeModel = glm::scale(glm::translate(glm::mat4(1.0f),glm::vec3(0.0f,-0.35f,-0.5f)), glm::vec3(2.0f));

	_dragon.update(dragonModel);
	_plane.update(planeModel);

}

void Renderer::draw(){

	// Compute the time elapsed since last frame
	float elapsed = glfwGetTime() - _timer;
	_timer = glfwGetTime();

	// Physics simulation
	physics(elapsed);

	glm::vec2 invRenderSize = 1.0f / _camera._renderSize;

	// --- Light pass -------

	// Draw the scene inside the framebuffer.
	for(auto& dirLight : _directionalLights){

		dirLight.bind();

		// Draw objects.
		_suzanne.drawDepth(dirLight._mvp);
		_dragon.drawDepth(dirLight._mvp);
		//_plane.drawDepth(planeModel, _light._mvp);

		dirLight.blurAndUnbind();

	}

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

	// --- Scene pass -------
	// Bind the full scene framebuffer.
	_gbuffer->bind();
	// Set screen viewport
	glViewport(0,0,_gbuffer->_width,_gbuffer->_height);

	// Clear the depth buffer (we know we will draw everywhere, no need to clear color.
	glClear(GL_DEPTH_BUFFER_BIT);

	// Draw objects
	_suzanne.draw(_camera._view, _camera._projection);
	_dragon.draw(_camera._view, _camera._projection);
	_plane.draw(_camera._view, _camera._projection);
	_skybox.draw(_camera._view, _camera._projection);

	// Unbind the full scene framebuffer.
	_gbuffer->unbind();
	// ----------------------

	glDisable(GL_DEPTH_TEST);

	// --- SSAO pass
	_ssaoFramebuffer->bind();
	glViewport(0,0,_ssaoFramebuffer->_width, _ssaoFramebuffer->_height);
	_ambientScreen.drawSSAO( invRenderSize, _camera._view, _camera._projection);
	_ssaoFramebuffer->unbind();

	// --- Gbuffer composition pass
	_sceneFramebuffer->bind();

	glViewport(0,0,_sceneFramebuffer->_width, _sceneFramebuffer->_height);

	_ambientScreen.draw( invRenderSize, _camera._view, _camera._projection);

	glEnable(GL_BLEND);
	for(auto& dirLight : _directionalLights){
		//dirLight.draw( invRenderSize, _camera._view, _camera._projection);
	}

	for(auto& pointLight : _pointLights){
		//pointLight.draw( invRenderSize, _camera._view, _camera._projection);
	}
	glDisable(GL_BLEND);

	_sceneFramebuffer->unbind();

	// --- FXAA pass -------
	// Bind the post-processing framebuffer.
	_fxaaFramebuffer->bind();
	// Set screen viewport.
	glViewport(0,0,_fxaaFramebuffer->_width, _fxaaFramebuffer->_height);

	// Draw the fullscreen quad
	_fxaaScreen.draw( invRenderSize );

	_fxaaFramebuffer->unbind();
	// ----------------------

	// --- Final pass -------
	// We now render a full screen quad in the default framebuffer, using sRGB space.
	glEnable(GL_FRAMEBUFFER_SRGB);

	// Set screen viewport.
	glViewport(0,0,_camera._screenSize[0],_camera._screenSize[1]);

	// Draw the fullscreen quad
	_finalScreen.draw( 1.0f / _camera._screenSize);

	glDisable(GL_FRAMEBUFFER_SRGB);
	// ----------------------
	glEnable(GL_DEPTH_TEST);

	// Update timer
	_timer = glfwGetTime();
}

void Renderer::physics(float elapsedTime){

	_camera.update(elapsedTime);

	// Update lights.
	_directionalLights[0].update(glm::vec3(2.0f, 1.5f + sin(0.5*_timer),2.0f), _camera._view);

	for(size_t i = 0; i <_pointLights.size(); ++i){
		auto& pointLight = _pointLights[i];
		glm::vec4 newPosition = glm::rotate(glm::mat4(1.0f), (i%2==0 ? 1.0f: -1.0f) * elapsedTime, glm::vec3(0.0f, 1.0f, 0.0f))*glm::vec4(pointLight._local, 1.0f);
		pointLight.update(glm::vec3(newPosition), _camera._view);
	}

	// Update objects.

	const glm::mat4 suzanneModel = glm::scale(glm::rotate(glm::translate(glm::mat4(1.0f), glm::vec3(0.2,0.0,0.0)),float(_timer),glm::vec3(0.0f,1.0f,0.0f)),glm::vec3(0.25f));
	_suzanne.update(suzanneModel);

}

void Renderer::clean(){
	// Clean objects.
	_suzanne.clean();
	_dragon.clean();
	_plane.clean();
	_skybox.clean();
	for(auto& dirLight : _directionalLights){
		dirLight.clean();
	}
	_ambientScreen.clean();
	_fxaaScreen.clean();
	_finalScreen.clean();
	_gbuffer->clean();
	_ssaoFramebuffer->clean();
	_sceneFramebuffer->clean();
	_fxaaFramebuffer->clean();
}

void Renderer::resize(int width, int height){
	//Update the size of the viewport.
	glViewport(0, 0, width, height);
	// Update the projection matrix.
	_camera.screen(width, height);
	// Resize the framebuffer.
	_gbuffer->resize(_camera._renderSize);
	_ssaoFramebuffer->resize(_camera._renderSize);
	_sceneFramebuffer->resize(_camera._renderSize);
	_fxaaFramebuffer->resize(_camera._renderSize);
}

void Renderer::keyPressed(int key, int action){
	if(action == GLFW_PRESS){
		_camera.key(key, true);
	} else if(action == GLFW_RELEASE) {
		_camera.key(key, false);
	}
}

void Renderer::buttonPressed(int button, int action, double x, double y){
	if (button == GLFW_MOUSE_BUTTON_LEFT) {
		if (action == GLFW_PRESS) {
			_camera.mouse(MouseMode::Start,x, y);
		} else if (action == GLFW_RELEASE) {
			_camera.mouse(MouseMode::End, 0.0, 0.0);
		}
	} else {
		std::cout << "Button: " << button << ", action: " << action << std::endl;
	}
}

void Renderer::mousePosition(int x, int y, bool leftPress, bool rightPress){
	if (leftPress){
		_camera.mouse(MouseMode::Move, float(x), float(y));
	}
}

<commit_msg>Lower SSAO resolution.<commit_after>#include <stdio.h>
#include <iostream>
#include <vector>
// glm additional header to generate transformation matrices directly.
#include <glm/gtc/matrix_transform.hpp>
#include <cstring> // For memcopy depending on the platform.

#include "helpers/ProgramUtilities.h"
#include "Renderer.h"

Renderer::~Renderer(){}

Renderer::Renderer(int width, int height){

	// Initialize the timer.
	_timer = glfwGetTime();
	// Initialize random generator;
	Random::seed();
	// Setup projection matrix.
	_camera.screen(width, height);

	_gbuffer = std::make_shared<Gbuffer>(_camera._renderSize[0],_camera._renderSize[1]);
	_ssaoFramebuffer = std::make_shared<Framebuffer>(0.5f * _camera._renderSize[0], 0.5f * _camera._renderSize[1], GL_RED, GL_UNSIGNED_BYTE, GL_LINEAR, GL_CLAMP_TO_EDGE);

	_sceneFramebuffer = std::make_shared<Framebuffer>(_camera._renderSize[0],_camera._renderSize[1], GL_RGBA,GL_UNSIGNED_BYTE,GL_LINEAR,GL_CLAMP_TO_EDGE);
	_fxaaFramebuffer = std::make_shared<Framebuffer>(_camera._renderSize[0],_camera._renderSize[1], GL_RGBA,GL_UNSIGNED_BYTE,GL_LINEAR,GL_CLAMP_TO_EDGE);

	// Create directional light.
	_directionalLights.emplace_back(glm::vec3(0.0f), glm::vec3(0.7f), glm::ortho(-0.75f,0.75f,-0.75f,0.75f,2.0f,6.0f));

	// Create point lights.
	const float lI = 6.0; // Light intensity.
	std::vector<glm::vec3> colors = { glm::vec3(lI,0.0,0.0), glm::vec3(0.0,lI,0.0), glm::vec3(0.0,0.0,lI), glm::vec3(lI,lI,0.0), glm::vec3(lI,0.0,lI), glm::vec3(0.0,lI,lI), glm::vec3(lI,lI,lI), glm::vec3(lI,lI/2.0,lI/3.0), glm::vec3(lI/3.0,lI,lI/2.0), glm::vec3(lI/2.0,lI/3.0,lI)};

	for(size_t i = 0; i < 64; ++i){
		// 8 by 8 grid, from -2 to 2 on both axis.
		float radius = Random::Float(0.3f, 0.6f);
		glm::vec3 position = glm::vec3(-2.0f + 4.0*float(i%9)/8.0f, Random::Float(-0.25f, 0.0f), -2.0f + 4.0*float(i/9)/8.0f );
		_pointLights.emplace_back(position, colors[Random::Int(0, 9)], radius);
	}

	PointLight::loadProgramAndGeometry();

	// Query the renderer identifier, and the supported OpenGL version.
	const GLubyte* renderer = glGetString(GL_RENDERER);
	const GLubyte* version = glGetString(GL_VERSION);
	std::cout << "Renderer: " << renderer << std::endl;
	std::cout << "OpenGL version supported: " << version << std::endl;
	checkGLError();

	// GL options
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CCW);
	glCullFace(GL_BACK);
	glBlendEquation (GL_FUNC_ADD);
	glBlendFunc(GL_ONE, GL_ONE);
	checkGLError();

	// Initialize objects.
	_suzanne.init( "ressources/suzanne.obj", {"ressources/suzanne_texture_color.png", "ressources/suzanne_texture_normal.png", "ressources/suzanne_texture_ao_specular_reflection.png"}, 1, true);

	_dragon.init("ressources/dragon.obj", {"ressources/dragon_texture_color.png", "ressources/dragon_texture_normal.png", "ressources/dragon_texture_ao_specular_reflection.png" },  1, true);

	_plane.init("ressources/plane.obj", { "ressources/plane_texture_color.png", "ressources/plane_texture_normal.png", "ressources/plane_texture_depthmap.png" },  2);

	_skybox.init();

	std::map<std::string, GLuint> ambientTextures = _gbuffer->textureIds({ TextureType::Albedo, TextureType::Normal, TextureType::Depth });
	ambientTextures["ssaoTexture"] = _ssaoFramebuffer->textureId();
	_ambientScreen.init(ambientTextures);

	const std::vector<TextureType> includedTextures = { TextureType::Albedo, TextureType::Depth, TextureType::Normal, TextureType::Effects };
	for(auto& dirLight : _directionalLights){
		dirLight.init(_gbuffer->textureIds(includedTextures));
	}

	for(auto& pointLight : _pointLights){
		pointLight.init(_gbuffer->textureIds(includedTextures));
	}

	_fxaaScreen.init(_sceneFramebuffer->textureId(), "ressources/shaders/screens/fxaa");
	_finalScreen.init(_fxaaFramebuffer->textureId(), "ressources/shaders/screens/final_screenquad");
	checkGLError();

	// Position fixed objects.
	const glm::mat4 dragonModel = glm::scale(glm::translate(glm::mat4(1.0f), glm::vec3(-0.1,-0.05,-0.25)),glm::vec3(0.5f));
	const glm::mat4 planeModel = glm::scale(glm::translate(glm::mat4(1.0f),glm::vec3(0.0f,-0.35f,-0.5f)), glm::vec3(2.0f));

	_dragon.update(dragonModel);
	_plane.update(planeModel);

}

void Renderer::draw(){

	// Compute the time elapsed since last frame
	float elapsed = glfwGetTime() - _timer;
	_timer = glfwGetTime();

	// Physics simulation
	physics(elapsed);

	glm::vec2 invRenderSize = 1.0f / _camera._renderSize;

	// --- Light pass -------

	// Draw the scene inside the framebuffer.
	for(auto& dirLight : _directionalLights){

		dirLight.bind();

		// Draw objects.
		_suzanne.drawDepth(dirLight._mvp);
		_dragon.drawDepth(dirLight._mvp);
		//_plane.drawDepth(planeModel, _light._mvp);

		dirLight.blurAndUnbind();

	}

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

	// --- Scene pass -------
	// Bind the full scene framebuffer.
	_gbuffer->bind();
	// Set screen viewport
	glViewport(0,0,_gbuffer->_width,_gbuffer->_height);

	// Clear the depth buffer (we know we will draw everywhere, no need to clear color.
	glClear(GL_DEPTH_BUFFER_BIT);

	// Draw objects
	_suzanne.draw(_camera._view, _camera._projection);
	_dragon.draw(_camera._view, _camera._projection);
	_plane.draw(_camera._view, _camera._projection);
	_skybox.draw(_camera._view, _camera._projection);

	// Unbind the full scene framebuffer.
	_gbuffer->unbind();
	// ----------------------

	glDisable(GL_DEPTH_TEST);

	// --- SSAO pass
	_ssaoFramebuffer->bind();
	glViewport(0,0,_ssaoFramebuffer->_width, _ssaoFramebuffer->_height);
	_ambientScreen.drawSSAO( 2.0f * invRenderSize, _camera._view, _camera._projection);
	_ssaoFramebuffer->unbind();

	// --- Gbuffer composition pass
	_sceneFramebuffer->bind();

	glViewport(0,0,_sceneFramebuffer->_width, _sceneFramebuffer->_height);

	_ambientScreen.draw( invRenderSize, _camera._view, _camera._projection);

	glEnable(GL_BLEND);
	for(auto& dirLight : _directionalLights){
		//dirLight.draw( invRenderSize, _camera._view, _camera._projection);
	}

	for(auto& pointLight : _pointLights){
		//pointLight.draw( invRenderSize, _camera._view, _camera._projection);
	}
	glDisable(GL_BLEND);

	_sceneFramebuffer->unbind();

	// --- FXAA pass -------
	// Bind the post-processing framebuffer.
	_fxaaFramebuffer->bind();
	// Set screen viewport.
	glViewport(0,0,_fxaaFramebuffer->_width, _fxaaFramebuffer->_height);

	// Draw the fullscreen quad
	_fxaaScreen.draw( invRenderSize );

	_fxaaFramebuffer->unbind();
	// ----------------------

	// --- Final pass -------
	// We now render a full screen quad in the default framebuffer, using sRGB space.
	glEnable(GL_FRAMEBUFFER_SRGB);

	// Set screen viewport.
	glViewport(0,0,_camera._screenSize[0],_camera._screenSize[1]);

	// Draw the fullscreen quad
	_finalScreen.draw( 1.0f / _camera._screenSize);

	glDisable(GL_FRAMEBUFFER_SRGB);
	// ----------------------
	glEnable(GL_DEPTH_TEST);

	// Update timer
	_timer = glfwGetTime();
}

void Renderer::physics(float elapsedTime){

	_camera.update(elapsedTime);

	// Update lights.
	_directionalLights[0].update(glm::vec3(2.0f, 1.5f + sin(0.5*_timer),2.0f), _camera._view);

	for(size_t i = 0; i <_pointLights.size(); ++i){
		auto& pointLight = _pointLights[i];
		glm::vec4 newPosition = glm::rotate(glm::mat4(1.0f), (i%2==0 ? 1.0f: -1.0f) * elapsedTime, glm::vec3(0.0f, 1.0f, 0.0f))*glm::vec4(pointLight._local, 1.0f);
		pointLight.update(glm::vec3(newPosition), _camera._view);
	}

	// Update objects.

	const glm::mat4 suzanneModel = glm::scale(glm::rotate(glm::translate(glm::mat4(1.0f), glm::vec3(0.2,0.0,0.0)),float(_timer),glm::vec3(0.0f,1.0f,0.0f)),glm::vec3(0.25f));
	_suzanne.update(suzanneModel);

}

void Renderer::clean(){
	// Clean objects.
	_suzanne.clean();
	_dragon.clean();
	_plane.clean();
	_skybox.clean();
	for(auto& dirLight : _directionalLights){
		dirLight.clean();
	}
	_ambientScreen.clean();
	_fxaaScreen.clean();
	_finalScreen.clean();
	_gbuffer->clean();
	_ssaoFramebuffer->clean();
	_sceneFramebuffer->clean();
	_fxaaFramebuffer->clean();
}

void Renderer::resize(int width, int height){
	//Update the size of the viewport.
	glViewport(0, 0, width, height);
	// Update the projection matrix.
	_camera.screen(width, height);
	// Resize the framebuffer.
	_gbuffer->resize(_camera._renderSize);
	_ssaoFramebuffer->resize(0.5f * _camera._renderSize);
	_sceneFramebuffer->resize(_camera._renderSize);
	_fxaaFramebuffer->resize(_camera._renderSize);
}

void Renderer::keyPressed(int key, int action){
	if(action == GLFW_PRESS){
		_camera.key(key, true);
	} else if(action == GLFW_RELEASE) {
		_camera.key(key, false);
	}
}

void Renderer::buttonPressed(int button, int action, double x, double y){
	if (button == GLFW_MOUSE_BUTTON_LEFT) {
		if (action == GLFW_PRESS) {
			_camera.mouse(MouseMode::Start,x, y);
		} else if (action == GLFW_RELEASE) {
			_camera.mouse(MouseMode::End, 0.0, 0.0);
		}
	} else {
		std::cout << "Button: " << button << ", action: " << action << std::endl;
	}
}

void Renderer::mousePosition(int x, int y, bool leftPress, bool rightPress){
	if (leftPress){
		_camera.mouse(MouseMode::Move, float(x), float(y));
	}
}

<|endoftext|>


<commit_before>/****************************************************
 * This is a test that will test the pthreads API   *
 *                                                  *
 ****************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

pthread_barrier_t barrier;

pthread_mutex_t mux1;
pthread_mutex_t mux2;
pthread_mutex_t mux3;

// Functions executed by threads
void* thread_func(void * threadid);
void* barrier_func(void * threadid);
void* mutex_func(void * threadid);
void* cond_func(void * threadid);

int main(int argc, char* argv[])  // main begins
{
   // Read in the command line arguments
   const unsigned int numThreads = 3;

   // Declare threads and related variables
   pthread_t threads[numThreads];

   pthread_barrier_init(&barrier, NULL, numThreads);
   pthread_mutex_init(&mux1, NULL);
   pthread_mutex_init(&mux2, NULL);
   pthread_mutex_init(&mux3, NULL);

   for(unsigned int i = 0; i < 2; i++)
   {
      fprintf(stdout, "Spawning thread %d\n", i);

      //spawn test
      for(unsigned int j = 0; j < numThreads; j++)
          pthread_create(&threads[j], NULL, thread_func, (void *) (j + 1));

      for(unsigned int j = 0; j < numThreads; j++)
          pthread_join(threads[j], NULL);

      //barrier test
      for(unsigned int j = 0; j < numThreads; j++)
          pthread_create(&threads[j], NULL, barrier_func, (void *) (j + 1));

      for(unsigned int j = 0; j < numThreads; j++)
          pthread_join(threads[j], NULL);

      //mutex test
      for(unsigned int j = 0; j < numThreads; j++)
          pthread_create(&threads[j], NULL, mutex_func, (void *) (j + 1));

      for(unsigned int j = 0; j < numThreads; j++)
          pthread_join(threads[j], NULL);

      //cond test
//      for(unsigned int j = 0; j < numThreads; j++)
//          pthread_create(&threads[j], NULL, cond_func, (void *) (j + 1));

//      for(unsigned int j = 0; j < numThreads; j++)
//          pthread_join(threads[j], NULL);
   }

   pthread_barrier_destroy(&barrier);

   pthread_mutex_destroy(&mux1);
   pthread_mutex_destroy(&mux2);
   pthread_mutex_destroy(&mux3);

   fprintf(stdout, "UserApplication: About to exit!\n");

   return 0;
}

void* thread_func(void *threadid)
{
   fprintf(stdout, "Thread Test : Spawned thread #(%li)\n", (long) threadid);
   return NULL;
}

void* barrier_func(void *threadid)
{
   fprintf(stdout, "Barrier Test: Spawned thread #(%li)\n", (long) threadid);

   for (unsigned int i = 0; i < 50; i++)
      pthread_barrier_wait(&barrier);

   return NULL;
}

void* mutex_func(void *threadid)
{
   fprintf(stdout, "Mutex Test  : Spawned thread #(%li)\n", (long) threadid);

   for (unsigned int i = 0; i < 10; i++)
   {
      pthread_mutex_lock(&mux1);
      pthread_mutex_lock(&mux2);
      pthread_mutex_lock(&mux3);
      if (i % 25 == 0)
         fprintf(stderr, "Thread %li got %dth lock...\n", (long) threadid, i);
      pthread_mutex_unlock(&mux3);
      pthread_mutex_unlock(&mux2);
      pthread_mutex_unlock(&mux1);
   }

   return NULL;
}

void* cond_func(void *threadid)
{
   fprintf(stdout, "Cond Test : Spawned thread #(%li)\n", (long) threadid);
   fprintf(stdout, "WARNING: Not implemented yet.\n");
}

<commit_msg>[tests][pthreads] Added new cases to the pthreads unit test<commit_after>/****************************************************
 * This is a test that will test the pthreads API   *
 *                                                  *
 ****************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

const int numThreads = 3;

pthread_barrier_t barrier;

pthread_mutex_t mux1;
pthread_mutex_t mux2;
pthread_mutex_t mux3;

pthread_cond_t cond;
pthread_mutex_t mux_cond;
int counter;
bool cycle;

// Functions executed by threads
void* thread_func(void * threadid);
void* barrier_func(void * threadid);
void* mutex_func(void * threadid);
void* cond_broadcast_func(void * threadid);
void* cond_signal_func(void * threadid);

int main(int argc, char* argv[])  // main begins
{
   // Declare threads and related variables
   pthread_t threads[numThreads];

   // Initialize for barrier test
   pthread_barrier_init(&barrier, NULL, numThreads);

   // Initialize for mutex test
   pthread_mutex_init(&mux1, NULL);
   pthread_mutex_init(&mux2, NULL);
   pthread_mutex_init(&mux3, NULL);

   // Initialize for condition variable test
   pthread_cond_init(&cond, NULL);
   pthread_mutex_init(&mux_cond, NULL);
   counter = 0;
   cycle = false;

   for(int i = 0; i < 2; i++)
   {
      //spawn test
      for(int j = 0; j < numThreads; j++)
         pthread_create(&threads[j], NULL, thread_func, (void *) (j + 1));

      for(int j = 0; j < numThreads; j++)
         pthread_join(threads[j], NULL);

      //barrier test
      for(int j = 0; j < numThreads; j++)
         pthread_create(&threads[j], NULL, barrier_func, (void *) (j + 1));

      for(int j = 0; j < numThreads; j++)
         pthread_join(threads[j], NULL);

      //mutex test
      for(int j = 0; j < numThreads; j++)
         pthread_create(&threads[j], NULL, mutex_func, (void *) (j + 1));

      for(int j = 0; j < numThreads; j++)
         pthread_join(threads[j], NULL);

      //cond broadcast test
      for(int j = 0; j < numThreads; j++)
         pthread_create(&threads[j], NULL, cond_broadcast_func, (void *) (j + 1));

     for(int j = 0; j < numThreads; j++)
         pthread_join(threads[j], NULL);

      //cond signal test
      for(int j = 0; j < 2; j++)
         pthread_create(&threads[j], NULL, cond_signal_func, (void *) (j + 1));

     for(int j = 0; j < 2; j++)
         pthread_join(threads[j], NULL);
   }

   // De-initialize for barrier test
   pthread_barrier_destroy(&barrier);

   // De-initialize for mutex test
   pthread_mutex_destroy(&mux1);
   pthread_mutex_destroy(&mux2);
   pthread_mutex_destroy(&mux3);

   // De-initialize for cond test
   pthread_cond_destroy(&cond);
   pthread_mutex_destroy(&mux_cond);

   fprintf(stdout, "UserApplication: About to exit!\n");

   return 0;
}

void* thread_func(void *threadid)
{
   fprintf(stdout, "Thread Test : Spawned thread #(%li)\n", (long) threadid);
   return NULL;
}

void* barrier_func(void *threadid)
{
   fprintf(stdout, "Barrier Test: Spawned thread #(%li)\n", (long) threadid);

   for (unsigned int i = 0; i < 50; i++)
      pthread_barrier_wait(&barrier);

   return NULL;
}

void* mutex_func(void *threadid)
{
   fprintf(stdout, "Mutex Test  : Spawned thread #(%li)\n", (long) threadid);

   for (unsigned int i = 0; i < 50; i++)
   {
      pthread_mutex_lock(&mux1);
      pthread_mutex_lock(&mux2);
      pthread_mutex_lock(&mux3);

      pthread_mutex_unlock(&mux3);
      pthread_mutex_unlock(&mux2);
      pthread_mutex_unlock(&mux1);
   }

   return NULL;
}

void* cond_broadcast_func(void *threadid)
{
   fprintf(stdout, "Condition Variable Broadcast Test : Spawned thread #(%li)\n", (long) threadid);

   for (unsigned int i = 0; i < 50; i++)
   {
      pthread_mutex_lock(&mux_cond);
      bool cycle_ = cycle;

      if (++counter != numThreads)
      {
         while (cycle_ == cycle)
         {
            int error = pthread_cond_wait(&cond, &mux_cond);
            if (error != 0)
               break;
         }
      }
      else
      {
         cycle = !cycle;
         counter = 0;
         pthread_cond_broadcast(&cond);
      }
      pthread_mutex_unlock(&mux_cond);
   }

   return NULL;
}

void* cond_signal_func(void *threadid)
{
   fprintf(stdout, "Cond Variable Signal Test : Spawned thread #(%li)\n", (long) threadid);

   for (unsigned int i = 0; i < 50; i++)
   {
      pthread_mutex_lock(&mux_cond);
      bool cycle_ = cycle;

      if (++counter != 2)
      {
         while (cycle_ == cycle)
         {
            int error = pthread_cond_wait(&cond, &mux_cond);
            if (error != 0)
               break;
         }
      }
      else
      {
         cycle = !cycle;
         counter = 0;
         pthread_cond_signal(&cond);
      }
      pthread_mutex_unlock(&mux_cond);
   }

   return NULL;
}
<|endoftext|>


<commit_before>#include "LoadingState.h"
#include "Input.h"
#include "Qor.h"
#include "TileMap.h"
#include "Sprite.h"
#include "kit/log/log.h"
#include <glm/glm.hpp>
#include <cstdlib>
using namespace std;
using namespace glm;

LoadingState :: LoadingState(Qor* qor):
    m_pQor(qor),
    m_pWindow(qor->window()),
    m_pInput(qor->input()),
    m_pRoot(std::make_shared<Node>()),
    m_pCamera(make_shared<Camera>()),
    m_Fade(qor->timer()->timeline()),
    m_pPipeline(qor->pipeline())
{
    m_pRoot->add(m_pCamera->as_node());
    //m_pPipeline = make_shared<Pipeline>(
    //    m_pWindow,
    //    m_pQor->resources(),
    //    m_pRoot,
    //    m_pCamera
    //);
    vec2 win = vec2(m_pWindow->size().x, m_pWindow->size().y);
    const float icon_size = win.x / 24.0f;
    const float half_icon_size = icon_size / 2.0f;

    m_pLogo = make_shared<Mesh>(
        make_shared<MeshGeometry>(
            Prefab::quad(
                -vec2(m_pWindow->size().y, m_pWindow->size().y)/4.0f,
                vec2(m_pWindow->size().y, m_pWindow->size().y)/4.0f
            )
        )
    );
    m_pLogo->add_modifier(make_shared<Wrap>(Prefab::quad_wrap()));
    m_pLogo->material(make_shared<MeshMaterial>(
        m_pQor->resources()->cache_as<ITexture>(
            "logo.png"
        )
    ));
    m_pLogo->move(vec3(
        m_pWindow->center().x,
        m_pWindow->center().y,
        -1.0f
    ));
    m_pRoot->add(m_pLogo);

    m_pWaitIcon = make_shared<Mesh>(
        make_shared<MeshGeometry>(
            Prefab::quad(
                vec2(-half_icon_size),
                vec2(half_icon_size)
            )
        )
    );
    m_pWaitIcon->position(vec3(
        //win.x - icon_size,
        //icon_size,
        m_pWindow->center().x,
        m_pWindow->size().y * 1.0f/8.0f,
        0.0f
    ));
    m_pWaitIcon->add_modifier(make_shared<Wrap>(Prefab::quad_wrap()));
    m_pWaitIcon->material(make_shared<MeshMaterial>(
        m_pQor->resources()->cache_as<ITexture>(
            "load-c.png"
        )
    ));
    m_pRoot->add(m_pWaitIcon);

    m_pPipeline->bg_color(Color::white());
    //fade_to(Color::white(), m_FadeTime);
    m_Fade.frame(Frame<Color>(
        Color::white(),
        Freq::Time::seconds(0.5f),
        INTERPOLATE(out_sine<Color>)
    ));
    //m_Fade.frame(Frame<Color>(
    //    Color::white(), // wait a while
    //    Freq::Time::seconds(1.0f),
    //    INTERPOLATE(Color, out_sine)
    //));
    m_pMusic = make_shared<Sound>("loading.ogg", m_pQor->resources());
    //m_pRoot->add(m_pMusic);
    m_pMusic->source()->play();
}

LoadingState :: ~LoadingState()
{
}

//void LoadingState :: fade_to(const Color& c, float t)
//{
//    //m_Fade.set(Freq::Time::seconds(t), ~c, c);
//}

void LoadingState :: logic(Freq::Time t)
{
    if(m_pInput->key(SDLK_ESCAPE))
        m_pQor->quit();

    m_pRoot->logic(t);

    //m_pPipeline->shader(1)->use();
    int fade = m_pPipeline->shader(1)->uniform("LightAmbient");
    if(fade != -1)
        m_pPipeline->shader(1)->uniform(
            fade,
            m_Fade.get().vec4()
        );
    m_pQor->do_tasks();

    m_pPipeline->bg_color(m_Fade.get());

    Matrix::rescale(*m_pLogo->matrix(), m_Fade.get().r());

    m_pMusic->source()->gain = m_Fade.get().r();
    m_pMusic->source()->refresh();

    m_pLogo->pend();

    *m_pWaitIcon->matrix() *= rotate(
        t.s() * 180.0f,
        vec3(0.0f, 0.0f, -1.0f)
    );
    m_pWaitIcon->position(vec3(
        m_pWaitIcon->position().x,
        (m_pWindow->size().y * 1.0f/8.0f) * m_Fade.get().r(),
        m_pWaitIcon->position().z
    ));
    m_pWaitIcon->pend();

    if(m_pQor->state(1)->finished_loading()) {
        if(m_Fade.elapsed()) {
            if(m_Fade.get() == Color::white())
            {
                m_Fade.frame(Frame<Color>(
                    Color::black(),
                    Freq::Time::seconds(0.5f),
                    INTERPOLATE(out_sine<Color>)
                ));
            }
            else
            {
                m_pPipeline->shader(1)->uniform(
                    m_pPipeline->shader(1)->uniform("LightAmbient"),
                    Color::white().vec4()
                );
                m_pQor->pop_state();
            }
        }
    }
}

void LoadingState :: render() const
{
    //m_pPipeline->render();
    m_pPipeline->render(m_pRoot.get(), m_pCamera.get());
}

<commit_msg>loading screen music now optional for mods<commit_after>#include "LoadingState.h"
#include "Input.h"
#include "Qor.h"
#include "TileMap.h"
#include "Sprite.h"
#include "kit/log/log.h"
#include <glm/glm.hpp>
#include <cstdlib>
using namespace std;
using namespace glm;

LoadingState :: LoadingState(Qor* qor):
    m_pQor(qor),
    m_pWindow(qor->window()),
    m_pInput(qor->input()),
    m_pRoot(std::make_shared<Node>()),
    m_pCamera(make_shared<Camera>()),
    m_Fade(qor->timer()->timeline()),
    m_pPipeline(qor->pipeline())
{
    m_pRoot->add(m_pCamera->as_node());
    //m_pPipeline = make_shared<Pipeline>(
    //    m_pWindow,
    //    m_pQor->resources(),
    //    m_pRoot,
    //    m_pCamera
    //);
    vec2 win = vec2(m_pWindow->size().x, m_pWindow->size().y);
    const float icon_size = win.x / 24.0f;
    const float half_icon_size = icon_size / 2.0f;

    m_pLogo = make_shared<Mesh>(
        make_shared<MeshGeometry>(
            Prefab::quad(
                -vec2(m_pWindow->size().y, m_pWindow->size().y)/4.0f,
                vec2(m_pWindow->size().y, m_pWindow->size().y)/4.0f
            )
        )
    );
    m_pLogo->add_modifier(make_shared<Wrap>(Prefab::quad_wrap()));
    m_pLogo->material(make_shared<MeshMaterial>(
        m_pQor->resources()->cache_as<ITexture>(
            "logo.png"
        )
    ));
    m_pLogo->move(vec3(
        m_pWindow->center().x,
        m_pWindow->center().y,
        -1.0f
    ));
    m_pRoot->add(m_pLogo);

    m_pWaitIcon = make_shared<Mesh>(
        make_shared<MeshGeometry>(
            Prefab::quad(
                vec2(-half_icon_size),
                vec2(half_icon_size)
            )
        )
    );
    m_pWaitIcon->position(vec3(
        //win.x - icon_size,
        //icon_size,
        m_pWindow->center().x,
        m_pWindow->size().y * 1.0f/8.0f,
        0.0f
    ));
    m_pWaitIcon->add_modifier(make_shared<Wrap>(Prefab::quad_wrap()));
    m_pWaitIcon->material(make_shared<MeshMaterial>(
        m_pQor->resources()->cache_as<ITexture>(
            "load-c.png"
        )
    ));
    m_pRoot->add(m_pWaitIcon);

    m_pPipeline->bg_color(Color::white());
    //fade_to(Color::white(), m_FadeTime);
    m_Fade.frame(Frame<Color>(
        Color::white(),
        Freq::Time::seconds(0.5f),
        INTERPOLATE(out_sine<Color>)
    ));
    //m_Fade.frame(Frame<Color>(
    //    Color::white(), // wait a while
    //    Freq::Time::seconds(1.0f),
    //    INTERPOLATE(Color, out_sine)
    //));
    try{
        Log::Silencer ls;
        m_pMusic = make_shared<Sound>("loading.ogg", m_pQor->resources());
    }catch(...){}
    //m_pRoot->add(m_pMusic);
    if(m_pMusic)
        m_pMusic->source()->play();
}

LoadingState :: ~LoadingState()
{
}

//void LoadingState :: fade_to(const Color& c, float t)
//{
//    //m_Fade.set(Freq::Time::seconds(t), ~c, c);
//}

void LoadingState :: logic(Freq::Time t)
{
    if(m_pInput->key(SDLK_ESCAPE))
        m_pQor->quit();

    m_pRoot->logic(t);

    //m_pPipeline->shader(1)->use();
    int fade = m_pPipeline->shader(1)->uniform("LightAmbient");
    if(fade != -1)
        m_pPipeline->shader(1)->uniform(
            fade,
            m_Fade.get().vec4()
        );
    m_pQor->do_tasks();

    m_pPipeline->bg_color(m_Fade.get());

    Matrix::rescale(*m_pLogo->matrix(), m_Fade.get().r());

    if(m_pMusic) {
        m_pMusic->source()->gain = m_Fade.get().r();
        m_pMusic->source()->refresh();
    }

    m_pLogo->pend();

    *m_pWaitIcon->matrix() *= rotate(
        t.s() * 180.0f,
        vec3(0.0f, 0.0f, -1.0f)
    );
    m_pWaitIcon->position(vec3(
        m_pWaitIcon->position().x,
        (m_pWindow->size().y * 1.0f/8.0f) * m_Fade.get().r(),
        m_pWaitIcon->position().z
    ));
    m_pWaitIcon->pend();

    if(m_pQor->state(1)->finished_loading()) {
        if(m_Fade.elapsed()) {
            if(m_Fade.get() == Color::white())
            {
                m_Fade.frame(Frame<Color>(
                    Color::black(),
                    Freq::Time::seconds(0.5f),
                    INTERPOLATE(out_sine<Color>)
                ));
            }
            else
            {
                m_pPipeline->shader(1)->uniform(
                    m_pPipeline->shader(1)->uniform("LightAmbient"),
                    Color::white().vec4()
                );
                m_pQor->pop_state();
            }
        }
    }
}

void LoadingState :: render() const
{
    //m_pPipeline->render();
    m_pPipeline->render(m_pRoot.get(), m_pCamera.get());
}

<|endoftext|>


<commit_before><?hh //strict

/**
 * This file is part of hhpack\color.
 *
 * (c) Noritaka Horio <holy.shared.design@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace hhpack\color;

enum StyleType : int
{
    DefaultStyle = 0;
    Bold = 1;
    Dim = 2;
    Underlined = 4;
    Blink = 5;
    Reverse = 7;
    Hidden = 8;
}
<commit_msg>add italic<commit_after><?hh //strict

/**
 * This file is part of hhpack\color.
 *
 * (c) Noritaka Horio <holy.shared.design@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace hhpack\color;

enum StyleType : int
{
    DefaultStyle = 0;
    Bold = 1;
    Dim = 2;
    Italic = 3;
    Underlined = 4;
    Blink = 5;
    Reverse = 7;
    Hidden = 8;
}
<|endoftext|>


<commit_before>/*  MStringArray - Dynamic Array of MString objects
    Copyright (C) 2001-2004 Jesse L. Lovelace (jllovela@eos.ncsu.edu)

    This program 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.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <fstream.h>
#include <iostream.h>
#include "MStringArray.h"
#include "MString.h"

class MArrayNode {
public:
	MArrayNode(MString string, MArrayNode* link = 0) {MLink_Forward = link; MInfo = string;}
	MArrayNode *MLink_Forward;
	MString MInfo;
};

static void deallocate(MArrayNode* p)
{
	MArrayNode* tmp;
	while (p) {
		tmp = p;
		p = p->MLink_Forward;
		delete tmp;
	}
}

static MArrayNode* findTail(MArrayNode * startPointer) {
	MArrayNode * tmp=startPointer;
	while (tmp) {
		if (!tmp->MLink_Forward)
			return tmp;
		tmp = tmp->MLink_Forward;
	}
	return startPointer;
}

static MArrayNode* copy(MArrayNode* p, MArrayNode*& tailNode)
{
	MArrayNode* head = 0;
	MArrayNode* tail = 0;

	while(p) {
		if (!head)
			head = tail = new MArrayNode(p->MInfo);
		else {
			tail->MLink_Forward = new MArrayNode(p->MInfo);
			tail = tail->MLink_Forward;
		}
		p = p->MLink_Forward;
	}
	tailNode = tail;
	return head;
}

MArrayNode* MStringArray::GetPointerAt(int nIndex) {

	MArrayNode* tmp = headMNode;

	for (int i = 0; (i < nIndex); i++) {

		if (NULL == tmp)
			return NULL;

		tmp = tmp->MLink_Forward;
	}
	return tmp;
}

MStringArray::~MStringArray() {
	deallocate(headMNode);
	headMNode = tailMNode = NULL;
}

MStringArray::MStringArray() {

	headMNode = tailMNode = NULL;
}

MStringArray::MStringArray(const MStringArray& arraySrc) {

	headMNode = copy(arraySrc.headMNode, tailMNode);
}

MStringArray::MStringArray(const MString& stringSrc) {

	headMNode = tailMNode = new MArrayNode(stringSrc);
}

const MStringArray& MStringArray::operator = (const MStringArray& arraySrc) {

	if (this != &arraySrc) {
		deallocate(headMNode);
		headMNode = tailMNode = NULL;
		headMNode = copy(arraySrc.headMNode, tailMNode);
	}
	return *this;
}

int MStringArray::GetSize() const {

	int count = 0;

	if (headMNode==NULL)
		return count;

	MArrayNode *tmp = headMNode;

	while(tmp) {
		count++;
		tmp = tmp->MLink_Forward;
	}
	return count;

}

int MStringArray::GetUpperBound() const {

	return (GetSize() - 1);
}

void MStringArray::SetSize(int nNewSize, int nGrowBy) {

	if (nNewSize < 0)
		return;
	//UNFINISHED FUNCTION
	//nGrowBy unreferenced formal param

}

void MStringArray::FreeExtra() {

	//UNFINISHED FUNCTION

}

void MStringArray::RemoveAll() {

	deallocate(headMNode);
	headMNode = tailMNode = NULL;

}

void MStringArray::test() {

	MArrayNode *tmp = headMNode;

	int count = 0;
	cout << "Head = " << headMNode << endl;
	while (tmp)
	{
		cout << "Index(" << count++ << ") " << tmp->MInfo << " " << tmp->MLink_Forward << endl;
		tmp = tmp->MLink_Forward;
	}
	cout << "Tail = " << tailMNode << endl;
	cout << "GetSize = " << GetSize() << endl;
}

MString MStringArray::GetAt(int nIndex) const {

	MString tmpStr;
	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return tmpStr;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	return tmp->MInfo;
}

void MStringArray::SetAt(int nIndex, const MString &newElement) {

	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	tmp->MInfo = newElement;
}

void MStringArray::SetAt(int nIndex, char newString[]) {

	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	tmp->MInfo = newString;
}

MString& MStringArray::ElementAt(int nIndex) {

	MString* tmpStr = NULL;
	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return *tmpStr;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	return tmp->MInfo;
}

// const MString* MStringArray::GetData() const;
// MString* MStringArray::GetData();

void MStringArray::SetAtGrow(int nIndex, const MString &newElement) {

	//Not written yet
}

void MStringArray::SetAtGrow(int nIndex, char newString[]) {
	//Not written yet

}

int MStringArray::Add(const MString &newElement) {

	InsertAt(GetSize(), newElement);

	return GetUpperBound();
}

int MStringArray::Add(char newString[]) { //works

	InsertAt(GetSize(), newString);

	return GetUpperBound();
}

int MStringArray::Append(const MStringArray &src) { //works

	InsertAt(GetSize(), src);

	return GetSize();
}

void MStringArray::Copy(const MStringArray &src) {

	headMNode = copy(src.headMNode, tailMNode);

}
void MStringArray::InsertAt(int nIndex, const MString &newElement, int nCount) { //works
	//MFC Uses pointer to MString,

	int length = GetSize();

	if ((nCount == 0) || (nIndex < 0))
		return;

	if (length == 0) {  //if size is zero
		headMNode = tailMNode = new MArrayNode(newElement);
		return;
	}

	if (nIndex == length) {//if just adding to end, use tailMNode
		for (int a = 0; a < nCount; a++) {
			tailMNode->MLink_Forward = new MArrayNode(newElement);
			tailMNode = tailMNode->MLink_Forward;
		}
		return;
	}

	if (nIndex == 0) {
		headMNode = new MArrayNode(newElement, headMNode);
		MArrayNode* tmp = headMNode;

		for (int i = 1; i < nCount; i++) {
			tmp->MLink_Forward = new MArrayNode(newElement, tmp->MLink_Forward);
			tmp = tmp->MLink_Forward;
		}
		return;

	}

	if (nIndex > (length - 1)) {//if space between new element and old ones,
								 // pad with null MStrings

		for (int adds = nIndex; nIndex > GetSize(); adds++) {
			MString tmpStr;
			Add(tmpStr);
		}

		for (int other = 0; other < nCount; other++) {
			Add(newElement);
		}
		return;
	}

	// if inserting in the middle somewhere
	MArrayNode * tmp = headMNode;
	for (int k = 0; k < (nIndex - 1); k++) { //go to index you want to insert infront of.
		tmp = tmp->MLink_Forward;
	}
	for (int w = 0; w < nCount; w++) {
		tmp->MLink_Forward = new MArrayNode(newElement, tmp->MLink_Forward);
		tmp = tmp->MLink_Forward;
	}
	return;

}

void MStringArray::InsertAt(int nStartIndex, MStringArray pNewArray){ //works

	int size = pNewArray.GetSize();

	for (int i = 0; i < size; i++)
		InsertAt(nStartIndex++, pNewArray.GetAt(i)); //sloppy jesse, don't use GetAt
}

void MStringArray::InsertAt(int nIndex, char newString[], int nCount) {

	MString tmp(newString);
	InsertAt(nIndex, tmp, nCount);

	return;

}

void MStringArray::RemoveAt(int nIndex, int nCount) {

	int length = GetSize();

	if ((length < 1) || (nIndex > length) || (nCount < 1))
		return;

	if (nCount > (length - nIndex))
		nCount = (length - nIndex);

	if (0 == nIndex) {
		MArrayNode* first = headMNode;
		MArrayNode* last = GetPointerAt((nIndex + nCount)-1);

		if (last->MLink_Forward) {
			headMNode = last->MLink_Forward;
			last->MLink_Forward = NULL;
			deallocate(first);
		}
		else {
			headMNode = NULL;
			deallocate(first);
		}

	}
	else {
		MArrayNode* toHead = GetPointerAt(nIndex - 1);
		MArrayNode* first = GetPointerAt(nIndex);

		MArrayNode* last = GetPointerAt((nCount + nIndex) - 1);

		if (last->MLink_Forward) {
			if (last->MLink_Forward->MLink_Forward) {
				toHead->MLink_Forward = last->MLink_Forward;
				last->MLink_Forward = NULL;
				deallocate(first);
			}
			else {
				toHead->MLink_Forward=last->MLink_Forward;
				last->MLink_Forward = NULL;
				deallocate(first);
			}
		}
		else {
			toHead->MLink_Forward = NULL;
			deallocate(first);
		}
	}
	tailMNode = findTail(headMNode);

}

MString& MStringArray::operator[](int nIndex) {

	MString* tmpStr = NULL;
	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return *tmpStr;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	return tmp->MInfo;
}

MString MStringArray::operator[](int nIndex) const {

	MString tmpStr;
	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return tmpStr;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	return tmp->MInfo;
}

	//New functions:

void MStringArray::Split(MString stringToSplit, char ch, int nStartIndex, int insertAt){

	MStringArray tmpArray;

	MString tmpString;

	int place = nStartIndex,
		nextFind = stringToSplit.Find(ch, place);

	while (nextFind >= 0) {

		tmpString = stringToSplit.Mid(place, nextFind - place);

		tmpString.Trim(ch);

		cout << tmpString << endl;
		cout << "place = " << place << endl;

		tmpArray.Add(tmpString);

		tmpString.Empty();

		place = nextFind + 1;
		nextFind = stringToSplit.Find(ch, place);

		cout << "place = " << place << endl;
	}
	tmpString = stringToSplit.Right(stringToSplit.GetLength() - place);
	//get the last word and add
	// it
	tmpString.Trim(ch);
	if (!tmpString.IsEmpty()) {
		tmpArray.Add(tmpString);
		tmpString.Empty();
	}

	InsertAt(insertAt, tmpArray);
}
<commit_msg>Changed to standard headers.<commit_after>/*  MStringArray - Dynamic Array of MString objects
    Copyright (C) 2001-2004 Jesse L. Lovelace (jllovela@eos.ncsu.edu)

    This program 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.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <fstream>
#include <iostream>
#include "MStringArray.h"
#include "MString.h"

using namespace std;

class MArrayNode {
public:
	MArrayNode(MString string, MArrayNode* link = 0) {MLink_Forward = link; MInfo = string;}
	MArrayNode *MLink_Forward;
	MString MInfo;
};

static void deallocate(MArrayNode* p)
{
	MArrayNode* tmp;
	while (p) {
		tmp = p;
		p = p->MLink_Forward;
		delete tmp;
	}
}

static MArrayNode* findTail(MArrayNode * startPointer) {
	MArrayNode * tmp=startPointer;
	while (tmp) {
		if (!tmp->MLink_Forward)
			return tmp;
		tmp = tmp->MLink_Forward;
	}
	return startPointer;
}

static MArrayNode* copy(MArrayNode* p, MArrayNode*& tailNode)
{
	MArrayNode* head = 0;
	MArrayNode* tail = 0;

	while(p) {
		if (!head)
			head = tail = new MArrayNode(p->MInfo);
		else {
			tail->MLink_Forward = new MArrayNode(p->MInfo);
			tail = tail->MLink_Forward;
		}
		p = p->MLink_Forward;
	}
	tailNode = tail;
	return head;
}

MArrayNode* MStringArray::GetPointerAt(int nIndex) {

	MArrayNode* tmp = headMNode;

	for (int i = 0; (i < nIndex); i++) {

		if (NULL == tmp)
			return NULL;

		tmp = tmp->MLink_Forward;
	}
	return tmp;
}

MStringArray::~MStringArray() {
	deallocate(headMNode);
	headMNode = tailMNode = NULL;
}

MStringArray::MStringArray() {

	headMNode = tailMNode = NULL;
}

MStringArray::MStringArray(const MStringArray& arraySrc) {

	headMNode = copy(arraySrc.headMNode, tailMNode);
}

MStringArray::MStringArray(const MString& stringSrc) {

	headMNode = tailMNode = new MArrayNode(stringSrc);
}

const MStringArray& MStringArray::operator = (const MStringArray& arraySrc) {

	if (this != &arraySrc) {
		deallocate(headMNode);
		headMNode = tailMNode = NULL;
		headMNode = copy(arraySrc.headMNode, tailMNode);
	}
	return *this;
}

int MStringArray::GetSize() const {

	int count = 0;

	if (headMNode==NULL)
		return count;

	MArrayNode *tmp = headMNode;

	while(tmp) {
		count++;
		tmp = tmp->MLink_Forward;
	}
	return count;

}

int MStringArray::GetUpperBound() const {

	return (GetSize() - 1);
}

void MStringArray::SetSize(int nNewSize, int nGrowBy) {

	if (nNewSize < 0)
		return;
	//UNFINISHED FUNCTION
	//nGrowBy unreferenced formal param

}

void MStringArray::FreeExtra() {

	//UNFINISHED FUNCTION

}

void MStringArray::RemoveAll() {

	deallocate(headMNode);
	headMNode = tailMNode = NULL;

}

void MStringArray::test() {

	MArrayNode *tmp = headMNode;

	int count = 0;
	cout << "Head = " << headMNode << endl;
	while (tmp)
	{
		cout << "Index(" << count++ << ") " << tmp->MInfo << " " << tmp->MLink_Forward << endl;
		tmp = tmp->MLink_Forward;
	}
	cout << "Tail = " << tailMNode << endl;
	cout << "GetSize = " << GetSize() << endl;
}

MString MStringArray::GetAt(int nIndex) const {

	MString tmpStr;
	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return tmpStr;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	return tmp->MInfo;
}

void MStringArray::SetAt(int nIndex, const MString &newElement) {

	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	tmp->MInfo = newElement;
}

void MStringArray::SetAt(int nIndex, char newString[]) {

	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	tmp->MInfo = newString;
}

MString& MStringArray::ElementAt(int nIndex) {

	MString* tmpStr = NULL;
	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return *tmpStr;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	return tmp->MInfo;
}

// const MString* MStringArray::GetData() const;
// MString* MStringArray::GetData();

void MStringArray::SetAtGrow(int nIndex, const MString &newElement) {

	//Not written yet
}

void MStringArray::SetAtGrow(int nIndex, char newString[]) {
	//Not written yet

}

int MStringArray::Add(const MString &newElement) {

	InsertAt(GetSize(), newElement);

	return GetUpperBound();
}

int MStringArray::Add(char newString[]) { //works

	InsertAt(GetSize(), newString);

	return GetUpperBound();
}

int MStringArray::Append(const MStringArray &src) { //works

	InsertAt(GetSize(), src);

	return GetSize();
}

void MStringArray::Copy(const MStringArray &src) {

	headMNode = copy(src.headMNode, tailMNode);

}
void MStringArray::InsertAt(int nIndex, const MString &newElement, int nCount) { //works
	//MFC Uses pointer to MString,

	int length = GetSize();

	if ((nCount == 0) || (nIndex < 0))
		return;

	if (length == 0) {  //if size is zero
		headMNode = tailMNode = new MArrayNode(newElement);
		return;
	}

	if (nIndex == length) {//if just adding to end, use tailMNode
		for (int a = 0; a < nCount; a++) {
			tailMNode->MLink_Forward = new MArrayNode(newElement);
			tailMNode = tailMNode->MLink_Forward;
		}
		return;
	}

	if (nIndex == 0) {
		headMNode = new MArrayNode(newElement, headMNode);
		MArrayNode* tmp = headMNode;

		for (int i = 1; i < nCount; i++) {
			tmp->MLink_Forward = new MArrayNode(newElement, tmp->MLink_Forward);
			tmp = tmp->MLink_Forward;
		}
		return;

	}

	if (nIndex > (length - 1)) {//if space between new element and old ones,
								 // pad with null MStrings

		for (int adds = nIndex; nIndex > GetSize(); adds++) {
			MString tmpStr;
			Add(tmpStr);
		}

		for (int other = 0; other < nCount; other++) {
			Add(newElement);
		}
		return;
	}

	// if inserting in the middle somewhere
	MArrayNode * tmp = headMNode;
	for (int k = 0; k < (nIndex - 1); k++) { //go to index you want to insert infront of.
		tmp = tmp->MLink_Forward;
	}
	for (int w = 0; w < nCount; w++) {
		tmp->MLink_Forward = new MArrayNode(newElement, tmp->MLink_Forward);
		tmp = tmp->MLink_Forward;
	}
	return;

}

void MStringArray::InsertAt(int nStartIndex, MStringArray pNewArray){ //works

	int size = pNewArray.GetSize();

	for (int i = 0; i < size; i++)
		InsertAt(nStartIndex++, pNewArray.GetAt(i)); //sloppy jesse, don't use GetAt
}

void MStringArray::InsertAt(int nIndex, char newString[], int nCount) {

	MString tmp(newString);
	InsertAt(nIndex, tmp, nCount);

	return;

}

void MStringArray::RemoveAt(int nIndex, int nCount) {

	int length = GetSize();

	if ((length < 1) || (nIndex > length) || (nCount < 1))
		return;

	if (nCount > (length - nIndex))
		nCount = (length - nIndex);

	if (0 == nIndex) {
		MArrayNode* first = headMNode;
		MArrayNode* last = GetPointerAt((nIndex + nCount)-1);

		if (last->MLink_Forward) {
			headMNode = last->MLink_Forward;
			last->MLink_Forward = NULL;
			deallocate(first);
		}
		else {
			headMNode = NULL;
			deallocate(first);
		}

	}
	else {
		MArrayNode* toHead = GetPointerAt(nIndex - 1);
		MArrayNode* first = GetPointerAt(nIndex);

		MArrayNode* last = GetPointerAt((nCount + nIndex) - 1);

		if (last->MLink_Forward) {
			if (last->MLink_Forward->MLink_Forward) {
				toHead->MLink_Forward = last->MLink_Forward;
				last->MLink_Forward = NULL;
				deallocate(first);
			}
			else {
				toHead->MLink_Forward=last->MLink_Forward;
				last->MLink_Forward = NULL;
				deallocate(first);
			}
		}
		else {
			toHead->MLink_Forward = NULL;
			deallocate(first);
		}
	}
	tailMNode = findTail(headMNode);

}

MString& MStringArray::operator[](int nIndex) {

	MString* tmpStr = NULL;
	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return *tmpStr;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	return tmp->MInfo;
}

MString MStringArray::operator[](int nIndex) const {

	MString tmpStr;
	if ((nIndex < 0) || (nIndex > GetUpperBound()))
		return tmpStr;   //return's null MString if the nIndex is to big or small.

	MArrayNode* tmp = headMNode;

	for (int i = 0; i < nIndex; i++)
		tmp=tmp->MLink_Forward;

	return tmp->MInfo;
}

	//New functions:

void MStringArray::Split(MString stringToSplit, char ch, int nStartIndex, int insertAt){

	MStringArray tmpArray;

	MString tmpString;

	int place = nStartIndex,
		nextFind = stringToSplit.Find(ch, place);

	while (nextFind >= 0) {

		tmpString = stringToSplit.Mid(place, nextFind - place);

		tmpString.Trim(ch);

		cout << tmpString << endl;
		cout << "place = " << place << endl;

		tmpArray.Add(tmpString);

		tmpString.Empty();

		place = nextFind + 1;
		nextFind = stringToSplit.Find(ch, place);

		cout << "place = " << place << endl;
	}
	tmpString = stringToSplit.Right(stringToSplit.GetLength() - place);
	//get the last word and add
	// it
	tmpString.Trim(ch);
	if (!tmpString.IsEmpty()) {
		tmpArray.Add(tmpString);
		tmpString.Empty();
	}

	InsertAt(insertAt, tmpArray);
}
<|endoftext|>


<commit_before>/*
 * File:   Topology.hpp
 * Author: emanuele
 *
 * Created on 27 April 2012, 11:18
 */

#ifndef TOPOLOGY_HPP
#define	TOPOLOGY_HPP

#include "ContentElement.hpp"
#include <string>
#include "boost/graph/adjacency_list.hpp"
#include "boost/graph/graph_traits.hpp"
#include <vector>
#include <map>
#include <set>
#include <fstream>
#include <boost/property_map/dynamic_property_map.hpp>

// forward declarations to avoid include circles
class Scheduler;
class Flow;

using std::string;

/**
 * enum to differentiate upstream, downstream, metro and core (symmetric) links.
 * Note that this is not assigned to the edge, but rather computed through the
 * values of ponCustomers of the two vertices connected by the edge.
 */
enum EdgeType {UPSTREAM, DOWNSTREAM, METRO, CORE, UNKNOWN_TYPE};

/**
 *  A struct used to define bundled properties for nodes in the topology graph.
 */
struct NetworkNode {
    int ponCustomers; /**< number of customers attached to this PON node. if == 0, then this is a core node and not a PON. */
    int asid; /**< All the PONs attached to the same (set of) core node(s) belong to the same Access Section (AS). This is needed to compute locality. */
};
/**
 * A struct used to define bundled properties for edges in the topology graph.
 * Note that edges are uni-directional, i.e., a link is a composed by a pair
 * of edges with opposite directions.
 */
struct NetworkEdge {
    double length; /**< The length of the edge in meters. */
    Capacity maxCapacity; /**< The maximum bandwidth available on this edge. */
    Capacity spareCapacity; /**< The amount of bandwidth currently availabe on this edge, i.e., after substracting the capacity already used by Flows transiting on it. */
    std::set<Flow*> activeFlows; /**< The set of Flows actively using this edge at the moment. */
    Capacity peakCapacity; /**< The highest bandwidth collectively used by Flows on this edge at any given time in the current simulation round. */
    EdgeType type; /**< The EdgeType of this edge. Used to differentiate between core, metro and access traffic. */
};

// Our graph template
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
        NetworkNode, NetworkEdge> DGraph;
// Utility definitions to save time
typedef DGraph::vertex_descriptor Vertex;
typedef boost::graph_traits<DGraph>::vertex_iterator VertexIterator;
typedef boost::graph_traits<DGraph>::edge_descriptor Edge;
typedef boost::graph_traits<DGraph>::edge_iterator EdgeIterator;
typedef std::vector<Vertex> VertexVec;
typedef std::map<unsigned int, std::vector<Vertex> > PredecessorMap;

typedef std::map<unsigned int, Vertex> VertexMap;
typedef std::map<Vertex, std::vector<unsigned int> > DistanceMap;
typedef std::map<Edge, Capacity> LoadMap;

struct NetworkStats {
  std::vector<Capacity> avgTot, avgCore, avgAccessUp, avgAccessDown, peakCore,
      peakAccessUp, peakAccessDown, avgPeakCore, avgPeakAccessUp,
      avgPeakAccessDown, avgMetro, peakMetro, avgPeakMetro;
};

class Topology {
protected:
    DGraph topology;
    uint numVertices;
    uint numEdges;
    uint numMetroEdges;
    uint numCoreEdges;
    uint numCustomers;
    uint numASes;
    DistanceMap dMap;
    PredecessorMap pMap;
    Vertex centralServer;
    VertexMap asCacheMap;
    NetworkStats stats;
    VertexVec ponNodes;
    string fileName;
    LoadMap loadMap;
    /* While not technically a topology parameter, the bitrate of the encoded
     * content is required both in updateCapacity to estimate the time at which
     * users will change channel (and thus to set the userViewEta) and to
     * figure out if there's enough capacity to serve a new customer.
     */
    uint bitrate;
    /* minFlowIncrease is used in updateCapacity when adding bandwidth to a flow
     * due to the removal of some completed flow; if the increase is below this
     * threshold, no update is performed (to reduce unnecessary small changes
     * and speed up simulations). Note: this seems to hardly have any effect on
     * simulation speed, and might be removed in the future.
     */
    Capacity minFlowIncrease;
    /* dynamic_properties are used to take snapshots of the network in
     * printTopology, e.g. write a graphml file with all the network metrics.
     * Generating this object every time in that method would be needlessly
     * expensive, so it's populated in the constructor provided that snapshots
     * are actually going to be taken (i.e. sanpshotFreq > 0).
     */
    boost::dynamic_properties snapDp;
    /* the following map keeps track of how many peers are present in each AS.
     * This is needed when calculating content rates in the cache optimization
     * problem. The map is populated in the constructor, when determining the
     * number of users per PON.
     */
    std::map<uint, uint> ASCustomersMap;
    //utility methods
    void updateRouteCapacity(std::vector<Edge> route, Capacity toAdd);
    void updateEta(Flow* flow, Scheduler* scheduler);

public:
    Topology(string fileName, po::variables_map vm);
    VertexVec getPonNodes() const;
    uint getDistance(uint source, uint dest) const;
    std::vector<Edge> getRoute(uint source, uint dest);
    // utility method after the addition of PonUsers
    std::vector<Edge> getRoute(PonUser source, PonUser destination) {
      return this->getRoute(source.first, destination.first);
    }
    void updateCapacity(Flow* flow, Scheduler* scheduler,
          bool addNotRemove);
    void printNetworkStats(uint currentRound, uint roundDuration);
    void resetFlows();
    void updateLoadMap(Flow* flow);
    void resetLoadMap();
    Vertex getCentralServer();
    bool isLocal(Vertex source, Vertex dest);
    Vertex getLocalCache(Vertex node);
    VertexVec getLocalCacheNodes();
    bool isCongested(PonUser source, PonUser destination);
    bool addEdge(Vertex src, Vertex dest, Capacity cap, EdgeType type);
    void printTopology(SimTime time, uint round);
    uint getAsid(PonUser node) {
      return topology[node.first].asid;
    }
    EdgeType getEdgeType(Edge e) const;
    uint getPonCustomers(Vertex v) const;

  string getFileName() const {
    return fileName;
  }

  uint getNumCustomers() const {
    return numCustomers;
  }

  uint getNumASes() const {
    return numASes;
  }

  NetworkStats getNetworkStats() const {
    return this->stats;
  }

  /* returns the number of customers for a given AS id
   */
  uint getASCustomers(uint asid) {
    return ASCustomersMap.at(asid);
  }
};

#endif	/* TOPOLOGY_HPP */

<commit_msg>Doxygen documentation added.<commit_after>/*
 * File:   Topology.hpp
 * Author: emanuele
 *
 * Created on 27 April 2012, 11:18
 */

#ifndef TOPOLOGY_HPP
#define	TOPOLOGY_HPP

#include "ContentElement.hpp"
#include <string>
#include "boost/graph/adjacency_list.hpp"
#include "boost/graph/graph_traits.hpp"
#include <vector>
#include <map>
#include <set>
#include <fstream>
#include <boost/property_map/dynamic_property_map.hpp>

// forward declarations to avoid include circles
class Scheduler;
class Flow;

using std::string;

/**
 * enum to differentiate upstream, downstream, metro and core (symmetric) links.
 * Note that this is not assigned to the edge, but rather computed through the
 * values of ponCustomers of the two vertices connected by the edge.
 */
enum EdgeType {UPSTREAM, DOWNSTREAM, METRO, CORE, UNKNOWN_TYPE};

/**
 *  A struct used to define bundled properties for nodes in the topology graph.
 */
struct NetworkNode {
    int ponCustomers; /**< number of customers attached to this PON node. if == 0, then this is a core node and not a PON. */
    int asid; /**< All the PONs attached to the same (set of) core node(s) belong to the same Access Section (AS). This is needed to compute locality. */
};
/**
 * A struct used to define bundled properties for edges in the topology graph.
 * Note that edges are uni-directional, i.e., a link is a composed by a pair
 * of edges with opposite directions.
 */
struct NetworkEdge {
    double length; /**< The length of the edge in meters. */
    Capacity maxCapacity; /**< The maximum bandwidth available on this edge. */
    Capacity spareCapacity; /**< The amount of bandwidth currently availabe on this edge, i.e., after substracting the capacity already used by Flows transiting on it. */
    std::set<Flow*> activeFlows; /**< The set of Flows actively using this edge at the moment. */
    Capacity peakCapacity; /**< The highest bandwidth collectively used by Flows on this edge at any given time in the current simulation round. */
    EdgeType type; /**< The EdgeType of this edge. Used to differentiate between core, metro and access traffic. */
};

// Our graph template
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
        NetworkNode, NetworkEdge> DGraph;
// Utility definitions to save time
typedef DGraph::vertex_descriptor Vertex;
typedef boost::graph_traits<DGraph>::vertex_iterator VertexIterator;
typedef boost::graph_traits<DGraph>::edge_descriptor Edge;
typedef boost::graph_traits<DGraph>::edge_iterator EdgeIterator;
typedef std::vector<Vertex> VertexVec;
typedef std::map<unsigned int, std::vector<Vertex> > PredecessorMap;

typedef std::map<unsigned int, Vertex> VertexMap;
typedef std::map<Vertex, std::vector<unsigned int> > DistanceMap;
typedef std::map<Edge, Capacity> LoadMap;

/**
 * A struct used to keep track of a number of statistics on traffic observed
 * during the simulations. Each vector has as many elements as the number of
 * rounds in the simulation; at the end of each round the appropriate statistics
 * are computed and saved here.
 */
struct NetworkStats {
  std::vector<Capacity> avgTot; /**< Average traffic observed on an edge, across the whole topology. */
  std::vector<Capacity> avgCore; /**< Average traffic observed on a core edge. */
  std::vector<Capacity> avgAccessUp; /**< Average traffic observed on an upstream access edge. */
  std::vector<Capacity> avgAccessDown; /**< Average traffic observed on a downstream access edge. */
  std::vector<Capacity> peakCore; /**< Peak traffic observed on a core edge. */
  std::vector<Capacity> peakAccessUp; /**< Peak traffic observed on an upstream access edge. */
  std::vector<Capacity> peakAccessDown; /**< Peak traffic observed on a downstream access edge. */
  std::vector<Capacity> avgPeakCore; /**< Average peak traffic observed on a core edge. */
  std::vector<Capacity> avgPeakAccessUp; /**< Average peak traffic observed on an upstream access edge. */
  std::vector<Capacity> avgPeakAccessDown; /**< Average peak traffic observed on a downstream access edge. */
  std::vector<Capacity> avgMetro; /**< Average traffic observed on a metro edge (if present). */
  std::vector<Capacity> peakMetro; /**< Peak traffic observed on a metro edge (if present). */
  std::vector<Capacity> avgPeakMetro; /**< Average peak traffic observed on a metro edge (if present). */
};

/**
 * A representation of the physical topology over which the data is transmitted.
 * It is based on the Boost Graph library, specifically on the Adjacency_List.
 * Bundled properties are used to store information of interests for edges and
 * links. Routing, bandwidth assignment and traffic statistic collection are all
 * performed by this class.
 */
class Topology {
protected:
    DGraph topology; /**< The graph representation of the topology. */
    uint numVertices; /**< The total number of vertices in the topology. */
    uint numEdges; /**< The total number of edges in the topology. */
    uint numMetroEdges; /**< The number of metro edges in the topology. */
    uint numCoreEdges; /**< The number of core edges in the topology. */
    uint numCustomers; /**< The total number of custoemrs (i.e., end-users) in the topology. */
    uint numASes;  /**< The total number of Access Sections (ASes) in the topology. Typically each core (or metro/core) node has an associated AS. */
    DistanceMap dMap; /**< A map keeping track of the distance between vertices, used for routing purposes. */
    PredecessorMap pMap; /**< A map of predecessors in the pre-computed shourtest path routes, used for routing purposes. */
    Vertex centralServer; /**< The core network vertex where we are placing the central repository, i.e., the source of all ContentElement when they are first introduced in the catalog or when there is no other source available. */
    VertexMap asCacheMap; /**< */
    NetworkStats stats; /**< A collection of statistic measurements of the traffic circulating over this topology. @see NetworkStats */
    VertexVec ponNodes; /**< */
    string fileName; /**< */
    LoadMap loadMap; /**< A Map associating to each edge the total traffic it has observed. Used to compute the traffic statistics at the end of each round. */
    uint bitrate; /**< While not technically a topology parameter, the bitrate of the encoded content is required both in updateCapacity to estimate the time at which users will change channel (and thus to set the userViewEta) and to figure out if there's enough capacity to serve a new customer.*/
    Capacity minFlowIncrease;/**< minFlowIncrease is used in updateCapacity when adding bandwidth to a flow
     * due to the removal of some completed flow; if the increase is below this
     * threshold, no update is performed (to reduce unnecessary small changes
     * and speed up simulations). Note: this seems to hardly have any effect on
     * simulation speed, and might be removed in the future. @deprecated */
    boost::dynamic_properties snapDp; /**< dynamic_properties are used to take snapshots of the network in
     * Topology::printTopology(), e.g., write a graphml file with all the network metrics.
     * Generating this object every time in that method would be needlessly
     * expensive, so it's populated in the constructor provided that snapshots
     * are actually going to be taken (i.e., if sanpshotFreq > 0). */
    std::map<uint, uint> ASCustomersMap; /**< A map that keeps track of how many peers are present in each AS.
     * This is needed when calculating content rates in the cache optimization
     * problem. The map is populated in the constructor, when determining the
     * number of users per PON. */

    // Utility methods to streamline internal subroutines.
    /**
     * Iteratively adjusts the available bandwidth at each of the edges that
     * compose the specified route.
     * @param route The route we want to update the capacity of.
     * @param toAdd The amount of bandwidth that needs to be added (or subtracted, if negative) to each of the edges of the specified route.
     */
    void updateRouteCapacity(std::vector<Edge> route, Capacity toAdd);

    /**
     * Updates the ETA of a Flow after a bandwidth assignment change.
     * @param flow The Flow whose bandwidth has just changed.
     * @param scheduler A pointer to the Scheduler, which is needed to update the queue order in case of a change of ETA.
     */
    void updateEta(Flow* flow, Scheduler* scheduler);

public:
    Topology(string fileName, po::variables_map vm);
    VertexVec getPonNodes() const;
    uint getDistance(uint source, uint dest) const;
    std::vector<Edge> getRoute(uint source, uint dest);
    // utility method after the addition of PonUsers
    std::vector<Edge> getRoute(PonUser source, PonUser destination) {
      return this->getRoute(source.first, destination.first);
    }
    void updateCapacity(Flow* flow, Scheduler* scheduler,
          bool addNotRemove);
    void printNetworkStats(uint currentRound, uint roundDuration);
    void resetFlows();
    void updateLoadMap(Flow* flow);
    void resetLoadMap();
    Vertex getCentralServer();
    bool isLocal(Vertex source, Vertex dest);
    Vertex getLocalCache(Vertex node);
    VertexVec getLocalCacheNodes();
    bool isCongested(PonUser source, PonUser destination);
    bool addEdge(Vertex src, Vertex dest, Capacity cap, EdgeType type);
    void printTopology(SimTime time, uint round);
    uint getAsid(PonUser node) {
      return topology[node.first].asid;
    }
    EdgeType getEdgeType(Edge e) const;
    uint getPonCustomers(Vertex v) const;

  string getFileName() const {
    return fileName;
  }

  uint getNumCustomers() const {
    return numCustomers;
  }

  uint getNumASes() const {
    return numASes;
  }

  NetworkStats getNetworkStats() const {
    return this->stats;
  }

  /* returns the number of customers for a given AS id
   */
  uint getASCustomers(uint asid) {
    return ASCustomersMap.at(asid);
  }
};

#endif	/* TOPOLOGY_HPP */

<|endoftext|>


<commit_before>/*
 *
 *
 */

// Conclusion:
//
<commit_msg>Update 847.cpp<commit_after>/*
 * BFS
 *
 */
class Solution {
public:
    int shortestPathLength(vector<vector<int>>& graph) {
        const int n = graph.size();
        const int kAns = (1 << n) - 1;
        queue<pair<int, int>> q;
        vector<vector<int>> visited(n, vector<int>(1 << n));
        for (int i = 0; i < n; ++i)
          q.push({i, 1 << i});
        int steps = 0;
        while (!q.empty()) {
          int s = q.size();
          while (s--) {
            auto p = q.front();
            q.pop();
            int node = p.first;
            int state = p.second;
            if (state == kAns) return steps;
            if (visited[node][state]) continue;
            visited[node][state] = 1;
            for (int next : graph[node])
              q.push({next, state | (1 << next)});
          }
          ++steps;
        }
        return -1;
    }
};

// Conclusion:
// The State in "pair" format has two keys: head and cover;
// head means the position it is now at;
// cover means the positions it's already pass.
//
// Reference:
// Huahua: https://youtu.be/Vo3OEN2xgwk

<|endoftext|>


<commit_before>#include "MarkupWindow.h"

MarkupWindow::MarkupWindow(BRect frame, const char* title)
	:	BWindow(frame, title, B_TITLED_WINDOW, B_NOT_H_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS, B_CURRENT_WORKSPACE)
{
	// initialize controls      s
	AddShortcut('q', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
	BRect r = Bounds();
	topicListView = new BListView(BRect(10, 10, 30, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	contentTextView = new BTextView(BRect(0, 0, r.right, 100), NULL, BRect(10, 10, r.right, 100), B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	contentTextView->SetWordWrap(true);
	contentTextView->MakeEditable(false);
	backView = new BView(Bounds(), "backview", B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	backView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	backView->SetHighColor((rgb_color){0, 0, 0, 255});
	AddChild(backView);
	// gui layout builder
	backView->SetLayout(new BGroupLayout(B_HORIZONTAL, 0.0));
	backView->AddChild(BGridLayoutBuilder()
		.Add(new BScrollView("scroll_topic", topicListView, B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 0, 0, 1, 3)
		.Add(new BScrollView("scroll_content", contentTextView, B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 1, 0, 5, 10)
		.SetInsets(0, 0, 0, 0)
	);
	topicListView->SetSelectionMessage(new BMessage(LOAD_CONTENT));
}
void MarkupWindow::AddMarkupItem(BString topicstring, BString contentstring)
{
	topicListView->AddItem(new HelpStringItem(topicstring, contentstring));
}
void MarkupWindow::MessageReceived(BMessage* msg)
{
	switch(msg->what)
	{
		case LOAD_CONTENT:
			selected = topicListView->CurrentSelection();
			if(selected >= 0) // you selected something
			{
				HelpStringItem* item;
				BString contentPath = GetAppDirPath();
				BFile file;
				item = dynamic_cast<HelpStringItem*>(topicListView->ItemAt(selected));
				contentPath += "/";
				contentPath += item->ReturnContent();
				printf("contentpath: %s\n", contentPath.String());
				if(file.SetTo(contentPath, B_READ_ONLY) == B_OK)
				{
					off_t length;
					char* text;
					file.GetSize(&length);
					text = (char*) malloc(length);
					if(text && (file.Read(text, length)) >= B_OK)
					{
						contentTextView->SetText(text, length);
					}
					free(text);
				}
			}
			break;

		default:
		{
			BWindow::MessageReceived(msg);
			break;
		}
	}
}
bool MarkupWindow::QuitRequested(void)
{
	return true;
}
<commit_msg>fixed it so markup window is resizable horizontal as well as vertical<commit_after>#include "MarkupWindow.h"

MarkupWindow::MarkupWindow(BRect frame, const char* title)
	:	BWindow(frame, title, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS, B_CURRENT_WORKSPACE)
{
	// initialize controls      s
	AddShortcut('q', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
	BRect r = Bounds();
	topicListView = new BListView(BRect(10, 10, 30, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	contentTextView = new BTextView(BRect(0, 0, r.right, 100), NULL, BRect(10, 10, r.right, 100), B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	contentTextView->SetWordWrap(true);
	contentTextView->MakeEditable(false);
	backView = new BView(Bounds(), "backview", B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	backView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	backView->SetHighColor((rgb_color){0, 0, 0, 255});
	AddChild(backView);
	// gui layout builder
	backView->SetLayout(new BGroupLayout(B_HORIZONTAL, 0.0));
	backView->AddChild(BGridLayoutBuilder()
		.Add(new BScrollView("scroll_topic", topicListView, B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 0, 0, 1, 3)
		.Add(new BScrollView("scroll_content", contentTextView, B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 1, 0, 5, 10)
		.SetInsets(0, 0, 0, 0)
	);
	topicListView->SetSelectionMessage(new BMessage(LOAD_CONTENT));
}
void MarkupWindow::AddMarkupItem(BString topicstring, BString contentstring)
{
	topicListView->AddItem(new HelpStringItem(topicstring, contentstring));
}
void MarkupWindow::MessageReceived(BMessage* msg)
{
	switch(msg->what)
	{
		case LOAD_CONTENT:
			selected = topicListView->CurrentSelection();
			if(selected >= 0) // you selected something
			{
				HelpStringItem* item;
				BString contentPath = GetAppDirPath();
				BFile file;
				item = dynamic_cast<HelpStringItem*>(topicListView->ItemAt(selected));
				contentPath += "/";
				contentPath += item->ReturnContent();
				printf("contentpath: %s\n", contentPath.String());
				if(file.SetTo(contentPath, B_READ_ONLY) == B_OK)
				{
					off_t length;
					char* text;
					file.GetSize(&length);
					text = (char*) malloc(length);
					if(text && (file.Read(text, length)) >= B_OK)
					{
						contentTextView->SetText(text, length);
					}
					free(text);
				}
			}
			break;

		default:
		{
			BWindow::MessageReceived(msg);
			break;
		}
	}
}
bool MarkupWindow::QuitRequested(void)
{
	return true;
}
<|endoftext|>