<commit_before>/*
 * Copyright (c) 2004-2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __CPU_O3_SPARC_DYN_INST_HH__
#define __CPU_O3_SPARC_DYN_INST_HH__

#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/types.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/sparc/cpu.hh"
#include "cpu/o3/sparc/impl.hh"

class Packet;

/**
 * Mostly implementation & ISA specific SparcDynInst. As with most
 * other classes in the new CPU model, it is templated on the Impl to
 * allow for passing in of all types, such as the CPU type and the ISA
 * type. The SparcDynInst serves as the primary interface to the CPU
 * for instructions that are executing.
 */
template <class Impl>
class SparcDynInst : public BaseDynInst<Impl>
{
  public:
    /** Typedef for the CPU. */
    typedef typename Impl::O3CPU O3CPU;

  public:
    /** BaseDynInst constructor given a binary instruction. */
    SparcDynInst(TheISA::ExtMachInst inst, Addr PC,
            Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu);

    /** BaseDynInst constructor given a static inst pointer. */
    SparcDynInst(StaticInstPtr &_staticInst);

    /** Executes the instruction.*/
    Fault execute();

    /** Initiates the access.  Only valid for memory operations. */
    Fault initiateAcc();

    /** Completes the access.  Only valid for memory operations. */
    Fault completeAcc(PacketPtr pkt);

  private:
    /** Initializes variables. */
    void initVars();

  public:
    /** Reads a miscellaneous register. */
    TheISA::MiscReg readMiscReg(int misc_reg)
    {
        return this->cpu->readMiscReg(misc_reg, this->threadNumber);
    }

    /** Reads a misc. register, including any side-effects the read
     * might have as defined by the architecture.
     */
    TheISA::MiscReg readMiscRegWithEffect(int misc_reg)
    {
        return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber);
    }

    /** Sets a misc. register. */
    void setMiscReg(int misc_reg, const TheISA::MiscReg &val)
    {
        this->instResult.integer = val;
        return this->cpu->setMiscReg(misc_reg, val, this->threadNumber);
    }

    /** Sets a misc. register, including any side-effects the write
     * might have as defined by the architecture.
     */
    void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val)
    {
        return this->cpu->setMiscRegWithEffect(misc_reg, val,
                                               this->threadNumber);
    }

#if FULL_SYSTEM
    /** Calls hardware return from error interrupt. */
    Fault hwrei();
    /** Traps to handle specified fault. */
    void trap(Fault fault);
    bool simPalCheck(int palFunc);
#else
    /** Calls a syscall. */
    void syscall(int64_t callnum);
#endif

  public:

    // The register accessor methods provide the index of the
    // instruction's operand (e.g., 0 or 1), not the architectural
    // register index, to simplify the implementation of register
    // renaming.  We find the architectural register index by indexing
    // into the instruction's own operand index table.  Note that a
    // raw pointer to the StaticInst is provided instead of a
    // ref-counted StaticInstPtr to redice overhead.  This is fine as
    // long as these methods don't copy the pointer into any long-term
    // storage (which is pretty hard to imagine they would have reason
    // to do).

    uint64_t readIntReg(const StaticInst *si, int idx)
    {
        uint64_t val = this->cpu->readIntReg(this->_srcRegIdx[idx]);
        DPRINTF(Sparc, "Reading int reg %d (%d, %d) as %x\n", (int)this->_flatSrcRegIdx[idx], (int)this->_srcRegIdx[idx], idx, val);
        return this->cpu->readIntReg(this->_srcRegIdx[idx]);
    }

    TheISA::FloatReg readFloatReg(const StaticInst *si, int idx, int width)
    {
        return this->cpu->readFloatReg(this->_flatSrcRegIdx[idx], width);
    }

    TheISA::FloatReg readFloatReg(const StaticInst *si, int idx)
    {
        return this->cpu->readFloatReg(this->_flatSrcRegIdx[idx]);
    }

    TheISA::FloatRegBits readFloatRegBits(const StaticInst *si,
            int idx, int width)
    {
        return this->cpu->readFloatRegBits(this->_flatSrcRegIdx[idx], width);
    }

    TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
    {
        return this->cpu->readFloatRegBits(this->_flatSrcRegIdx[idx]);
    }

    /** @todo: Make results into arrays so they can handle multiple dest
     *  registers.
     */
    void setIntReg(const StaticInst *si, int idx, uint64_t val)
    {
        DPRINTF(Sparc, "Setting int reg %d (%d, %d) to %x\n", (int)this->_flatDestRegIdx[idx], (int)this->_destRegIdx[idx], idx, val);
        this->cpu->setIntReg(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setIntReg(si, idx, val);
    }

    void setFloatReg(const StaticInst *si, int idx,
            TheISA::FloatReg val, int width)
    {
        this->cpu->setFloatReg(this->_flatDestRegIdx[idx], val, width);
        BaseDynInst<Impl>::setFloatReg(si, idx, val, width);
    }

    void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val)
    {
        this->cpu->setFloatReg(this->_flatDestRegIdx[idx], val);
        BaseDynInst<Impl>::setFloatReg(si, idx, val);
    }

    void setFloatRegBits(const StaticInst *si, int idx,
            TheISA::FloatRegBits val, int width)
    {
        this->cpu->setFloatRegBits(this->_flatDestRegIdx[idx], val, width);
        BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
    }

    void setFloatRegBits(const StaticInst *si,
            int idx, TheISA::FloatRegBits val)
    {
        this->cpu->setFloatRegBits(this->_flatDestRegIdx[idx], val);
        BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
    }

  public:
    /** Calculates EA part of a memory instruction. Currently unused,
     * though it may be useful in the future if we want to split
     * memory operations into EA calculation and memory access parts.
     */
    Fault calcEA()
    {
        return this->staticInst->eaCompInst()->execute(this, this->traceData);
    }

    /** Does the memory access part of a memory instruction. Currently unused,
     * though it may be useful in the future if we want to split
     * memory operations into EA calculation and memory access parts.
     */
    Fault memAccess()
    {
        return this->staticInst->memAccInst()->execute(this, this->traceData);
    }
};

#endif // __CPU_O3_SPARC_DYN_INST_HH__

<commit_msg>Use the renamed register index, rather than the flattened one.<commit_after>/*
 * Copyright (c) 2004-2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __CPU_O3_SPARC_DYN_INST_HH__
#define __CPU_O3_SPARC_DYN_INST_HH__

#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/types.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/sparc/cpu.hh"
#include "cpu/o3/sparc/impl.hh"

class Packet;

/**
 * Mostly implementation & ISA specific SparcDynInst. As with most
 * other classes in the new CPU model, it is templated on the Impl to
 * allow for passing in of all types, such as the CPU type and the ISA
 * type. The SparcDynInst serves as the primary interface to the CPU
 * for instructions that are executing.
 */
template <class Impl>
class SparcDynInst : public BaseDynInst<Impl>
{
  public:
    /** Typedef for the CPU. */
    typedef typename Impl::O3CPU O3CPU;

  public:
    /** BaseDynInst constructor given a binary instruction. */
    SparcDynInst(TheISA::ExtMachInst inst, Addr PC,
            Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu);

    /** BaseDynInst constructor given a static inst pointer. */
    SparcDynInst(StaticInstPtr &_staticInst);

    /** Executes the instruction.*/
    Fault execute();

    /** Initiates the access.  Only valid for memory operations. */
    Fault initiateAcc();

    /** Completes the access.  Only valid for memory operations. */
    Fault completeAcc(PacketPtr pkt);

  private:
    /** Initializes variables. */
    void initVars();

  public:
    /** Reads a miscellaneous register. */
    TheISA::MiscReg readMiscReg(int misc_reg)
    {
        return this->cpu->readMiscReg(misc_reg, this->threadNumber);
    }

    /** Reads a misc. register, including any side-effects the read
     * might have as defined by the architecture.
     */
    TheISA::MiscReg readMiscRegWithEffect(int misc_reg)
    {
        return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber);
    }

    /** Sets a misc. register. */
    void setMiscReg(int misc_reg, const TheISA::MiscReg &val)
    {
        this->instResult.integer = val;
        return this->cpu->setMiscReg(misc_reg, val, this->threadNumber);
    }

    /** Sets a misc. register, including any side-effects the write
     * might have as defined by the architecture.
     */
    void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val)
    {
        return this->cpu->setMiscRegWithEffect(misc_reg, val,
                                               this->threadNumber);
    }

#if FULL_SYSTEM
    /** Calls hardware return from error interrupt. */
    Fault hwrei();
    /** Traps to handle specified fault. */
    void trap(Fault fault);
    bool simPalCheck(int palFunc);
#else
    /** Calls a syscall. */
    void syscall(int64_t callnum);
#endif

  public:

    // The register accessor methods provide the index of the
    // instruction's operand (e.g., 0 or 1), not the architectural
    // register index, to simplify the implementation of register
    // renaming.  We find the architectural register index by indexing
    // into the instruction's own operand index table.  Note that a
    // raw pointer to the StaticInst is provided instead of a
    // ref-counted StaticInstPtr to redice overhead.  This is fine as
    // long as these methods don't copy the pointer into any long-term
    // storage (which is pretty hard to imagine they would have reason
    // to do).

    uint64_t readIntReg(const StaticInst *si, int idx)
    {
        uint64_t val = this->cpu->readIntReg(this->_srcRegIdx[idx]);
        DPRINTF(Sparc, "Reading int reg %d (%d, %d) as %x\n", (int)this->_flatSrcRegIdx[idx], (int)this->_srcRegIdx[idx], idx, val);
        return this->cpu->readIntReg(this->_srcRegIdx[idx]);
    }

    TheISA::FloatReg readFloatReg(const StaticInst *si, int idx, int width)
    {
        return this->cpu->readFloatReg(this->_srcRegIdx[idx], width);
    }

    TheISA::FloatReg readFloatReg(const StaticInst *si, int idx)
    {
        return this->cpu->readFloatReg(this->_srcRegIdx[idx]);
    }

    TheISA::FloatRegBits readFloatRegBits(const StaticInst *si,
            int idx, int width)
    {
        return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width);
    }

    TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
    {
        return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]);
    }

    /** @todo: Make results into arrays so they can handle multiple dest
     *  registers.
     */
    void setIntReg(const StaticInst *si, int idx, uint64_t val)
    {
        DPRINTF(Sparc, "Setting int reg %d (%d, %d) to %x\n", (int)this->_flatDestRegIdx[idx], (int)this->_destRegIdx[idx], idx, val);
        this->cpu->setIntReg(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setIntReg(si, idx, val);
    }

    void setFloatReg(const StaticInst *si, int idx,
            TheISA::FloatReg val, int width)
    {
        this->cpu->setFloatReg(this->_destRegIdx[idx], val, width);
        BaseDynInst<Impl>::setFloatReg(si, idx, val, width);
    }

    void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val)
    {
        this->cpu->setFloatReg(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setFloatReg(si, idx, val);
    }

    void setFloatRegBits(const StaticInst *si, int idx,
            TheISA::FloatRegBits val, int width)
    {
        this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width);
        BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
    }

    void setFloatRegBits(const StaticInst *si,
            int idx, TheISA::FloatRegBits val)
    {
        this->cpu->setFloatRegBits(this->_destRegIdx[idx], val);
        BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
    }

  public:
    /** Calculates EA part of a memory instruction. Currently unused,
     * though it may be useful in the future if we want to split
     * memory operations into EA calculation and memory access parts.
     */
    Fault calcEA()
    {
        return this->staticInst->eaCompInst()->execute(this, this->traceData);
    }

    /** Does the memory access part of a memory instruction. Currently unused,
     * though it may be useful in the future if we want to split
     * memory operations into EA calculation and memory access parts.
     */
    Fault memAccess()
    {
        return this->staticInst->memAccInst()->execute(this, this->traceData);
    }
};

#endif // __CPU_O3_SPARC_DYN_INST_HH__

<|endoftext|>


<commit_before>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.51
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "Simulation.h"
#include "Setup.h"          //For setup object

#include "EnergyTypes.h"
#include "PSFOutput.h"
#include <iostream>
#include <iomanip>

Simulation::Simulation(char const*const configFileName, MultiSim const*const& multisim):ms(multisim)
{
  startStep = 0;
  //NOTE:
  //IMPORTANT! Keep this order...
  //as system depends on staticValues, and cpu sometimes depends on both.
  set.Init(configFileName, multisim);
  totalSteps = set.config.sys.step.total;
  staticValues = new StaticVals(set);
  system = new System(*staticValues);
  staticValues->Init(set, *system);
  system->Init(set, startStep);
  //recal Init for static value for initializing ewald since ewald is
  //initialized in system
  staticValues->InitOver(set, *system);
  cpu = new CPUSide(*system, *staticValues);
  cpu->Init(set.pdb, set.config.out, set.config.sys.step.equil,
            totalSteps, startStep);

  //Dump combined PSF
  PSFOutput psfOut(staticValues->mol, *system, set.mol.kindMap,
                   set.pdb.atoms.resKindNames);
  psfOut.PrintPSF(set.config.out.state.files.psf.name);
  std::cout << "Printed combined psf to file "
            << set.config.out.state.files.psf.name << '\n';

  if(totalSteps == 0) {
    frameSteps = set.pdb.GetFrameSteps(set.config.in.files.pdb.name);
  }
#if GOMC_LIB_MPI
  PTUtils = set.config.sys.step.parallelTemp ? new ParallelTemperingUtilities(ms, *system, *staticValues, set.config.sys.step.parallelTempFreq): NULL;
  exchangeResults.resize(ms->worldSize, false);
#endif
}

Simulation::~Simulation()
{
  delete cpu;
  delete system;
  delete staticValues;
}

void Simulation::RunSimulation(void)
{
  double startEnergy = system->potential.totalEnergy.total;
  if(totalSteps == 0) {
    for(int i = 0; i < frameSteps.size(); i++) {
      if(i == 0) {
        cpu->Output(frameSteps[0] - 1);
        continue;
      }
      system->RecalculateTrajectory(set, i + 1);
      cpu->Output(frameSteps[i] - 1);
    }
  }
  for (ulong step = startStep; step < totalSteps; step++) {
    system->moveSettings.AdjustMoves(step);
    system->ChooseAndRunMove(step);
    cpu->Output(step);

    if((step + 1) == cpu->equilSteps) {
      double currEnergy = system->potential.totalEnergy.total;
      if(abs(currEnergy - startEnergy) > 1.0e+10) {
        printf("Info: Recalculating the total energies to insure the accuracy"
               " of the computed \n"
               "      running energies.\n\n");
        system->calcEwald->Init();
        system->potential = system->calcEnergy.SystemTotal();
      }
    }
  #if GOMC_LIB_MPI

    if( staticValues->simEventFreq.parallelTemp && step % staticValues->simEventFreq.parallelTempFreq == 0){

      exchangeResults = PTUtils->evaluateExchangeCriteria(step);

      if (exchangeResults[ms->worldRank] == true){
        //PTUtils->exchangePositions(system->coordinates, ms, ms->worldRank-1, true);
        //PTUtils->exchangeCOMs(system->com, ms, ms->worldRank-1, true);

        system->cellList.GridAll(system->boxDimRef, system->coordinates, system->molLookup);
        for (uint bPick = 0; bPick < BOX_TOTAL; bPick++){
          system->calcEwald->BoxReciprocalSetup(bPick, system->coordinates);
          system->calcEwald->UpdateRecip(bPick);
        }
        system->potential = system->calcEnergy.SystemTotal();

      } else if(ms->worldRank+1 != ms->worldSize && exchangeResults[ms->worldRank+1] == true) {
        //PTUtils->exchangePositions(system->coordinates, ms, ms->worldRank+1, false);
        //PTUtils->exchangeCOMs(system->com, ms, ms->worldRank+1, false);

        system->cellList.GridAll(system->boxDimRef, system->coordinates, system->molLookup);

        for (uint bPick = 0; bPick < BOX_TOTAL; bPick++){
          system->calcEwald->BoxReciprocalSetup(bPick, system->coordinates);
          system->calcEwald->UpdateRecip(bPick);
        }
        system->potential = system->calcEnergy.SystemTotal();

      }

    }
  #endif

#ifndef NDEBUG
    if((step + 1) % 1000 == 0)
      RunningCheck(step);
#endif
  }
  system->PrintAcceptance();
  system->PrintTime();
}

#ifndef NDEBUG
void Simulation::RunningCheck(const uint step)
{
  system->calcEwald->UpdateVectorsAndRecipTerms();
  SystemPotential pot = system->calcEnergy.SystemTotal();

  std::cout
      << "================================================================="
      << std::endl << "-------------------------" << std::endl
      << " STEP: " << step + 1
      << std::endl << "-------------------------" << std::endl
      << "Energy       INTRA B |     INTRA NB |        INTER |           TC |         REAL |         SELF |   CORRECTION |        RECIP"
      << std::endl
      << "System: "
      << std::setw(12) << system->potential.totalEnergy.intraBond << " | "
      << std::setw(12) << system->potential.totalEnergy.intraNonbond << " | "
      << std::setw(12) << system->potential.totalEnergy.inter << " | "
      << std::setw(12) << system->potential.totalEnergy.tc << " | "
      << std::setw(12) << system->potential.totalEnergy.real << " | "
      << std::setw(12) << system->potential.totalEnergy.self << " | "
      << std::setw(12) << system->potential.totalEnergy.correction << " | "
      << std::setw(12) << system->potential.totalEnergy.recip << std::endl
      << "Recalc: "
      << std::setw(12) << pot.totalEnergy.intraBond << " | "
      << std::setw(12) << pot.totalEnergy.intraNonbond << " | "
      << std::setw(12) << pot.totalEnergy.inter << " | "
      << std::setw(12) << pot.totalEnergy.tc << " | "
      << std::setw(12) << pot.totalEnergy.real << " | "
      << std::setw(12) << pot.totalEnergy.self << " | "
      << std::setw(12) << pot.totalEnergy.correction << " | "
      << std::setw(12) << pot.totalEnergy.recip << std::endl
      << "================================================================"
      << std::endl << std::endl;

}

#endif
<commit_msg>added back swapping<commit_after>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.51
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "Simulation.h"
#include "Setup.h"          //For setup object

#include "EnergyTypes.h"
#include "PSFOutput.h"
#include <iostream>
#include <iomanip>

Simulation::Simulation(char const*const configFileName, MultiSim const*const& multisim):ms(multisim)
{
  startStep = 0;
  //NOTE:
  //IMPORTANT! Keep this order...
  //as system depends on staticValues, and cpu sometimes depends on both.
  set.Init(configFileName, multisim);
  totalSteps = set.config.sys.step.total;
  staticValues = new StaticVals(set);
  system = new System(*staticValues);
  staticValues->Init(set, *system);
  system->Init(set, startStep);
  //recal Init for static value for initializing ewald since ewald is
  //initialized in system
  staticValues->InitOver(set, *system);
  cpu = new CPUSide(*system, *staticValues);
  cpu->Init(set.pdb, set.config.out, set.config.sys.step.equil,
            totalSteps, startStep);

  //Dump combined PSF
  PSFOutput psfOut(staticValues->mol, *system, set.mol.kindMap,
                   set.pdb.atoms.resKindNames);
  psfOut.PrintPSF(set.config.out.state.files.psf.name);
  std::cout << "Printed combined psf to file "
            << set.config.out.state.files.psf.name << '\n';

  if(totalSteps == 0) {
    frameSteps = set.pdb.GetFrameSteps(set.config.in.files.pdb.name);
  }
#if GOMC_LIB_MPI
  PTUtils = set.config.sys.step.parallelTemp ? new ParallelTemperingUtilities(ms, *system, *staticValues, set.config.sys.step.parallelTempFreq): NULL;
  exchangeResults.resize(ms->worldSize, false);
#endif
}

Simulation::~Simulation()
{
  delete cpu;
  delete system;
  delete staticValues;
}

void Simulation::RunSimulation(void)
{
  double startEnergy = system->potential.totalEnergy.total;
  if(totalSteps == 0) {
    for(int i = 0; i < frameSteps.size(); i++) {
      if(i == 0) {
        cpu->Output(frameSteps[0] - 1);
        continue;
      }
      system->RecalculateTrajectory(set, i + 1);
      cpu->Output(frameSteps[i] - 1);
    }
  }
  for (ulong step = startStep; step < totalSteps; step++) {
    system->moveSettings.AdjustMoves(step);
    system->ChooseAndRunMove(step);
    cpu->Output(step);

    if((step + 1) == cpu->equilSteps) {
      double currEnergy = system->potential.totalEnergy.total;
      if(abs(currEnergy - startEnergy) > 1.0e+10) {
        printf("Info: Recalculating the total energies to insure the accuracy"
               " of the computed \n"
               "      running energies.\n\n");
        system->calcEwald->Init();
        system->potential = system->calcEnergy.SystemTotal();
      }
    }
  #if GOMC_LIB_MPI

    if( staticValues->simEventFreq.parallelTemp && step % staticValues->simEventFreq.parallelTempFreq == 0){

      exchangeResults = PTUtils->evaluateExchangeCriteria(step);

      if (exchangeResults[ms->worldRank] == true){
        PTUtils->exchangePositions(system->coordinates, ms, ms->worldRank-1, true);
        PTUtils->exchangeCOMs(system->com, ms, ms->worldRank-1, true);

        system->cellList.GridAll(system->boxDimRef, system->coordinates, system->molLookup);
        for (uint bPick = 0; bPick < BOX_TOTAL; bPick++){
          system->calcEwald->BoxReciprocalSetup(bPick, system->coordinates);
          system->calcEwald->UpdateRecip(bPick);
        }
        system->potential = system->calcEnergy.SystemTotal();

      } else if(ms->worldRank+1 != ms->worldSize && exchangeResults[ms->worldRank+1] == true) {
        PTUtils->exchangePositions(system->coordinates, ms, ms->worldRank+1, false);
        PTUtils->exchangeCOMs(system->com, ms, ms->worldRank+1, false);

        system->cellList.GridAll(system->boxDimRef, system->coordinates, system->molLookup);

        for (uint bPick = 0; bPick < BOX_TOTAL; bPick++){
          system->calcEwald->BoxReciprocalSetup(bPick, system->coordinates);
          system->calcEwald->UpdateRecip(bPick);
        }
        system->potential = system->calcEnergy.SystemTotal();

      }

    }
  #endif

#ifndef NDEBUG
    if((step + 1) % 1000 == 0)
      RunningCheck(step);
#endif
  }
  system->PrintAcceptance();
  system->PrintTime();
}

#ifndef NDEBUG
void Simulation::RunningCheck(const uint step)
{
  system->calcEwald->UpdateVectorsAndRecipTerms();
  SystemPotential pot = system->calcEnergy.SystemTotal();

  std::cout
      << "================================================================="
      << std::endl << "-------------------------" << std::endl
      << " STEP: " << step + 1
      << std::endl << "-------------------------" << std::endl
      << "Energy       INTRA B |     INTRA NB |        INTER |           TC |         REAL |         SELF |   CORRECTION |        RECIP"
      << std::endl
      << "System: "
      << std::setw(12) << system->potential.totalEnergy.intraBond << " | "
      << std::setw(12) << system->potential.totalEnergy.intraNonbond << " | "
      << std::setw(12) << system->potential.totalEnergy.inter << " | "
      << std::setw(12) << system->potential.totalEnergy.tc << " | "
      << std::setw(12) << system->potential.totalEnergy.real << " | "
      << std::setw(12) << system->potential.totalEnergy.self << " | "
      << std::setw(12) << system->potential.totalEnergy.correction << " | "
      << std::setw(12) << system->potential.totalEnergy.recip << std::endl
      << "Recalc: "
      << std::setw(12) << pot.totalEnergy.intraBond << " | "
      << std::setw(12) << pot.totalEnergy.intraNonbond << " | "
      << std::setw(12) << pot.totalEnergy.inter << " | "
      << std::setw(12) << pot.totalEnergy.tc << " | "
      << std::setw(12) << pot.totalEnergy.real << " | "
      << std::setw(12) << pot.totalEnergy.self << " | "
      << std::setw(12) << pot.totalEnergy.correction << " | "
      << std::setw(12) << pot.totalEnergy.recip << std::endl
      << "================================================================"
      << std::endl << std::endl;

}

#endif
<|endoftext|>


<commit_before>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.51
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "Simulation.h"
#include "Setup.h"          //For setup object

#include "EnergyTypes.h"
#include "PSFOutput.h"
#include <iostream>
#include <iomanip>

Simulation::Simulation(char const*const configFileName, MultiSim const*const& multisim):ms(multisim)
{
  startStep = 0;
  //NOTE:
  //IMPORTANT! Keep this order...
  //as system depends on staticValues, and cpu sometimes depends on both.
  set.Init(configFileName, multisim);
  totalSteps = set.config.sys.step.total;
  staticValues = new StaticVals(set);
  system = new System(*staticValues);
  staticValues->Init(set, *system);
  system->Init(set, startStep);
  //recal Init for static value for initializing ewald since ewald is
  //initialized in system
  staticValues->InitOver(set, *system);
  cpu = new CPUSide(*system, *staticValues);
  cpu->Init(set.pdb, set.config.out, set.config.sys.step.equil,
            totalSteps, startStep);

  //Dump combined PSF
  PSFOutput psfOut(staticValues->mol, *system, set.mol.kindMap,
                   set.pdb.atoms.resKindNames);
  psfOut.PrintPSF(set.config.out.state.files.psf.name);
  std::cout << "Printed combined psf to file "
            << set.config.out.state.files.psf.name << '\n';

  if(totalSteps == 0) {
    frameSteps = set.pdb.GetFrameSteps(set.config.in.files.pdb.name);
  }
#if GOMC_LIB_MPI
  PTUtils = set.config.sys.step.parallelTemp ? new ParallelTemperingUtilities(ms, *system, *staticValues, set.config.sys.step.parallelTempFreq): NULL;
  exchangeResults.resize(ms->worldSize, false);
#endif
}

Simulation::~Simulation()
{
  delete cpu;
  delete system;
  delete staticValues;
}

void Simulation::RunSimulation(void)
{
  double startEnergy = system->potential.totalEnergy.total;
  if(totalSteps == 0) {
    for(int i = 0; i < frameSteps.size(); i++) {
      if(i == 0) {
        cpu->Output(frameSteps[0] - 1);
        continue;
      }
      system->RecalculateTrajectory(set, i + 1);
      cpu->Output(frameSteps[i] - 1);
    }
  }
  for (ulong step = startStep; step < totalSteps; step++) {
    system->moveSettings.AdjustMoves(step);
    system->ChooseAndRunMove(step);
    cpu->Output(step);

    if((step + 1) == cpu->equilSteps) {
      double currEnergy = system->potential.totalEnergy.total;
      if(abs(currEnergy - startEnergy) > 1.0e+10) {
        printf("Info: Recalculating the total energies to insure the accuracy"
               " of the computed \n"
               "      running energies.\n\n");
        system->calcEwald->Init();
        system->potential = system->calcEnergy.SystemTotal();
      }
    }
  #if GOMC_LIB_MPI
    //
    if( step > cpu->equilSteps && step % staticValues->simEventFreq.parallelTempFreq == 0){

   // if( staticValues->simEventFreq.parallelTemp && step > cpu->equilSteps && step % staticValues->simEventFreq.parallelTempFreq == 0){
      std::cout << "Entered outer if for pt " << step << std::endl;

      system->potential = system->calcEnergy.SystemTotal();

      exchangeResults = PTUtils->evaluateExchangeCriteria(step);
      if (staticValues->simEventFreq.parallelTemp){
        std::cout << "Entered inner if for pt " << step << std::endl;

        if (exchangeResults[ms->worldRank] == true){

          std::cout << "A swap took place on step " << step << std::endl;

          PTUtils->conductExchanges(system->coordinates, system->com, ms, exchangeResults);

        } else if(ms->worldRank+1 != ms->worldSize && exchangeResults[ms->worldRank+1] == true) {

          std::cout << "A swap took place on step " << step << std::endl;

          PTUtils->conductExchanges(system->coordinates, system->com, ms, exchangeResults);

        }
      }
      system->cellList.GridAll(system->boxDimRef, system->coordinates, system->molLookup);

      system->potential = system->calcEnergy.SystemTotal();

    }
  #endif

#ifndef NDEBUG
    if((step + 1) % 1000 == 0)
      RunningCheck(step);
#endif
  }
  system->PrintAcceptance();
  system->PrintTime();
}

#ifndef NDEBUG
void Simulation::RunningCheck(const uint step)
{
  system->calcEwald->UpdateVectorsAndRecipTerms();
  SystemPotential pot = system->calcEnergy.SystemTotal();

  std::cout
      << "================================================================="
      << std::endl << "-------------------------" << std::endl
      << " STEP: " << step + 1
      << std::endl << "-------------------------" << std::endl
      << "Energy       INTRA B |     INTRA NB |        INTER |           TC |         REAL |         SELF |   CORRECTION |        RECIP"
      << std::endl
      << "System: "
      << std::setw(12) << system->potential.totalEnergy.intraBond << " | "
      << std::setw(12) << system->potential.totalEnergy.intraNonbond << " | "
      << std::setw(12) << system->potential.totalEnergy.inter << " | "
      << std::setw(12) << system->potential.totalEnergy.tc << " | "
      << std::setw(12) << system->potential.totalEnergy.real << " | "
      << std::setw(12) << system->potential.totalEnergy.self << " | "
      << std::setw(12) << system->potential.totalEnergy.correction << " | "
      << std::setw(12) << system->potential.totalEnergy.recip << std::endl
      << "Recalc: "
      << std::setw(12) << pot.totalEnergy.intraBond << " | "
      << std::setw(12) << pot.totalEnergy.intraNonbond << " | "
      << std::setw(12) << pot.totalEnergy.inter << " | "
      << std::setw(12) << pot.totalEnergy.tc << " | "
      << std::setw(12) << pot.totalEnergy.real << " | "
      << std::setw(12) << pot.totalEnergy.self << " | "
      << std::setw(12) << pot.totalEnergy.correction << " | "
      << std::setw(12) << pot.totalEnergy.recip << std::endl
      << "================================================================"
      << std::endl << std::endl;

}

#endif
<commit_msg>moved evalCrit into inner if state<commit_after>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.51
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "Simulation.h"
#include "Setup.h"          //For setup object

#include "EnergyTypes.h"
#include "PSFOutput.h"
#include <iostream>
#include <iomanip>

Simulation::Simulation(char const*const configFileName, MultiSim const*const& multisim):ms(multisim)
{
  startStep = 0;
  //NOTE:
  //IMPORTANT! Keep this order...
  //as system depends on staticValues, and cpu sometimes depends on both.
  set.Init(configFileName, multisim);
  totalSteps = set.config.sys.step.total;
  staticValues = new StaticVals(set);
  system = new System(*staticValues);
  staticValues->Init(set, *system);
  system->Init(set, startStep);
  //recal Init for static value for initializing ewald since ewald is
  //initialized in system
  staticValues->InitOver(set, *system);
  cpu = new CPUSide(*system, *staticValues);
  cpu->Init(set.pdb, set.config.out, set.config.sys.step.equil,
            totalSteps, startStep);

  //Dump combined PSF
  PSFOutput psfOut(staticValues->mol, *system, set.mol.kindMap,
                   set.pdb.atoms.resKindNames);
  psfOut.PrintPSF(set.config.out.state.files.psf.name);
  std::cout << "Printed combined psf to file "
            << set.config.out.state.files.psf.name << '\n';

  if(totalSteps == 0) {
    frameSteps = set.pdb.GetFrameSteps(set.config.in.files.pdb.name);
  }
#if GOMC_LIB_MPI
  PTUtils = set.config.sys.step.parallelTemp ? new ParallelTemperingUtilities(ms, *system, *staticValues, set.config.sys.step.parallelTempFreq): NULL;
  exchangeResults.resize(ms->worldSize, false);
#endif
}

Simulation::~Simulation()
{
  delete cpu;
  delete system;
  delete staticValues;
}

void Simulation::RunSimulation(void)
{
  double startEnergy = system->potential.totalEnergy.total;
  if(totalSteps == 0) {
    for(int i = 0; i < frameSteps.size(); i++) {
      if(i == 0) {
        cpu->Output(frameSteps[0] - 1);
        continue;
      }
      system->RecalculateTrajectory(set, i + 1);
      cpu->Output(frameSteps[i] - 1);
    }
  }
  for (ulong step = startStep; step < totalSteps; step++) {
    system->moveSettings.AdjustMoves(step);
    system->ChooseAndRunMove(step);
    cpu->Output(step);

    if((step + 1) == cpu->equilSteps) {
      double currEnergy = system->potential.totalEnergy.total;
      if(abs(currEnergy - startEnergy) > 1.0e+10) {
        printf("Info: Recalculating the total energies to insure the accuracy"
               " of the computed \n"
               "      running energies.\n\n");
        system->calcEwald->Init();
        system->potential = system->calcEnergy.SystemTotal();
      }
    }
  #if GOMC_LIB_MPI
    //
    if( step > cpu->equilSteps && step % staticValues->simEventFreq.parallelTempFreq == 0){

   // if( staticValues->simEventFreq.parallelTemp && step > cpu->equilSteps && step % staticValues->simEventFreq.parallelTempFreq == 0){
      std::cout << "Entered outer if for pt " << step << std::endl;

      system->potential = system->calcEnergy.SystemTotal();

      if (staticValues->simEventFreq.parallelTemp){

        exchangeResults = PTUtils->evaluateExchangeCriteria(step);

        std::cout << "Entered inner if for pt " << step << std::endl;

        if (exchangeResults[ms->worldRank] == true){

          std::cout << "A swap took place on step " << step << std::endl;

          PTUtils->conductExchanges(system->coordinates, system->com, ms, exchangeResults);

        } else if(ms->worldRank+1 != ms->worldSize && exchangeResults[ms->worldRank+1] == true) {

          std::cout << "A swap took place on step " << step << std::endl;

          PTUtils->conductExchanges(system->coordinates, system->com, ms, exchangeResults);

        }
      }
      system->cellList.GridAll(system->boxDimRef, system->coordinates, system->molLookup);

      system->potential = system->calcEnergy.SystemTotal();

    }
  #endif

#ifndef NDEBUG
    if((step + 1) % 1000 == 0)
      RunningCheck(step);
#endif
  }
  system->PrintAcceptance();
  system->PrintTime();
}

#ifndef NDEBUG
void Simulation::RunningCheck(const uint step)
{
  system->calcEwald->UpdateVectorsAndRecipTerms();
  SystemPotential pot = system->calcEnergy.SystemTotal();

  std::cout
      << "================================================================="
      << std::endl << "-------------------------" << std::endl
      << " STEP: " << step + 1
      << std::endl << "-------------------------" << std::endl
      << "Energy       INTRA B |     INTRA NB |        INTER |           TC |         REAL |         SELF |   CORRECTION |        RECIP"
      << std::endl
      << "System: "
      << std::setw(12) << system->potential.totalEnergy.intraBond << " | "
      << std::setw(12) << system->potential.totalEnergy.intraNonbond << " | "
      << std::setw(12) << system->potential.totalEnergy.inter << " | "
      << std::setw(12) << system->potential.totalEnergy.tc << " | "
      << std::setw(12) << system->potential.totalEnergy.real << " | "
      << std::setw(12) << system->potential.totalEnergy.self << " | "
      << std::setw(12) << system->potential.totalEnergy.correction << " | "
      << std::setw(12) << system->potential.totalEnergy.recip << std::endl
      << "Recalc: "
      << std::setw(12) << pot.totalEnergy.intraBond << " | "
      << std::setw(12) << pot.totalEnergy.intraNonbond << " | "
      << std::setw(12) << pot.totalEnergy.inter << " | "
      << std::setw(12) << pot.totalEnergy.tc << " | "
      << std::setw(12) << pot.totalEnergy.real << " | "
      << std::setw(12) << pot.totalEnergy.self << " | "
      << std::setw(12) << pot.totalEnergy.correction << " | "
      << std::setw(12) << pot.totalEnergy.recip << std::endl
      << "================================================================"
      << std::endl << std::endl;

}

#endif
<|endoftext|>


<commit_before>#include "SysProcess.h"
#include <thread>
#include <string.h>
#include <memory>
#include <thread>

#include "maraton.h"

SysProcess::~SysProcess()
{

    if ( this->file_ != NULL )
    {
        delete this->file_;
        this->file_ = NULL;
    }

    if ( this->args_ != NULL )
    {
        delete this->args_;
        this->args_ = NULL;
    }

    if ( this->directory_ != NULL )
    {
        delete this->directory_;
        this->directory_ = NULL;
    }

}

void SysProcess::desctroy( SysProcess ** process )
{
    if ( process != nullptr && *process != nullptr )
    {
        delete *process;
        *process = nullptr;
    }
}

SysProcess * SysProcess::create( std::string file , std::string args , std::string directry , prceoss_callback_t on_finish )
{
    auto ret = new SysProcess( file , args , directry , on_finish );
    return ret;
}

SysProcess * SysProcess::create( std::string file , std::string args , prceoss_callback_t on_finish )
{
    auto ret = new SysProcess( file , args ,  on_finish );
    return ret;
}

SysProcess * SysProcess::create( std::string file , prceoss_callback_t on_finish )
{
    auto ret = new SysProcess( file , on_finish );
    return ret;
}

void SysProcess::uv_process_exit_callback( uv_process_t * process , int64_t exit_status , int term_signal )
{
    SysProcess* instance = static_cast< SysProcess* >( process->data );
    uv_close( ( uv_handle_t* )process , SysProcess::uv_process_close_callback );
    instance->callback( instance , exit_status );
}

void SysProcess::uv_process_close_callback( uv_handle_t * handle )
{
    SysProcess* instance = static_cast< SysProcess* >( handle->data );
    SAFE_DELETE( instance );
}

void SysProcess::uv_process_alloc_buffer( uv_handle_t * handle , size_t suggested_size , uv_buf_t * buf )
{
    *buf = uv_buf_init( ( char* )malloc( suggested_size ) , suggested_size );
}

void SysProcess::uv_prcoess_read_stream( uv_stream_t * stream , ssize_t nread , const uv_buf_t * buf )
{
    SysProcess* inst = static_cast< SysProcess* > ( stream->data );

    if ( nread < 0 )
    {
        if ( nread == UV_EOF )
        {
            // end of file
            uv_close( ( uv_handle_t * )&inst->pipe_ , NULL );
        }

        return;
    }

    inst->std_out_ = std::string( buf->base , nread );

    if ( buf->base )
        delete buf->base;
}

SysProcess::SysProcess()
{
    //uv_sem_init( &this->sem , 0 );
}

SysProcess::SysProcess( std::string  file, std::string args, std::string  directry, prceoss_callback_t on_finish )
    : SysProcess()
{
    std::string newArgs = " " +  args;

    this->file_ = new char[this->STR_LENGTH];
    this->args_ = new char[this->STR_LENGTH];
    this->directory_ = new char[this->STR_LENGTH];
    memset( this->file_, 0, this->STR_LENGTH );
    memset( this->args_, 0, this->STR_LENGTH );
    memset( this->directory_, 0, this->STR_LENGTH );

    memcpy( this->file_, file.c_str() , file.length() );
    memcpy( this->args_, newArgs.c_str(), newArgs.length() );
    memcpy( this->directory_, directry.c_str(), directry.length() );
    this->callback = on_finish;
}

SysProcess::SysProcess( std::string  file, std::string args, prceoss_callback_t on_finish )
    : SysProcess()
{
    std::string newArgs = " " + args;

    this->file_ = new char[this->STR_LENGTH];
    this->args_ = new char[this->STR_LENGTH];
    memset( this->file_, 0, this->STR_LENGTH );
    memset( this->args_, 0, this->STR_LENGTH );

    memcpy( this->file_, file.c_str(), file.length() );
    memcpy( this->args_, newArgs.c_str(), newArgs.length() );

    this->callback = on_finish;
}

SysProcess::SysProcess( std::string  file, prceoss_callback_t on_finish )
    : SysProcess()
{
    this->file_ = new char[this->STR_LENGTH];
    memset( this->file_, 0, this->STR_LENGTH );

    memcpy( this->file_, file.c_str(), file.length() );
    this->callback = on_finish;
}

void SysProcess::invoke()
{
    int r;
    char** args = nullptr;

    if ( args_ == nullptr )
    {
        args = new char*[1];
        args[0] = NULL;
    }
    else
    {
        args = new char*[128];
        for ( size_t i = 0; i < 128; i++ )
        {
            args[i] = new char[512];
            memset( args[i] , 0 , 512 );
            args[i][0] = ' ';
        }
        auto raw_args = this->args_;
        size_t len = strlen( this->args_ );

        int start_pos = 0;

#ifdef _WIN32
        int row = 0;
#else
        int row = 0;
#endif

        int col = 0;
        for ( int e = start_pos; e < len; e++ )
        {
            if ( raw_args[e] == ' ')
            {
                col = 0;
                row++;
                //std::string str( raw_args + f , ( e - f + 1 ) );
                //list.push_back( str );
                //f = e;
            }
            else
            {
                args[row][col] = raw_args[e];
                col++;
            }
        }

        args[row+1] = NULL;
    }
    auto loop = uv_default_loop();
    this->pipe_ = { 0 };

    r = uv_pipe_init( loop , &this->pipe_ , 0 );

    this->pipe_.data = this;

    this->options.exit_cb = SysProcess::uv_process_exit_callback;
    this->options.file = this->file_;
    this->options.args = args;
    this->options.cwd = this->directory_;
    this->child_req.data = this;

    this->options.stdio_count = 3;
    uv_stdio_container_t child_stdio[3];

    child_stdio[0].flags = UV_IGNORE;// ( uv_stdio_flags )( UV_CREATE_PIPE | UV_READABLE_PIPE );

    child_stdio[1].flags = ( uv_stdio_flags )( UV_CREATE_PIPE | UV_WRITABLE_PIPE );
    child_stdio[1].data.stream = ( uv_stream_t* )&this->pipe_;

    child_stdio[2].flags = UV_IGNORE;

    this->options.stdio = child_stdio;

    r  = uv_spawn( loop , &this->child_req , &this->options );
    if ( r != 0 )
    {
        printf( "uv_spawn: %s\r\n" , uv_strerror( r ) );
    }

    r = uv_read_start( ( uv_stream_t* )&this->pipe_ , SysProcess::uv_process_alloc_buffer , SysProcess::uv_prcoess_read_stream );
    if ( r != 0 )
    {
        printf( "uv_read_start: %s\r\n" , uv_strerror( r ) );
    }

    delete[] args;
}

size_t SysProcess::wait_for_exit()
{
   // uv_sem_wait( &this->sem );
    //uv_sem_destroy( &this->sem );
    return this->result;
}

void SysProcess::start()
{
    this->invoke();
}

void SysProcess::kill()
{

    uv_process_kill( &this->child_req , 1 );

#ifdef _WIN32

    //TerminateProcess( this->pi_.hProcess, -1 );

#else

    pclose( p_stream );

#endif // _WIN32
}

<commit_msg>try fix bugs<commit_after>#include "SysProcess.h"
#include <thread>
#include <string.h>
#include <memory>
#include <thread>

#include "maraton.h"

#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif

SysProcess::~SysProcess()
{

    if ( this->file_ != NULL )
    {
        delete this->file_;
        this->file_ = NULL;
    }

    if ( this->args_ != NULL )
    {
        delete this->args_;
        this->args_ = NULL;
    }

    if ( this->directory_ != NULL )
    {
        delete this->directory_;
        this->directory_ = NULL;
    }

}

void SysProcess::desctroy( SysProcess ** process )
{
    if ( process != nullptr && *process != nullptr )
    {
        delete *process;
        *process = nullptr;
    }
}

SysProcess * SysProcess::create( std::string file , std::string args , std::string directry , prceoss_callback_t on_finish )
{
    auto ret = new SysProcess( file , args , directry , on_finish );
    return ret;
}

SysProcess * SysProcess::create( std::string file , std::string args , prceoss_callback_t on_finish )
{
    auto ret = new SysProcess( file , args ,  on_finish );
    return ret;
}

SysProcess * SysProcess::create( std::string file , prceoss_callback_t on_finish )
{
    auto ret = new SysProcess( file , on_finish );
    return ret;
}

void SysProcess::uv_process_exit_callback( uv_process_t * process , int64_t exit_status , int term_signal )
{
    SysProcess* instance = static_cast< SysProcess* >( process->data );
    uv_close( ( uv_handle_t* )process , SysProcess::uv_process_close_callback );
    instance->callback( instance , exit_status );
}

void SysProcess::uv_process_close_callback( uv_handle_t * handle )
{
    SysProcess* instance = static_cast< SysProcess* >( handle->data );
    SAFE_DELETE( instance );
}

void SysProcess::uv_process_alloc_buffer( uv_handle_t * handle , size_t suggested_size , uv_buf_t * buf )
{
    *buf = uv_buf_init( ( char* )malloc( suggested_size ) , suggested_size );
}

void SysProcess::uv_prcoess_read_stream( uv_stream_t * stream , ssize_t nread , const uv_buf_t * buf )
{
    SysProcess* inst = static_cast< SysProcess* > ( stream->data );

    if ( nread < 0 )
    {
        if ( nread == UV_EOF )
        {
            // end of file
            uv_close( ( uv_handle_t * )&inst->pipe_ , NULL );
        }

        return;
    }

    inst->std_out_ = std::string( buf->base , nread );

    if ( buf->base )
        delete buf->base;
}

SysProcess::SysProcess()
{
    //uv_sem_init( &this->sem , 0 );
}

SysProcess::SysProcess( std::string  file, std::string args, std::string  directry, prceoss_callback_t on_finish )
    : SysProcess()
{
    std::string newArgs = " " +  args;

    this->file_ = new char[this->STR_LENGTH];
    this->args_ = new char[this->STR_LENGTH];
    this->directory_ = new char[this->STR_LENGTH];
    memset( this->file_, 0, this->STR_LENGTH );
    memset( this->args_, 0, this->STR_LENGTH );
    memset( this->directory_, 0, this->STR_LENGTH );

    memcpy( this->file_, file.c_str() , file.length() );
    memcpy( this->args_, newArgs.c_str(), newArgs.length() );
    memcpy( this->directory_, directry.c_str(), directry.length() );
    this->callback = on_finish;
}

SysProcess::SysProcess( std::string  file, std::string args, prceoss_callback_t on_finish )
    : SysProcess()
{
    std::string newArgs = " " + args;

    this->file_ = new char[this->STR_LENGTH];
    this->args_ = new char[this->STR_LENGTH];
    memset( this->file_, 0, this->STR_LENGTH );
    memset( this->args_, 0, this->STR_LENGTH );

    memcpy( this->file_, file.c_str(), file.length() );
    memcpy( this->args_, newArgs.c_str(), newArgs.length() );

    this->callback = on_finish;
}

SysProcess::SysProcess( std::string  file, prceoss_callback_t on_finish )
    : SysProcess()
{
    this->file_ = new char[this->STR_LENGTH];
    memset( this->file_, 0, this->STR_LENGTH );

    memcpy( this->file_, file.c_str(), file.length() );
    this->callback = on_finish;
}

void SysProcess::invoke()
{
    int r;
    char** args = nullptr;

    if ( args_ == nullptr )
    {
        char path[512] = { 0 };
        getcwd( path , 512 );
        args = new char*[2];
        args[0] = new char[strlen( path ) + 1];
        memset( args[0] , 0 , strlen( path ) + 1 );
        memcpy( args[0] , path , strlen( path ) );
        args[1] = NULL;
    }
    else
    {
        args = new char*[128];
        for ( size_t i = 0; i < 128; i++ )
        {
            args[i] = new char[512];
            memset( args[i] , 0 , 512 );
            args[i][0] = ' ';
        }
        auto raw_args = this->args_;
        size_t len = strlen( this->args_ );

        int start_pos = 0;

#ifdef _WIN32
        int row = 0;
#else
        int row = 0;
#endif

        int col = 0;
        for ( int e = start_pos; e < len; e++ )
        {
            if ( raw_args[e] == ' ')
            {
                col = 0;
                row++;
            }
            else
            {
                args[row][col] = raw_args[e];
                col++;
            }
        }

        args[row+1] = NULL;
    }
    auto loop = uv_default_loop();
    this->pipe_ = { 0 };

    r = uv_pipe_init( loop , &this->pipe_ , 0 );

    this->pipe_.data = this;

    this->options.exit_cb = SysProcess::uv_process_exit_callback;
    this->options.file = this->file_;
    this->options.args = args;
    this->options.cwd = this->directory_;
    this->child_req.data = this;

    this->options.stdio_count = 3;
    uv_stdio_container_t child_stdio[3];

    child_stdio[0].flags = UV_IGNORE;// ( uv_stdio_flags )( UV_CREATE_PIPE | UV_READABLE_PIPE );

    child_stdio[1].flags = ( uv_stdio_flags )( UV_CREATE_PIPE | UV_WRITABLE_PIPE );
    child_stdio[1].data.stream = ( uv_stream_t* )&this->pipe_;

    child_stdio[2].flags = UV_IGNORE;

    this->options.stdio = child_stdio;

    r  = uv_spawn( loop , &this->child_req , &this->options );
    if ( r != 0 )
    {
        printf( "uv_spawn: %s\r\n" , uv_strerror( r ) );
    }

    r = uv_read_start( ( uv_stream_t* )&this->pipe_ , SysProcess::uv_process_alloc_buffer , SysProcess::uv_prcoess_read_stream );
    if ( r != 0 )
    {
        printf( "uv_read_start: %s\r\n" , uv_strerror( r ) );
    }

    delete[] args;
}

size_t SysProcess::wait_for_exit()
{
   // uv_sem_wait( &this->sem );
    //uv_sem_destroy( &this->sem );
    return this->result;
}

void SysProcess::start()
{
    this->invoke();
}

void SysProcess::kill()
{

    uv_process_kill( &this->child_req , 1 );

#ifdef _WIN32

    //TerminateProcess( this->pi_.hProcess, -1 );

#else

    pclose( p_stream );

#endif // _WIN32
}

<|endoftext|>


<commit_before>#include "design/resource_attr.h"

#include "iroha/i_design.h"
#include "iroha/insn_operands.h"
#include "iroha/resource_class.h"

namespace iroha {

int ResourceAttr::NumMultiCycleInsn(const IState *st) {
  int n = 0;
  for (IInsn *insn : st->insns_) {
    if (IsMultiCycleInsn(insn)) {
      ++n;
    }
  }
  return n;
}

bool ResourceAttr::IsMultiCycleInsn(IInsn *insn) {
  IResource *res = insn->GetResource();
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsTaskCall(rc) ||
      resource::IsSharedMemory(rc) ||
      resource::IsSharedMemoryReader(rc) ||
      resource::IsSharedMemoryWriter(rc) ||
      resource::IsExtTaskDone(rc) ||
      resource::IsExtTaskCall(rc) ||
      resource::IsExtTaskWait(rc)) {
    return true;
  }
  if (resource::IsStudy(rc) ||
      resource::IsStudyReader(rc) ||
      resource::IsStudyWriter(rc)) {
    return true;
  }
  if (resource::IsAxiMasterPort(rc) ||
      resource::IsAxiSlavePort(rc)) {
    return true;
  }
  if (resource::IsFifo(rc) ||
      resource::IsFifoReader(rc)) {
    return true;
  }
  if (resource::IsFifoWriter(rc) &&
      insn->GetOperand() != operand::kNoWait) {
    return true;
  }
  if (resource::IsSharedRegReader(rc)) {
    if (insn->GetOperand() == operand::kWaitNotify ||
	insn->GetOperand() == operand::kGetMailbox) {
      return true;
    }
  }
  if (resource::IsSharedRegWriter(rc)) {
    if (insn->GetOperand() == operand::kPutMailbox) {
      return true;
    }
  }
  return false;
}

bool ResourceAttr::IsExtAccessResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsExtInput(rc) ||
      resource::IsExtOutput(rc) ||
      resource::IsAxiMasterPort(rc) ||
      resource::IsAxiSlavePort(rc) ||
      resource::IsExtTask(rc) ||
      resource::IsExtTaskDone(rc) ||
      resource::IsExtTaskCall(rc) ||
      resource::IsExtTaskWait(rc)) {
    return true;
  }
  return false;
}

bool ResourceAttr::IsExtWaitInsn(IInsn *insn) {
  return resource::IsAxiSlavePort(*(insn->GetResource()->GetClass()));
}

bool ResourceAttr::IsExtAccessInsn(IInsn *insn) {
  return IsExtAccessResource(insn->GetResource());
}

int ResourceAttr::NumExtAccessInsn(const IState *st) {
  int n = 0;
  for (IInsn *insn : st->insns_) {
    if (IsExtAccessInsn(insn)) {
      ++n;
    }
  }
  return n;
}

bool ResourceAttr::IsDuplicatableResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  const string &name = rc.GetName();
  // add, sub, mul, gt, gte and ext-combinational for now.
  if (name == resource::kEq) {
    return false;
  }
  if (resource::IsExtCombinational(rc)) {
    return true;
  }
  return resource::IsExclusiveBinOp(rc);
}

bool ResourceAttr::IsOrderedResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsArray(rc) || resource::IsMapped(rc)) {
    return true;
  }
  return false;
}

}  // namespace iroha
<commit_msg>Add attributes of sram_if resource.<commit_after>#include "design/resource_attr.h"

#include "iroha/i_design.h"
#include "iroha/insn_operands.h"
#include "iroha/resource_class.h"

namespace iroha {

int ResourceAttr::NumMultiCycleInsn(const IState *st) {
  int n = 0;
  for (IInsn *insn : st->insns_) {
    if (IsMultiCycleInsn(insn)) {
      ++n;
    }
  }
  return n;
}

bool ResourceAttr::IsMultiCycleInsn(IInsn *insn) {
  IResource *res = insn->GetResource();
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsTaskCall(rc) ||
      resource::IsSharedMemory(rc) ||
      resource::IsSharedMemoryReader(rc) ||
      resource::IsSharedMemoryWriter(rc) ||
      resource::IsExtTaskDone(rc) ||
      resource::IsExtTaskCall(rc) ||
      resource::IsExtTaskWait(rc)) {
    return true;
  }
  if (resource::IsStudy(rc) ||
      resource::IsStudyReader(rc) ||
      resource::IsStudyWriter(rc)) {
    return true;
  }
  if (resource::IsAxiMasterPort(rc) ||
      resource::IsAxiSlavePort(rc) ||
      resource::IsSramIf(rc)) {
    return true;
  }
  if (resource::IsFifo(rc) ||
      resource::IsFifoReader(rc)) {
    return true;
  }
  if (resource::IsFifoWriter(rc) &&
      insn->GetOperand() != operand::kNoWait) {
    return true;
  }
  if (resource::IsSharedRegReader(rc)) {
    if (insn->GetOperand() == operand::kWaitNotify ||
	insn->GetOperand() == operand::kGetMailbox) {
      return true;
    }
  }
  if (resource::IsSharedRegWriter(rc)) {
    if (insn->GetOperand() == operand::kPutMailbox) {
      return true;
    }
  }
  return false;
}

bool ResourceAttr::IsExtAccessResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsExtInput(rc) ||
      resource::IsExtOutput(rc) ||
      resource::IsAxiMasterPort(rc) ||
      resource::IsAxiSlavePort(rc) ||
      resource::IsSramIf(rc) ||
      resource::IsExtTask(rc) ||
      resource::IsExtTaskDone(rc) ||
      resource::IsExtTaskCall(rc) ||
      resource::IsExtTaskWait(rc)) {
    return true;
  }
  return false;
}

bool ResourceAttr::IsExtWaitInsn(IInsn *insn) {
  IResourceClass &rc = *(insn->GetResource()->GetClass());
  return resource::IsAxiSlavePort(rc) || resource::IsSramIf(rc);
}

bool ResourceAttr::IsExtAccessInsn(IInsn *insn) {
  return IsExtAccessResource(insn->GetResource());
}

int ResourceAttr::NumExtAccessInsn(const IState *st) {
  int n = 0;
  for (IInsn *insn : st->insns_) {
    if (IsExtAccessInsn(insn)) {
      ++n;
    }
  }
  return n;
}

bool ResourceAttr::IsDuplicatableResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  const string &name = rc.GetName();
  // add, sub, mul, gt, gte and ext-combinational for now.
  if (name == resource::kEq) {
    return false;
  }
  if (resource::IsExtCombinational(rc)) {
    return true;
  }
  return resource::IsExclusiveBinOp(rc);
}

bool ResourceAttr::IsOrderedResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsArray(rc) || resource::IsMapped(rc)) {
    return true;
  }
  return false;
}

}  // namespace iroha
<|endoftext|>


<commit_before>/*
  User Server code for CMPT 276 Group Assignment, Spring 2016.

  This server manages a user’s social networking session.

  This server supports sign on/off, add friend, unfriend, update status,
  get user's friend list.

  This server handles disallowed method malformed request.

  As defined in ServerUrls.h, the URI for this server is
  http://localhost:34572.
*/

#include <exception>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <string>

#include <cpprest/base_uri.h>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>

#include <pplx/pplxtasks.h>

#include <was/common.h>
#include <was/storage_account.h>
#include <was/table.h>

#include "../include/ClientUtils.h"
#include "../include/ServerUrls.h"
#include "../include/ServerUtils.h"
#include "../include/TableCache.h"

#include "../include/azure_keys.h"

using azure::storage::cloud_storage_account;
using azure::storage::storage_credentials;
using azure::storage::storage_exception;
using azure::storage::cloud_table;
using azure::storage::cloud_table_client;
using azure::storage::edm_type;
using azure::storage::entity_property;
using azure::storage::table_entity;
using azure::storage::table_operation;
using azure::storage::table_query;
using azure::storage::table_query_iterator;
using azure::storage::table_result;

using pplx::extensibility::critical_section_t;
using pplx::extensibility::scoped_critical_section_t;

using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::make_pair;
using std::pair;
using std::string;
using std::unordered_map;
using std::vector;
using std::get;

using web::http::client::http_client;
using web::http::http_headers;
using web::http::http_request;
using web::http::http_response;
using web::http::method;
using web::http::methods;
using web::http::status_code;
using web::http::status_codes;
using web::http::uri;

using web::json::value;

using web::http::experimental::listener::http_listener;

using prop_vals_t = vector<pair<string,value>>;

const string get_update_data_op {"GetUpdateData"};

const string read_entity_auth_op {"ReadEntityAuth"};
const string update_entity_auth_op {"UpdateEntityAuth"};

const string auth_table_partition {"Userid"};
const string data_table {"DataTable"};

const string sign_on {"SignOn"}; //POST
const string sign_off {"SignOff"}; //POST

const string add_friend {"AddFriend"}; // PUT
const string unfriend {"UnFriend"}; //PUT
const string update_status {"UpdateStatus"}; //PUT
const string push_status {"PushStatus"}; //Post

const string get_friend_list {"ReadFriendList"}; //GET

// Cache of active sessions
std::unordered_map< string, std::tuple<string/*token*/, string/*partition*/, string/*row*/> > sessions;

/*
  Return true if an HTTP request has a JSON body

  This routine can be called multiple times on the same message.
 */
bool has_json_body (http_request message) {
  return message.headers()["Content-type"] == "application/json";
}

/*
  Given an HTTP message with a JSON body, return the JSON
  body as an unordered map of strings to strings.
  get_json_body and get_json_bourne are valid and identical function calls.

  If the message has no JSON body, return an empty map.

  THIS ROUTINE CAN ONLY BE CALLED ONCE FOR A GIVEN MESSAGE
  (see http://microsoft.github.io/cpprestsdk/classweb_1_1http_1_1http__request.html#ae6c3d7532fe943de75dcc0445456cbc7
  for source of this limit).

  Note that all types of JSON values are returned as strings.
  Use C++ conversion utilities to convert to numbers or dates
  as necessary.
 */
unordered_map<string,string> get_json_body(http_request message) {
  unordered_map<string,string> results {};
  const http_headers& headers {message.headers()};
  auto content_type (headers.find("Content-Type"));
  if (content_type == headers.end() ||
      content_type->second != "application/json")
    return results;

  value json{};
  message.extract_json(true)
    .then([&json](value v) -> bool
          {
            json = v;
            return true;
          })
    .wait();

  if (json.is_object()) {
    for (const auto& v : json.as_object()) {
      if (v.second.is_string()) {
        results[v.first] = v.second.as_string();
      }
      else {
        results[v.first] = v.second.serialize();
      }
    }
  }
  return results;
}

unordered_map<string,string> get_json_bourne(http_request message) {
 return get_json_body(message);
}

void handle_post (http_request message){
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  // Operation name and user ID
  if(paths.size() < 2) {
    message.reply(status_codes::BadRequest);
    return;
  }
  else if(paths[0] != sign_on && paths[0] != sign_off) {
    message.reply(status_codes::BadRequest);
  }

  const string operation = paths[0];
  const string userid = paths[1];

  if(operation == sign_on) {
    if(!has_json_body(message)) {
      message.reply(status_codes::BadRequest);
      return;
    }

    unordered_map<string, string> json_body {get_json_bourne(message)};
    if(json_body.size() != 1) {
      message.reply(status_codes::BadRequest);
      return;
    }

    unordered_map<string, string>::const_iterator json_body_password_iterator {json_body.find("Password")};
    // No 'Password' property
    if(json_body_password_iterator == json_body.end()) {
      message.reply(status_codes::BadRequest);
      return;
    }

    vector<pair<string, value>> json_pw;
    json_pw.push_back(make_pair(
        json_body_password_iterator->first,
        value::string(json_body_password_iterator->second)
    ));

    pair<status_code, value> result;
    result = do_request(
      methods::GET,
      string(server_urls::auth_server) + "/" +
      get_update_data_op + "/" +
      userid,
      value::object(json_pw)
    );
    if(result.first != status_codes::OK) {
      message.reply(result.first);
      return;
    }
    else if(result.second.size() != 3) {
      message.reply(status_codes::InternalError);
      return;
    }

    const string token = get_json_object_prop(
      result.second,
      "token"
    );
    const string data_partition = get_json_object_prop(
      result.second,
      "DataPartition"
    );
    const string data_row = get_json_object_prop(
      result.second,
      "DataRow"
    );
    if(token.empty() ||
       data_partition.empty() ||
       data_row.empty() ) {
      message.reply(status_codes::InternalError);
      return;
    }

    std::tuple<string, string, string> tuple_insert(
      token,
      data_partition,
      data_row);
    std::pair<string, std::tuple<string, string, string>> pair_insert(
      userid,
      tuple_insert
    );
    sessions.insert(pair_insert);

    message.reply(status_codes::OK);
    return;
  }

  else if(operation == sign_off) {
    auto session = sessions.find(userid);
    if(session == sessions.end()) {
      message.reply(status_codes::NotFound);
      return;
    }

    sessions.erase(session);
    message.reply(status_codes::OK);
    return;
  }

  else {
    message.reply(status_codes::InternalError);
    return;
  }
}

void handle_put (http_request message) {
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  pair<status_code, value> result;
  string user_id {paths[1]};
  string user_token {get<0>(sessions[user_id])};
  string user_partition {get<1>(sessions[user_id])};
  string user_row {get<2>(sessions[user_id])};
  if(true/*basic criteria*/){}
  else if (paths[0] == add_friend) {
    // TODO: Check validity of the request
    // Get current friends list
    result = do_request(
      methods::GET,
      string(server_urls::basic_server) + "/" +
      read_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row
      );
    // TODO: Check status code
    // Parse JSON body
    unordered_map<string,string> json_body = unpack_json_object(result.second);
    friends_list_t user_friends = parse_friends_list(json_body["Friends"]);
    // Add new friend to list
    user_friends.push_back(make_pair(paths[2],paths[3]));
    // Rebuild json body
    string user_friends_string = friends_list_to_string(user_friends);
    result.second = build_json_value("Friends", user_friends_string);
    // Put new friends list
    do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    // TODO: Check return results
    message.reply(status_codes::OK);
    return;
  }
  /*
   * UnFriend
   */
  else if (paths[0] == unfriend) {
    // TODO: Check validity of request
    // Get current friends list
    result = do_request(
      methods::GET,
      string(server_urls::basic_server) + "/" +
      read_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row
      );
    // TODO: Check status code
    // Parse Json body
    unordered_map<string,string> json_body = unpack_json_object(result.second);
    friends_list_t user_friends = parse_friends_list(json_body["Friends"]);
    // Remove friend from list
    friends_list_t new_user_friends;
    for (int i = 0; i < user_friends.size(); ++i)
    {
      if (user_friends[i].first != paths[2] || user_friends[i].second != paths[3])
      {
        new_user_friends.push_back(user_friends[i]);
      }
    }
    // Rebuild json body
    string user_friends_string = friends_list_to_string(new_user_friends);
    result.second = build_json_value("Friends", user_friends_string);
    // Put new friends list
    do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      string(paths[2]) + "/" +
      string(paths[3]),
      result.second
      );
    // TODO: Check return results
    message.reply(status_codes::OK);
    return;
  }
  else if (paths[0] == update_status) {}
  else {
    // malformed request
    vector<value> vec;
    message.reply(status_codes::BadRequest, value::array(vec));
    return;
  }
}

void handle_get (http_request message) {
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  if(true/*basic criteria*/){}
  else if (paths[0] == get_friend_list) {}
  else {
    // malformed request
    vector<value> vec;
    message.reply(status_codes::BadRequest, value::array(vec));
    return;
  }
}

int main (int argc, char const * argv[]) {
  cout << "Opening listener" << endl;
  http_listener listener {server_urls::user_server};
  listener.support(methods::GET, &handle_get); // Get user's friend list
  listener.support(methods::POST, &handle_post); // SignOn, SignOff
  listener.support(methods::PUT, &handle_put); // Add friend, Unfriend, Update Status
  /*TO DO: Disallowed method*/
  listener.open().wait(); // Wait for listener to complete starting

  cout << "Enter carriage return to stop server." << endl;
  string line;
  getline(std::cin, line);

  // Shut it down
  listener.close().wait();
  cout << "Closed" << endl;
}
<commit_msg>fix unfriend put call<commit_after>/*
  User Server code for CMPT 276 Group Assignment, Spring 2016.

  This server manages a user’s social networking session.

  This server supports sign on/off, add friend, unfriend, update status,
  get user's friend list.

  This server handles disallowed method malformed request.

  As defined in ServerUrls.h, the URI for this server is
  http://localhost:34572.
*/

#include <exception>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <string>

#include <cpprest/base_uri.h>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>

#include <pplx/pplxtasks.h>

#include <was/common.h>
#include <was/storage_account.h>
#include <was/table.h>

#include "../include/ClientUtils.h"
#include "../include/ServerUrls.h"
#include "../include/ServerUtils.h"
#include "../include/TableCache.h"

#include "../include/azure_keys.h"

using azure::storage::cloud_storage_account;
using azure::storage::storage_credentials;
using azure::storage::storage_exception;
using azure::storage::cloud_table;
using azure::storage::cloud_table_client;
using azure::storage::edm_type;
using azure::storage::entity_property;
using azure::storage::table_entity;
using azure::storage::table_operation;
using azure::storage::table_query;
using azure::storage::table_query_iterator;
using azure::storage::table_result;

using pplx::extensibility::critical_section_t;
using pplx::extensibility::scoped_critical_section_t;

using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::make_pair;
using std::pair;
using std::string;
using std::unordered_map;
using std::vector;
using std::get;

using web::http::client::http_client;
using web::http::http_headers;
using web::http::http_request;
using web::http::http_response;
using web::http::method;
using web::http::methods;
using web::http::status_code;
using web::http::status_codes;
using web::http::uri;

using web::json::value;

using web::http::experimental::listener::http_listener;

using prop_vals_t = vector<pair<string,value>>;

const string get_update_data_op {"GetUpdateData"};

const string read_entity_auth_op {"ReadEntityAuth"};
const string update_entity_auth_op {"UpdateEntityAuth"};

const string auth_table_partition {"Userid"};
const string data_table {"DataTable"};

const string sign_on {"SignOn"}; //POST
const string sign_off {"SignOff"}; //POST

const string add_friend {"AddFriend"}; // PUT
const string unfriend {"UnFriend"}; //PUT
const string update_status {"UpdateStatus"}; //PUT
const string push_status {"PushStatus"}; //Post

const string get_friend_list {"ReadFriendList"}; //GET

// Cache of active sessions
std::unordered_map< string, std::tuple<string/*token*/, string/*partition*/, string/*row*/> > sessions;

/*
  Return true if an HTTP request has a JSON body

  This routine can be called multiple times on the same message.
 */
bool has_json_body (http_request message) {
  return message.headers()["Content-type"] == "application/json";
}

/*
  Given an HTTP message with a JSON body, return the JSON
  body as an unordered map of strings to strings.
  get_json_body and get_json_bourne are valid and identical function calls.

  If the message has no JSON body, return an empty map.

  THIS ROUTINE CAN ONLY BE CALLED ONCE FOR A GIVEN MESSAGE
  (see http://microsoft.github.io/cpprestsdk/classweb_1_1http_1_1http__request.html#ae6c3d7532fe943de75dcc0445456cbc7
  for source of this limit).

  Note that all types of JSON values are returned as strings.
  Use C++ conversion utilities to convert to numbers or dates
  as necessary.
 */
unordered_map<string,string> get_json_body(http_request message) {
  unordered_map<string,string> results {};
  const http_headers& headers {message.headers()};
  auto content_type (headers.find("Content-Type"));
  if (content_type == headers.end() ||
      content_type->second != "application/json")
    return results;

  value json{};
  message.extract_json(true)
    .then([&json](value v) -> bool
          {
            json = v;
            return true;
          })
    .wait();

  if (json.is_object()) {
    for (const auto& v : json.as_object()) {
      if (v.second.is_string()) {
        results[v.first] = v.second.as_string();
      }
      else {
        results[v.first] = v.second.serialize();
      }
    }
  }
  return results;
}

unordered_map<string,string> get_json_bourne(http_request message) {
 return get_json_body(message);
}

void handle_post (http_request message){
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  // Operation name and user ID
  if(paths.size() < 2) {
    message.reply(status_codes::BadRequest);
    return;
  }
  else if(paths[0] != sign_on && paths[0] != sign_off) {
    message.reply(status_codes::BadRequest);
  }

  const string operation = paths[0];
  const string userid = paths[1];

  if(operation == sign_on) {
    if(!has_json_body(message)) {
      message.reply(status_codes::BadRequest);
      return;
    }

    unordered_map<string, string> json_body {get_json_bourne(message)};
    if(json_body.size() != 1) {
      message.reply(status_codes::BadRequest);
      return;
    }

    unordered_map<string, string>::const_iterator json_body_password_iterator {json_body.find("Password")};
    // No 'Password' property
    if(json_body_password_iterator == json_body.end()) {
      message.reply(status_codes::BadRequest);
      return;
    }

    vector<pair<string, value>> json_pw;
    json_pw.push_back(make_pair(
        json_body_password_iterator->first,
        value::string(json_body_password_iterator->second)
    ));

    pair<status_code, value> result;
    result = do_request(
      methods::GET,
      string(server_urls::auth_server) + "/" +
      get_update_data_op + "/" +
      userid,
      value::object(json_pw)
    );
    if(result.first != status_codes::OK) {
      message.reply(result.first);
      return;
    }
    else if(result.second.size() != 3) {
      message.reply(status_codes::InternalError);
      return;
    }

    const string token = get_json_object_prop(
      result.second,
      "token"
    );
    const string data_partition = get_json_object_prop(
      result.second,
      "DataPartition"
    );
    const string data_row = get_json_object_prop(
      result.second,
      "DataRow"
    );
    if(token.empty() ||
       data_partition.empty() ||
       data_row.empty() ) {
      message.reply(status_codes::InternalError);
      return;
    }

    std::tuple<string, string, string> tuple_insert(
      token,
      data_partition,
      data_row);
    std::pair<string, std::tuple<string, string, string>> pair_insert(
      userid,
      tuple_insert
    );
    sessions.insert(pair_insert);

    message.reply(status_codes::OK);
    return;
  }

  else if(operation == sign_off) {
    auto session = sessions.find(userid);
    if(session == sessions.end()) {
      message.reply(status_codes::NotFound);
      return;
    }

    sessions.erase(session);
    message.reply(status_codes::OK);
    return;
  }

  else {
    message.reply(status_codes::InternalError);
    return;
  }
}

void handle_put (http_request message) {
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  pair<status_code, value> result;
  string user_id {paths[1]};
  string user_token {get<0>(sessions[user_id])};
  string user_partition {get<1>(sessions[user_id])};
  string user_row {get<2>(sessions[user_id])};
  if(true/*basic criteria*/){}
  else if (paths[0] == add_friend) {
    // TODO: Check validity of the request
    // Get current friends list
    result = do_request(
      methods::GET,
      string(server_urls::basic_server) + "/" +
      read_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row
      );
    // TODO: Check status code
    // Parse JSON body
    unordered_map<string,string> json_body = unpack_json_object(result.second);
    friends_list_t user_friends = parse_friends_list(json_body["Friends"]);
    // Add new friend to list
    user_friends.push_back(make_pair(paths[2],paths[3]));
    // Rebuild json body
    string user_friends_string = friends_list_to_string(user_friends);
    result.second = build_json_value("Friends", user_friends_string);
    // Put new friends list
    do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    // TODO: Check return results
    message.reply(status_codes::OK);
    return;
  }
  /*
   * UnFriend
   */
  else if (paths[0] == unfriend) {
    // TODO: Check validity of request
    // Get current friends list
    result = do_request(
      methods::GET,
      string(server_urls::basic_server) + "/" +
      read_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row
      );
    // TODO: Check status code
    // Parse Json body
    unordered_map<string,string> json_body = unpack_json_object(result.second);
    friends_list_t user_friends = parse_friends_list(json_body["Friends"]);
    // Remove friend from list
    friends_list_t new_user_friends;
    for (int i = 0; i < user_friends.size(); ++i)
    {
      if (user_friends[i].first != paths[2] || user_friends[i].second != paths[3])
      {
        new_user_friends.push_back(user_friends[i]);
      }
    }
    // Rebuild json body
    string user_friends_string = friends_list_to_string(new_user_friends);
    result.second = build_json_value("Friends", user_friends_string);
    // Put new friends list
    do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    // TODO: Check return results
    message.reply(status_codes::OK);
    return;
  }
  else if (paths[0] == update_status) {}
  else {
    // malformed request
    vector<value> vec;
    message.reply(status_codes::BadRequest, value::array(vec));
    return;
  }
}

void handle_get (http_request message) {
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  if(true/*basic criteria*/){}
  else if (paths[0] == get_friend_list) {}
  else {
    // malformed request
    vector<value> vec;
    message.reply(status_codes::BadRequest, value::array(vec));
    return;
  }
}

int main (int argc, char const * argv[]) {
  cout << "Opening listener" << endl;
  http_listener listener {server_urls::user_server};
  listener.support(methods::GET, &handle_get); // Get user's friend list
  listener.support(methods::POST, &handle_post); // SignOn, SignOff
  listener.support(methods::PUT, &handle_put); // Add friend, Unfriend, Update Status
  /*TO DO: Disallowed method*/
  listener.open().wait(); // Wait for listener to complete starting

  cout << "Enter carriage return to stop server." << endl;
  string line;
  getline(std::cin, line);

  // Shut it down
  listener.close().wait();
  cout << "Closed" << endl;
}
<|endoftext|>


<commit_before>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_ABORT_FLAG_HXX
#define BENG_ABORT_FLAG_HXX

#include "async.hxx"

/**
 * An async_operation implementation which sets a flag.  This can be
 * used by libraries which don't have their own implementation, but
 * need to know whether the operation has been aborted.
 */
struct AbortFlag {
    struct async_operation operation;

    bool aborted = false;

    AbortFlag(async_operation_ref &async_ref) {
        operation.Init2<AbortFlag>();
        async_ref.Set(operation);
    }

    void Abort() {
        assert(!aborted);

        aborted = true;
    }
};

#endif
<commit_msg>abort_flag: convert to class<commit_after>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_ABORT_FLAG_HXX
#define BENG_ABORT_FLAG_HXX

#include "async.hxx"

/**
 * An async_operation implementation which sets a flag.  This can be
 * used by libraries which don't have their own implementation, but
 * need to know whether the operation has been aborted.
 */
class AbortFlag {
    struct async_operation operation;

public:
    bool aborted = false;

    AbortFlag(async_operation_ref &async_ref) {
        operation.Init2<AbortFlag, &AbortFlag::operation, &AbortFlag::Abort>();
        async_ref.Set(operation);
    }

private:
    void Abort() {
        assert(!aborted);

        aborted = true;
    }
};

#endif
<|endoftext|>


<commit_before>/*
    Copyright 2011 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    EVENT SHALL JOE HERMASZEWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "opengl_states.hpp"

#include <joelang/config.h>

#ifdef JOELANG_WITH_OPENGL

#include <GL/GLee.h>

#if defined(__APPLE__)
#include <OpenGL/gl3.h>
#else
#include <GL3/gl3.h>
#endif

#include <joemath/joemath.hpp>

#include <joelang/context.hpp>
#include <joelang/state.hpp>

using namespace JoeMath;

namespace JoeLang
{

void RegisterOpenGLStates( Context& context )
{
    //
    // Clearing
    //

    static
    State<float4> clear_color( "clear_color" );
    clear_color.SetCallbacks( [](float4 v)->void
                              {glClearColor(v.x(), v.y(), v.z(), v.w());},
                              []()->void
                              {glClearColor(0.f, 0.f, 0.f, 0.f);} );

    static
    State<float> clear_depth( "clear_depth" );
    clear_depth.SetCallbacks( [](float v)->void
                              {glClearDepth(v);},
                              []()->void
                              {glClearDepth(1.f);} );

    static
    State<s32> clear_stencil( "clear_stencil" );
    clear_stencil.SetCallbacks( [](s32 v)->void
                                {glClearStencil(v);},
                                []()->void
                                {glClearStencil(0);} );

    //
    // Blending
    //

    static
    State<float4> blend_color( "blend_color" );
    blend_color.SetCallbacks( [](float4 v)->void
                              {glBlendColor(v.x(), v.y(), v.z(), v.w());},
                              []()->void
                              {glBlendColor(0,0,0,0);} );

    static
    State<bool> blend_enable( "blend_enable" );
    blend_enable.SetCallbacks( [](bool v)->void
                               {if(v)
                                   glEnable(GL_BLEND);
                                else
                                   glDisable(GL_BLEND);},
                               []()->void
                               {glDisable(GL_BLEND);} );

    const static std::map<std::string, u32> blend_equation_enumerants =
    {
        {"ADD",              GL_FUNC_ADD},
        {"SUBTRACT",         GL_FUNC_SUBTRACT},
        {"REVERSE_SUBTRACT", GL_FUNC_REVERSE_SUBTRACT},
        {"MIN",              GL_MIN},
        {"MAX",              GL_MAX}
    };

    const static std::map<std::string, u32> blend_func_enumerants =
    {
        {"ZERO",                     GL_ZERO},
        {"ONE",                      GL_ONE},
        {"SRC_COLOR",                GL_SRC_COLOR},
        {"ONE_MINUS_SRC_COLOR",      GL_ONE_MINUS_SRC_COLOR},
        {"DST_COLOR",                GL_DST_COLOR},
        {"ONE_MINUS_DST_COLOR",      GL_ONE_MINUS_DST_COLOR},
        {"SRC_ALPHA",                GL_SRC_ALPHA},
        {"ONE_MINUS_SRC_ALPHA",      GL_ONE_MINUS_SRC_ALPHA},
        {"DST_ALPHA",                GL_DST_ALPHA},
        {"ONE_MINUS_DST_ALPHA",      GL_ONE_MINUS_DST_ALPHA},
        {"CONSTANT_COLOR",           GL_CONSTANT_COLOR},
        {"ONE_MINUS_CONSTANT_COLOR", GL_ONE_MINUS_CONSTANT_COLOR},
        {"CONSTANT_ALPHA",           GL_CONSTANT_ALPHA},
        {"ONE_MINUS_CONSTANT_ALPHA", GL_ONE_MINUS_CONSTANT_ALPHA},
        {"SRC_ALPHA_SATURATE",       GL_SRC_ALPHA_SATURATE}
    };

    static
    State<u32> blend_equation( "blend_equation", blend_equation_enumerants );
    blend_equation.SetCallbacks( [](u32 v)->void
                                 {glBlendEquation(v);},
                                 []()->void
                                 {glBlendEquation(GL_FUNC_ADD);} );

    /*
    static
    State<uint2> blend_equation_separate( "blend_equation_separate",
                                         blend_equation_enumerants );
    blend_equation_separate.SetCallbacks( [](uint2 v)->void
                                          {glBlendEquationSeparate(v.x(),
                                                                   v.y());},
                                          []()->void
                                          {glBlendEquation(GL_FUNC_ADD,
                                                           GL_FUNC_ADD);} );

    static
    State<uint2> blend_func( "blend_func", blend_func_enumerants );
    blend_func.SetCallbacks( [](uint2 v)->void
                             {glBlendFunc(v.x(), v.y());},
                             []()->void
                             {glBlendFunc(GL_ONE, GL_ZERO);} );

    static
    State<uint4> blend_func_separate( "blend_func_separate",
                                      blend_func_enumerants );
    blend_func_separate.SetCallbacks( [](uint4 v)->void
                                      {glBlendFuncSeparate(v.x(),
                                                           v.y(),
                                                           v.z(),
                                                           v.w());},
                                      []()->void
                                      {glBlendFuncSeparate(GL_ONE, GL_ZERO,
                                                           GL_ONE, GL_ZERO);} );
    */

    bool good = true;

    good &= context.AddState( &clear_color );
    good &= context.AddState( &clear_depth );
    good &= context.AddState( &clear_stencil );

    good &= context.AddState( &blend_color );
    good &= context.AddState( &blend_equation );
    /*
    good &= context.AddState( &blend_equation_separate );
    good &= context.AddState( &blend_func );
    good &= context.AddState( &blend_func_separate );
    */

    assert( good && "Error adding opengl state" );

}

void RegisterOpenGLActions( Context& context )
{
    // todo different casing perhaps for actions
    static
    State<u32> clear( "clear",
                      {{"COLOR",  GL_COLOR_BUFFER_BIT},
                       {"DEPTH",  GL_DEPTH_BUFFER_BIT},
                       {"STENCIL",GL_STENCIL_BUFFER_BIT}} );
    clear.SetCallbacks( [](u32 v)->void
                        {glClear(v);} );

    bool good = context.AddState( &clear );
    assert( good && "Error adding opengl action" );
}

} // namespace JoeLang

#endif
<commit_msg>[+] More states<commit_after>/*
    Copyright 2011 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    EVENT SHALL JOE HERMASZEWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "opengl_states.hpp"

#include <joelang/config.h>

#ifdef JOELANG_WITH_OPENGL

#include <GL/GLee.h>

#if defined(__APPLE__)
#include <OpenGL/gl3.h>
#else
#include <GL3/gl3.h>
#endif

#include <joemath/joemath.hpp>

#include <joelang/context.hpp>
#include <joelang/state.hpp>

using namespace JoeMath;

namespace JoeLang
{

void RegisterOpenGLStates( Context& context )
{
    //
    // Clearing
    //

    static
    State<float4> clear_color( "clear_color" );
    clear_color.SetCallbacks( [](float4 v)->void
                              {glClearColor(v.x(), v.y(), v.z(), v.w());},
                              []()->void
                              {glClearColor(0.f, 0.f, 0.f, 0.f);} );

    static
    State<float> clear_depth( "clear_depth" );
    clear_depth.SetCallbacks( [](float v)->void
                              {glClearDepth(v);},
                              []()->void
                              {glClearDepth(1.f);} );

    static
    State<s32> clear_stencil( "clear_stencil" );
    clear_stencil.SetCallbacks( [](s32 v)->void
                                {glClearStencil(v);},
                                []()->void
                                {glClearStencil(0);} );

    //
    // Blending
    //

    static
    State<float4> blend_color( "blend_color" );
    blend_color.SetCallbacks( [](float4 v)->void
                              {glBlendColor(v.x(), v.y(), v.z(), v.w());},
                              []()->void
                              {glBlendColor(0,0,0,0);} );

    static
    State<bool> blend_enable( "blend_enable" );
    blend_enable.SetCallbacks( [](bool v)->void
                               {if(v)
                                   glEnable(GL_BLEND);
                                else
                                   glDisable(GL_BLEND);},
                               []()->void
                               {glDisable(GL_BLEND);} );

    const static std::map<std::string, int> blend_equation_enumerants =
    {
        {"ADD",              GL_FUNC_ADD},
        {"SUBTRACT",         GL_FUNC_SUBTRACT},
        {"REVERSE_SUBTRACT", GL_FUNC_REVERSE_SUBTRACT},
        {"MIN",              GL_MIN},
        {"MAX",              GL_MAX}
    };

    const static std::map<std::string, int> blend_func_enumerants =
    {
        {"ZERO",                     GL_ZERO},
        {"ONE",                      GL_ONE},
        {"SRC_COLOR",                GL_SRC_COLOR},
        {"ONE_MINUS_SRC_COLOR",      GL_ONE_MINUS_SRC_COLOR},
        {"DST_COLOR",                GL_DST_COLOR},
        {"ONE_MINUS_DST_COLOR",      GL_ONE_MINUS_DST_COLOR},
        {"SRC_ALPHA",                GL_SRC_ALPHA},
        {"ONE_MINUS_SRC_ALPHA",      GL_ONE_MINUS_SRC_ALPHA},
        {"DST_ALPHA",                GL_DST_ALPHA},
        {"ONE_MINUS_DST_ALPHA",      GL_ONE_MINUS_DST_ALPHA},
        {"CONSTANT_COLOR",           GL_CONSTANT_COLOR},
        {"ONE_MINUS_CONSTANT_COLOR", GL_ONE_MINUS_CONSTANT_COLOR},
        {"CONSTANT_ALPHA",           GL_CONSTANT_ALPHA},
        {"ONE_MINUS_CONSTANT_ALPHA", GL_ONE_MINUS_CONSTANT_ALPHA},
        {"SRC_ALPHA_SATURATE",       GL_SRC_ALPHA_SATURATE}
    };

    static
    State<u32> blend_equation( "blend_equation", blend_equation_enumerants );
    blend_equation.SetCallbacks( [](u32 v)->void
                                 {glBlendEquation(v);},
                                 []()->void
                                 {glBlendEquation(GL_FUNC_ADD);} );

    static
    State<uint2> blend_equation_separate( "blend_equation_separate",
                                          blend_equation_enumerants );
    blend_equation_separate.SetCallbacks( [](uint2 v)->void
                                          {glBlendEquationSeparate(v.x(),
                                                                   v.y());},
                                          []()->void
                                          {glBlendEquationSeparate(
                                                               GL_FUNC_ADD,
                                                               GL_FUNC_ADD);} );

    static
    State<uint2> blend_func( "blend_func", blend_func_enumerants );
    blend_func.SetCallbacks( [](uint2 v)->void
                             {glBlendFunc(v.x(), v.y());},
                             []()->void
                             {glBlendFunc(GL_ONE, GL_ZERO);} );

    static
    State<uint4> blend_func_separate( "blend_func_separate",
                                      blend_func_enumerants );
    blend_func_separate.SetCallbacks( [](uint4 v)->void
                                      {glBlendFuncSeparate(v.x(),
                                                           v.y(),
                                                           v.z(),
                                                           v.w());},
                                      []()->void
                                      {glBlendFuncSeparate(GL_ONE, GL_ZERO,
                                                           GL_ONE, GL_ZERO);} );

    bool good = true;

    good &= context.AddState( &clear_color );
    good &= context.AddState( &clear_depth );
    good &= context.AddState( &clear_stencil );

    good &= context.AddState( &blend_color );
    good &= context.AddState( &blend_enable );
    good &= context.AddState( &blend_equation );
    good &= context.AddState( &blend_equation_separate );
    good &= context.AddState( &blend_func );
    good &= context.AddState( &blend_func_separate );

    assert( good && "Error adding opengl state" );
}

void RegisterOpenGLActions( Context& context )
{
    // todo different casing perhaps for actions
    static
    State<u32> clear( "clear",
                      {{"COLOR",  GL_COLOR_BUFFER_BIT},
                       {"DEPTH",  GL_DEPTH_BUFFER_BIT},
                       {"STENCIL",GL_STENCIL_BUFFER_BIT}} );
    clear.SetCallbacks( [](u32 v)->void
                        {glClear(v);} );

    bool good = context.AddState( &clear );
    assert( good && "Error adding opengl action" );
}

} // namespace JoeLang

#endif
<|endoftext|>