<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageCacheFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkImageCacheFilter.h"

#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"

vtkCxxRevisionMacro(vtkImageCacheFilter, "1.20");
vtkStandardNewMacro(vtkImageCacheFilter);

//----------------------------------------------------------------------------
vtkImageCacheFilter::vtkImageCacheFilter()
{
  this->CacheSize = 0;
  this->Data = NULL;
  this->Times = NULL;

  this->SetCacheSize(10);
}

//----------------------------------------------------------------------------
vtkImageCacheFilter::~vtkImageCacheFilter()
{
  this->SetCacheSize(0);
}

//----------------------------------------------------------------------------
void vtkImageCacheFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  int idx, *ext;
  vtkIndent i2 = indent.GetNextIndent();

  os << indent << "CacheSize: " << this->CacheSize << endl;
  os << indent << "Caches: \n";
  for (idx = 0; idx < this->CacheSize; ++idx)
    {
    if (this->Data[idx])
      {
      ext = this->Data[idx]->GetExtent();
      os << i2 << idx << ": (" << this->Times[idx]
         << ") " << ext[0] << ", " << ext[1] << ", " << ext[2] << ", "
         << ext[3] << ", " << ext[4] << ", " << ext[5] << endl;
      }
    }
}

void vtkImageCacheFilter::SetCacheSize(int size)
{
  int idx;

  if (size == this->CacheSize)
    {
    return;
    }

  this->Modified();

  // free the old data
  for (idx = 0; idx < this->CacheSize; ++idx)
    {
    if (this->Data[idx])
      {
      this->Data[idx]->Delete();
      this->Data[idx] = NULL;
      }
    }
  if (this->Data)
    {
    delete [] this->Data;
    this->Data = NULL;
    }
  if (this->Times)
    {
    delete [] this->Times;
    this->Times = NULL;
    }

  this->CacheSize = size;
  if (size == 0)
    {
    return;
    }

  this->Data = new vtkImageData* [size];
  this->Times = new unsigned long [size];

  for (idx = 0; idx < size; ++idx)
    {
    this->Data[idx] = NULL;
    this->Times[idx] = 0;
    }
}

//----------------------------------------------------------------------------
// This method simply copies by reference the input data to the output.
void vtkImageCacheFilter::UpdateData(vtkDataObject *outObject)
{
  unsigned long pmt;
  int *uExt, *ext;
  vtkImageData *outData = (vtkImageData *)(outObject);
  vtkImageData *inData = this->GetInput();
  int i;
  int flag = 0;

  if (!inData)
    {
    vtkErrorMacro(<< "Input not set.");
    return;
    }

  uExt = outData->GetUpdateExtent();

  // First look through the cached data to see if it is still valid.
  pmt = inData->GetPipelineMTime();
  for (i = 0; i < this->CacheSize; ++i)
    {
    if (this->Data[i] && this->Times[i] < pmt)
      {
      this->Data[i]->Delete();
      this->Times[i] = 0;
      }
    }

  // Look for data that contains UpdateExtent.
  for (i = 0; i < this->CacheSize; ++i)
    {
    if (this->Data[i])
      {
      ext = this->Data[i]->GetExtent();
      if (uExt[0] >= ext[0] && uExt[1] <= ext[1] &&
          uExt[2] >= ext[2] && uExt[3] <= ext[3] &&
          uExt[4] >= ext[4] && uExt[5] <= ext[5])
        {
        vtkDebugMacro("Found Cached Data to meet request" );

        // Pass this data to output.
        outData->SetExtent(ext);
        outData->GetPointData()->PassData(this->Data[i]->GetPointData());
        outData->DataHasBeenGenerated();
        flag = 1;
        }
      }
    }

  if (flag == 0)
    {
    unsigned long bestTime = VTK_LARGE_INTEGER;
    int bestIdx = 0;

    // we need to update.
    inData->SetUpdateExtent(uExt);
    inData->PropagateUpdateExtent();
    inData->UpdateData();

    if (inData->GetDataReleased())
      { // special case
      return;
      }

    vtkDebugMacro("Generating Data to meet request" );

    outData->SetExtent(inData->GetExtent());
    outData->GetPointData()->PassData(inData->GetPointData());
    outData->DataHasBeenGenerated();

    // Save the image in cache.
    // Find a spot to put the data.
    for (i = 0; i < this->CacheSize; ++i)
      {
      if (this->Data[i] == NULL)
        {
        bestIdx = i;
        bestTime = 0;
        break;
        }
      if (this->Times[i] < bestTime)
        {
        bestIdx = i;
        bestTime = this->Times[i];
        }
      }
    if (this->Data[bestIdx] == NULL)
      {
      this->Data[bestIdx] = vtkImageData::New();
      }
    this->Data[bestIdx]->ReleaseData();
    this->Data[bestIdx]->SetScalarType(inData->GetScalarType());
    this->Data[bestIdx]->SetExtent(inData->GetExtent());
    this->Data[bestIdx]->SetNumberOfScalarComponents(inData->GetNumberOfScalarComponents());
    this->Data[bestIdx]->GetPointData()->SetScalars(inData->GetPointData()->GetScalars());
    this->Times[bestIdx] = inData->GetUpdateTime();

    // release input data
    if (this->GetInput()->ShouldIReleaseData())
      {
      this->GetInput()->ReleaseData();
      }
    }
}

<commit_msg>BUG: Fix Bug #787 - Exception on vtkImageCacheFilter after modifying the pipeline.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageCacheFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkImageCacheFilter.h"

#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"

vtkCxxRevisionMacro(vtkImageCacheFilter, "1.21");
vtkStandardNewMacro(vtkImageCacheFilter);

//----------------------------------------------------------------------------
vtkImageCacheFilter::vtkImageCacheFilter()
{
  this->CacheSize = 0;
  this->Data = NULL;
  this->Times = NULL;

  this->SetCacheSize(10);
}

//----------------------------------------------------------------------------
vtkImageCacheFilter::~vtkImageCacheFilter()
{
  this->SetCacheSize(0);
}

//----------------------------------------------------------------------------
void vtkImageCacheFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  int idx, *ext;
  vtkIndent i2 = indent.GetNextIndent();

  os << indent << "CacheSize: " << this->CacheSize << endl;
  os << indent << "Caches: \n";
  for (idx = 0; idx < this->CacheSize; ++idx)
    {
    if (this->Data[idx])
      {
      ext = this->Data[idx]->GetExtent();
      os << i2 << idx << ": (" << this->Times[idx]
         << ") " << ext[0] << ", " << ext[1] << ", " << ext[2] << ", "
         << ext[3] << ", " << ext[4] << ", " << ext[5] << endl;
      }
    }
}

//----------------------------------------------------------------------------
void vtkImageCacheFilter::SetCacheSize(int size)
{
  int idx;

  if (size == this->CacheSize)
    {
    return;
    }

  this->Modified();

  // free the old data
  for (idx = 0; idx < this->CacheSize; ++idx)
    {
    if (this->Data[idx])
      {
      this->Data[idx]->Delete();
      this->Data[idx] = NULL;
      }
    }
  if (this->Data)
    {
    delete [] this->Data;
    this->Data = NULL;
    }
  if (this->Times)
    {
    delete [] this->Times;
    this->Times = NULL;
    }

  this->CacheSize = size;
  if (size == 0)
    {
    return;
    }

  this->Data = new vtkImageData* [size];
  this->Times = new unsigned long [size];

  for (idx = 0; idx < size; ++idx)
    {
    this->Data[idx] = NULL;
    this->Times[idx] = 0;
    }
}

//----------------------------------------------------------------------------
// This method simply copies by reference the input data to the output.
void vtkImageCacheFilter::UpdateData(vtkDataObject *outObject)
{
  unsigned long pmt;
  int *uExt, *ext;
  vtkImageData *outData = (vtkImageData *)(outObject);
  vtkImageData *inData = this->GetInput();
  int i;
  int flag = 0;

  if (!inData)
    {
    vtkErrorMacro(<< "Input not set.");
    return;
    }

  uExt = outData->GetUpdateExtent();

  // First look through the cached data to see if it is still valid.
  pmt = inData->GetPipelineMTime();
  for (i = 0; i < this->CacheSize; ++i)
    {
    if (this->Data[i] && this->Times[i] < pmt)
      {
      this->Data[i]->Delete();
      this->Data[i] = NULL;
      this->Times[i] = 0;
      }
    }

  // Look for data that contains UpdateExtent.
  for (i = 0; i < this->CacheSize; ++i)
    {
    if (this->Data[i])
      {
      ext = this->Data[i]->GetExtent();
      if (uExt[0] >= ext[0] && uExt[1] <= ext[1] &&
          uExt[2] >= ext[2] && uExt[3] <= ext[3] &&
          uExt[4] >= ext[4] && uExt[5] <= ext[5])
        {
        vtkDebugMacro("Found Cached Data to meet request" );

        // Pass this data to output.
        outData->SetExtent(ext);
        outData->GetPointData()->PassData(this->Data[i]->GetPointData());
        outData->DataHasBeenGenerated();
        flag = 1;
        }
      }
    }

  if (flag == 0)
    {
    unsigned long bestTime = VTK_LARGE_INTEGER;
    int bestIdx = 0;

    // we need to update.
    inData->SetUpdateExtent(uExt);
    inData->PropagateUpdateExtent();
    inData->UpdateData();

    if (inData->GetDataReleased())
      { // special case
      return;
      }

    vtkDebugMacro("Generating Data to meet request" );

    outData->SetExtent(inData->GetExtent());
    outData->GetPointData()->PassData(inData->GetPointData());
    outData->DataHasBeenGenerated();

    // Save the image in cache.
    // Find a spot to put the data.
    for (i = 0; i < this->CacheSize; ++i)
      {
      if (this->Data[i] == NULL)
        {
        bestIdx = i;
        bestTime = 0;
        break;
        }
      if (this->Times[i] < bestTime)
        {
        bestIdx = i;
        bestTime = this->Times[i];
        }
      }
    if (this->Data[bestIdx] == NULL)
      {
      this->Data[bestIdx] = vtkImageData::New();
      }
    this->Data[bestIdx]->ReleaseData();
    this->Data[bestIdx]->SetScalarType(inData->GetScalarType());
    this->Data[bestIdx]->SetExtent(inData->GetExtent());
    this->Data[bestIdx]->SetNumberOfScalarComponents(inData->GetNumberOfScalarComponents());
    this->Data[bestIdx]->GetPointData()->SetScalars(inData->GetPointData()->GetScalars());
    this->Times[bestIdx] = inData->GetUpdateTime();

    // release input data
    if (this->GetInput()->ShouldIReleaseData())
      {
      this->GetInput()->ReleaseData();
      }
    }
}

<|endoftext|>


<commit_before>#define GROUP_TEST(regex, anchor, input, n) \
    test_case(_FORMAT(regex, anchor, input)) { \
        re2::StringPiece g2[n]; \
        re2::StringPiece gj[n]; \
        if ( _RE2_RUN(_RE2(regex), input, anchor, g2, n) \
          != _R2J_RUN(_R2J(regex), input, anchor, gj, n)) return Result::Fail("invalid answer"); \
        for (size_t i = 0; i < n; i++) { \
            if (g2[i] != gj[i]) { \
                return Result::Fail( \
                    "group %zu incorrect\n" \
                    "    expected [%d] '%s'\n" \
                    "    matched  [%d] '%s'", i, g2[i].size(), g2[i].data(), gj[i].size(), gj[i].data()); \
            } \
        } \
    }

GROUP_TEST("Hello, (.*)!", ANCHOR_START, "Hello, World!", 2);
GROUP_TEST("([^ ]*?), (.*)", UNANCHORED, "Hi there, world!", 3);
GROUP_TEST("([+-]?(?:(0b)[01]+|(0o)[0-7]+|(0x)[0-9a-f]+))", ANCHOR_BOTH, "0b00010", 6);
GROUP_TEST("([+-]?(?:(0b)[01]+|(0o)[0-7]+|(0x)[0-9a-f]+|[0-9]+((?:\\.[0-9]+)?(?:e[+-]?[0-9]+)?)(j)?))", ANCHOR_BOTH, "0b00010", 6);
GROUP_TEST("([+-]?(?:(0b)[01]+|(0o)[0-7]+|(0x)[0-9a-f]+|[0-9]+((?:\\.[0-9]+)?(?:e[+-]?[0-9]+)?)(j)?))", ANCHOR_BOTH, "30.5e+1j", 6);
<commit_msg>Fix subgroup output in failing tests.<commit_after>#define GROUP_TEST(regex, anchor, input, n) \
    test_case(_FORMAT(regex, anchor, input)) { \
        re2::StringPiece g2[n]; \
        re2::StringPiece gj[n]; \
        if ( _RE2_RUN(_RE2(regex), input, anchor, g2, n) \
          != _R2J_RUN(_R2J(regex), input, anchor, gj, n)) return Result::Fail("invalid answer"); \
        for (size_t i = 0; i < n; i++) { \
            if (g2[i] != gj[i]) { \
                return Result::Fail( \
                    "group %zu incorrect\n" \
                    "    expected [%d] '%.*s'\n" \
                    "    matched  [%d] '%.*s'", i, g2[i].size(), g2[i].size(), g2[i].data(), \
                                                   gj[i].size(), gj[i].size(), gj[i].data()); \
            } \
        } \
    }

GROUP_TEST("Hello, (.*)!", ANCHOR_START, "Hello, World!", 2);
GROUP_TEST("([^ ]*?), (.*)", UNANCHORED, "Hi there, world!", 3);
GROUP_TEST("([+-]?(?:(0b)[01]+|(0o)[0-7]+|(0x)[0-9a-f]+))", ANCHOR_BOTH, "0b00010", 6);
GROUP_TEST("([+-]?(?:(0b)[01]+|(0o)[0-7]+|(0x)[0-9a-f]+|[0-9]+((?:\\.[0-9]+)?(?:e[+-]?[0-9]+)?)(j)?))", ANCHOR_BOTH, "0b00010", 6);
GROUP_TEST("([+-]?(?:(0b)[01]+|(0o)[0-7]+|(0x)[0-9a-f]+|[0-9]+((?:\\.[0-9]+)?(?:e[+-]?[0-9]+)?)(j)?))", ANCHOR_BOTH, "30.5e+1j", 6);
<|endoftext|>


<commit_before>
#include <plan_and_run/demo_application.h>

/* LOAD PARAMETERS
  Goal:
    - Load missing application parameters into the from the ros parameter server.
    - Use a private NodeHandle in order to load parameters defined in the node's namespace.

  Hints:
    - Look at how the 'config_' structure is used to save the parameters.
    - A private NodeHandle can be created by passing the "~" string to its constructor.
*/

namespace plan_and_run
{

void DemoApplication::loadParameters()
{
  //ROS_ERROR_STREAM("Task '"<<__FUNCTION__ <<"' is incomplete. Exiting"); exit(-1);

  /*  Fill Code:
   * Goal:
   * - Create a private handle by passing the "~" string to its constructor
   * Hint:
   * - Replace the string in ph below with "~" to make it a private node.
   */
  ros::NodeHandle ph("~");

  // creating handle with public scope
  ros::NodeHandle nh;

  /*  Fill Code:
   * Goal:
   * - Read missing parameters 'tip_link' and 'world_frame' from ros parameter server
   */
  if(ph.getParam("group_name",config_.group_name) &&

      ph.getParam("tip_link",config_.tip_link) &&

      ph.getParam("base_link",config_.base_link) &&

      ph.getParam("world_frame",config_.world_frame) &&

      ph.getParam("trajectory/time_delay",config_.time_delay) &&
      ph.getParam("trajectory/foci_distance",config_.foci_distance) &&
      ph.getParam("trajectory/radius",config_.radius) &&
      ph.getParam("trajectory/num_points",config_.num_points) &&
      ph.getParam("trajectory/num_lemniscates",config_.num_lemniscates) &&
      ph.getParam("trajectory/center",config_.center) &&
      ph.getParam("trajectory/seed_pose",config_.seed_pose) &&
      ph.getParam("visualization/min_point_distance",config_.min_point_distance) &&
      nh.getParam("controller_joint_names",config_.joint_names) )
  {
    ROS_INFO_STREAM("Loaded application parameters");

  }
  else
  {
    ROS_ERROR_STREAM("Failed to load application parameters");
    exit(-1);
  }

  ROS_INFO_STREAM("Task '"<<__FUNCTION__<<"' completed");

}

}
<commit_msg>Fixing Typo in load_parameter Solution Comments<commit_after>
#include <plan_and_run/demo_application.h>

/* LOAD PARAMETERS
  Goal:
    - Load missing application parameters from the ros parameter server.
    - Use a private NodeHandle in order to load parameters defined in the node's namespace.

  Hints:
    - Look at how the 'config_' structure is used to save the parameters.
    - A private NodeHandle can be created by passing the "~" string to its constructor.
*/

namespace plan_and_run
{

void DemoApplication::loadParameters()
{
  //ROS_ERROR_STREAM("Task '"<<__FUNCTION__ <<"' is incomplete. Exiting"); exit(-1);

  /*  Fill Code:
   * Goal:
   * - Create a private handle by passing the "~" string to its constructor
   * Hint:
   * - Replace the string in ph below with "~" to make it a private node.
   */
  ros::NodeHandle ph("~");

  // creating handle with public scope
  ros::NodeHandle nh;

  /*  Fill Code:
   * Goal:
   * - Read missing parameters 'tip_link' and 'world_frame' from ros parameter server
   */
  if(ph.getParam("group_name",config_.group_name) &&

      ph.getParam("tip_link",config_.tip_link) &&

      ph.getParam("base_link",config_.base_link) &&

      ph.getParam("world_frame",config_.world_frame) &&

      ph.getParam("trajectory/time_delay",config_.time_delay) &&
      ph.getParam("trajectory/foci_distance",config_.foci_distance) &&
      ph.getParam("trajectory/radius",config_.radius) &&
      ph.getParam("trajectory/num_points",config_.num_points) &&
      ph.getParam("trajectory/num_lemniscates",config_.num_lemniscates) &&
      ph.getParam("trajectory/center",config_.center) &&
      ph.getParam("trajectory/seed_pose",config_.seed_pose) &&
      ph.getParam("visualization/min_point_distance",config_.min_point_distance) &&
      nh.getParam("controller_joint_names",config_.joint_names) )
  {
    ROS_INFO_STREAM("Loaded application parameters");

  }
  else
  {
    ROS_ERROR_STREAM("Failed to load application parameters");
    exit(-1);
  }

  ROS_INFO_STREAM("Task '"<<__FUNCTION__<<"' completed");

}

}
<|endoftext|>


<commit_before>//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting descriptions of the calling
// conventions supported by this target.
//
//===----------------------------------------------------------------------===//

#include "CallingConvEmitter.h"
#include "Record.h"
#include "CodeGenTarget.h"
using namespace llvm;

void CallingConvEmitter::run(std::ostream &O) {
  EmitSourceFileHeader("Calling Convention Implementation Fragment", O);

  std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");

  // Emit prototypes for all of the CC's so that they can forward ref each
  // other.
  for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
    O << "static bool " << CCs[i]->getName()
      << "(unsigned ValNo, MVT ValVT,\n"
      << std::string(CCs[i]->getName().size()+13, ' ')
      << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
      << std::string(CCs[i]->getName().size()+13, ' ')
      << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
  }

  // Emit each calling convention description in full.
  for (unsigned i = 0, e = CCs.size(); i != e; ++i)
    EmitCallingConv(CCs[i], O);
}

void CallingConvEmitter::EmitCallingConv(Record *CC, std::ostream &O) {
  ListInit *CCActions = CC->getValueAsListInit("Actions");
  Counter = 0;

  O << "\n\nstatic bool " << CC->getName()
    << "(unsigned ValNo, MVT ValVT,\n"
    << std::string(CC->getName().size()+13, ' ')
    << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
    << std::string(CC->getName().size()+13, ' ')
    << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
  // Emit all of the actions, in order.
  for (unsigned i = 0, e = CCActions->getSize(); i != e; ++i) {
    O << "\n";
    EmitAction(CCActions->getElementAsRecord(i), 2, O);
  }

  O << "\n  return true;  // CC didn't match.\n";
  O << "}\n";
}

void CallingConvEmitter::EmitAction(Record *Action,
                                    unsigned Indent, std::ostream &O) {
  std::string IndentStr = std::string(Indent, ' ');

  if (Action->isSubClassOf("CCPredicateAction")) {
    O << IndentStr << "if (";

    if (Action->isSubClassOf("CCIfType")) {
      ListInit *VTs = Action->getValueAsListInit("VTs");
      for (unsigned i = 0, e = VTs->getSize(); i != e; ++i) {
        Record *VT = VTs->getElementAsRecord(i);
        if (i != 0) O << " ||\n    " << IndentStr;
        O << "LocVT == " << getEnumName(getValueType(VT));
      }

    } else if (Action->isSubClassOf("CCIf")) {
      O << Action->getValueAsString("Predicate");
    } else {
      Action->dump();
      throw "Unknown CCPredicateAction!";
    }

    O << ") {\n";
    EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
    O << IndentStr << "}\n";
  } else {
    if (Action->isSubClassOf("CCDelegateTo")) {
      Record *CC = Action->getValueAsDef("CC");
      O << IndentStr << "if (!" << CC->getName()
        << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
        << IndentStr << "  return false;\n";
    } else if (Action->isSubClassOf("CCAssignToReg")) {
      ListInit *RegList = Action->getValueAsListInit("RegList");
      if (RegList->getSize() == 1) {
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
        O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";
      } else {
        O << IndentStr << "static const unsigned RegList" << ++Counter
          << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(RegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
          << Counter << ", " << RegList->getSize() << ")) {\n";
      }
      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
        << "Reg, LocVT, LocInfo));\n";
      O << IndentStr << "  return false;\n";
      O << IndentStr << "}\n";
    } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
      ListInit *RegList = Action->getValueAsListInit("RegList");
      ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
      if (ShadowRegList->getSize() >0 &&
          ShadowRegList->getSize() != RegList->getSize())
        throw "Invalid length of list of shadowed registers";

      if (RegList->getSize() == 1) {
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
        O << getQualifiedName(RegList->getElementAsRecord(0));
        O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
        O << ")) {\n";
      } else {
        unsigned RegListNumber = ++Counter;
        unsigned ShadowRegListNumber = ++Counter;

        O << IndentStr << "static const unsigned RegList" << RegListNumber
          << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(RegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";

        O << IndentStr << "static const unsigned RegList"
          << ShadowRegListNumber << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";

        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
          << RegListNumber << ", " << "RegList" << ShadowRegListNumber
          << ", " << RegList->getSize() << ")) {\n";
      }
      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
        << "Reg, LocVT, LocInfo));\n";
      O << IndentStr << "  return false;\n";
      O << IndentStr << "}\n";
    } else if (Action->isSubClassOf("CCAssignToStack")) {
      int Size = Action->getValueAsInt("Size");
      int Align = Action->getValueAsInt("Align");

      O << IndentStr << "unsigned Offset" << ++Counter
        << " = State.AllocateStack(";
      if (Size)
        O << Size << ", ";
      else
        O << "\n" << IndentStr << "  State.getTarget().getTargetData()"
          "->getTypePaddedSize(LocVT.getTypeForMVT()), ";
      if (Align)
        O << Align;
      else
        O << "\n" << IndentStr << "  State.getTarget().getTargetData()"
          "->getABITypeAlignment(LocVT.getTypeForMVT())";
      O << ");\n" << IndentStr
        << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
        << Counter << ", LocVT, LocInfo));\n";
      O << IndentStr << "return false;\n";
    } else if (Action->isSubClassOf("CCPromoteToType")) {
      Record *DestTy = Action->getValueAsDef("DestTy");
      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
      O << IndentStr << "if (ArgFlags.isSExt())\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
        << IndentStr << "else if (ArgFlags.isZExt())\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
        << IndentStr << "else\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
    } else if (Action->isSubClassOf("CCPassByVal")) {
      int Size = Action->getValueAsInt("Size");
      int Align = Action->getValueAsInt("Align");
      O << IndentStr
        << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
        << Size << ", " << Align << ", ArgFlags);\n";
      O << IndentStr << "return false;\n";
    } else {
      Action->dump();
      throw "Unknown CCAction!";
    }
  }
}
<commit_msg>Use CallConvLower.h and TableGen descriptions of the calling conventions for ARM.  Patch by Sandeep Patel.<commit_after>//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting descriptions of the calling
// conventions supported by this target.
//
//===----------------------------------------------------------------------===//

#include "CallingConvEmitter.h"
#include "Record.h"
#include "CodeGenTarget.h"
using namespace llvm;

void CallingConvEmitter::run(std::ostream &O) {
  EmitSourceFileHeader("Calling Convention Implementation Fragment", O);

  std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");

  // Emit prototypes for all of the CC's so that they can forward ref each
  // other.
  for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
    O << "static bool " << CCs[i]->getName()
      << "(unsigned ValNo, MVT ValVT,\n"
      << std::string(CCs[i]->getName().size()+13, ' ')
      << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
      << std::string(CCs[i]->getName().size()+13, ' ')
      << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
  }

  // Emit each calling convention description in full.
  for (unsigned i = 0, e = CCs.size(); i != e; ++i)
    EmitCallingConv(CCs[i], O);
}

void CallingConvEmitter::EmitCallingConv(Record *CC, std::ostream &O) {
  ListInit *CCActions = CC->getValueAsListInit("Actions");
  Counter = 0;

  O << "\n\nstatic bool " << CC->getName()
    << "(unsigned ValNo, MVT ValVT,\n"
    << std::string(CC->getName().size()+13, ' ')
    << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
    << std::string(CC->getName().size()+13, ' ')
    << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
  // Emit all of the actions, in order.
  for (unsigned i = 0, e = CCActions->getSize(); i != e; ++i) {
    O << "\n";
    EmitAction(CCActions->getElementAsRecord(i), 2, O);
  }

  O << "\n  return true;  // CC didn't match.\n";
  O << "}\n";
}

void CallingConvEmitter::EmitAction(Record *Action,
                                    unsigned Indent, std::ostream &O) {
  std::string IndentStr = std::string(Indent, ' ');

  if (Action->isSubClassOf("CCPredicateAction")) {
    O << IndentStr << "if (";

    if (Action->isSubClassOf("CCIfType")) {
      ListInit *VTs = Action->getValueAsListInit("VTs");
      for (unsigned i = 0, e = VTs->getSize(); i != e; ++i) {
        Record *VT = VTs->getElementAsRecord(i);
        if (i != 0) O << " ||\n    " << IndentStr;
        O << "LocVT == " << getEnumName(getValueType(VT));
      }

    } else if (Action->isSubClassOf("CCIf")) {
      O << Action->getValueAsString("Predicate");
    } else {
      Action->dump();
      throw "Unknown CCPredicateAction!";
    }

    O << ") {\n";
    EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
    O << IndentStr << "}\n";
  } else {
    if (Action->isSubClassOf("CCDelegateTo")) {
      Record *CC = Action->getValueAsDef("CC");
      O << IndentStr << "if (!" << CC->getName()
        << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
        << IndentStr << "  return false;\n";
    } else if (Action->isSubClassOf("CCAssignToReg")) {
      ListInit *RegList = Action->getValueAsListInit("RegList");
      if (RegList->getSize() == 1) {
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
        O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";
      } else {
        O << IndentStr << "static const unsigned RegList" << ++Counter
          << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(RegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
          << Counter << ", " << RegList->getSize() << ")) {\n";
      }
      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
        << "Reg, LocVT, LocInfo));\n";
      O << IndentStr << "  return false;\n";
      O << IndentStr << "}\n";
    } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
      ListInit *RegList = Action->getValueAsListInit("RegList");
      ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
      if (ShadowRegList->getSize() >0 &&
          ShadowRegList->getSize() != RegList->getSize())
        throw "Invalid length of list of shadowed registers";

      if (RegList->getSize() == 1) {
        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
        O << getQualifiedName(RegList->getElementAsRecord(0));
        O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
        O << ")) {\n";
      } else {
        unsigned RegListNumber = ++Counter;
        unsigned ShadowRegListNumber = ++Counter;

        O << IndentStr << "static const unsigned RegList" << RegListNumber
          << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(RegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";

        O << IndentStr << "static const unsigned RegList"
          << ShadowRegListNumber << "[] = {\n";
        O << IndentStr << "  ";
        for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) {
          if (i != 0) O << ", ";
          O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
        }
        O << "\n" << IndentStr << "};\n";

        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
          << RegListNumber << ", " << "RegList" << ShadowRegListNumber
          << ", " << RegList->getSize() << ")) {\n";
      }
      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
        << "Reg, LocVT, LocInfo));\n";
      O << IndentStr << "  return false;\n";
      O << IndentStr << "}\n";
    } else if (Action->isSubClassOf("CCAssignToStack")) {
      int Size = Action->getValueAsInt("Size");
      int Align = Action->getValueAsInt("Align");

      O << IndentStr << "unsigned Offset" << ++Counter
        << " = State.AllocateStack(";
      if (Size)
        O << Size << ", ";
      else
        O << "\n" << IndentStr << "  State.getTarget().getTargetData()"
          "->getTypePaddedSize(LocVT.getTypeForMVT()), ";
      if (Align)
        O << Align;
      else
        O << "\n" << IndentStr << "  State.getTarget().getTargetData()"
          "->getABITypeAlignment(LocVT.getTypeForMVT())";
      O << ");\n" << IndentStr
        << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
        << Counter << ", LocVT, LocInfo));\n";
      O << IndentStr << "return false;\n";
    } else if (Action->isSubClassOf("CCPromoteToType")) {
      Record *DestTy = Action->getValueAsDef("DestTy");
      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
      O << IndentStr << "if (ArgFlags.isSExt())\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
        << IndentStr << "else if (ArgFlags.isZExt())\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
        << IndentStr << "else\n"
        << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
    } else if (Action->isSubClassOf("CCBitConvertToType")) {
      Record *DestTy = Action->getValueAsDef("DestTy");
      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
      O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
    } else if (Action->isSubClassOf("CCPassByVal")) {
      int Size = Action->getValueAsInt("Size");
      int Align = Action->getValueAsInt("Align");
      O << IndentStr
        << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
        << Size << ", " << Align << ", ArgFlags);\n";
      O << IndentStr << "return false;\n";
    } else if (Action->isSubClassOf("CCCustom")) {
      O << IndentStr
        << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
        << "LocVT, LocInfo, ArgFlags, State))\n";
      O << IndentStr << IndentStr << "return false;\n";
    } else {
      Action->dump();
      throw "Unknown CCAction!";
    }
  }
}
<|endoftext|>


<commit_before>/*
 * PerformanceCounter.cpp  10.08.2006 (mueller)
 *
 * Copyright (C) 2006 by Universitaet Stuttgart (VIS). Alle Rechte vorbehalten.
 * Copyright (C) 2005 by Christoph Mueller (christoph.mueller@vis.uni-stuttgart.de). Alle Rechte vorbehalten.
 */

#ifdef _WIN32
#include <windows.h>
#else /* _WIN32 */
#include <sys/time.h>
#endif /* _WIN32 */

#include "vislib/assert.h"
#include "vislib/memutils.h"
#include "vislib/PerformanceCounter.h"
#include "vislib/SystemException.h"
#include "vislib/Trace.h"

/*
 * vislib::sys::PerformanceCounter::Query
 */
UINT64 vislib::sys::PerformanceCounter::Query(void) {
#ifdef _WIN32
	LARGE_INTEGER timerFreq, timerCount;

    if (!::QueryPerformanceFrequency(&timerFreq)) {
        TRACE(_T("QueryPerformanceFrequency failed in ")
            _T("vislib::sys::PerformanceCounter::Query\n"));
        throw SystemException(::GetLastError(), __FILE__, __LINE__);
	}

    if (!::QueryPerformanceCounter(&timerCount)) {
        TRACE(_T("QueryPerformanceCounter failed in ")
            _T("vislib::sys::PerformanceCounter::Query\n"));
        throw SystemException(::GetLastError(), __FILE__, __LINE__);
    }

	return (timerCount.QuadPart * 1000) / timerFreq.QuadPart;

#else /* _WIN32 */
    struct timeval t;
    ::gettimeofday(&t, NULL);
    return static_cast<UINT64>((t.tv_sec * 1e6 + t.tv_usec) / 1000.0);

#endif /* _WIN32 */
}

/*
 * vislib::sys::PerformanceCounter::operator =
 */
vislib::sys::PerformanceCounter& vislib::sys::PerformanceCounter::operator =(
        const PerformanceCounter& rhs) {
    if (this != &rhs) {
        this->mark = rhs.mark;
    }

    return *this;
}
<commit_msg>Linux error handling.<commit_after>/*
 * PerformanceCounter.cpp  10.08.2006 (mueller)
 *
 * Copyright (C) 2006 by Universitaet Stuttgart (VIS). Alle Rechte vorbehalten.
 * Copyright (C) 2005 by Christoph Mueller (christoph.mueller@vis.uni-stuttgart.de). Alle Rechte vorbehalten.
 */

#ifdef _WIN32
#include <windows.h>
#else /* _WIN32 */
#include <sys/time.h>
#endif /* _WIN32 */

#include "vislib/assert.h"
#include "vislib/error.h"
#include "vislib/memutils.h"
#include "vislib/PerformanceCounter.h"
#include "vislib/SystemException.h"
#include "vislib/Trace.h"

/*
 * vislib::sys::PerformanceCounter::Query
 */
UINT64 vislib::sys::PerformanceCounter::Query(void) {
#ifdef _WIN32
	LARGE_INTEGER timerFreq, timerCount;

    if (!::QueryPerformanceFrequency(&timerFreq)) {
        TRACE(_T("QueryPerformanceFrequency failed in ")
            _T("vislib::sys::PerformanceCounter::Query\n"));
        throw SystemException(::GetLastError(), __FILE__, __LINE__);
	}

    if (!::QueryPerformanceCounter(&timerCount)) {
        TRACE(_T("QueryPerformanceCounter failed in ")
            _T("vislib::sys::PerformanceCounter::Query\n"));
        throw SystemException(::GetLastError(), __FILE__, __LINE__);
    }

	return (timerCount.QuadPart * 1000) / timerFreq.QuadPart;

#else /* _WIN32 */
    struct timeval t;
    if (::gettimeofday(&t, NULL) == -1) {
        throw SystemException(::GetLastError(), __FILE__, __LINE__);
    }

    return static_cast<UINT64>((t.tv_sec * 1e6 + t.tv_usec) / 1000.0);

#endif /* _WIN32 */
}

/*
 * vislib::sys::PerformanceCounter::operator =
 */
vislib::sys::PerformanceCounter& vislib::sys::PerformanceCounter::operator =(
        const PerformanceCounter& rhs) {
    if (this != &rhs) {
        this->mark = rhs.mark;
    }

    return *this;
}
<|endoftext|>


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

#include "OrbitClientModel/CaptureSerializer.h"

#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/message.h>

#include <fstream>
#include <memory>

#include "Callstack.h"
#include "EventTracer.h"
#include "FunctionUtils.h"
#include "OrbitBase/MakeUniqueForOverwrite.h"
#include "OrbitProcess.h"
#include "absl/strings/str_format.h"
#include "capture_data.pb.h"

using orbit_client_protos::CallstackEvent;
using orbit_client_protos::CallstackInfo;
using orbit_client_protos::CaptureInfo;
using orbit_client_protos::FunctionInfo;
using orbit_client_protos::FunctionStats;
using orbit_client_protos::TimerInfo;

void CaptureDeserializer::WriteMessage(const google::protobuf::Message* message,
                                       google::protobuf::io::CodedOutputStream* output) {
  uint32_t message_size = message->ByteSizeLong();
  output->WriteLittleEndian32(message_size);
  message->SerializeToCodedStream(output);
}

CaptureInfo CaptureDeserializer::GenerateCaptureInfo(
    const CaptureData& capture_data,
    const absl::flat_hash_map<uint64_t, std::string>& key_to_string_map) {
  CaptureInfo capture_info;
  for (const auto& pair : capture_data.selected_functions()) {
    capture_info.add_selected_functions()->CopyFrom(pair.second);
  }

  capture_info.set_process_id(capture_data.process_id());
  capture_info.set_process_name(capture_data.process_name());

  capture_info.mutable_thread_names()->insert(capture_data.thread_names().begin(),
                                              capture_data.thread_names().end());

  capture_info.mutable_address_infos()->Reserve(capture_data.address_infos().size());
  for (const auto& address_info : capture_data.address_infos()) {
    orbit_client_protos::LinuxAddressInfo* added_address_info = capture_info.add_address_infos();
    added_address_info->CopyFrom(address_info.second);
    // Fix names in address infos (some might only be in process):
    added_address_info->set_function_name(
        capture_data.GetFunctionNameByAddress(added_address_info->absolute_address()));
  }

  const absl::flat_hash_map<uint64_t, FunctionStats>& functions_stats =
      capture_data.functions_stats();
  capture_info.mutable_function_stats()->insert(functions_stats.begin(), functions_stats.end());

  // TODO: this is not really synchronized, since GetCallstacks processing below
  // is not under the same mutex lock we could end up having list of callstacks
  // inconsistent with unique_callstacks. Revisit sampling profiler data
  // thread-safety.
  capture_data.GetCallstackData()->ForEachUniqueCallstack(
      [&capture_info](const CallStack& call_stack) {
        CallstackInfo* callstack = capture_info.add_callstacks();
        *callstack->mutable_data() = {call_stack.GetFrames().begin(), call_stack.GetFrames().end()};
      });

  const auto& callstacks = capture_data.GetCallstackData()->callstack_events();
  capture_info.mutable_callstack_events()->Reserve(callstacks.size());
  for (const auto& callstack : callstacks) {
    capture_info.add_callstack_events()->CopyFrom(callstack);
  }

  capture_info.mutable_key_to_string()->insert(key_to_string_map.begin(), key_to_string_map.end());

  return capture_info;
}
<commit_msg>Ammend comment to match renamed method<commit_after>// Copyright (c) 2020 The Orbit Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "OrbitClientModel/CaptureSerializer.h"

#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/message.h>

#include <fstream>
#include <memory>

#include "Callstack.h"
#include "EventTracer.h"
#include "FunctionUtils.h"
#include "OrbitBase/MakeUniqueForOverwrite.h"
#include "OrbitProcess.h"
#include "absl/strings/str_format.h"
#include "capture_data.pb.h"

using orbit_client_protos::CallstackEvent;
using orbit_client_protos::CallstackInfo;
using orbit_client_protos::CaptureInfo;
using orbit_client_protos::FunctionInfo;
using orbit_client_protos::FunctionStats;
using orbit_client_protos::TimerInfo;

void CaptureDeserializer::WriteMessage(const google::protobuf::Message* message,
                                       google::protobuf::io::CodedOutputStream* output) {
  uint32_t message_size = message->ByteSizeLong();
  output->WriteLittleEndian32(message_size);
  message->SerializeToCodedStream(output);
}

CaptureInfo CaptureDeserializer::GenerateCaptureInfo(
    const CaptureData& capture_data,
    const absl::flat_hash_map<uint64_t, std::string>& key_to_string_map) {
  CaptureInfo capture_info;
  for (const auto& pair : capture_data.selected_functions()) {
    capture_info.add_selected_functions()->CopyFrom(pair.second);
  }

  capture_info.set_process_id(capture_data.process_id());
  capture_info.set_process_name(capture_data.process_name());

  capture_info.mutable_thread_names()->insert(capture_data.thread_names().begin(),
                                              capture_data.thread_names().end());

  capture_info.mutable_address_infos()->Reserve(capture_data.address_infos().size());
  for (const auto& address_info : capture_data.address_infos()) {
    orbit_client_protos::LinuxAddressInfo* added_address_info = capture_info.add_address_infos();
    added_address_info->CopyFrom(address_info.second);
    // Fix names in address infos (some might only be in process):
    added_address_info->set_function_name(
        capture_data.GetFunctionNameByAddress(added_address_info->absolute_address()));
  }

  const absl::flat_hash_map<uint64_t, FunctionStats>& functions_stats =
      capture_data.functions_stats();
  capture_info.mutable_function_stats()->insert(functions_stats.begin(), functions_stats.end());

  // TODO: this is not really synchronized, since GetCallstackData processing below is not under the
  // same mutex lock we could end up having list of callstacks inconsistent with unique_callstacks.
  // Revisit sampling profiler data thread-safety.
  capture_data.GetCallstackData()->ForEachUniqueCallstack(
      [&capture_info](const CallStack& call_stack) {
        CallstackInfo* callstack = capture_info.add_callstacks();
        *callstack->mutable_data() = {call_stack.GetFrames().begin(), call_stack.GetFrames().end()};
      });

  const auto& callstacks = capture_data.GetCallstackData()->callstack_events();
  capture_info.mutable_callstack_events()->Reserve(callstacks.size());
  for (const auto& callstack : callstacks) {
    capture_info.add_callstack_events()->CopyFrom(callstack);
  }

  capture_info.mutable_key_to_string()->insert(key_to_string_map.begin(), key_to_string_map.end());

  return capture_info;
}
<|endoftext|>


<commit_before>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <sstream>
// StdAir
#include <stdair/STDAIR_Service.hpp>
// AirSched
#include <airsched/basic/BasConst_AIRSCHED_Service.hpp>
#include <airsched/service/AIRSCHED_ServiceContext.hpp>

namespace AIRSCHED {

  // //////////////////////////////////////////////////////////////////////
  AIRSCHED_ServiceContext::AIRSCHED_ServiceContext()
    : _ownStdairService (false) {
  }

  // //////////////////////////////////////////////////////////////////////
  AIRSCHED_ServiceContext::
  AIRSCHED_ServiceContext (const AIRSCHED_ServiceContext&) {
    assert (false);
  }

  // //////////////////////////////////////////////////////////////////////
  AIRSCHED_ServiceContext::~AIRSCHED_ServiceContext() {
  }

  // ////////////////////////////////////////////////////////////////////
  stdair::STDAIR_Service& AIRSCHED_ServiceContext::getSTDAIR_Service() const {
    assert (_stdairService != NULL);
    return *_stdairService;
  }

  // //////////////////////////////////////////////////////////////////////
  const std::string AIRSCHED_ServiceContext::shortDisplay() const {
    std::ostringstream oStr;
    oStr << "AIRSCHED_ServiceContext -- Owns StdAir service: "
         << _ownStdairService;
    return oStr.str();
  }

  // //////////////////////////////////////////////////////////////////////
  const std::string AIRSCHED_ServiceContext::display() const {
    std::ostringstream oStr;
    oStr << shortDisplay();
    return oStr.str();
  }

  // //////////////////////////////////////////////////////////////////////
  const std::string AIRSCHED_ServiceContext::describe() const {
    return shortDisplay();
  }

  // ////////////////////////////////////////////////////////////////////
  void AIRSCHED_ServiceContext::reset() {
    if (_ownStdairService == true) {
      _stdairService.reset();
    }
  }

}
<commit_msg>[Dev] Reset the stdair service shared pointer in order to decrease the count by one every time (and not only when owning the stdair service).<commit_after>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <sstream>
// StdAir
#include <stdair/STDAIR_Service.hpp>
// AirSched
#include <airsched/basic/BasConst_AIRSCHED_Service.hpp>
#include <airsched/service/AIRSCHED_ServiceContext.hpp>

namespace AIRSCHED {

  // //////////////////////////////////////////////////////////////////////
  AIRSCHED_ServiceContext::AIRSCHED_ServiceContext()
    : _ownStdairService (false) {
  }

  // //////////////////////////////////////////////////////////////////////
  AIRSCHED_ServiceContext::
  AIRSCHED_ServiceContext (const AIRSCHED_ServiceContext&) {
    assert (false);
  }

  // //////////////////////////////////////////////////////////////////////
  AIRSCHED_ServiceContext::~AIRSCHED_ServiceContext() {
  }

  // ////////////////////////////////////////////////////////////////////
  stdair::STDAIR_Service& AIRSCHED_ServiceContext::getSTDAIR_Service() const {
    assert (_stdairService != NULL);
    return *_stdairService;
  }

  // //////////////////////////////////////////////////////////////////////
  const std::string AIRSCHED_ServiceContext::shortDisplay() const {
    std::ostringstream oStr;
    oStr << "AIRSCHED_ServiceContext -- Owns StdAir service: "
         << _ownStdairService;
    return oStr.str();
  }

  // //////////////////////////////////////////////////////////////////////
  const std::string AIRSCHED_ServiceContext::display() const {
    std::ostringstream oStr;
    oStr << shortDisplay();
    return oStr.str();
  }

  // //////////////////////////////////////////////////////////////////////
  const std::string AIRSCHED_ServiceContext::describe() const {
    return shortDisplay();
  }

  // ////////////////////////////////////////////////////////////////////
  void AIRSCHED_ServiceContext::reset() {

    // The shared_ptr<>::reset() method drops the refcount by one.
    // If the count result is dropping to zero, the resource pointed to
    // by the shared_ptr<> will be freed.

    // Reset the stdair shared pointer
    _stdairService.reset();
  }

}
<|endoftext|>


<commit_before>//
//  splitter_dbs.cc
//  P2PSP
//
//  This code is distributed under the GNU General Public License (see
//  THE_GENERAL_GNU_PUBLIC_LICENSE.txt for extending this information).
//  Copyright (C) 2016, the P2PSP team.
//  http://www.p2psp.org
//
//  DBS: Data Broadcasting Set of rules
//

#include "splitter_dbs.h"
#include "../util/trace.h"

namespace p2psp {
  using namespace std;
  using namespace boost;

  const int SplitterDBS::kMaxChunkLoss =
      32;  // Chunk losses threshold to reject a peer from the team
  const int SplitterDBS::kMonitorNumber = 1;

  SplitterDBS::SplitterDBS() : SplitterIMS(), losses_(0, &SplitterDBS::GetHash) {
    // TODO: Check if there is a better way to replace kMcastAddr with 0.0.0.0
    mcast_addr_ = "0.0.0.0";
    max_number_of_chunk_loss_ = kMaxChunkLoss;
    max_number_of_monitors_ = kMonitorNumber;

    peer_number_ = 0;
    destination_of_chunk_.reserve(buffer_size_);
    magic_flags_ = Common::kDBS;

    TRACE("max_number_of_chunk_loss = " << max_number_of_chunk_loss_);
    TRACE("mcast_addr = " << mcast_addr_);
    TRACE("Initialized DBS");
  }

  SplitterDBS::~SplitterDBS() {}

  char SplitterDBS::GetMagicFlags() {
    return magic_flags_;
  }

  void SplitterDBS::SendMagicFlags(
                                   const std::shared_ptr<boost::asio::ip::tcp::socket> &peer_serve_socket) {
    char message[1];

    message[0] = magic_flags_;
    peer_serve_socket->send(asio::buffer(message));
    LOG("Magic flags = " << bitset<8>(message[0]));
  }

  void SplitterDBS::SendTheListSize(
                                    const std::shared_ptr<boost::asio::ip::tcp::socket> &peer_serve_socket) {
    char message[2];

    TRACE("Sending the number of monitors " << max_number_of_monitors_);
    (*(uint16_t *)&message) = htons(max_number_of_monitors_);
    peer_serve_socket->send(asio::buffer(message));

    TRACE("Sending a list of peers of size " << to_string(peer_list_.size()));
    (*(uint16_t *)&message) = htons(peer_list_.size());
    peer_serve_socket->send(asio::buffer(message));
  }

  void SplitterDBS::SendTheListOfPeers(
                                       const std::shared_ptr<boost::asio::ip::tcp::socket> &peer_serve_socket) {
    SendTheListSize(peer_serve_socket);

    int counter = 0;

    char message[6];
    in_addr addr;

    for (std::vector<asio::ip::udp::endpoint>::iterator it = peer_list_.begin();
         it != peer_list_.end(); ++it) {
      inet_aton(it->address().to_string().c_str(), &addr);
      (*(in_addr *)&message) = addr;
      (*(uint16_t *)(message + 4)) = htons(it->port());
      peer_serve_socket->send(asio::buffer(message));

      TRACE(to_string(counter) << ", " << *it);
      counter++;
    }
  }

  void SplitterDBS::SendThePeerEndpoint(
                                        const std::shared_ptr<boost::asio::ip::tcp::socket> &peer_serve_socket) {
    asio::ip::tcp::endpoint peer_endpoint = peer_serve_socket->remote_endpoint();

    char message[6];
    in_addr addr;
    inet_aton(peer_endpoint.address().to_string().c_str(), &addr);
    (*(in_addr *)&message) = addr;
    (*(uint16_t *)(message + 4)) = htons(peer_endpoint.port());
    peer_serve_socket->send(asio::buffer(message));
  }

  void SplitterDBS::SendConfiguration(
                                      const std::shared_ptr<boost::asio::ip::tcp::socket> &sock) {
    SplitterIMS::SendConfiguration(sock);
    SendThePeerEndpoint(sock);
    SendMagicFlags(sock);
  }

  void SplitterDBS::InsertPeer(const boost::asio::ip::udp::endpoint &peer) {
    if (find(peer_list_.begin(), peer_list_.end(), peer) != peer_list_.end()) {
      peer_list_.erase(find(peer_list_.begin(), peer_list_.end(), peer));
    }
    peer_list_.push_back(peer);
    losses_[peer] = 0;
    TRACE("Inserted peer " << peer);
  }

  void SplitterDBS::HandleAPeerArrival(
                                       std::shared_ptr<boost::asio::ip::tcp::socket> serve_socket) {
    /* In the DBS, the splitter sends to the incomming peer the
       list of peers. Notice that the transmission of the list of
       peers (something that could need some time if the team is
       big or if the peer is slow) is done in a separate thread. This
       helps to avoid DoS (Denial of Service) attacks.
    */

    asio::ip::tcp::endpoint incoming_peer = serve_socket->remote_endpoint();

    TRACE("Accepted connection from peer " << incoming_peer);

    SendConfiguration(serve_socket);
    SendTheListOfPeers(serve_socket);
    serve_socket->close();
    InsertPeer(boost::asio::ip::udp::endpoint(incoming_peer.address(),
                                              incoming_peer.port()));

    // TODO: In original code, incoming_peer is returned, but is not used
  }

  size_t SplitterDBS::ReceiveMessage(std::vector<char> &message,
                                     boost::asio::ip::udp::endpoint &endpoint) {
    system::error_code ec;

    size_t bytes_transferred =
      team_socket_.receive_from(asio::buffer(message), endpoint, 0, ec);

    if (ec) {
      ERROR("Unexepected error: " << ec.message());
    }

    return bytes_transferred;
  }

  void SplitterDBS::IncrementUnsupportivityOfPeer(
                                                  const boost::asio::ip::udp::endpoint &peer) {
    bool peerExists = true;

    try {
      losses_[peer] += 1;
    } catch (std::exception e) {
      TRACE("The unsupportive peer " << peer << " does not exist!");
      peerExists = false;
    }

    if (peerExists) {
      TRACE("" << peer << " has lost " << to_string(losses_[peer]) << " chunks");

      if (losses_[peer] > max_number_of_chunk_loss_) {
        TRACE("" << peer << " removed");
        RemovePeer(peer);
      }
    }
  }

  void SplitterDBS::ProcessLostChunk(
                                     int lost_chunk_number, const boost::asio::ip::udp::endpoint &sender) {
    asio::ip::udp::endpoint destination = GetLosser(lost_chunk_number);

    TRACE("" << sender << " complains about lost chunk "
          << to_string(lost_chunk_number) << " sent to " << destination);

    if (find(peer_list_.begin() + max_number_of_monitors_, peer_list_.end(),
             destination) != peer_list_.end()) {
      TRACE("Lost chunk index = " << lost_chunk_number);
    }

    IncrementUnsupportivityOfPeer(destination);
  }

  uint16_t SplitterDBS::GetLostChunkNumber(const std::vector<char> &message) {
    // TODO: Check if this is totally correct
    return ntohs(*(uint16_t *)message.data());
  }

  asio::ip::udp::endpoint SplitterDBS::GetLosser(int lost_chunk_number) {
    return destination_of_chunk_[lost_chunk_number % buffer_size_];
  }

  void SplitterDBS::RemovePeer(const asio::ip::udp::endpoint &peer) {
    // If peer_list_ contains the peer, remove it
    if (find(peer_list_.begin(), peer_list_.end(), peer) != peer_list_.end()) {
      peer_list_.erase(remove(peer_list_.begin(), peer_list_.end(), peer),
                       peer_list_.end());

      // In order to avoid negative peer_number_ value while peer_list_ still
      // contains any peer (in Python this is not necessary because negative
      // indexes can be used)
      if (peer_list_.size() > 0) {
        peer_number_ = (peer_number_ - 1) % peer_list_.size();
      } else {
        peer_number_--;
      }
    }

    losses_.erase(peer);
  }

  void SplitterDBS::ProcessGoodbye(const boost::asio::ip::udp::endpoint &peer) {
    TRACE("Received 'goodbye' from " << peer);

    // TODO: stdout flush?

    RemovePeer(peer);
  }

  void SplitterDBS::ModerateTheTeam() {
    std::vector<char> message(2);
    asio::ip::udp::endpoint sender;

    while (alive_) {
      size_t bytes_transferred = ReceiveMessage(message, sender);

      if (bytes_transferred == 2) {
        /*
          The peer complains about a lost chunk.

          In this situation, the splitter counts the number of
          complains. If this number exceeds a threshold, the
          unsupportive peer is expelled from the
          team.
        */

        uint16_t lost_chunk_number = GetLostChunkNumber(message);
        ProcessLostChunk(lost_chunk_number, sender);

      } else {
        /*
          The peer wants to leave the team.

          A !2-length payload means that the peer wants to go
          away.
        */

        ProcessGoodbye(sender);
      }
    }
  }

  void SplitterDBS::SetupTeamSocket() {
    system::error_code ec;
    asio::ip::udp::endpoint endpoint(asio::ip::udp::v4(), team_port_);

    team_socket_.open(asio::ip::udp::v4());

    asio::socket_base::reuse_address reuseAddress(true);
    team_socket_.set_option(reuseAddress, ec);
    team_socket_.bind(endpoint);

    if (ec) {
      ERROR(ec.message());
    }
  }

  void SplitterDBS::ResetCounters() {
    unordered::unordered_map<asio::ip::udp::endpoint, int>::iterator it;
    for (it = losses_.begin(); it != losses_.end(); ++it) {
      losses_[it->first] = it->second / 2;
    }
  }

  void SplitterDBS::ResetCountersThread() {
    while (alive_) {
      ResetCounters();
      this_thread::sleep(posix_time::seconds(Common::kCountersTiming));
    }
  }

  void SplitterDBS::ComputeNextPeerNumber(asio::ip::udp::endpoint &peer) {
    peer_number_ = (peer_number_ + 1) % peer_list_.size();
  }

  void SplitterDBS::Run() {
    ReceiveTheHeader();

    /* A DBS splitter runs 4 threads. The main one and the
       "handle_arrivals" thread are equivalent to the daemons used
       by the IMS splitter. "moderate_the_team" and
       "reset_counters_thread" are new.
    */

    TRACE("waiting for the monitor peers ...");

    std::shared_ptr<asio::ip::tcp::socket> connection =
      make_shared<asio::ip::tcp::socket>(boost::ref(io_service_));
    acceptor_.accept(*connection);
    HandleAPeerArrival(connection);

    // Threads
    thread t1(bind(&SplitterIMS::HandleArrivals, this));
    thread t2(bind(&SplitterDBS::ModerateTheTeam, this));
    thread t3(bind(&SplitterDBS::ResetCountersThread, this));

    vector<char> message(sizeof(uint16_t) + chunk_size_);
    asio::ip::udp::endpoint peer;

    while (alive_) {
      asio::streambuf chunk;
      size_t bytes_transferred = ReceiveChunk(chunk);
      try {
        peer = peer_list_.at(peer_number_);

        (*(uint16_t *)message.data()) = htons(chunk_number_);

        copy(asio::buffer_cast<const char *>(chunk.data()),
             asio::buffer_cast<const char *>(chunk.data()) + chunk.size(),
             message.data() + sizeof(uint16_t));

        SendChunk(message, peer);

        destination_of_chunk_[chunk_number_ % buffer_size_] = peer;
        chunk_number_ = (chunk_number_ + 1) % Common::kMaxChunkNumber;
        ComputeNextPeerNumber(peer);
      } catch (const std::out_of_range &oor) {
        TRACE("The monitor peer has died!");
        exit(-1);
      }

      chunk.consume(bytes_transferred);
    }
  }

  std::vector<boost::asio::ip::udp::endpoint> SplitterDBS::GetPeerList() {
    return peer_list_;
  }

  int SplitterDBS::GetLoss(const boost::asio::ip::udp::endpoint &peer) {
    return losses_[peer];
  }

  void SplitterDBS::SetMaxNumberOfChunkLoss(int max_number_of_chunk_loss) {
    max_number_of_chunk_loss_ = max_number_of_chunk_loss;
  }

  int SplitterDBS::GetMaxNumberOfChunkLoss() {
    return max_number_of_chunk_loss_;
  }

  void SplitterDBS::SetMaxNumberOfMonitors(int max_number_of_monitors) {
    max_number_of_monitors_ = max_number_of_monitors;
  }

  int SplitterDBS::GetMaxNumberOfMonitors() {
    return max_number_of_monitors_;
  }

  void SplitterDBS::Start() {
    TRACE("Start");
    thread_.reset(new boost::thread(boost::bind(&SplitterDBS::Run, this)));
  }

  int SplitterDBS::GetDefaultMaxNumberOfChunkLoss() {
    return kMaxChunkLoss;
  }

  int SplitterDBS::GetDefaultMaxNumberOfMonitors() {
    return kMonitorNumber;
  }
}
<commit_msg>Write chunk data to file<commit_after>//
//  splitter_dbs.cc
//  P2PSP
//
//  This code is distributed under the GNU General Public License (see
//  THE_GENERAL_GNU_PUBLIC_LICENSE.txt for extending this information).
//  Copyright (C) 2016, the P2PSP team.
//  http://www.p2psp.org
//
//  DBS: Data Broadcasting Set of rules
//

#include "splitter_dbs.h"
#include "../util/trace.h"
#include <fstream>
#include <cstdlib>
#include <iterator>
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
#include <boost/uuid/uuid.hpp>
using boost::uuids::uuid;
#include <boost/uuid/uuid_generators.hpp>
using boost::uuids::random_generator;
#include <boost/uuid/uuid_io.hpp>

namespace p2psp {
  using namespace std;
  using namespace boost;

  const int SplitterDBS::kMaxChunkLoss =
      32;  // Chunk losses threshold to reject a peer from the team
  const int SplitterDBS::kMonitorNumber = 1;

  SplitterDBS::SplitterDBS() : SplitterIMS(), losses_(0, &SplitterDBS::GetHash) {
    // TODO: Check if there is a better way to replace kMcastAddr with 0.0.0.0
    mcast_addr_ = "0.0.0.0";
    max_number_of_chunk_loss_ = kMaxChunkLoss;
    max_number_of_monitors_ = kMonitorNumber;

    peer_number_ = 0;
    destination_of_chunk_.reserve(buffer_size_);
    magic_flags_ = Common::kDBS;

    TRACE("max_number_of_chunk_loss = " << max_number_of_chunk_loss_);
    TRACE("mcast_addr = " << mcast_addr_);
    TRACE("Initialized DBS");
  }

  SplitterDBS::~SplitterDBS() {}

  char SplitterDBS::GetMagicFlags() {
    return magic_flags_;
  }

  void SplitterDBS::SendMagicFlags(
                                   const std::shared_ptr<boost::asio::ip::tcp::socket> &peer_serve_socket) {
    char message[1];

    message[0] = magic_flags_;
    peer_serve_socket->send(asio::buffer(message));
    LOG("Magic flags = " << bitset<8>(message[0]));
  }

  void SplitterDBS::SendTheListSize(
                                    const std::shared_ptr<boost::asio::ip::tcp::socket> &peer_serve_socket) {
    char message[2];

    TRACE("Sending the number of monitors " << max_number_of_monitors_);
    (*(uint16_t *)&message) = htons(max_number_of_monitors_);
    peer_serve_socket->send(asio::buffer(message));

    TRACE("Sending a list of peers of size " << to_string(peer_list_.size()));
    (*(uint16_t *)&message) = htons(peer_list_.size());
    peer_serve_socket->send(asio::buffer(message));
  }

  void SplitterDBS::SendTheListOfPeers(
                                       const std::shared_ptr<boost::asio::ip::tcp::socket> &peer_serve_socket) {
    SendTheListSize(peer_serve_socket);

    int counter = 0;

    char message[6];
    in_addr addr;

    for (std::vector<asio::ip::udp::endpoint>::iterator it = peer_list_.begin();
         it != peer_list_.end(); ++it) {
      inet_aton(it->address().to_string().c_str(), &addr);
      (*(in_addr *)&message) = addr;
      (*(uint16_t *)(message + 4)) = htons(it->port());
      peer_serve_socket->send(asio::buffer(message));

      TRACE(to_string(counter) << ", " << *it);
      counter++;
    }
  }

  void SplitterDBS::SendThePeerEndpoint(
                                        const std::shared_ptr<boost::asio::ip::tcp::socket> &peer_serve_socket) {
    asio::ip::tcp::endpoint peer_endpoint = peer_serve_socket->remote_endpoint();

    char message[6];
    in_addr addr;
    inet_aton(peer_endpoint.address().to_string().c_str(), &addr);
    (*(in_addr *)&message) = addr;
    (*(uint16_t *)(message + 4)) = htons(peer_endpoint.port());
    peer_serve_socket->send(asio::buffer(message));
  }

  void SplitterDBS::SendConfiguration(
                                      const std::shared_ptr<boost::asio::ip::tcp::socket> &sock) {
    SplitterIMS::SendConfiguration(sock);
    SendThePeerEndpoint(sock);
    SendMagicFlags(sock);
  }

  void SplitterDBS::InsertPeer(const boost::asio::ip::udp::endpoint &peer) {
    if (find(peer_list_.begin(), peer_list_.end(), peer) != peer_list_.end()) {
      peer_list_.erase(find(peer_list_.begin(), peer_list_.end(), peer));
    }
    peer_list_.push_back(peer);
    losses_[peer] = 0;
    TRACE("Inserted peer " << peer);
  }

  void SplitterDBS::HandleAPeerArrival(
                                       std::shared_ptr<boost::asio::ip::tcp::socket> serve_socket) {
    /* In the DBS, the splitter sends to the incomming peer the
       list of peers. Notice that the transmission of the list of
       peers (something that could need some time if the team is
       big or if the peer is slow) is done in a separate thread. This
       helps to avoid DoS (Denial of Service) attacks.
    */

    asio::ip::tcp::endpoint incoming_peer = serve_socket->remote_endpoint();

    TRACE("Accepted connection from peer " << incoming_peer);

    SendConfiguration(serve_socket);
    SendTheListOfPeers(serve_socket);
    serve_socket->close();
    InsertPeer(boost::asio::ip::udp::endpoint(incoming_peer.address(),
                                              incoming_peer.port()));

    // TODO: In original code, incoming_peer is returned, but is not used
  }

  size_t SplitterDBS::ReceiveMessage(std::vector<char> &message,
                                     boost::asio::ip::udp::endpoint &endpoint) {
    system::error_code ec;

    size_t bytes_transferred =
      team_socket_.receive_from(asio::buffer(message), endpoint, 0, ec);

    if (ec) {
      ERROR("Unexepected error: " << ec.message());
    }

    return bytes_transferred;
  }

  void SplitterDBS::IncrementUnsupportivityOfPeer(
                                                  const boost::asio::ip::udp::endpoint &peer) {
    bool peerExists = true;

    try {
      losses_[peer] += 1;
    } catch (std::exception e) {
      TRACE("The unsupportive peer " << peer << " does not exist!");
      peerExists = false;
    }

    if (peerExists) {
      TRACE("" << peer << " has lost " << to_string(losses_[peer]) << " chunks");

      if (losses_[peer] > max_number_of_chunk_loss_) {
        TRACE("" << peer << " removed");
        RemovePeer(peer);
      }
    }
  }

  void SplitterDBS::ProcessLostChunk(
                                     int lost_chunk_number, const boost::asio::ip::udp::endpoint &sender) {
    asio::ip::udp::endpoint destination = GetLosser(lost_chunk_number);

    TRACE("" << sender << " complains about lost chunk "
          << to_string(lost_chunk_number) << " sent to " << destination);

    if (find(peer_list_.begin() + max_number_of_monitors_, peer_list_.end(),
             destination) != peer_list_.end()) {
      TRACE("Lost chunk index = " << lost_chunk_number);
    }

    IncrementUnsupportivityOfPeer(destination);
  }

  uint16_t SplitterDBS::GetLostChunkNumber(const std::vector<char> &message) {
    // TODO: Check if this is totally correct
    return ntohs(*(uint16_t *)message.data());
  }

  asio::ip::udp::endpoint SplitterDBS::GetLosser(int lost_chunk_number) {
    return destination_of_chunk_[lost_chunk_number % buffer_size_];
  }

  void SplitterDBS::RemovePeer(const asio::ip::udp::endpoint &peer) {
    // If peer_list_ contains the peer, remove it
    if (find(peer_list_.begin(), peer_list_.end(), peer) != peer_list_.end()) {
      peer_list_.erase(remove(peer_list_.begin(), peer_list_.end(), peer),
                       peer_list_.end());

      // In order to avoid negative peer_number_ value while peer_list_ still
      // contains any peer (in Python this is not necessary because negative
      // indexes can be used)
      if (peer_list_.size() > 0) {
        peer_number_ = (peer_number_ - 1) % peer_list_.size();
      } else {
        peer_number_--;
      }
    }

    losses_.erase(peer);
  }

  void SplitterDBS::ProcessGoodbye(const boost::asio::ip::udp::endpoint &peer) {
    TRACE("Received 'goodbye' from " << peer);

    // TODO: stdout flush?

    RemovePeer(peer);
  }

  void SplitterDBS::ModerateTheTeam() {
    std::vector<char> message(2);
    asio::ip::udp::endpoint sender;

    while (alive_) {
      size_t bytes_transferred = ReceiveMessage(message, sender);

      if (bytes_transferred == 2) {
        /*
          The peer complains about a lost chunk.

          In this situation, the splitter counts the number of
          complains. If this number exceeds a threshold, the
          unsupportive peer is expelled from the
          team.
        */

        uint16_t lost_chunk_number = GetLostChunkNumber(message);
        ProcessLostChunk(lost_chunk_number, sender);

      } else {
        /*
          The peer wants to leave the team.

          A !2-length payload means that the peer wants to go
          away.
        */

        ProcessGoodbye(sender);
      }
    }
  }

  void SplitterDBS::SetupTeamSocket() {
    system::error_code ec;
    asio::ip::udp::endpoint endpoint(asio::ip::udp::v4(), team_port_);

    team_socket_.open(asio::ip::udp::v4());

    asio::socket_base::reuse_address reuseAddress(true);
    team_socket_.set_option(reuseAddress, ec);
    team_socket_.bind(endpoint);

    if (ec) {
      ERROR(ec.message());
    }
  }

  void SplitterDBS::ResetCounters() {
    unordered::unordered_map<asio::ip::udp::endpoint, int>::iterator it;
    for (it = losses_.begin(); it != losses_.end(); ++it) {
      losses_[it->first] = it->second / 2;
    }
  }

  void SplitterDBS::ResetCountersThread() {
    while (alive_) {
      ResetCounters();
      this_thread::sleep(posix_time::seconds(Common::kCountersTiming));
    }
  }

  void SplitterDBS::ComputeNextPeerNumber(asio::ip::udp::endpoint &peer) {
    peer_number_ = (peer_number_ + 1) % peer_list_.size();
  }

  void SplitterDBS::Run() {
    ReceiveTheHeader();

    /* A DBS splitter runs 4 threads. The main one and the
       "handle_arrivals" thread are equivalent to the daemons used
       by the IMS splitter. "moderate_the_team" and
       "reset_counters_thread" are new.
    */

    TRACE("waiting for the monitor peers ...");

    std::shared_ptr<asio::ip::tcp::socket> connection =
      make_shared<asio::ip::tcp::socket>(boost::ref(io_service_));
    acceptor_.accept(*connection);
    HandleAPeerArrival(connection);
	//File to examine chunk data
	//string fname = "chunk_output"+to_string(rand()%10+1)+".txt";
	string fname = lexical_cast<string>((random_generator())());
	fstream file(fname,ios::out);
	ostream_iterator<char> output_iterator(file);
	ostream_iterator<char> output_iterator2(file, "\nChunk Number\n");
	ostringstream oss,f4b;
    // Threads
    thread t1(bind(&SplitterIMS::HandleArrivals, this));
    thread t2(bind(&SplitterDBS::ModerateTheTeam, this));
    thread t3(bind(&SplitterDBS::ResetCountersThread, this));

    vector<char> message(sizeof(uint16_t) + chunk_size_);
    asio::ip::udp::endpoint peer;

    while (alive_) {
      asio::streambuf chunk;
      size_t bytes_transferred = ReceiveChunk(chunk);
      try {
        peer = peer_list_.at(peer_number_);

        (*(uint16_t *)message.data()) = htons(chunk_number_);

        copy(asio::buffer_cast<const char *>(chunk.data()),
             asio::buffer_cast<const char *>(chunk.data()) + chunk.size(),
             message.data() + sizeof(uint16_t));
             size_t len = to_string(chunk_number_).length();
		//file<<to_string(chunk_number_).c_str()<<endl;
		//copy(asio::buffer_cast<const char *>(chunk.data()),
             //asio::buffer_cast<const char *>(chunk.data()) + 4,ostream_iterator<char>(f4b));
		//file << "First 4 bytes of chunk\n"<<f4b.str()<<"\n\n";
		//cout<<chunk_number_<<"\n\n";
		//*message.data() = ntohs(*message.data());
        copy(asio::buffer_cast<const char *>(chunk.data()),
             asio::buffer_cast<const char *>(chunk.data()) + chunk.size(),ostream_iterator<char>(oss));
        file << oss.str();
        oss.str("");//f4b.str("");
        SendChunk(message, peer);

        destination_of_chunk_[chunk_number_ % buffer_size_] = peer;
        chunk_number_ = (chunk_number_ + 1) % Common::kMaxChunkNumber;
        ComputeNextPeerNumber(peer);
      } catch (const std::out_of_range &oor) {
        TRACE("The monitor peer has died!");
        file.close();
        exit(-1);
      }

      chunk.consume(bytes_transferred);

    }
  }

  std::vector<boost::asio::ip::udp::endpoint> SplitterDBS::GetPeerList() {
    return peer_list_;
  }

  int SplitterDBS::GetLoss(const boost::asio::ip::udp::endpoint &peer) {
    return losses_[peer];
  }

  void SplitterDBS::SetMaxNumberOfChunkLoss(int max_number_of_chunk_loss) {
    max_number_of_chunk_loss_ = max_number_of_chunk_loss;
  }

  int SplitterDBS::GetMaxNumberOfChunkLoss() {
    return max_number_of_chunk_loss_;
  }

  void SplitterDBS::SetMaxNumberOfMonitors(int max_number_of_monitors) {
    max_number_of_monitors_ = max_number_of_monitors;
  }

  int SplitterDBS::GetMaxNumberOfMonitors() {
    return max_number_of_monitors_;
  }

  void SplitterDBS::Start() {
    TRACE("Start");
    thread_.reset(new boost::thread(boost::bind(&SplitterDBS::Run, this)));
  }

  int SplitterDBS::GetDefaultMaxNumberOfChunkLoss() {
    return kMaxChunkLoss;
  }

  int SplitterDBS::GetDefaultMaxNumberOfMonitors() {
    return kMonitorNumber;
  }
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  M6567Window.cc
//------------------------------------------------------------------------------
#include "M6567Window.h"
#include "IMUI/IMUI.h"
#include "Util.h"
#include "yakc/util/breadboard.h"

using namespace Oryol;

namespace YAKC {

//------------------------------------------------------------------------------
void
M6567Window::Setup(yakc& emu) {
    this->setName("M6567 (VIC-II) State");
    for (int i = 0; i < 16; i++) {
        this->paletteColors[i] = Util::RGBA8toImVec4(m6567_color(i));
    }
}

//------------------------------------------------------------------------------
void
M6567Window::drawColor(const char* text, uint8_t palIndex) {
    ImGui::Text("%s%02X", text, palIndex);
    ImGui::SameLine();
    ImGui::ColorButton(text, this->paletteColors[palIndex&0xF], ImGuiColorEditFlags_NoAlpha, ImVec2(12, 12));
}

//------------------------------------------------------------------------------
static void drawSpriteShifter(const char* label, uint32_t shf) {
    char str[33] = { };
    for (int i = 0; i < 32; i++) {
        str[i] = (((shf<<i) & (1<<31)) != 0) ? 'X':'.';
    }
    str[32] = 0;
    ImGui::Text("%s: %s\n", label, str);
}

//------------------------------------------------------------------------------
#define UINT8_BITS(m) m&(1<<7)?'1':'0',m&(1<<6)?'1':'0',m&(1<<5)?'1':'0',m&(1<<4)?'1':'0',m&(1<<3)?'1':'0',m&(1<<2)?'1':'0',m&(1<<1)?'1':'0',m&(1<<0)?'1':'0'
bool
M6567Window::Draw(yakc& emu) {
    ImGui::SetNextWindowSize(ImVec2(380, 460), ImGuiSetCond_Once);
    if (ImGui::Begin(this->title.AsCStr(), &this->Visible)) {
        m6567_t& vic = board.m6567;
        const char* type = "unknown";
        switch (vic.type) {
            case M6567_TYPE_6567R8: type = "6567R8 (NTSC)"; break;
            case M6567_TYPE_6569: type = "6569 (PAL)"; break;
        }
        ImGui::Text("Type: %s", type);
        ImGui::Checkbox("Debug Visualization", &board.m6567.debug_vis);
        if (ImGui::CollapsingHeader("Registers", "#vicreg", true, true)) {
            const auto& r = vic.reg;
            ImGui::Text("M0XY: %02X %02X M1XY: %02X %02X M2XY: %02X %02X M3XY: %02X %02X",
                r.mxy[0][0], r.mxy[0][1], r.mxy[1][0], r.mxy[1][1],
                r.mxy[2][0], r.mxy[2][1], r.mxy[3][0], r.mxy[3][1]);
            ImGui::Text("M4XY: %02X %02X M5XY: %02X %02X M6XY: %02X %02X M7XY: %02X %02X",
                r.mxy[4][0], r.mxy[4][1], r.mxy[5][0], r.mxy[6][1],
                r.mxy[6][0], r.mxy[6][1], r.mxy[7][0], r.mxy[7][1]);
            ImGui::Text("CTRL1 RST8:%c ECM:%c BMM:%c DEN:%c RSEL:%c YSCROLL:%d\n",
                r.ctrl_1 & (1<<7) ? '1':'0',
                r.ctrl_1 & (1<<6) ? '1':'0',
                r.ctrl_1 & (1<<5) ? '1':'0',
                r.ctrl_1 & (1<<4) ? '1':'0',
                r.ctrl_1 & (1<<3) ? '1':'0',
                r.ctrl_1 & 7);
            ImGui::Text("MSBX: %c%c%c%c%c%c%c%c RASTER: %02X LPX: %02X LPY: %02X",
                UINT8_BITS(r.mx8),
                r.raster, r.lightpen_xy[0], r.lightpen_xy[1]);
            ImGui::Text("ME:   %c%c%c%c%c%c%c%c", UINT8_BITS(r.me));
            ImGui::Text("CTRL2 RES:%c MCM:%c CSEL:%c XSCROLL:%d",
                r.ctrl_2 & (1<<5) ? '1':'0',
                r.ctrl_2 & (1<<4) ? '1':'0',
                r.ctrl_2 & (1<<3) ? '1':'0',
                r.ctrl_2 & 7);
            ImGui::Text("MYE:  %c%c%c%c%c%c%c%c", UINT8_BITS(r.mye));
            ImGui::Text("MEMPTRS VM:%02X CB:%02X", (r.mem_ptrs>>4)&0x0F, (r.mem_ptrs>>1)&0x07);
            ImGui::Text("INT IRQ:%c ILP:%c IMMC:%c IMBC:%c IRST:%c",
                r.int_latch & (1<<7) ? '1':'0',
                r.int_latch & (1<<3) ? '1':'0',
                r.int_latch & (1<<2) ? '1':'0',
                r.int_latch & (1<<1) ? '1':'0',
                r.int_latch & (1<<0) ? '1':'0');
            ImGui::Text("INT MASK  ELP:%c EMMC:%c EMBC:%c ERST:%c",
                r.int_mask & (1<<3) ? '1':'0',
                r.int_mask & (1<<2) ? '1':'0',
                r.int_mask & (1<<1) ? '1':'0',
                r.int_mask & (1<<0) ? '1':'0');
            ImGui::Text("MDP: %c%c%c%c%c%c%c%c  MMC: %c%c%c%c%c%c%c%c",
                UINT8_BITS(r.mob_data_priority),
                UINT8_BITS(r.mmc));
            ImGui::Text("MXE: %c%c%c%c%c%c%c%c", UINT8_BITS(r.mxe));
            ImGui::Text("MCM: %c%c%c%c%c%c%c%c  MDM: %c%c%c%c%c%c%c%c",
                UINT8_BITS(r.mob_mob_coll), UINT8_BITS(r.mob_data_coll));
            this->drawColor("EC: ", r.ec);
            this->drawColor("B0C: ", r.bc[0]); ImGui::SameLine();
            this->drawColor("B1C: ", r.bc[1]); ImGui::SameLine();
            this->drawColor("B2C: ", r.bc[2]); ImGui::SameLine();
            this->drawColor("B3C: ", r.bc[3]);
            this->drawColor("MM0: ", r.mm[0]); ImGui::SameLine();
            this->drawColor("MM1: ", r.mm[1]);
            this->drawColor("M0C: ", r.mc[0]); ImGui::SameLine();
            this->drawColor("M1C: ", r.mc[1]); ImGui::SameLine();
            this->drawColor("M2C: ", r.mc[2]); ImGui::SameLine();
            this->drawColor("M3C: ", r.mc[3]);
            this->drawColor("M4C: ", r.mc[4]); ImGui::SameLine();
            this->drawColor("M5C: ", r.mc[5]); ImGui::SameLine();
            this->drawColor("M6C: ", r.mc[6]); ImGui::SameLine();
            this->drawColor("M7C: ", r.mc[7]);
        }
        if (ImGui::CollapsingHeader("Sprite Units", "#sprite", true, false)) {
            for (int i = 0; i < 8; i++) {
                ImGui::PushID(i);
                static const char* labels[8] = {
                    "Sprite Unit 0", "Sprite Unit 1", "Sprite Unit 2", "Sprite Unit 3",
                    "Sprite Unit 4", "Sprite Unit 5", "Sprite Unit 6", "Sprite Unit 7",
                };
                if (ImGui::CollapsingHeader(labels[i], "#sprite", true, false)) {
                    const auto& su = vic.sunit[i];
                    ImGui::Text("h_first/last/offset:  %2d <=> %2d, %d", su.h_first, su.h_last, su.h_offset);
                    ImGui::Text("p_data: %02X", su.p_data); ImGui::SameLine();
                    ImGui::Text("mc: %02X", su.mc); ImGui::SameLine();
                    ImGui::Text("mc_base: %02X", su.mc_base);
                    ImGui::Text("dma_enabled: %s", su.dma_enabled ? "ON ":"OFF"); ImGui::SameLine();
                    ImGui::Text("disp_enabled: %s", su.disp_enabled ? "ON ":"OFF"); ImGui::SameLine();
                    ImGui::Text("expand: %s", su.expand ? "ON":"OFF");
                    drawSpriteShifter("shifter", su.shift);
                }
                ImGui::PopID();
            }
        }
        if (ImGui::CollapsingHeader("Internal State", "#vicstate", true, true)) {
            ImGui::Text("g_mode: %d   v_irq_line: %3d\n", vic.gunit.mode, vic.rs.v_irqline);
            ImGui::Text("h_count:   %2d  v_count: %3d", vic.rs.h_count, vic.rs.v_count);
            ImGui::Text("vc: %04X: vcbase: %04X rc: %d vmli: %2d", vic.rs.vc, vic.rs.vc_base, vic.rs.rc, vic.vm.vmli);
            ImGui::Text("c_addr_or: %04X i_addr:     %04X", vic.mem.c_addr_or, vic.mem.i_addr);
            ImGui::Text("g_addr_or: %04X g_addr_and: %04X",vic.mem.g_addr_or, vic.mem.g_addr_and);
            ImGui::Text("brd_left:  %2d  brd_top: %3d", vic.brd.left, vic.brd.top);
            ImGui::Text("brd_right: %2d  brd_btm: %3d", vic.brd.right, vic.brd.bottom);
            ImGui::Text("m_border: %s v_border:  %s", vic.brd.main?"ON ":"OFF", vic.brd.vert?"ON ":"OFF");
            ImGui::Text("badline:  %s display:   %s", vic.rs.badline?"ON ":"OFF", vic.rs.display_state?"ON ":"OFF");
            ImGui::Text("crt_x: %2d crt_y: %3d", vic.crt.x, vic.crt.y);
            ImGui::Text("line buffer:");
            const uint16_t* l = vic.vm.line;
            ImGui::Text("  %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X\n"
                        "  %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X\n"
                        "  %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X\n"
                        "  %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X",
                        l[ 0], l[ 1], l[ 2], l[ 3], l[ 4], l[ 5], l[ 6], l[ 7], l[ 8], l[ 9],
                        l[10], l[11], l[12], l[13], l[14], l[15], l[16], l[17], l[18], l[19],
                        l[20], l[21], l[22], l[23], l[24], l[25], l[26], l[27], l[28], l[29],
                        l[30], l[31], l[32], l[33], l[34], l[35], l[36], l[37], l[38], l[39]);
        }
        if (board.dbg.break_stopped()) {
            ImGui::Separator();
            if (ImGui::Button(">| Bad")) {
                this->badline = vic.rs.badline;
                emu.step_until([this](uint32_t ticks)->bool {
                    bool cur_badline = board.m6567.rs.badline;
                    bool triggered = (cur_badline != this->badline) && cur_badline;
                    this->badline = cur_badline;
                    return (ticks > (64*312)) || triggered;
                });
            }
            if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Run to next badline"); }
        }
    }
    ImGui::End();
    return this->Visible;
}

} // namespace YAKC
<commit_msg>fixes for m6567 changes<commit_after>//------------------------------------------------------------------------------
//  M6567Window.cc
//------------------------------------------------------------------------------
#include "M6567Window.h"
#include "IMUI/IMUI.h"
#include "Util.h"
#include "yakc/util/breadboard.h"

using namespace Oryol;

namespace YAKC {

//------------------------------------------------------------------------------
void
M6567Window::Setup(yakc& emu) {
    this->setName("M6567 (VIC-II) State");
    for (int i = 0; i < 16; i++) {
        this->paletteColors[i] = Util::RGBA8toImVec4(m6567_color(i));
    }
}

//------------------------------------------------------------------------------
void
M6567Window::drawColor(const char* text, uint8_t palIndex) {
    ImGui::Text("%s%02X", text, palIndex);
    ImGui::SameLine();
    ImGui::ColorButton(text, this->paletteColors[palIndex&0xF], ImGuiColorEditFlags_NoAlpha, ImVec2(12, 12));
}

//------------------------------------------------------------------------------
static void drawSpriteShifter(const char* label, uint32_t shf) {
    char str[33] = { };
    for (int i = 0; i < 32; i++) {
        str[i] = (((shf<<i) & (1<<31)) != 0) ? 'X':'.';
    }
    str[32] = 0;
    ImGui::Text("%s: %s\n", label, str);
}

//------------------------------------------------------------------------------
#define UINT8_BITS(m) m&(1<<7)?'1':'0',m&(1<<6)?'1':'0',m&(1<<5)?'1':'0',m&(1<<4)?'1':'0',m&(1<<3)?'1':'0',m&(1<<2)?'1':'0',m&(1<<1)?'1':'0',m&(1<<0)?'1':'0'
bool
M6567Window::Draw(yakc& emu) {
    ImGui::SetNextWindowSize(ImVec2(380, 460), ImGuiSetCond_Once);
    if (ImGui::Begin(this->title.AsCStr(), &this->Visible)) {
        m6567_t& vic = board.m6567;
        const char* type = "unknown";
        switch (vic.type) {
            case M6567_TYPE_6567R8: type = "6567R8 (NTSC)"; break;
            case M6567_TYPE_6569: type = "6569 (PAL)"; break;
        }
        ImGui::Text("Type: %s", type);
        ImGui::Checkbox("Debug Visualization", &board.m6567.debug_vis);
        if (ImGui::CollapsingHeader("Registers", "#vicreg", true, true)) {
            const auto& r = vic.reg;
            ImGui::Text("M0XY: %02X %02X M1XY: %02X %02X M2XY: %02X %02X M3XY: %02X %02X",
                r.mxy[0][0], r.mxy[0][1], r.mxy[1][0], r.mxy[1][1],
                r.mxy[2][0], r.mxy[2][1], r.mxy[3][0], r.mxy[3][1]);
            ImGui::Text("M4XY: %02X %02X M5XY: %02X %02X M6XY: %02X %02X M7XY: %02X %02X",
                r.mxy[4][0], r.mxy[4][1], r.mxy[5][0], r.mxy[6][1],
                r.mxy[6][0], r.mxy[6][1], r.mxy[7][0], r.mxy[7][1]);
            ImGui::Text("CTRL1 RST8:%c ECM:%c BMM:%c DEN:%c RSEL:%c YSCROLL:%d\n",
                r.ctrl_1 & (1<<7) ? '1':'0',
                r.ctrl_1 & (1<<6) ? '1':'0',
                r.ctrl_1 & (1<<5) ? '1':'0',
                r.ctrl_1 & (1<<4) ? '1':'0',
                r.ctrl_1 & (1<<3) ? '1':'0',
                r.ctrl_1 & 7);
            ImGui::Text("MSBX: %c%c%c%c%c%c%c%c RASTER: %02X LPX: %02X LPY: %02X",
                UINT8_BITS(r.mx8),
                r.raster, r.lightpen_xy[0], r.lightpen_xy[1]);
            ImGui::Text("ME:   %c%c%c%c%c%c%c%c", UINT8_BITS(r.me));
            ImGui::Text("CTRL2 RES:%c MCM:%c CSEL:%c XSCROLL:%d",
                r.ctrl_2 & (1<<5) ? '1':'0',
                r.ctrl_2 & (1<<4) ? '1':'0',
                r.ctrl_2 & (1<<3) ? '1':'0',
                r.ctrl_2 & 7);
            ImGui::Text("MYE:  %c%c%c%c%c%c%c%c", UINT8_BITS(r.mye));
            ImGui::Text("MEMPTRS VM:%02X CB:%02X", (r.mem_ptrs>>4)&0x0F, (r.mem_ptrs>>1)&0x07);
            ImGui::Text("INT IRQ:%c ILP:%c IMMC:%c IMBC:%c IRST:%c",
                r.int_latch & (1<<7) ? '1':'0',
                r.int_latch & (1<<3) ? '1':'0',
                r.int_latch & (1<<2) ? '1':'0',
                r.int_latch & (1<<1) ? '1':'0',
                r.int_latch & (1<<0) ? '1':'0');
            ImGui::Text("INT MASK  ELP:%c EMMC:%c EMBC:%c ERST:%c",
                r.int_mask & (1<<3) ? '1':'0',
                r.int_mask & (1<<2) ? '1':'0',
                r.int_mask & (1<<1) ? '1':'0',
                r.int_mask & (1<<0) ? '1':'0');
            ImGui::Text("MDP: %c%c%c%c%c%c%c%c  MMC: %c%c%c%c%c%c%c%c",
                UINT8_BITS(r.mdp),
                UINT8_BITS(r.mmc));
            ImGui::Text("MXE: %c%c%c%c%c%c%c%c", UINT8_BITS(r.mxe));
            ImGui::Text("MCM: %c%c%c%c%c%c%c%c  MDM: %c%c%c%c%c%c%c%c",
                UINT8_BITS(r.mob_mob_coll), UINT8_BITS(r.mob_data_coll));
            this->drawColor("EC: ", r.ec);
            this->drawColor("B0C: ", r.bc[0]); ImGui::SameLine();
            this->drawColor("B1C: ", r.bc[1]); ImGui::SameLine();
            this->drawColor("B2C: ", r.bc[2]); ImGui::SameLine();
            this->drawColor("B3C: ", r.bc[3]);
            this->drawColor("MM0: ", r.mm[0]); ImGui::SameLine();
            this->drawColor("MM1: ", r.mm[1]);
            this->drawColor("M0C: ", r.mc[0]); ImGui::SameLine();
            this->drawColor("M1C: ", r.mc[1]); ImGui::SameLine();
            this->drawColor("M2C: ", r.mc[2]); ImGui::SameLine();
            this->drawColor("M3C: ", r.mc[3]);
            this->drawColor("M4C: ", r.mc[4]); ImGui::SameLine();
            this->drawColor("M5C: ", r.mc[5]); ImGui::SameLine();
            this->drawColor("M6C: ", r.mc[6]); ImGui::SameLine();
            this->drawColor("M7C: ", r.mc[7]);
        }
        if (ImGui::CollapsingHeader("Sprite Units", "#sprite", true, false)) {
            for (int i = 0; i < 8; i++) {
                ImGui::PushID(i);
                static const char* labels[8] = {
                    "Sprite Unit 0", "Sprite Unit 1", "Sprite Unit 2", "Sprite Unit 3",
                    "Sprite Unit 4", "Sprite Unit 5", "Sprite Unit 6", "Sprite Unit 7",
                };
                if (ImGui::CollapsingHeader(labels[i], "#sprite", true, false)) {
                    const auto& su = vic.sunit[i];
                    ImGui::Text("h_first/last/offset:  %2d <=> %2d, %d", su.h_first, su.h_last, su.h_offset);
                    ImGui::Text("p_data: %02X", su.p_data); ImGui::SameLine();
                    ImGui::Text("mc: %02X", su.mc); ImGui::SameLine();
                    ImGui::Text("mc_base: %02X", su.mc_base);
                    ImGui::Text("dma_enabled: %s", su.dma_enabled ? "ON ":"OFF"); ImGui::SameLine();
                    ImGui::Text("disp_enabled: %s", su.disp_enabled ? "ON ":"OFF"); ImGui::SameLine();
                    ImGui::Text("expand: %s", su.expand ? "ON":"OFF");
                    drawSpriteShifter("shifter", su.shift);
                }
                ImGui::PopID();
            }
        }
        if (ImGui::CollapsingHeader("Internal State", "#vicstate", true, true)) {
            ImGui::Text("g_mode: %d   v_irq_line: %3d\n", vic.gunit.mode, vic.rs.v_irqline);
            ImGui::Text("h_count:   %2d  v_count: %3d", vic.rs.h_count, vic.rs.v_count);
            ImGui::Text("vc: %04X: vcbase: %04X rc: %d vmli: %2d", vic.rs.vc, vic.rs.vc_base, vic.rs.rc, vic.vm.vmli);
            ImGui::Text("c_addr_or: %04X i_addr:     %04X", vic.mem.c_addr_or, vic.mem.i_addr);
            ImGui::Text("g_addr_or: %04X g_addr_and: %04X",vic.mem.g_addr_or, vic.mem.g_addr_and);
            ImGui::Text("brd_left:  %2d  brd_top: %3d", vic.brd.left, vic.brd.top);
            ImGui::Text("brd_right: %2d  brd_btm: %3d", vic.brd.right, vic.brd.bottom);
            ImGui::Text("m_border: %s v_border:  %s", vic.brd.main?"ON ":"OFF", vic.brd.vert?"ON ":"OFF");
            ImGui::Text("badline:  %s display:   %s", vic.rs.badline?"ON ":"OFF", vic.rs.display_state?"ON ":"OFF");
            ImGui::Text("crt_x: %2d crt_y: %3d", vic.crt.x, vic.crt.y);
            ImGui::Text("line buffer:");
            const uint16_t* l = vic.vm.line;
            ImGui::Text("  %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X\n"
                        "  %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X\n"
                        "  %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X\n"
                        "  %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X",
                        l[ 0], l[ 1], l[ 2], l[ 3], l[ 4], l[ 5], l[ 6], l[ 7], l[ 8], l[ 9],
                        l[10], l[11], l[12], l[13], l[14], l[15], l[16], l[17], l[18], l[19],
                        l[20], l[21], l[22], l[23], l[24], l[25], l[26], l[27], l[28], l[29],
                        l[30], l[31], l[32], l[33], l[34], l[35], l[36], l[37], l[38], l[39]);
        }
        if (board.dbg.break_stopped()) {
            ImGui::Separator();
            if (ImGui::Button(">| Bad")) {
                this->badline = vic.rs.badline;
                emu.step_until([this](uint32_t ticks)->bool {
                    bool cur_badline = board.m6567.rs.badline;
                    bool triggered = (cur_badline != this->badline) && cur_badline;
                    this->badline = cur_badline;
                    return (ticks > (64*312)) || triggered;
                });
            }
            if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Run to next badline"); }
        }
    }
    ImGui::End();
    return this->Visible;
}

} // namespace YAKC
<|endoftext|>