<commit_before>#include "PlayerInfoPaneWidget.hpp"
#include <QDebug>
#include <QDesktopServices>
#include <QMessageBox>
#include "ui_PlayerInfoPaneWidget.h"
#include "App.hpp"
#include "Logics/Config.hpp"

PlayerInfoPaneWidget::PlayerInfoPaneWidget(QWidget *parent, OwPlayer player) :
    QWidget(parent),
    ui(new Ui::PlayerInfoPaneWidget),
    player(player)
{
    ui->setupUi(this);
    ui->plainTextEdit_playerNote->installEventFilter(this);
    this->ui->lineEdit_playerBattleTag->setText(player.getBattleTag());
    this->ui->comboBox_owRegion->setCurrentText(player.getRegion());
    this->ui->plainTextEdit_playerNote->setPlainText(player.getNote());
    this->ui->checkBox_isFavorite->setChecked(player.isFavorite());
    this->ui->radioButton_likesPlayer->setChecked(player.getRating() == OwPlayer::Rating::Like);
    this->ui->radioButto_undecidedPlayer->setChecked(player.getRating() == OwPlayer::Rating::Undecided);
    this->ui->radioButton_dislikesPlayer->setChecked(player.getRating() == OwPlayer::Rating::Dislike);
    this->isPlayerInfoDirty = false;

    this->updateStatsSiteButtons();
    this->updateToolButtons();
}

PlayerInfoPaneWidget::~PlayerInfoPaneWidget(void)
{
    delete ui;
}

bool PlayerInfoPaneWidget::eventFilter(QObject * object, QEvent * event)
{
    if (object != this->ui->plainTextEdit_playerNote)
        return QWidget::eventFilter(object, event);

    switch (event->type())
    {
        case QEvent::FocusOut:
            this->ui->plainTextEdit_playerNote->setStyleSheet(Config::getGlobalStylesheet());
        break;

        case QEvent::FocusIn:
        {
            QString stylesheet = Config::getGlobalStylesheet().section("QPlainTextEdit:focus {", 1, 1).section("}", 0, 0);
            this->ui->plainTextEdit_playerNote->setStyleSheet(stylesheet);
        }
        break;

    default: /* do nothing. */ break;
    }

    return QWidget::eventFilter(object, event);
}

void PlayerInfoPaneWidget::updateStatsSiteButtons(void)
{
    if (this->player.getBattleTag().isEmpty())
    {
        this->ui->toolButton_openUrlPlayOverwatch->hide();
        this->ui->toolButton_openUrlMasterOverwatch->hide();
        this->ui->toolButton_openUrlOverbuff->hide();
    }
    else
    {
        this->ui->toolButton_openUrlPlayOverwatch->show();
        this->ui->toolButton_openUrlMasterOverwatch->show();
        this->ui->toolButton_openUrlOverbuff->show();
    }
}

void PlayerInfoPaneWidget::updateToolButtons(void)
{
    auto dataSource = App::getInstance()->getDataSource();
    if (this->player.isNew())
    {
        if (this->isPlayerInfoDirty && dataSource->validatePlayer(this->player))
            this->ui->toolButton_savePlayerInfo->show();
        else
            this->ui->toolButton_savePlayerInfo->hide();
        this->ui->toolButton_updatePlayerInfo->hide();
        this->ui->toolButton_deletePlayerInfo->hide();
    }
    else
    {
        this->ui->toolButton_savePlayerInfo->hide();
        if (this->isPlayerInfoDirty && dataSource->validatePlayer(this->player))
            this->ui->toolButton_updatePlayerInfo->show();
        else
            this->ui->toolButton_updatePlayerInfo->hide();
        this->ui->toolButton_deletePlayerInfo->show();
    }
}

void PlayerInfoPaneWidget::saveCurrentPlayerInfo(void)
{
    if (!this->player.validate())
    {
        QMessageBox::critical(this, "Validation Error", "Validation failed. Save cancelled");
        return;
    }

    this->player.setBattleTag(this->player.getBattleTag().trimmed());
    this->ui->lineEdit_playerBattleTag->setText(this->player.getBattleTag());

    if (!this->player.save())
    {
        QMessageBox::critical(this, "Save Error", "Player info failed to save.");
        return;
    }

    this->isPlayerInfoDirty = false;
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_toolButton_savePlayerInfo_clicked(void)
{
    this->saveCurrentPlayerInfo();
    emit playerInfoChanged(this->player);
}

void PlayerInfoPaneWidget::on_toolButton_updatePlayerInfo_clicked(void)
{
    this->saveCurrentPlayerInfo();
    emit playerInfoChanged(this->player);
}

void PlayerInfoPaneWidget::on_toolButton_deletePlayerInfo_clicked(void)
{
    auto buttonPressed = QMessageBox::question(this, "Confirmation", "Are you sure you would like to delete this player record?",
                                          QMessageBox::Yes, QMessageBox::Cancel, QMessageBox::NoButton);
    if (buttonPressed != QMessageBox::Yes)
        return;

    if (!this->player.remove())
    {
        QMessageBox::critical(this, "Save Error", "Failed to remove player info.");
        return;
    }

    emit playerInfoChanged(this->player);
    this->updateToolButtons();
    this->deleteLater();
}

void PlayerInfoPaneWidget::on_lineEdit_playerBattleTag_textEdited(const QString & newBattleTag)
{
    player.setBattleTag(newBattleTag);
    this->isPlayerInfoDirty = true;
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_comboBox_owRegion_currentIndexChanged(const QString & region)
{
    player.setRegion(region);
    this->isPlayerInfoDirty = true;
    this->updateStatsSiteButtons();
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_plainTextEdit_playerNote_textChanged(void)
{
    player.setNote(this->ui->plainTextEdit_playerNote->toPlainText());
    this->isPlayerInfoDirty = true;
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_checkBox_isFavorite_toggled(bool checked)
{
    player.setFavorite(checked);
    this->isPlayerInfoDirty = true;
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_radioButton_likesPlayer_toggled(bool checked)
{
    if (checked)
    {
        player.setRating(OwPlayer::Rating::Like);
        this->isPlayerInfoDirty = true;
        this->updateToolButtons();
    }
}

void PlayerInfoPaneWidget::on_radioButto_undecidedPlayer_toggled(bool checked)
{
    if (checked)
    {
        player.setRating(OwPlayer::Rating::Undecided);
        this->isPlayerInfoDirty = true;
        this->updateToolButtons();
    }
}

void PlayerInfoPaneWidget::on_toolButton_openUrlPlayOverwatch_clicked(void)
{
    QDesktopServices::openUrl(QUrl("https://playoverwatch.com/en-us/career/" + this->player.getPlatform() + "/" + this->player.getRegion() + "/" + QString(this->player.getBattleTag()).replace("#", "-")));
}

void PlayerInfoPaneWidget::on_toolButton_openUrlMasterOverwatch_clicked(void)
{
    QDesktopServices::openUrl(QUrl("http://masteroverwatch.com/profile/" + this->player.getPlatform() + "/" + this->player.getRegion() + "/" + QString(this->player.getBattleTag()).replace("#", "-")));
}

void PlayerInfoPaneWidget::on_toolButton_openUrlOverbuff_clicked(void)
{
    QDesktopServices::openUrl(QUrl("https://www.overbuff.com/players/" + this->player.getPlatform() + "/" + QString(this->player.getBattleTag()).replace("#", "-")));
}

void PlayerInfoPaneWidget::on_radioButton_dislikesPlayer_toggled(bool checked)
{
    if (checked)
    {
        player.setRating(OwPlayer::Rating::Dislike);
        this->isPlayerInfoDirty = true;
        this->updateToolButtons();
    }
}
<commit_msg>refactor<commit_after>#include "PlayerInfoPaneWidget.hpp"
#include <QDebug>
#include <QDesktopServices>
#include <QMessageBox>
#include "ui_PlayerInfoPaneWidget.h"
#include "App.hpp"
#include "Logics/Config.hpp"

PlayerInfoPaneWidget::PlayerInfoPaneWidget(QWidget *parent, OwPlayer player) :
    QWidget(parent),
    ui(new Ui::PlayerInfoPaneWidget),
    player(player)
{
    ui->setupUi(this);
    ui->plainTextEdit_playerNote->installEventFilter(this);
    this->ui->lineEdit_playerBattleTag->setText(player.getBattleTag());
    this->ui->comboBox_owRegion->setCurrentText(player.getRegion());
    this->ui->plainTextEdit_playerNote->setPlainText(player.getNote());
    this->ui->checkBox_isFavorite->setChecked(player.isFavorite());
    this->ui->radioButton_likesPlayer->setChecked(player.getRating() == OwPlayer::Rating::Like);
    this->ui->radioButto_undecidedPlayer->setChecked(player.getRating() == OwPlayer::Rating::Undecided);
    this->ui->radioButton_dislikesPlayer->setChecked(player.getRating() == OwPlayer::Rating::Dislike);
    this->isPlayerInfoDirty = false;

    this->updateStatsSiteButtons();
    this->updateToolButtons();
}

PlayerInfoPaneWidget::~PlayerInfoPaneWidget(void)
{
    delete ui;
}

bool PlayerInfoPaneWidget::eventFilter(QObject * object, QEvent * event)
{
    if (object != this->ui->plainTextEdit_playerNote)
        return QWidget::eventFilter(object, event);

    switch (event->type())
    {
        case QEvent::FocusOut:
            this->ui->plainTextEdit_playerNote->setStyleSheet(Config::getGlobalStylesheet());
        break;

        case QEvent::FocusIn:
        {
            QString stylesheet = Config::getGlobalStylesheet().section("QPlainTextEdit:focus {", 1, 1).section("}", 0, 0);
            this->ui->plainTextEdit_playerNote->setStyleSheet(stylesheet);
        }
        break;

    default: /* do nothing. */ break;
    }

    return QWidget::eventFilter(object, event);
}

void PlayerInfoPaneWidget::updateStatsSiteButtons(void)
{
    if (this->player.getBattleTag().isEmpty())
    {
        this->ui->toolButton_openUrlPlayOverwatch->hide();
        this->ui->toolButton_openUrlMasterOverwatch->hide();
        this->ui->toolButton_openUrlOverbuff->hide();
    }
    else
    {
        this->ui->toolButton_openUrlPlayOverwatch->show();
        this->ui->toolButton_openUrlMasterOverwatch->show();
        this->ui->toolButton_openUrlOverbuff->show();
    }
}

void PlayerInfoPaneWidget::updateToolButtons(void)
{
    auto dataSource = App::getInstance()->getDataSource();
    if (this->player.isNew())
    {
        if (this->isPlayerInfoDirty && dataSource->validatePlayer(this->player))
            this->ui->toolButton_savePlayerInfo->show();
        else
            this->ui->toolButton_savePlayerInfo->hide();
        this->ui->toolButton_updatePlayerInfo->hide();
        this->ui->toolButton_deletePlayerInfo->hide();
    }
    else
    {
        this->ui->toolButton_savePlayerInfo->hide();
        if (this->isPlayerInfoDirty && dataSource->validatePlayer(this->player))
            this->ui->toolButton_updatePlayerInfo->show();
        else
            this->ui->toolButton_updatePlayerInfo->hide();
        this->ui->toolButton_deletePlayerInfo->show();
    }
}

void PlayerInfoPaneWidget::saveCurrentPlayerInfo(void)
{
    if (!this->player.validate())
    {
        QMessageBox::critical(this, "Validation Error", "Validation failed. Save cancelled");
        return;
    }

    this->player.setBattleTag(this->player.getBattleTag().trimmed());
    this->ui->lineEdit_playerBattleTag->setText(this->player.getBattleTag());

    if (!this->player.save())
    {
        QMessageBox::critical(this, "Save Error", "Player info failed to save.");
        return;
    }

    this->isPlayerInfoDirty = false;
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_toolButton_savePlayerInfo_clicked(void)
{
    this->saveCurrentPlayerInfo();
    emit playerInfoChanged(this->player);
}

void PlayerInfoPaneWidget::on_toolButton_updatePlayerInfo_clicked(void)
{
    this->saveCurrentPlayerInfo();
    emit playerInfoChanged(this->player);
}

void PlayerInfoPaneWidget::on_toolButton_deletePlayerInfo_clicked(void)
{
    auto buttonPressed = QMessageBox::question(this, "Confirmation", "Are you sure you would like to delete this player record?",
                                          QMessageBox::Yes, QMessageBox::Cancel, QMessageBox::NoButton);
    if (buttonPressed != QMessageBox::Yes)
        return;

    if (!this->player.remove())
    {
        QMessageBox::critical(this, "Save Error", "Failed to remove player info.");
        return;
    }

    emit playerInfoChanged(this->player);
    this->updateToolButtons();
    this->deleteLater();
}

void PlayerInfoPaneWidget::on_lineEdit_playerBattleTag_textEdited(const QString & newBattleTag)
{
    player.setBattleTag(newBattleTag);
    this->isPlayerInfoDirty = true;
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_comboBox_owRegion_currentIndexChanged(const QString & region)
{
    player.setRegion(region);
    this->isPlayerInfoDirty = true;
    this->updateStatsSiteButtons();
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_plainTextEdit_playerNote_textChanged(void)
{
    player.setNote(this->ui->plainTextEdit_playerNote->toPlainText());
    this->isPlayerInfoDirty = true;
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_checkBox_isFavorite_toggled(bool checked)
{
    player.setFavorite(checked);
    this->isPlayerInfoDirty = true;
    this->updateToolButtons();
}

void PlayerInfoPaneWidget::on_radioButton_likesPlayer_toggled(bool checked)
{
    if (checked)
    {
        player.setRating(OwPlayer::Rating::Like);
        this->isPlayerInfoDirty = true;
        this->updateToolButtons();
    }
}

void PlayerInfoPaneWidget::on_radioButto_undecidedPlayer_toggled(bool checked)
{
    if (checked)
    {
        player.setRating(OwPlayer::Rating::Undecided);
        this->isPlayerInfoDirty = true;
        this->updateToolButtons();
    }
}

void PlayerInfoPaneWidget::on_radioButton_dislikesPlayer_toggled(bool checked)
{
    if (checked)
    {
        player.setRating(OwPlayer::Rating::Dislike);
        this->isPlayerInfoDirty = true;
        this->updateToolButtons();
    }
}

void PlayerInfoPaneWidget::on_toolButton_openUrlPlayOverwatch_clicked(void)
{
    QDesktopServices::openUrl(QUrl("https://playoverwatch.com/en-us/career/" + this->player.getPlatform() + "/" + this->player.getRegion() + "/" + QString(this->player.getBattleTag()).replace("#", "-")));
}

void PlayerInfoPaneWidget::on_toolButton_openUrlMasterOverwatch_clicked(void)
{
    QDesktopServices::openUrl(QUrl("http://masteroverwatch.com/profile/" + this->player.getPlatform() + "/" + this->player.getRegion() + "/" + QString(this->player.getBattleTag()).replace("#", "-")));
}

void PlayerInfoPaneWidget::on_toolButton_openUrlOverbuff_clicked(void)
{
    QDesktopServices::openUrl(QUrl("https://www.overbuff.com/players/" + this->player.getPlatform() + "/" + QString(this->player.getBattleTag()).replace("#", "-")));
}
<|endoftext|>


<commit_before>// Standard library includes
#include <thread>
// External library includes
#include <GLFW/glfw3.h>
#include <AntTweakBar.h>
// Custom header includes
#include "shared.hpp"
#include "simulation.hpp"
#include "render.hpp"
#include "body.hpp"
#include "ui.hpp"

// Sim thread startup function
void startup(shared* sharedAP);
// GLFW and OpenGL startup Functions
void initDisplay(int lXRes, int lYRes);
GLFWwindow* windowSetup(void);
// Default Scenario startup
void setupDefaultScenario(render* renderAP, shared* sharedAP);

int main(void) {
  // Setup window and give pointer
  GLFWwindow* window = windowSetup();

  // Create objects
  render renderMain;
  shared sharedMain;

  // Create access pointers
  render* renderAP = &renderMain;
  shared* sharedAP = &sharedMain;

  setupDefaultScenario(renderAP, sharedAP);

  setupGUI(window, renderAP);

  // Create simulation thread
  std::thread simThread(startup, sharedAP);

  // Main Runtime Loop
  while(!glfwWindowShouldClose(window)) {
    // Clear screen before drawing
    glClear(GL_COLOR_BUFFER_BIT);

    sharedAP->updateControl(renderAP->getControl());

    if(renderAP->getPaused()) {
      updateBody(renderAP); // Update body storage from interface
      // Send update to shared
      sharedAP->updateBodies(renderAP->getBodies());
    } else {
      updateUI(renderAP); // Update interface from body store
      // Get update from shared
      renderAP->updateBodies(sharedAP->getBodies());
    }

    // Wake sim thread
    sharedAP->simWait.notify_all();

    // Render scene
    renderAP->drawScene();

    // Apply camera transform and scale
    applyCamera(window);

    // Draw GUI
    TwDraw();

    // Display is double buffered to prevent screen tearing
    // Swap display buffers
    glfwSwapBuffers(window);
    // Poll and process events
    glfwPollEvents();
  }

  // Unpause and Exit, direct to shared
  sharedAP->setPaused(0);
  sharedAP->setExit(1);

  // Repeat sim wait notify until exit is acknowleged, directly check shared
  while(sharedAP->getExit()) {
    sharedAP->simWait.notify_all();
  }

  // Program exit
  simThread.join();

  // Terminate Libraries
  glfwDestroyWindow(window);
  glfwTerminate();

  return 0;
}

void initDisplay(int lXRes, int lYRes) {
  // Init Projection
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-lXRes, lXRes, -lYRes, lYRes, 1.0f, -1.0f);

  // Init Modelview
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  // Set Viewport Extents
  glViewport(0, 0, lXRes, lYRes);
  glClearColor(0.0f, 0.0f, 0.0f, 1);
}

GLFWwindow* windowSetup() {
    /*                       */
   // GLFW Init Boilerplate //
  /*                       */
  if(!glfwInit()) {
    // Exit if GLFW does not init
    std::cerr << "GLFW could not init" << std::endl;
    exit(1);
  }

  GLFWwindow* window; // Create window
  glfwWindowHint(GLFW_SAMPLES,8); // MSAA 8x
  // Get user screen resolution
  const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
  // Make window smaller than screen
  int wXRes = mode->width * 0.8;
  int wYRes = mode->height * 0.8;

  window = glfwCreateWindow(wXRes, wYRes, "Exo N-Body", NULL, NULL);
  if (!window) {
    // Terminate and exit if window cannot open
    std::cerr << "GLFW could not create window" << std::endl;
    glfwTerminate();
    exit(1);
  }

  glfwMakeContextCurrent(window);
  initDisplay(wXRes, wYRes);
  setCallbacks(window);

  return window;
    /*                       */
   // GLFW Boilerplate End  //
  /*                       */
}

void setupDefaultScenario(render* renderAP, shared* sharedAP) {
  // Tempoary control structure for setup
  control temp;
  temp.UGC = 0.1;
  temp.IDT = 0.1;
  temp.IPF = 1;
  temp.paused = false;
  temp.exit = false;
  temp.collide = true;

  // Update local
  renderAP->updateControl(temp);
  renderAP->createSuperstructure(1000, 10000, 0.1, 10, 1, 0, 0, 0, 0, 50.0, 500.0);

  // Update shared area
  sharedAP->updateControl(renderAP->getControl());
  sharedAP->updateBodies(renderAP->getBodies());
}

// SIM THREAD CALL
// Second thread, concurrent execution of simulation
void startup(shared* sharedAP) {
  // Sim wait control mutex
  std::mutex simWaitMTX;

  // Create sim object
  simulation simMain;

  // Create access pointer
  simulation* simAP = &simMain;

  // Get new data from shared
  simAP->updateBodies(sharedAP->getBodies());
  simAP->updateControl(sharedAP->getControl());

  while(!simAP->getExit()) {
    // Wait for data change - Thread Sync
    std::unique_lock<std::mutex> uniqueSimWaitMTX(simWaitMTX);
    sharedAP->simWait.wait(uniqueSimWaitMTX);

    // Update local control structure
    simAP->updateControl(sharedAP->getControl());

    if(!simAP->getPaused()) {
      for(int iter = 0; iter < simAP->getIPF(); iter++) {
        // Do itteration
        simAP->itteration();
        // Break out of ipf loop if paused or exit.
        if(sharedAP->getPaused() | sharedAP->getExit()) break;
      }

      // Update shared bodies
      sharedAP->updateBodies(simAP->getBodies());
    } else {
      // Get from shared if paused
      simAP->updateBodies(sharedAP->getBodies());
    }
  }
  // Directly unset shared exit variable to confirm sim exit.
  sharedAP->setExit(0);
}
<commit_msg>readded iostream include to main.<commit_after>// Standard library includes
#include <iostream>
#include <thread>
// External library includes
#include <GLFW/glfw3.h>
#include <AntTweakBar.h>
// Custom header includes
#include "shared.hpp"
#include "simulation.hpp"
#include "render.hpp"
#include "body.hpp"
#include "ui.hpp"

// Sim thread startup function
void startup(shared* sharedAP);
// GLFW and OpenGL startup Functions
void initDisplay(int lXRes, int lYRes);
GLFWwindow* windowSetup(void);
// Default Scenario startup
void setupDefaultScenario(render* renderAP, shared* sharedAP);

int main(void) {
  // Setup window and give pointer
  GLFWwindow* window = windowSetup();

  // Create objects
  render renderMain;
  shared sharedMain;

  // Create access pointers
  render* renderAP = &renderMain;
  shared* sharedAP = &sharedMain;

  setupDefaultScenario(renderAP, sharedAP);

  setupGUI(window, renderAP);

  // Create simulation thread
  std::thread simThread(startup, sharedAP);

  // Main Runtime Loop
  while(!glfwWindowShouldClose(window)) {
    // Clear screen before drawing
    glClear(GL_COLOR_BUFFER_BIT);

    sharedAP->updateControl(renderAP->getControl());

    if(renderAP->getPaused()) {
      updateBody(renderAP); // Update body storage from interface
      // Send update to shared
      sharedAP->updateBodies(renderAP->getBodies());
    } else {
      updateUI(renderAP); // Update interface from body store
      // Get update from shared
      renderAP->updateBodies(sharedAP->getBodies());
    }

    // Wake sim thread
    sharedAP->simWait.notify_all();

    // Render scene
    renderAP->drawScene();

    // Apply camera transform and scale
    applyCamera(window);

    // Draw GUI
    TwDraw();

    // Display is double buffered to prevent screen tearing
    // Swap display buffers
    glfwSwapBuffers(window);
    // Poll and process events
    glfwPollEvents();
  }

  // Unpause and Exit, direct to shared
  sharedAP->setPaused(0);
  sharedAP->setExit(1);

  // Repeat sim wait notify until exit is acknowleged, directly check shared
  while(sharedAP->getExit()) {
    sharedAP->simWait.notify_all();
  }

  // Program exit
  simThread.join();

  // Terminate Libraries
  glfwDestroyWindow(window);
  glfwTerminate();

  return 0;
}

void initDisplay(int lXRes, int lYRes) {
  // Init Projection
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-lXRes, lXRes, -lYRes, lYRes, 1.0f, -1.0f);

  // Init Modelview
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  // Set Viewport Extents
  glViewport(0, 0, lXRes, lYRes);
  glClearColor(0.0f, 0.0f, 0.0f, 1);
}

GLFWwindow* windowSetup() {
    /*                       */
   // GLFW Init Boilerplate //
  /*                       */
  if(!glfwInit()) {
    // Exit if GLFW does not init
    std::cerr << "GLFW could not init" << std::endl;
    exit(1);
  }

  GLFWwindow* window; // Create window
  glfwWindowHint(GLFW_SAMPLES,8); // MSAA 8x
  // Get user screen resolution
  const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
  // Make window smaller than screen
  int wXRes = mode->width * 0.8;
  int wYRes = mode->height * 0.8;

  window = glfwCreateWindow(wXRes, wYRes, "Exo N-Body", NULL, NULL);
  if (!window) {
    // Terminate and exit if window cannot open
    std::cerr << "GLFW could not create window" << std::endl;
    glfwTerminate();
    exit(1);
  }

  glfwMakeContextCurrent(window);
  initDisplay(wXRes, wYRes);
  setCallbacks(window);

  return window;
    /*                       */
   // GLFW Boilerplate End  //
  /*                       */
}

void setupDefaultScenario(render* renderAP, shared* sharedAP) {
  // Tempoary control structure for setup
  control temp;
  temp.UGC = 0.1;
  temp.IDT = 0.1;
  temp.IPF = 1;
  temp.paused = false;
  temp.exit = false;
  temp.collide = true;

  // Update local
  renderAP->updateControl(temp);
  renderAP->createSuperstructure(1000, 10000, 0.1, 10, 1, 0, 0, 0, 0, 50.0, 500.0);

  // Update shared area
  sharedAP->updateControl(renderAP->getControl());
  sharedAP->updateBodies(renderAP->getBodies());
}

// SIM THREAD CALL
// Second thread, concurrent execution of simulation
void startup(shared* sharedAP) {
  // Sim wait control mutex
  std::mutex simWaitMTX;

  // Create sim object
  simulation simMain;

  // Create access pointer
  simulation* simAP = &simMain;

  // Get new data from shared
  simAP->updateBodies(sharedAP->getBodies());
  simAP->updateControl(sharedAP->getControl());

  while(!simAP->getExit()) {
    // Wait for data change - Thread Sync
    std::unique_lock<std::mutex> uniqueSimWaitMTX(simWaitMTX);
    sharedAP->simWait.wait(uniqueSimWaitMTX);

    // Update local control structure
    simAP->updateControl(sharedAP->getControl());

    if(!simAP->getPaused()) {
      for(int iter = 0; iter < simAP->getIPF(); iter++) {
        // Do itteration
        simAP->itteration();
        // Break out of ipf loop if paused or exit.
        if(sharedAP->getPaused() | sharedAP->getExit()) break;
      }

      // Update shared bodies
      sharedAP->updateBodies(simAP->getBodies());
    } else {
      // Get from shared if paused
      simAP->updateBodies(sharedAP->getBodies());
    }
  }
  // Directly unset shared exit variable to confirm sim exit.
  sharedAP->setExit(0);
}
<|endoftext|>


<commit_before>/*******************************************************************************
  Copyright (c) 2011 Dmitry Matveev <me@dmitrymatveev.co.uk>

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*******************************************************************************/

#include "fail_test.hh"

fail_test::fail_test (journal &j)
: test ("Failures", j)
{
}

void fail_test::setup ()
{
    cleanup ();
    system ("touch fail-working");
}

void fail_test::run ()
{
    consumer cons;
    int wid = 0;

    /* Add a watch, should fail */
    cons.input.setup ("non-existent", IN_ALL_EVENTS);
    cons.output.wait ();

    wid = cons.output.added_watch_id ();
    should ("watch id is -1 when starting watching a non-existent file", wid == -1);

    cons.output.reset ();
    cons.input.setup ("fail-working", IN_ATTRIB | IN_ONLYDIR);
    cons.output.wait ();

    wid = cons.output.added_watch_id ();
    should ("do not start watching a file if IN_ONLYDIR flag is set", wid == -1);

    cons.output.reset ();
    cons.input.setup ("fail-working", 0);
    cons.output.wait ();

    wid = cons.output.added_watch_id ();
    should ("do not start watching a file if no event flags are set", wid == -1);

    cons.input.interrupt ();
}

void fail_test::cleanup ()
{
    system ("rm -rf fail-working");
}
<commit_msg>Fixed tests compilation error on NetBSD<commit_after>/*******************************************************************************
  Copyright (c) 2011 Dmitry Matveev <me@dmitrymatveev.co.uk>

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*******************************************************************************/

#include <cstdlib>
#include "fail_test.hh"

fail_test::fail_test (journal &j)
: test ("Failures", j)
{
}

void fail_test::setup ()
{
    cleanup ();
    system ("touch fail-working");
}

void fail_test::run ()
{
    consumer cons;
    int wid = 0;

    /* Add a watch, should fail */
    cons.input.setup ("non-existent", IN_ALL_EVENTS);
    cons.output.wait ();

    wid = cons.output.added_watch_id ();
    should ("watch id is -1 when starting watching a non-existent file", wid == -1);

    cons.output.reset ();
    cons.input.setup ("fail-working", IN_ATTRIB | IN_ONLYDIR);
    cons.output.wait ();

    wid = cons.output.added_watch_id ();
    should ("do not start watching a file if IN_ONLYDIR flag is set", wid == -1);

    cons.output.reset ();
    cons.input.setup ("fail-working", 0);
    cons.output.wait ();

    wid = cons.output.added_watch_id ();
    should ("do not start watching a file if no event flags are set", wid == -1);

    cons.input.interrupt ();
}

void fail_test::cleanup ()
{
    system ("rm -rf fail-working");
}
<|endoftext|>


<commit_before>#ifndef PIPELINEPATTERN_HPP
#define PIPELINEPATTERN_HPP

#if __cplusplus >= 201103L
#define USE_CPP11
#endif

#ifdef USE_CPP11

// Defines for C++98 compatibility -> we might want to automate this somehow
#define Action2 Action
#define Action3 Action

template<typename T, typename... T2>
class Action : public Action<T2...> {
    public:
		// Explicitly deny access to default constructor
		Action() = delete;

        Action(T& t1, T2&... t2...) : _t1(t1), Action<T2...>(t2...) {
			;
        }

        void operator() (void) {
            _t1();
            Action<T2...>::operator()();
        }

		void operator() (uint32_t x) {
			_t1(x);
			Action<T2...>::operator()(x);
		}
    private:
	    T& _t1;
};

template<typename T>
class Action<T> {
    public:
		// Explicitly deny access to default constructor
		Action() = delete;

		// TODO declare move constructor
		Action(T& t1) : _t1(t1) {
			;
		}

        void operator() (void) {
            _t1();
        }

		void operator() (uint32_t x) {
			_t1(x);
		}

    private:
        T& _t1;
};

#else

template<typename T>
class Action {
    public:
		// TODO declare move constructor
		Action(T& t1) : _t1(t1) {
			;
		}

        void operator() (void) {
            _t1();
        }

		void operator() (uint32_t x) {
			_t1(x);
		}

    private:
		Action();
        T& _t1;
};

template<typename T, typename T2>
class Action2 : public Action<T2> {
	public:
		Action2(T& t1, T2& t2) : Action<T2>(t2), _t1(t1) {
			;
		}

		void operator() (void) {
            _t1();
            Action<T2>::operator()();
        }

		void operator() (uint32_t x) {
			_t1(x);
			Action<T2>::operator()(x);
		}
	private:
		Action2();
		T& _t1;
};

template<typename T, typename T2, typename T3>
class Action3 : public Action2<T2, T3> {
	public:
		Action3(T& t1, T2& t2, T3& t3) : Action2<T2, T3>(t2, t3), _t1(t1) {
			;
		}

		void operator() (void) {
			_t1();
			Action2<T2, T3>::operator()();
		}

		void operator() (uint32_t x) {
			_t1(x);
			Action2<T2, T3>::operator()(x);
		}
	private:
		Action3();
		T& _t1;
};
#endif

template<typename Func>
void pipeline (Func t) {
    t();
}

template<typename Func>
void elementPipeline(Func t, uint32_t x) {
	t(x);
}

#endif
<commit_msg>Removed erroneous TODO<commit_after>#ifndef PIPELINEPATTERN_HPP
#define PIPELINEPATTERN_HPP

#if __cplusplus >= 201103L
#define USE_CPP11
#endif

#ifdef USE_CPP11

// Defines for C++98 compatibility -> we might want to automate this somehow
#define Action2 Action
#define Action3 Action

template<typename T, typename... T2>
class Action : public Action<T2...> {
    public:
		// Explicitly deny access to default constructor
		Action() = delete;

        Action(T& t1, T2&... t2...) : _t1(t1), Action<T2...>(t2...) {
			;
        }

        void operator() (void) {
            _t1();
            Action<T2...>::operator()();
        }

		void operator() (uint32_t x) {
			_t1(x);
			Action<T2...>::operator()(x);
		}
    private:
	    T& _t1;
};

template<typename T>
class Action<T> {
    public:
		// Explicitly deny access to default constructor
		Action() = delete;

		// TODO declare move constructor
		Action(T& t1) : _t1(t1) {
			;
		}

        void operator() (void) {
            _t1();
        }

		void operator() (uint32_t x) {
			_t1(x);
		}

    private:
        T& _t1;
};

#else

template<typename T>
class Action {
    public:
		Action(T& t1) : _t1(t1) {
			;
		}

        void operator() (void) {
            _t1();
        }

		void operator() (uint32_t x) {
			_t1(x);
		}

    private:
		Action();
        T& _t1;
};

template<typename T, typename T2>
class Action2 : public Action<T2> {
	public:
		Action2(T& t1, T2& t2) : Action<T2>(t2), _t1(t1) {
			;
		}

		void operator() (void) {
            _t1();
            Action<T2>::operator()();
        }

		void operator() (uint32_t x) {
			_t1(x);
			Action<T2>::operator()(x);
		}
	private:
		Action2();
		T& _t1;
};

template<typename T, typename T2, typename T3>
class Action3 : public Action2<T2, T3> {
	public:
		Action3(T& t1, T2& t2, T3& t3) : Action2<T2, T3>(t2, t3), _t1(t1) {
			;
		}

		void operator() (void) {
			_t1();
			Action2<T2, T3>::operator()();
		}

		void operator() (uint32_t x) {
			_t1(x);
			Action2<T2, T3>::operator()(x);
		}
	private:
		Action3();
		T& _t1;
};
#endif

template<typename Func>
void pipeline (Func t) {
    t();
}

template<typename Func>
void elementPipeline(Func t, uint32_t x) {
	t(x);
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/network_change_notifier_linux.h"

#include <errno.h>
#include <sys/socket.h>

#include "base/compiler_specific.h"
#include "base/eintr_wrapper.h"
#include "base/task.h"
#include "base/threading/thread.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier_netlink_linux.h"

namespace net {

namespace {

const int kInvalidSocket = -1;

}  // namespace

class NetworkChangeNotifierLinux::Thread
    : public base::Thread, public MessageLoopForIO::Watcher {
 public:
  Thread();
  virtual ~Thread();

  // MessageLoopForIO::Watcher:
  virtual void OnFileCanReadWithoutBlocking(int fd);
  virtual void OnFileCanWriteWithoutBlocking(int /* fd */);

 protected:
  // base::Thread
  virtual void Init();
  virtual void CleanUp();

 private:
  void NotifyObserversOfIPAddressChange() {
    NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
  }

  // Starts listening for netlink messages.  Also handles the messages if there
  // are any available on the netlink socket.
  void ListenForNotifications();

  // Attempts to read from the netlink socket into |buf| of length |len|.
  // Returns the bytes read on synchronous success and ERR_IO_PENDING if the
  // recv() would block.  Otherwise, it returns a net error code.
  int ReadNotificationMessage(char* buf, size_t len);

  // The netlink socket descriptor.
  int netlink_fd_;
  MessageLoopForIO::FileDescriptorWatcher netlink_watcher_;

  // Technically only needed for ChromeOS, but it's ugly to #ifdef out.
  ScopedRunnableMethodFactory<Thread> method_factory_;

  DISALLOW_COPY_AND_ASSIGN(Thread);
};

NetworkChangeNotifierLinux::Thread::Thread()
    : base::Thread("NetworkChangeNotifier"),
      netlink_fd_(kInvalidSocket),
      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}

NetworkChangeNotifierLinux::Thread::~Thread() {}

void NetworkChangeNotifierLinux::Thread::Init() {
  netlink_fd_ = InitializeNetlinkSocket();
  if (netlink_fd_ < 0) {
    netlink_fd_ = kInvalidSocket;
    return;
  }
  ListenForNotifications();
}

void NetworkChangeNotifierLinux::Thread::CleanUp() {
  if (netlink_fd_ != kInvalidSocket) {
    if (HANDLE_EINTR(close(netlink_fd_)) != 0)
      PLOG(ERROR) << "Failed to close socket";
    netlink_fd_ = kInvalidSocket;
    netlink_watcher_.StopWatchingFileDescriptor();
  }
}

void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) {
  DCHECK_EQ(fd, netlink_fd_);
  ListenForNotifications();
}

void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking(
    int /* fd */) {
  NOTREACHED();
}

void NetworkChangeNotifierLinux::Thread::ListenForNotifications() {
  char buf[4096];
  int rv = ReadNotificationMessage(buf, arraysize(buf));
  while (rv > 0) {
    if (HandleNetlinkMessage(buf, rv)) {
      VLOG(1) << "Detected IP address changes.";
#if defined(OS_CHROMEOS)
      // TODO(oshima): chromium-os:8285 - introduced artificial delay to
      // work around the issue of network load issue after connection
      // restored. See the bug for more details.
      //  This should be removed once this bug is properly fixed.
      const int kObserverNotificationDelayMS = 200;
      message_loop()->PostDelayedTask(
          FROM_HERE,
          method_factory_.NewRunnableMethod(
              &Thread::NotifyObserversOfIPAddressChange),
          kObserverNotificationDelayMS);
#else
      NotifyObserversOfIPAddressChange();
#endif
    }
    rv = ReadNotificationMessage(buf, arraysize(buf));
  }

  if (rv == ERR_IO_PENDING) {
    rv = MessageLoopForIO::current()->WatchFileDescriptor(netlink_fd_, false,
        MessageLoopForIO::WATCH_READ, &netlink_watcher_, this);
    LOG_IF(ERROR, !rv) << "Failed to watch netlink socket: " << netlink_fd_;
  }
}

int NetworkChangeNotifierLinux::Thread::ReadNotificationMessage(
    char* buf,
    size_t len) {
  DCHECK_NE(len, 0u);
  DCHECK(buf);
  memset(buf, 0, sizeof(buf));
  int rv = recv(netlink_fd_, buf, len, 0);
  if (rv > 0)
    return rv;

  DCHECK_NE(rv, 0);
  if (errno != EAGAIN && errno != EWOULDBLOCK) {
    PLOG(DFATAL) << "recv";
    return ERR_FAILED;
  }

  return ERR_IO_PENDING;
}

NetworkChangeNotifierLinux::NetworkChangeNotifierLinux()
    : notifier_thread_(new Thread) {
  // We create this notifier thread because the notification implementation
  // needs a MessageLoopForIO, and there's no guarantee that
  // MessageLoop::current() meets that criterion.
  base::Thread::Options thread_options(MessageLoop::TYPE_IO, 0);
  notifier_thread_->StartWithOptions(thread_options);
}

NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() {
  // We don't need to explicitly Stop(), but doing so allows us to sanity-
  // check that the notifier thread shut down properly.
  notifier_thread_->Stop();
}

bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const {
  // TODO(eroman): http://crbug.com/53473
  return false;
}

}  // namespace net
<commit_msg>Fix memset bug in NetworkChangeNotifierLinux.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/network_change_notifier_linux.h"

#include <errno.h>
#include <sys/socket.h>

#include "base/compiler_specific.h"
#include "base/eintr_wrapper.h"
#include "base/task.h"
#include "base/threading/thread.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier_netlink_linux.h"

namespace net {

namespace {

const int kInvalidSocket = -1;

}  // namespace

class NetworkChangeNotifierLinux::Thread
    : public base::Thread, public MessageLoopForIO::Watcher {
 public:
  Thread();
  virtual ~Thread();

  // MessageLoopForIO::Watcher:
  virtual void OnFileCanReadWithoutBlocking(int fd);
  virtual void OnFileCanWriteWithoutBlocking(int /* fd */);

 protected:
  // base::Thread
  virtual void Init();
  virtual void CleanUp();

 private:
  void NotifyObserversOfIPAddressChange() {
    NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
  }

  // Starts listening for netlink messages.  Also handles the messages if there
  // are any available on the netlink socket.
  void ListenForNotifications();

  // Attempts to read from the netlink socket into |buf| of length |len|.
  // Returns the bytes read on synchronous success and ERR_IO_PENDING if the
  // recv() would block.  Otherwise, it returns a net error code.
  int ReadNotificationMessage(char* buf, size_t len);

  // The netlink socket descriptor.
  int netlink_fd_;
  MessageLoopForIO::FileDescriptorWatcher netlink_watcher_;

  // Technically only needed for ChromeOS, but it's ugly to #ifdef out.
  ScopedRunnableMethodFactory<Thread> method_factory_;

  DISALLOW_COPY_AND_ASSIGN(Thread);
};

NetworkChangeNotifierLinux::Thread::Thread()
    : base::Thread("NetworkChangeNotifier"),
      netlink_fd_(kInvalidSocket),
      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}

NetworkChangeNotifierLinux::Thread::~Thread() {}

void NetworkChangeNotifierLinux::Thread::Init() {
  netlink_fd_ = InitializeNetlinkSocket();
  if (netlink_fd_ < 0) {
    netlink_fd_ = kInvalidSocket;
    return;
  }
  ListenForNotifications();
}

void NetworkChangeNotifierLinux::Thread::CleanUp() {
  if (netlink_fd_ != kInvalidSocket) {
    if (HANDLE_EINTR(close(netlink_fd_)) != 0)
      PLOG(ERROR) << "Failed to close socket";
    netlink_fd_ = kInvalidSocket;
    netlink_watcher_.StopWatchingFileDescriptor();
  }
}

void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) {
  DCHECK_EQ(fd, netlink_fd_);
  ListenForNotifications();
}

void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking(
    int /* fd */) {
  NOTREACHED();
}

void NetworkChangeNotifierLinux::Thread::ListenForNotifications() {
  char buf[4096];
  int rv = ReadNotificationMessage(buf, arraysize(buf));
  while (rv > 0) {
    if (HandleNetlinkMessage(buf, rv)) {
      VLOG(1) << "Detected IP address changes.";
#if defined(OS_CHROMEOS)
      // TODO(oshima): chromium-os:8285 - introduced artificial delay to
      // work around the issue of network load issue after connection
      // restored. See the bug for more details.
      //  This should be removed once this bug is properly fixed.
      const int kObserverNotificationDelayMS = 200;
      message_loop()->PostDelayedTask(
          FROM_HERE,
          method_factory_.NewRunnableMethod(
              &Thread::NotifyObserversOfIPAddressChange),
          kObserverNotificationDelayMS);
#else
      NotifyObserversOfIPAddressChange();
#endif
    }
    rv = ReadNotificationMessage(buf, arraysize(buf));
  }

  if (rv == ERR_IO_PENDING) {
    rv = MessageLoopForIO::current()->WatchFileDescriptor(netlink_fd_, false,
        MessageLoopForIO::WATCH_READ, &netlink_watcher_, this);
    LOG_IF(ERROR, !rv) << "Failed to watch netlink socket: " << netlink_fd_;
  }
}

int NetworkChangeNotifierLinux::Thread::ReadNotificationMessage(
    char* buf,
    size_t len) {
  DCHECK_NE(len, 0u);
  DCHECK(buf);
  memset(buf, 0, len);
  int rv = recv(netlink_fd_, buf, len, 0);
  if (rv > 0)
    return rv;

  DCHECK_NE(rv, 0);
  if (errno != EAGAIN && errno != EWOULDBLOCK) {
    PLOG(DFATAL) << "recv";
    return ERR_FAILED;
  }

  return ERR_IO_PENDING;
}

NetworkChangeNotifierLinux::NetworkChangeNotifierLinux()
    : notifier_thread_(new Thread) {
  // We create this notifier thread because the notification implementation
  // needs a MessageLoopForIO, and there's no guarantee that
  // MessageLoop::current() meets that criterion.
  base::Thread::Options thread_options(MessageLoop::TYPE_IO, 0);
  notifier_thread_->StartWithOptions(thread_options);
}

NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() {
  // We don't need to explicitly Stop(), but doing so allows us to sanity-
  // check that the notifier thread shut down properly.
  notifier_thread_->Stop();
}

bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const {
  // TODO(eroman): http://crbug.com/53473
  return false;
}

}  // namespace net
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <rapidxml_utils.hpp>

#include "llvm/compiler.hpp"
#include "parser/xmlParser.hpp"

class LLVMCompilerTest: public ::testing::Test {
protected:
  XMLParser xpx = XMLParser();

  inline rapidxml::file<> xmlFile(std::string path) {
    path = DATA_PARENT_DIR + ("/" + path);
    return rapidxml::file<>(path.c_str());
  }

  inline void noThrowOnCompile(std::string xmlFilePath) {
    xpx.parse(xmlFile(xmlFilePath));
    CompileVisitor::Link visitor = CompileVisitor::create(globalContext, xmlFilePath, xpx.getTree());
    try {
      visitor->visit();
    } catch (InternalError& err) {
      EXPECT_NO_THROW(throw InternalError(err));
      println(err.what());
    }
    visitor->getModule()->dump();
  }
};

TEST_F(LLVMCompilerTest, ExitCodes) {
  noThrowOnCompile("data/llvm/exit_code.xml");
  noThrowOnCompile("data/llvm/stored_return.xml");
}

TEST_F(LLVMCompilerTest, Declarations) {
  noThrowOnCompile("data/llvm/primitive.xml");
}

TEST_F(LLVMCompilerTest, Assignment) {
  noThrowOnCompile("data/llvm/return_assign.xml");
}

TEST_F(LLVMCompilerTest, Branches) {
  noThrowOnCompile("data/llvm/if.xml");
  noThrowOnCompile("data/llvm/if-else.xml");
  noThrowOnCompile("data/llvm/else-if.xml");
}
<commit_msg>Only print llvm ir if the test failed<commit_after>#include <gtest/gtest.h>
#include <rapidxml_utils.hpp>

#include "llvm/compiler.hpp"
#include "parser/xmlParser.hpp"

class LLVMCompilerTest: public ::testing::Test {
protected:
  XMLParser xpx = XMLParser();

  inline rapidxml::file<> xmlFile(std::string path) {
    path = DATA_PARENT_DIR + ("/" + path);
    return rapidxml::file<>(path.c_str());
  }

  inline void noThrowOnCompile(std::string xmlFilePath) {
    xpx.parse(xmlFile(xmlFilePath));
    CompileVisitor::Link visitor = CompileVisitor::create(globalContext, xmlFilePath, xpx.getTree());
    try {
      visitor->visit();
    } catch (InternalError& err) {
      EXPECT_NO_THROW(throw InternalError(err));
      println(err.what());
      visitor->getModule()->dump();
    }
  }
};

TEST_F(LLVMCompilerTest, ExitCodes) {
  noThrowOnCompile("data/llvm/exit_code.xml");
  noThrowOnCompile("data/llvm/stored_return.xml");
}

TEST_F(LLVMCompilerTest, Declarations) {
  noThrowOnCompile("data/llvm/primitive.xml");
}

TEST_F(LLVMCompilerTest, Assignment) {
  noThrowOnCompile("data/llvm/return_assign.xml");
}

TEST_F(LLVMCompilerTest, Branches) {
  noThrowOnCompile("data/llvm/if.xml");
  noThrowOnCompile("data/llvm/if-else.xml");
  noThrowOnCompile("data/llvm/else-if.xml");
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/http_proxy_client_socket_pool.h"

#include <algorithm>

#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_errors.h"
#include "net/http/http_network_session.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/tcp_client_socket_pool.h"

namespace net {

HttpProxySocketParams::HttpProxySocketParams(
    const scoped_refptr<TCPSocketParams>& tcp_params,
    const scoped_refptr<SSLSocketParams>& ssl_params,
    const GURL& request_url,
    const std::string& user_agent,
    HostPortPair endpoint,
    scoped_refptr<HttpNetworkSession> session,
    bool tunnel)
    : tcp_params_(tcp_params),
      ssl_params_(ssl_params),
      request_url_(request_url),
      user_agent_(user_agent),
      endpoint_(endpoint),
      session_(tunnel ? session : NULL),
      tunnel_(tunnel) {
  DCHECK((tcp_params == NULL && ssl_params != NULL) ||
         (tcp_params != NULL && ssl_params == NULL));
}

const HostResolver::RequestInfo& HttpProxySocketParams::destination() const {
  if (tcp_params_ == NULL)
    return ssl_params_->tcp_params()->destination();
  else
    return tcp_params_->destination();
}

HttpProxySocketParams::~HttpProxySocketParams() {}

// HttpProxyConnectJobs will time out after this many seconds.  Note this is on
// top of the timeout for the transport socket.
static const int kHttpProxyConnectJobTimeoutInSeconds = 30;

HttpProxyConnectJob::HttpProxyConnectJob(
    const std::string& group_name,
    const scoped_refptr<HttpProxySocketParams>& params,
    const base::TimeDelta& timeout_duration,
    const scoped_refptr<TCPClientSocketPool>& tcp_pool,
    const scoped_refptr<SSLClientSocketPool>& ssl_pool,
    const scoped_refptr<HostResolver>& host_resolver,
    Delegate* delegate,
    NetLog* net_log)
    : ConnectJob(group_name, timeout_duration, delegate,
                 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
      params_(params),
      tcp_pool_(tcp_pool),
      ssl_pool_(ssl_pool),
      resolver_(host_resolver),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          callback_(this, &HttpProxyConnectJob::OnIOComplete)) {
}

HttpProxyConnectJob::~HttpProxyConnectJob() {}

LoadState HttpProxyConnectJob::GetLoadState() const {
  switch (next_state_) {
    case kStateTCPConnect:
    case kStateTCPConnectComplete:
    case kStateSSLConnect:
    case kStateSSLConnectComplete:
      return transport_socket_handle_->GetLoadState();
    case kStateHttpProxyConnect:
    case kStateHttpProxyConnectComplete:
      return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
    default:
      NOTREACHED();
      return LOAD_STATE_IDLE;
  }
}

int HttpProxyConnectJob::ConnectInternal() {
  if (params_->tcp_params())
    next_state_ = kStateTCPConnect;
  else
    next_state_ = kStateSSLConnect;
  return DoLoop(OK);
}

void HttpProxyConnectJob::OnIOComplete(int result) {
  int rv = DoLoop(result);
  if (rv != ERR_IO_PENDING)
    NotifyDelegateOfCompletion(rv);  // Deletes |this|
}

int HttpProxyConnectJob::DoLoop(int result) {
  DCHECK_NE(next_state_, kStateNone);

  int rv = result;
  do {
    State state = next_state_;
    next_state_ = kStateNone;
    switch (state) {
      case kStateTCPConnect:
        DCHECK_EQ(OK, rv);
        rv = DoTCPConnect();
        break;
      case kStateTCPConnectComplete:
        rv = DoTCPConnectComplete(rv);
        break;
      case kStateSSLConnect:
        DCHECK_EQ(OK, rv);
        rv = DoSSLConnect();
        break;
      case kStateSSLConnectComplete:
        rv = DoSSLConnectComplete(rv);
        break;
      case kStateHttpProxyConnect:
        DCHECK_EQ(OK, rv);
        rv = DoHttpProxyConnect();
        break;
      case kStateHttpProxyConnectComplete:
        rv = DoHttpProxyConnectComplete(rv);
        break;
      default:
        NOTREACHED() << "bad state";
        rv = ERR_FAILED;
        break;
    }
  } while (rv != ERR_IO_PENDING && next_state_ != kStateNone);

  return rv;
}

int HttpProxyConnectJob::DoTCPConnect() {
  next_state_ = kStateTCPConnectComplete;
  transport_socket_handle_.reset(new ClientSocketHandle());
  return transport_socket_handle_->Init(
      group_name(), params_->tcp_params(),
      params_->tcp_params()->destination().priority(), &callback_, tcp_pool_,
      net_log());
}

int HttpProxyConnectJob::DoTCPConnectComplete(int result) {
  if (result != OK)
    return result;

  // Reset the timer to just the length of time allowed for HttpProxy handshake
  // so that a fast TCP connection plus a slow HttpProxy failure doesn't take
  // longer to timeout than it should.
  ResetTimer(base::TimeDelta::FromSeconds(
      kHttpProxyConnectJobTimeoutInSeconds));
  next_state_ = kStateHttpProxyConnect;
  return result;
}

int HttpProxyConnectJob::DoSSLConnect() {
  next_state_ = kStateSSLConnectComplete;
  transport_socket_handle_.reset(new ClientSocketHandle());
  return transport_socket_handle_->Init(
      group_name(), params_->ssl_params(),
      params_->ssl_params()->tcp_params()->destination().priority(),
      &callback_, ssl_pool_, net_log());
}

int HttpProxyConnectJob::DoSSLConnectComplete(int result) {
  if (result < 0) {
    if (transport_socket_handle_->socket())
      transport_socket_handle_->socket()->Disconnect();
    return result;
  }

  // Reset the timer to just the length of time allowed for HttpProxy handshake
  // so that a fast SSL connection plus a slow HttpProxy failure doesn't take
  // longer to timeout than it should.
  ResetTimer(base::TimeDelta::FromSeconds(
      kHttpProxyConnectJobTimeoutInSeconds));
  next_state_ = kStateHttpProxyConnect;
  return result;
}

int HttpProxyConnectJob::DoHttpProxyConnect() {
  next_state_ = kStateHttpProxyConnectComplete;
  const HostResolver::RequestInfo& tcp_destination = params_->destination();
  HostPortPair proxy_server(tcp_destination.hostname(),
                            tcp_destination.port());

  // Add a HttpProxy connection on top of the tcp socket.
  transport_socket_.reset(
      new HttpProxyClientSocket(transport_socket_handle_.release(),
                                params_->request_url(),
                                params_->user_agent(),
                                params_->endpoint(),
                                proxy_server, params_->session(),
                                params_->tunnel()));
  int result = transport_socket_->Connect(&callback_);

  // Clear the circular reference to HttpNetworkSession (|params_| reference
  // HttpNetworkSession, which reference HttpProxyClientSocketPool, which
  // references |this|) here because it is safe to do so now but not at other
  // points.  This may cancel this ConnectJob.
  params_ = NULL;
  return result;
}

int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
  if (result == OK || result == ERR_PROXY_AUTH_REQUESTED)
      set_socket(transport_socket_.release());

  return result;
}

HttpProxyClientSocketPool::
HttpProxyConnectJobFactory::HttpProxyConnectJobFactory(
    const scoped_refptr<TCPClientSocketPool>& tcp_pool,
    const scoped_refptr<SSLClientSocketPool>& ssl_pool,
    HostResolver* host_resolver,
    NetLog* net_log)
    : tcp_pool_(tcp_pool),
      ssl_pool_(ssl_pool),
      host_resolver_(host_resolver),
      net_log_(net_log) {
  base::TimeDelta max_pool_timeout = base::TimeDelta();
  if (tcp_pool_)
    max_pool_timeout = tcp_pool_->ConnectionTimeout();
  if (ssl_pool_)
    max_pool_timeout = std::max(max_pool_timeout,
                                ssl_pool_->ConnectionTimeout());
  timeout_ = max_pool_timeout +
    base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds);
}

ConnectJob*
HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob(
    const std::string& group_name,
    const PoolBase::Request& request,
    ConnectJob::Delegate* delegate) const {
  return new HttpProxyConnectJob(group_name, request.params(),
                                 ConnectionTimeout(), tcp_pool_, ssl_pool_,
                                 host_resolver_, delegate, net_log_);
}

HttpProxyClientSocketPool::HttpProxyClientSocketPool(
    int max_sockets,
    int max_sockets_per_group,
    const scoped_refptr<ClientSocketPoolHistograms>& histograms,
    const scoped_refptr<HostResolver>& host_resolver,
    const scoped_refptr<TCPClientSocketPool>& tcp_pool,
    const scoped_refptr<SSLClientSocketPool>& ssl_pool,
    NetLog* net_log)
    : base_(max_sockets, max_sockets_per_group, histograms,
            base::TimeDelta::FromSeconds(
                ClientSocketPool::unused_idle_socket_timeout()),
            base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout),
            new HttpProxyConnectJobFactory(tcp_pool, ssl_pool, host_resolver,
                                           net_log)) {}

HttpProxyClientSocketPool::~HttpProxyClientSocketPool() {}

int HttpProxyClientSocketPool::RequestSocket(const std::string& group_name,
                                             const void* socket_params,
                                             RequestPriority priority,
                                             ClientSocketHandle* handle,
                                             CompletionCallback* callback,
                                             const BoundNetLog& net_log) {
  const scoped_refptr<HttpProxySocketParams>* casted_socket_params =
      static_cast<const scoped_refptr<HttpProxySocketParams>*>(socket_params);

  return base_.RequestSocket(group_name, *casted_socket_params, priority,
                             handle, callback, net_log);
}

void HttpProxyClientSocketPool::CancelRequest(
    const std::string& group_name,
    ClientSocketHandle* handle) {
  base_.CancelRequest(group_name, handle);
}

void HttpProxyClientSocketPool::ReleaseSocket(const std::string& group_name,
                                              ClientSocket* socket, int id) {
  base_.ReleaseSocket(group_name, socket, id);
}

void HttpProxyClientSocketPool::Flush() {
  base_.Flush();
}

void HttpProxyClientSocketPool::CloseIdleSockets() {
  base_.CloseIdleSockets();
}

int HttpProxyClientSocketPool::IdleSocketCountInGroup(
    const std::string& group_name) const {
  return base_.IdleSocketCountInGroup(group_name);
}

LoadState HttpProxyClientSocketPool::GetLoadState(
    const std::string& group_name, const ClientSocketHandle* handle) const {
  return base_.GetLoadState(group_name, handle);
}

}  // namespace net
<commit_msg>Ignore certificate errors when connecting to an HTTPS Proxy if LOAD_IGNORE_ALL_CERT_ERRORS is set.  This happens when the --ignore_certificate_errors command line flag is present.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/http_proxy_client_socket_pool.h"

#include <algorithm>

#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_network_session.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/tcp_client_socket_pool.h"

namespace net {

HttpProxySocketParams::HttpProxySocketParams(
    const scoped_refptr<TCPSocketParams>& tcp_params,
    const scoped_refptr<SSLSocketParams>& ssl_params,
    const GURL& request_url,
    const std::string& user_agent,
    HostPortPair endpoint,
    scoped_refptr<HttpNetworkSession> session,
    bool tunnel)
    : tcp_params_(tcp_params),
      ssl_params_(ssl_params),
      request_url_(request_url),
      user_agent_(user_agent),
      endpoint_(endpoint),
      session_(tunnel ? session : NULL),
      tunnel_(tunnel) {
  DCHECK((tcp_params == NULL && ssl_params != NULL) ||
         (tcp_params != NULL && ssl_params == NULL));
}

const HostResolver::RequestInfo& HttpProxySocketParams::destination() const {
  if (tcp_params_ == NULL)
    return ssl_params_->tcp_params()->destination();
  else
    return tcp_params_->destination();
}

HttpProxySocketParams::~HttpProxySocketParams() {}

// HttpProxyConnectJobs will time out after this many seconds.  Note this is on
// top of the timeout for the transport socket.
static const int kHttpProxyConnectJobTimeoutInSeconds = 30;

HttpProxyConnectJob::HttpProxyConnectJob(
    const std::string& group_name,
    const scoped_refptr<HttpProxySocketParams>& params,
    const base::TimeDelta& timeout_duration,
    const scoped_refptr<TCPClientSocketPool>& tcp_pool,
    const scoped_refptr<SSLClientSocketPool>& ssl_pool,
    const scoped_refptr<HostResolver>& host_resolver,
    Delegate* delegate,
    NetLog* net_log)
    : ConnectJob(group_name, timeout_duration, delegate,
                 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
      params_(params),
      tcp_pool_(tcp_pool),
      ssl_pool_(ssl_pool),
      resolver_(host_resolver),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          callback_(this, &HttpProxyConnectJob::OnIOComplete)) {
}

HttpProxyConnectJob::~HttpProxyConnectJob() {}

LoadState HttpProxyConnectJob::GetLoadState() const {
  switch (next_state_) {
    case kStateTCPConnect:
    case kStateTCPConnectComplete:
    case kStateSSLConnect:
    case kStateSSLConnectComplete:
      return transport_socket_handle_->GetLoadState();
    case kStateHttpProxyConnect:
    case kStateHttpProxyConnectComplete:
      return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
    default:
      NOTREACHED();
      return LOAD_STATE_IDLE;
  }
}

int HttpProxyConnectJob::ConnectInternal() {
  if (params_->tcp_params())
    next_state_ = kStateTCPConnect;
  else
    next_state_ = kStateSSLConnect;
  return DoLoop(OK);
}

void HttpProxyConnectJob::OnIOComplete(int result) {
  int rv = DoLoop(result);
  if (rv != ERR_IO_PENDING)
    NotifyDelegateOfCompletion(rv);  // Deletes |this|
}

int HttpProxyConnectJob::DoLoop(int result) {
  DCHECK_NE(next_state_, kStateNone);

  int rv = result;
  do {
    State state = next_state_;
    next_state_ = kStateNone;
    switch (state) {
      case kStateTCPConnect:
        DCHECK_EQ(OK, rv);
        rv = DoTCPConnect();
        break;
      case kStateTCPConnectComplete:
        rv = DoTCPConnectComplete(rv);
        break;
      case kStateSSLConnect:
        DCHECK_EQ(OK, rv);
        rv = DoSSLConnect();
        break;
      case kStateSSLConnectComplete:
        rv = DoSSLConnectComplete(rv);
        break;
      case kStateHttpProxyConnect:
        DCHECK_EQ(OK, rv);
        rv = DoHttpProxyConnect();
        break;
      case kStateHttpProxyConnectComplete:
        rv = DoHttpProxyConnectComplete(rv);
        break;
      default:
        NOTREACHED() << "bad state";
        rv = ERR_FAILED;
        break;
    }
  } while (rv != ERR_IO_PENDING && next_state_ != kStateNone);

  return rv;
}

int HttpProxyConnectJob::DoTCPConnect() {
  next_state_ = kStateTCPConnectComplete;
  transport_socket_handle_.reset(new ClientSocketHandle());
  return transport_socket_handle_->Init(
      group_name(), params_->tcp_params(),
      params_->tcp_params()->destination().priority(), &callback_, tcp_pool_,
      net_log());
}

int HttpProxyConnectJob::DoTCPConnectComplete(int result) {
  if (result != OK)
    return result;

  // Reset the timer to just the length of time allowed for HttpProxy handshake
  // so that a fast TCP connection plus a slow HttpProxy failure doesn't take
  // longer to timeout than it should.
  ResetTimer(base::TimeDelta::FromSeconds(
      kHttpProxyConnectJobTimeoutInSeconds));
  next_state_ = kStateHttpProxyConnect;
  return result;
}

int HttpProxyConnectJob::DoSSLConnect() {
  next_state_ = kStateSSLConnectComplete;
  transport_socket_handle_.reset(new ClientSocketHandle());
  return transport_socket_handle_->Init(
      group_name(), params_->ssl_params(),
      params_->ssl_params()->tcp_params()->destination().priority(),
      &callback_, ssl_pool_, net_log());
}

int HttpProxyConnectJob::DoSSLConnectComplete(int result) {
  if (IsCertificateError(result) &&
      params_->ssl_params()->load_flags() & LOAD_IGNORE_ALL_CERT_ERRORS)
    result = OK;
  if (result < 0) {
    if (transport_socket_handle_->socket())
      transport_socket_handle_->socket()->Disconnect();
    return result;
  }

  // Reset the timer to just the length of time allowed for HttpProxy handshake
  // so that a fast SSL connection plus a slow HttpProxy failure doesn't take
  // longer to timeout than it should.
  ResetTimer(base::TimeDelta::FromSeconds(
      kHttpProxyConnectJobTimeoutInSeconds));
  next_state_ = kStateHttpProxyConnect;
  return result;
}

int HttpProxyConnectJob::DoHttpProxyConnect() {
  next_state_ = kStateHttpProxyConnectComplete;
  const HostResolver::RequestInfo& tcp_destination = params_->destination();
  HostPortPair proxy_server(tcp_destination.hostname(),
                            tcp_destination.port());

  // Add a HttpProxy connection on top of the tcp socket.
  transport_socket_.reset(
      new HttpProxyClientSocket(transport_socket_handle_.release(),
                                params_->request_url(),
                                params_->user_agent(),
                                params_->endpoint(),
                                proxy_server, params_->session(),
                                params_->tunnel()));
  int result = transport_socket_->Connect(&callback_);

  // Clear the circular reference to HttpNetworkSession (|params_| reference
  // HttpNetworkSession, which reference HttpProxyClientSocketPool, which
  // references |this|) here because it is safe to do so now but not at other
  // points.  This may cancel this ConnectJob.
  params_ = NULL;
  return result;
}

int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
  if (result == OK || result == ERR_PROXY_AUTH_REQUESTED)
      set_socket(transport_socket_.release());

  return result;
}

HttpProxyClientSocketPool::
HttpProxyConnectJobFactory::HttpProxyConnectJobFactory(
    const scoped_refptr<TCPClientSocketPool>& tcp_pool,
    const scoped_refptr<SSLClientSocketPool>& ssl_pool,
    HostResolver* host_resolver,
    NetLog* net_log)
    : tcp_pool_(tcp_pool),
      ssl_pool_(ssl_pool),
      host_resolver_(host_resolver),
      net_log_(net_log) {
  base::TimeDelta max_pool_timeout = base::TimeDelta();
  if (tcp_pool_)
    max_pool_timeout = tcp_pool_->ConnectionTimeout();
  if (ssl_pool_)
    max_pool_timeout = std::max(max_pool_timeout,
                                ssl_pool_->ConnectionTimeout());
  timeout_ = max_pool_timeout +
    base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds);
}

ConnectJob*
HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob(
    const std::string& group_name,
    const PoolBase::Request& request,
    ConnectJob::Delegate* delegate) const {
  return new HttpProxyConnectJob(group_name, request.params(),
                                 ConnectionTimeout(), tcp_pool_, ssl_pool_,
                                 host_resolver_, delegate, net_log_);
}

HttpProxyClientSocketPool::HttpProxyClientSocketPool(
    int max_sockets,
    int max_sockets_per_group,
    const scoped_refptr<ClientSocketPoolHistograms>& histograms,
    const scoped_refptr<HostResolver>& host_resolver,
    const scoped_refptr<TCPClientSocketPool>& tcp_pool,
    const scoped_refptr<SSLClientSocketPool>& ssl_pool,
    NetLog* net_log)
    : base_(max_sockets, max_sockets_per_group, histograms,
            base::TimeDelta::FromSeconds(
                ClientSocketPool::unused_idle_socket_timeout()),
            base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout),
            new HttpProxyConnectJobFactory(tcp_pool, ssl_pool, host_resolver,
                                           net_log)) {}

HttpProxyClientSocketPool::~HttpProxyClientSocketPool() {}

int HttpProxyClientSocketPool::RequestSocket(const std::string& group_name,
                                             const void* socket_params,
                                             RequestPriority priority,
                                             ClientSocketHandle* handle,
                                             CompletionCallback* callback,
                                             const BoundNetLog& net_log) {
  const scoped_refptr<HttpProxySocketParams>* casted_socket_params =
      static_cast<const scoped_refptr<HttpProxySocketParams>*>(socket_params);

  return base_.RequestSocket(group_name, *casted_socket_params, priority,
                             handle, callback, net_log);
}

void HttpProxyClientSocketPool::CancelRequest(
    const std::string& group_name,
    ClientSocketHandle* handle) {
  base_.CancelRequest(group_name, handle);
}

void HttpProxyClientSocketPool::ReleaseSocket(const std::string& group_name,
                                              ClientSocket* socket, int id) {
  base_.ReleaseSocket(group_name, socket, id);
}

void HttpProxyClientSocketPool::Flush() {
  base_.Flush();
}

void HttpProxyClientSocketPool::CloseIdleSockets() {
  base_.CloseIdleSockets();
}

int HttpProxyClientSocketPool::IdleSocketCountInGroup(
    const std::string& group_name) const {
  return base_.IdleSocketCountInGroup(group_name);
}

LoadState HttpProxyClientSocketPool::GetLoadState(
    const std::string& group_name, const ClientSocketHandle* handle) const {
  return base_.GetLoadState(group_name, handle);
}

}  // namespace net
<|endoftext|>


<commit_before>#include "../include/NexusFileReader.h"
#include <iostream>
#include <cmath>

using namespace H5;

/**
 * Create a object to read the specified file
 *
 * @param filename - the full path of the NeXus file
 * @return - an object with which to read information from the file
 */
NexusFileReader::NexusFileReader(const std::string &filename)
    : m_file(new H5File(filename, H5F_ACC_RDONLY)) {
  DataSet dataset = m_file->openDataSet("/raw_data_1/good_frames");
  size_t numOfFrames;
  dataset.read(&numOfFrames, PredType::NATIVE_UINT64);
  m_numberOfFrames = numOfFrames;
}

/**
 * Get the size of the NeXus file in bytes
 *
 * @return - the size of the file in bytes
 */
hsize_t NexusFileReader::getFileSize() { return m_file->getFileSize(); }

uint64_t NexusFileReader::getTotalEventCount() {
  DataSet dataset =
      m_file->openDataSet("/raw_data_1/detector_1_events/total_counts");
  uint64_t totalCount;
  dataset.read(&totalCount, PredType::NATIVE_UINT64);

  return totalCount;
}

/**
 * Gets the event index of the start of the specified frame
 *
 * @param frameNumber - find the event index for the start of this frame
 * @return - event index corresponding to the start of the specified frame
 */
hsize_t NexusFileReader::getFrameStart(hsize_t frameNumber) {
  auto dataset =
      m_file->openDataSet("/raw_data_1/detector_1_events/event_index");
  uint64_t frameStart;

  hsize_t count = 1;
  hsize_t offset = frameNumber;
  hsize_t stride = 1;
  hsize_t block = 1;

  auto dataspace = dataset.getSpace();
  dataspace.selectHyperslab(H5S_SELECT_SET, &count, &offset, &stride, &block);

  hsize_t dimsm = 1;
  DataSpace memspace(1, &dimsm);

  dataset.read(&frameStart, PredType::NATIVE_UINT64, memspace, dataspace);

  return frameStart;
}

/**
 * Get the number of events which are in the specified frame
 *
 * @param frameNumber - the number of the frame in which to count the number of events
 * @return - the number of events in the specified frame
 */
hsize_t NexusFileReader::getNumberOfEventsInFrame(hsize_t frameNumber) {
  // if this is the last frame then we cannot get number of events by looking at event index of next frame
  // instead use the total_counts field
  if (frameNumber == (m_numberOfFrames - 1)) {
    return getTotalEventCount() - getFrameStart(frameNumber);
  }
  return getFrameStart(frameNumber + 1) - getFrameStart(frameNumber);
}

/**
 * Get the list of detector IDs corresponding to events in the specifed frame
 *
 * @param detIds - vector in which to store the detector IDs
 * @param frameNumber - the number of the frame in which to get the detector IDs
 * @return - false if the specified frame number is not the data range, true otherwise
 */
bool NexusFileReader::getEventDetIds(std::vector<uint32_t> &detIds,
                                     hsize_t frameNumber) {
  if (frameNumber >= m_numberOfFrames)
    return false;
  auto dataset =
      m_file->openDataSet("/raw_data_1/detector_1_events/event_id");

  auto numberOfEventsInFrame = getNumberOfEventsInFrame(frameNumber);

  hsize_t count = numberOfEventsInFrame;
  hsize_t offset = getFrameStart(frameNumber);
  hsize_t stride = 1;
  hsize_t block = 1;

  auto dataspace = dataset.getSpace();
  dataspace.selectHyperslab(H5S_SELECT_SET, &count, &offset, &stride, &block);

  // resize detIds to the correct size to put the new data in
  detIds.resize(numberOfEventsInFrame);

  hsize_t dimsm = numberOfEventsInFrame;
  DataSpace memspace(1, &dimsm);

  dataset.read(detIds.data(), PredType::NATIVE_UINT32, memspace, dataspace);

  return true;
}

/**
 * Get the list of flight times corresponding to events in the specifed frame
 *
 * @param tofs - vector in which to store the time-of-flight
 * @param frameNumber - the number of the frame in which to get the time-of-flights
 * @return - false if the specified frame number is not the data range, true otherwise
 */
bool NexusFileReader::getEventTofs(std::vector<uint64_t> &tofs,
                                   hsize_t frameNumber) {
  if (frameNumber >= m_numberOfFrames)
    return false;
  auto dataset =
      m_file->openDataSet("/raw_data_1/detector_1_events/event_time_offset");

  auto numberOfEventsInFrame = getNumberOfEventsInFrame(frameNumber);

  hsize_t count = numberOfEventsInFrame;
  hsize_t offset = getFrameStart(frameNumber);
  hsize_t stride = 1;
  hsize_t block = 1;

  auto dataspace = dataset.getSpace();
  dataspace.selectHyperslab(H5S_SELECT_SET, &count, &offset, &stride, &block);

  std::vector<double> timeOffsetArray(numberOfEventsInFrame);

  hsize_t dimsm = numberOfEventsInFrame;
  DataSpace memspace(1, &dimsm);

  dataset.read(timeOffsetArray.data(), PredType::NATIVE_DOUBLE, memspace, dataspace);

  tofs.resize(numberOfEventsInFrame);

  for (size_t tofIndex = 0; tofIndex < numberOfEventsInFrame; tofIndex++) {
    tofs[tofIndex] = static_cast<uint64_t>((timeOffsetArray[tofIndex] * 1e3));
  }

  return true;
}

std::vector<int>
NexusFileReader::getFramePartsPerFrame(int maxEventsPerMessage) {
  std::vector<int> framePartsPerFrame;
  framePartsPerFrame.resize(m_numberOfFrames);
  for (hsize_t frameNumber = 0; frameNumber < m_numberOfFrames; frameNumber++) {
    framePartsPerFrame[frameNumber] = static_cast<int>(
        std::ceil(static_cast<float>(getNumberOfEventsInFrame(frameNumber)) /
                  static_cast<float>(maxEventsPerMessage)));
  }
  return framePartsPerFrame;
}
<commit_msg>Re #4 send a message even if there are no events in the frame to ensure files match<commit_after>#include "../include/NexusFileReader.h"
#include <iostream>
#include <cmath>

using namespace H5;

/**
 * Create a object to read the specified file
 *
 * @param filename - the full path of the NeXus file
 * @return - an object with which to read information from the file
 */
NexusFileReader::NexusFileReader(const std::string &filename)
    : m_file(new H5File(filename, H5F_ACC_RDONLY)) {
  DataSet dataset = m_file->openDataSet("/raw_data_1/good_frames");
  size_t numOfFrames;
  dataset.read(&numOfFrames, PredType::NATIVE_UINT64);
  m_numberOfFrames = numOfFrames;
}

/**
 * Get the size of the NeXus file in bytes
 *
 * @return - the size of the file in bytes
 */
hsize_t NexusFileReader::getFileSize() { return m_file->getFileSize(); }

uint64_t NexusFileReader::getTotalEventCount() {
  DataSet dataset =
      m_file->openDataSet("/raw_data_1/detector_1_events/total_counts");
  uint64_t totalCount;
  dataset.read(&totalCount, PredType::NATIVE_UINT64);

  return totalCount;
}

/**
 * Gets the event index of the start of the specified frame
 *
 * @param frameNumber - find the event index for the start of this frame
 * @return - event index corresponding to the start of the specified frame
 */
hsize_t NexusFileReader::getFrameStart(hsize_t frameNumber) {
  auto dataset =
      m_file->openDataSet("/raw_data_1/detector_1_events/event_index");
  uint64_t frameStart;

  hsize_t count = 1;
  hsize_t offset = frameNumber;
  hsize_t stride = 1;
  hsize_t block = 1;

  auto dataspace = dataset.getSpace();
  dataspace.selectHyperslab(H5S_SELECT_SET, &count, &offset, &stride, &block);

  hsize_t dimsm = 1;
  DataSpace memspace(1, &dimsm);

  dataset.read(&frameStart, PredType::NATIVE_UINT64, memspace, dataspace);

  return frameStart;
}

/**
 * Get the number of events which are in the specified frame
 *
 * @param frameNumber - the number of the frame in which to count the number of events
 * @return - the number of events in the specified frame
 */
hsize_t NexusFileReader::getNumberOfEventsInFrame(hsize_t frameNumber) {
  // if this is the last frame then we cannot get number of events by looking at event index of next frame
  // instead use the total_counts field
  if (frameNumber == (m_numberOfFrames - 1)) {
    return getTotalEventCount() - getFrameStart(frameNumber);
  }
  return getFrameStart(frameNumber + 1) - getFrameStart(frameNumber);
}

/**
 * Get the list of detector IDs corresponding to events in the specifed frame
 *
 * @param detIds - vector in which to store the detector IDs
 * @param frameNumber - the number of the frame in which to get the detector IDs
 * @return - false if the specified frame number is not the data range, true otherwise
 */
bool NexusFileReader::getEventDetIds(std::vector<uint32_t> &detIds,
                                     hsize_t frameNumber) {
  if (frameNumber >= m_numberOfFrames)
    return false;
  auto dataset =
      m_file->openDataSet("/raw_data_1/detector_1_events/event_id");

  auto numberOfEventsInFrame = getNumberOfEventsInFrame(frameNumber);

  hsize_t count = numberOfEventsInFrame;
  hsize_t offset = getFrameStart(frameNumber);
  hsize_t stride = 1;
  hsize_t block = 1;

  auto dataspace = dataset.getSpace();
  dataspace.selectHyperslab(H5S_SELECT_SET, &count, &offset, &stride, &block);

  // resize detIds to the correct size to put the new data in
  detIds.resize(numberOfEventsInFrame);

  hsize_t dimsm = numberOfEventsInFrame;
  DataSpace memspace(1, &dimsm);

  dataset.read(detIds.data(), PredType::NATIVE_UINT32, memspace, dataspace);

  return true;
}

/**
 * Get the list of flight times corresponding to events in the specifed frame
 *
 * @param tofs - vector in which to store the time-of-flight
 * @param frameNumber - the number of the frame in which to get the time-of-flights
 * @return - false if the specified frame number is not the data range, true otherwise
 */
bool NexusFileReader::getEventTofs(std::vector<uint64_t> &tofs,
                                   hsize_t frameNumber) {
  if (frameNumber >= m_numberOfFrames)
    return false;
  auto dataset =
      m_file->openDataSet("/raw_data_1/detector_1_events/event_time_offset");

  auto numberOfEventsInFrame = getNumberOfEventsInFrame(frameNumber);

  hsize_t count = numberOfEventsInFrame;
  hsize_t offset = getFrameStart(frameNumber);
  hsize_t stride = 1;
  hsize_t block = 1;

  auto dataspace = dataset.getSpace();
  dataspace.selectHyperslab(H5S_SELECT_SET, &count, &offset, &stride, &block);

  std::vector<double> timeOffsetArray(numberOfEventsInFrame);

  hsize_t dimsm = numberOfEventsInFrame;
  DataSpace memspace(1, &dimsm);

  dataset.read(timeOffsetArray.data(), PredType::NATIVE_DOUBLE, memspace, dataspace);

  tofs.resize(numberOfEventsInFrame);

  for (size_t tofIndex = 0; tofIndex < numberOfEventsInFrame; tofIndex++) {
    tofs[tofIndex] = static_cast<uint64_t>((timeOffsetArray[tofIndex] * 1e3));
  }

  return true;
}

std::vector<int>
NexusFileReader::getFramePartsPerFrame(int maxEventsPerMessage) {
  std::vector<int> framePartsPerFrame;
  framePartsPerFrame.resize(m_numberOfFrames);
  for (hsize_t frameNumber = 0; frameNumber < m_numberOfFrames; frameNumber++) {
    int frameParts = static_cast<int>(
        std::ceil(static_cast<float>(getNumberOfEventsInFrame(frameNumber)) /
                  static_cast<float>(maxEventsPerMessage)));
    // If there are no events in the frame a message should still be sent
    // otherwise the output file will not match the input file
    if (frameParts > 0)
      framePartsPerFrame[frameNumber] = frameParts;
    else
      framePartsPerFrame[frameNumber] = 1;
  }
  return framePartsPerFrame;
}
<|endoftext|>


<commit_before>// ffmpeg_utils.cpp
// part of MusicPlayer, https://github.com/albertz/music-player
// Copyright (c) 2012, Albert Zeyer, www.az2000.de
// All rights reserved.
// This code is under the 2-clause BSD license, see License.txt in the root directory of this project.

#include "ffmpeg.h"
#include <unistd.h>

#if defined(__APPLE__)
#include <execinfo.h>

static __attribute__((noinline))
void* getStackPtr(int n) {
	n += 1; // getStackPtr() itself
	void* stack[20];
	static const int Size = sizeof(stack)/sizeof(stack[0]);
	if(n >= Size) return NULL;
	int c = backtrace(stack, Size);
	if(n >= c) return NULL;
	return stack[n];
}

static const char* getStackSymbol(void* pt) {
	char** s_ = backtrace_symbols(&pt, 1);
	if(!s_) return "?";
	char* s = *s_;
	free(s_);
	if(!s) return "?";
	// s = "<number>     <filename>    <interesting-part>"
	// we only want the interesting part.
	while(*s && *s != ' ') ++s; // advance the number
	while(*s && *s == ' ') ++s; // advance the spaces
	while(*s && *s != ' ') ++s; // advance the filename
	while(*s && *s == ' ') ++s; // advance the spaces
	return s;
}

#else
static void* getStackPtr(int n) { return NULL; }
static const char* getStackSymbol(void* pt) { return "?"; }
#endif

size_t Buffer::size() const {
	size_t c = 0;
	for(auto& it : chunks)
		c += it.size();
	return c;
}

bool Buffer::empty() {
	for(auto& it : chunks)
		if(it.size() > 0)
			return false;
	return true;
}

size_t Buffer::pop(uint8_t* target, size_t target_size) {
	size_t c = 0;
	while(!chunks.empty()) {
		Chunk& chunk = chunks.front();
		int s = chunk.end - chunk.start;
		assert(s > 0);
		if((size_t)s > target_size) s = (int)target_size;
		memcpy(target, chunk.data + chunk.start, s);
		chunk.start += s;
		target += s;
		target_size -= s;
		c += s;
		if(chunk.start < chunk.end) {
			assert(target_size == 0);
			break;
		}
		chunks.pop_front();
	}
	return c;
}

void Buffer::push(const uint8_t* data, size_t size) {
	while(size > 0) {
		if(chunks.empty() || !chunks.back().freeDataAvailable())
			chunks.push_back(Chunk());
		Chunk& chunk = chunks.back();
		size_t s = std::min(size, (size_t)chunk.freeDataAvailable());
		memcpy(chunk.data + chunk.end, data, s);
		data += s;
		size -= s;
		chunk.end += s;
	}
}

int PyDict_SetItemString_retain(PyObject* dict, const char* key, PyObject* value) {
	int ret = PyDict_SetItemString(dict, key, value);
	Py_DECREF(value);
	return ret;
}

PyMutex::PyMutex() {
	l = PyThread_allocate_lock();
}

PyMutex::~PyMutex() {
	PyThread_free_lock(l);
}

void PyMutex::lock() {
	PyThread_acquire_lock(l, WAIT_LOCK);
}

bool PyMutex::lock_nowait() {
	return PyThread_acquire_lock(l, NOWAIT_LOCK);
}

void PyMutex::unlock() {
	PyThread_release_lock(l);
}

PyScopedLock::PyScopedLock(PyMutex& m) : mutex(m) {
	printf("%p locks %p from %s\n", (void*)PyThread_get_thread_ident(), &mutex, getStackSymbol(getStackPtr(2)));
	mutex.lock();
}

PyScopedLock::~PyScopedLock() {
	printf("%p unlocks %p from %s\n", (void*)PyThread_get_thread_ident(), &mutex, getStackSymbol(getStackPtr(2)));
	mutex.unlock();
}

PyScopedUnlock::PyScopedUnlock(PyMutex& m) : mutex(m) {
	mutex.unlock();
}

PyScopedUnlock::~PyScopedUnlock() {
	mutex.lock();
}

PyThread::PyThread() {
	running = false;
	stopSignal = false;
	ident = -1;
}

PyThread::~PyThread() {
	stop();
}

static void PyThread_thread(void* p) {
	PyThread* t = (PyThread*)p;
	t->func(t->lock, t->stopSignal);
	{
		PyScopedLock l(t->lock);
		t->running = false;
	}
}

bool PyThread::start() {
	PyScopedLock l(lock);
	if(running) return true;
	stopSignal = false;
	running = true;
	ident = PyThread_start_new_thread(PyThread_thread, this);
	if(ident == -1) {
		running = false;
		return false;
	}
	return true;
}

void PyThread::wait() {
	while(true) {
		{
			PyScopedLock l(lock);
			if(!running) return;
		}
		usleep(1000);
	}
}

void PyThread::stop() {
	{
		PyScopedLock l(lock);
		if(!running) return;
		stopSignal = true;
	}
	wait();
}

ProtectionData::ProtectionData() {
	lockThreadIdent = 0;
	lockCounter = 0;
	isValid = true;
}

ProtectionData::~ProtectionData() {
	assert(lockCounter == 0);
	assert(lockThreadIdent == 0);
}

void ProtectionData::lock() {
	long myThreadIdent = PyThread_get_thread_ident();
	while(true) {
		PyScopedLock lock(mutex);
		if(lockCounter > 0 && lockThreadIdent != myThreadIdent) {
			usleep(10);
			continue;
		}
		lockCounter++;
		lockThreadIdent = myThreadIdent;
		return;
	}
}

void ProtectionData::unlock() {
	PyScopedLock lock(mutex);
	assert(lockCounter > 0);
	assert(lockThreadIdent == PyThread_get_thread_ident());
	lockCounter--;
}

ProtectionScope::ProtectionScope(const Protection& p) : prot(p.prot) {
	if(prot.get()) prot->lock();
}

ProtectionScope::~ProtectionScope() {
	if(prot.get()) prot->unlock();
}

void ProtectionScope::setInvalid() {
	if(prot.get()) prot->isValid = false;
}

bool ProtectionScope::isValid() {
	if(prot.get()) return prot->isValid;
	return false;
}
<commit_msg>disable debugging<commit_after>// ffmpeg_utils.cpp
// part of MusicPlayer, https://github.com/albertz/music-player
// Copyright (c) 2012, Albert Zeyer, www.az2000.de
// All rights reserved.
// This code is under the 2-clause BSD license, see License.txt in the root directory of this project.

#include "ffmpeg.h"
#include <unistd.h>

#if defined(__APPLE__)
#include <execinfo.h>

__attribute__((noinline))
void* getStackPtr(int n) {
	n += 1; // getStackPtr() itself
	void* stack[20];
	static const int Size = sizeof(stack)/sizeof(stack[0]);
	if(n >= Size) return NULL;
	int c = backtrace(stack, Size);
	if(n >= c) return NULL;
	return stack[n];
}

const char* getStackSymbol(void* pt) {
	char** s_ = backtrace_symbols(&pt, 1);
	if(!s_) return "?";
	char* s = *s_;
	free(s_);
	if(!s) return "?";
	// s = "<number>     <filename>    <interesting-part>"
	// we only want the interesting part.
	while(*s && *s != ' ') ++s; // advance the number
	while(*s && *s == ' ') ++s; // advance the spaces
	while(*s && *s != ' ') ++s; // advance the filename
	while(*s && *s == ' ') ++s; // advance the spaces
	return s;
}

#else
void* getStackPtr(int n) { return NULL; }
const char* getStackSymbol(void* pt) { return "?"; }
#endif

size_t Buffer::size() const {
	size_t c = 0;
	for(auto& it : chunks)
		c += it.size();
	return c;
}

bool Buffer::empty() {
	for(auto& it : chunks)
		if(it.size() > 0)
			return false;
	return true;
}

size_t Buffer::pop(uint8_t* target, size_t target_size) {
	size_t c = 0;
	while(!chunks.empty()) {
		Chunk& chunk = chunks.front();
		int s = chunk.end - chunk.start;
		assert(s > 0);
		if((size_t)s > target_size) s = (int)target_size;
		memcpy(target, chunk.data + chunk.start, s);
		chunk.start += s;
		target += s;
		target_size -= s;
		c += s;
		if(chunk.start < chunk.end) {
			assert(target_size == 0);
			break;
		}
		chunks.pop_front();
	}
	return c;
}

void Buffer::push(const uint8_t* data, size_t size) {
	while(size > 0) {
		if(chunks.empty() || !chunks.back().freeDataAvailable())
			chunks.push_back(Chunk());
		Chunk& chunk = chunks.back();
		size_t s = std::min(size, (size_t)chunk.freeDataAvailable());
		memcpy(chunk.data + chunk.end, data, s);
		data += s;
		size -= s;
		chunk.end += s;
	}
}

int PyDict_SetItemString_retain(PyObject* dict, const char* key, PyObject* value) {
	int ret = PyDict_SetItemString(dict, key, value);
	Py_DECREF(value);
	return ret;
}

PyMutex::PyMutex() {
	l = PyThread_allocate_lock();
}

PyMutex::~PyMutex() {
	PyThread_free_lock(l);
}

void PyMutex::lock() {
	PyThread_acquire_lock(l, WAIT_LOCK);
}

bool PyMutex::lock_nowait() {
	return PyThread_acquire_lock(l, NOWAIT_LOCK);
}

void PyMutex::unlock() {
	PyThread_release_lock(l);
}

PyScopedLock::PyScopedLock(PyMutex& m) : mutex(m) {
#ifdef MUTEX_DEBUG
	printf("%p locks %p from %s\n", (void*)PyThread_get_thread_ident(), &mutex, getStackSymbol(getStackPtr(2)));
#endif
	mutex.lock();
}

PyScopedLock::~PyScopedLock() {
#ifdef MUTEX_DEBUG
	printf("%p unlocks %p from %s\n", (void*)PyThread_get_thread_ident(), &mutex, getStackSymbol(getStackPtr(2)));
#endif
	mutex.unlock();
}

PyScopedUnlock::PyScopedUnlock(PyMutex& m) : mutex(m) {
	mutex.unlock();
}

PyScopedUnlock::~PyScopedUnlock() {
	mutex.lock();
}

PyThread::PyThread() {
	running = false;
	stopSignal = false;
	ident = -1;
}

PyThread::~PyThread() {
	stop();
}

static void PyThread_thread(void* p) {
	PyThread* t = (PyThread*)p;
	t->func(t->lock, t->stopSignal);
	{
		PyScopedLock l(t->lock);
		t->running = false;
	}
}

bool PyThread::start() {
	PyScopedLock l(lock);
	if(running) return true;
	stopSignal = false;
	running = true;
	ident = PyThread_start_new_thread(PyThread_thread, this);
	if(ident == -1) {
		running = false;
		return false;
	}
	return true;
}

void PyThread::wait() {
	while(true) {
		{
			PyScopedLock l(lock);
			if(!running) return;
		}
		usleep(1000);
	}
}

void PyThread::stop() {
	{
		PyScopedLock l(lock);
		if(!running) return;
		stopSignal = true;
	}
	wait();
}

ProtectionData::ProtectionData() {
	lockThreadIdent = 0;
	lockCounter = 0;
	isValid = true;
}

ProtectionData::~ProtectionData() {
	assert(lockCounter == 0);
	assert(lockThreadIdent == 0);
}

void ProtectionData::lock() {
	long myThreadIdent = PyThread_get_thread_ident();
	while(true) {
		PyScopedLock lock(mutex);
		if(lockCounter > 0 && lockThreadIdent != myThreadIdent) {
			usleep(10);
			continue;
		}
		lockCounter++;
		lockThreadIdent = myThreadIdent;
		return;
	}
}

void ProtectionData::unlock() {
	PyScopedLock lock(mutex);
	assert(lockCounter > 0);
	assert(lockThreadIdent == PyThread_get_thread_ident());
	lockCounter--;
}

ProtectionScope::ProtectionScope(const Protection& p) : prot(p.prot) {
	if(prot.get()) prot->lock();
}

ProtectionScope::~ProtectionScope() {
	if(prot.get()) prot->unlock();
}

void ProtectionScope::setInvalid() {
	if(prot.get()) prot->isValid = false;
}

bool ProtectionScope::isValid() {
	if(prot.get()) return prot->isValid;
	return false;
}
<|endoftext|>