<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetReaderTest
#include <cstddef>
#include <iostream>
#include <vector>
#include <boost/test/unit_test.hpp>
#include <TError.h> /// gErrorIgnoreLevel
#include <TObjString.h>

#include "../JPetReader/JPetReader.h"
#include "../JPetWriter/JPetWriter.h"

// method list
  //JPetReader(void); //maybe remove this one
  //explicit JPetReader(const char* p_filename);

  //virtual Event& getCurrentEvent();
  //virtual bool nextEvent();
  //virtual bool firstEvent();
  //virtual bool lastEvent();
  //virtual bool nthEvent(int n);
  //virtual long long getCurrentEventNumber();
  //virtual long long getNbOfAllEvents();

  //virtual bool openFileAndLoadData(const char* filename, const char* treename = "tree");
  //virtual void closeFile();
//   //JPetTreeHeader* getHeaderClone() const;

  //virtual TObject* getObjectFromFile(const char* name);
  //virtual bool isOpen() const;

BOOST_AUTO_TEST_SUITE (JPetReaderTestSuite)

BOOST_AUTO_TEST_CASE (default_constructor)
{
  JPetReader reader;
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("Empty event"));
  BOOST_REQUIRE(!reader.isOpen());
  BOOST_REQUIRE(!reader.nextEvent());
  BOOST_REQUIRE(!reader.firstEvent());
  BOOST_REQUIRE(!reader.lastEvent());
  BOOST_REQUIRE(!reader.nthEvent(0));
  BOOST_REQUIRE(!reader.nthEvent(1));
  BOOST_REQUIRE(!reader.nthEvent(-1));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), -1);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 0);
  BOOST_REQUIRE(!reader.getHeaderClone());
  BOOST_REQUIRE(!reader.getObjectFromFile("testObj"));
}

BOOST_AUTO_TEST_CASE (bad_file)
{
  gErrorIgnoreLevel = 6000; /// we turn off the ROOT error messages
  JPetReader reader;
  /// not a ROOT file
  BOOST_REQUIRE(!reader.openFileAndLoadData("bad_file.txt", "tree"));
  BOOST_REQUIRE(!reader.isOpen());
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("Empty event"));
  BOOST_REQUIRE(!reader.nextEvent());
  BOOST_REQUIRE(!reader.firstEvent());
  BOOST_REQUIRE(!reader.lastEvent());
  BOOST_REQUIRE(!reader.nthEvent(0));
  BOOST_REQUIRE(!reader.nthEvent(1));
  BOOST_REQUIRE(!reader.nthEvent(-1));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), -1);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 0);
  BOOST_REQUIRE(!reader.getHeaderClone());
  BOOST_REQUIRE(!reader.getObjectFromFile("testObj"));
}

BOOST_AUTO_TEST_CASE (good_file_with_constructor)
{
  JPetReader reader("unitTestData/JPetReaderTest/timewindows.root");
  BOOST_REQUIRE(reader.isOpen());
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("JPetTimeWindow"));
  BOOST_REQUIRE(reader.nextEvent());
  BOOST_REQUIRE(reader.firstEvent());
  BOOST_REQUIRE(reader.lastEvent());
  BOOST_REQUIRE(reader.nthEvent(0));
  BOOST_REQUIRE(reader.nthEvent(5));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), 5);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 10);
  BOOST_REQUIRE(reader.getHeaderClone());
}
BOOST_AUTO_TEST_CASE (good_file_getObject)
{
  JPetReader reader("unitTestData/JPetReaderTest/timewindows.root");
  BOOST_REQUIRE(!reader.getObjectFromFile("nonExistentObj"));
  BOOST_REQUIRE(reader.getObjectFromFile("tree"));
}

BOOST_AUTO_TEST_CASE (good_file_openFileAndLoadData)
{
  JPetReader reader;
  BOOST_REQUIRE(reader.openFileAndLoadData("unitTestData/JPetReaderTest/timewindows.root","tree"));
  BOOST_REQUIRE(reader.isOpen());
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("JPetTimeWindow"));
  BOOST_REQUIRE(reader.firstEvent());
  BOOST_REQUIRE(reader.nextEvent());
  BOOST_REQUIRE(reader.lastEvent());
  BOOST_REQUIRE(reader.nthEvent(0));
  BOOST_REQUIRE(reader.nthEvent(5));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), 5);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 10);
  BOOST_REQUIRE(reader.getHeaderClone());

}

BOOST_AUTO_TEST_CASE (good_file_closeFile)
{
  JPetReader reader;
  BOOST_REQUIRE(reader.openFileAndLoadData("unitTestData/JPetReaderTest/timewindows.root","tree"));
  BOOST_REQUIRE(reader.isOpen());
  reader.closeFile();
  BOOST_REQUIRE(!reader.isOpen());
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("Empty event"));
  BOOST_REQUIRE(!reader.nextEvent());
  BOOST_REQUIRE(!reader.firstEvent());
  BOOST_REQUIRE(!reader.lastEvent());
  BOOST_REQUIRE(!reader.nthEvent(0));
  BOOST_REQUIRE(!reader.nthEvent(1));
  BOOST_REQUIRE(!reader.nthEvent(-1));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), -1);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 0);
  BOOST_REQUIRE(!reader.getHeaderClone());
  BOOST_REQUIRE(!reader.getObjectFromFile("testObj"));
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Change name of test file used for develop version<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetReaderTest
#include <cstddef>
#include <iostream>
#include <vector>
#include <boost/test/unit_test.hpp>
#include <TError.h> /// gErrorIgnoreLevel
#include <TObjString.h>

#include "../JPetReader/JPetReader.h"
#include "../JPetWriter/JPetWriter.h"

// method list
  //JPetReader(void); //maybe remove this one
  //explicit JPetReader(const char* p_filename);

  //virtual Event& getCurrentEvent();
  //virtual bool nextEvent();
  //virtual bool firstEvent();
  //virtual bool lastEvent();
  //virtual bool nthEvent(int n);
  //virtual long long getCurrentEventNumber();
  //virtual long long getNbOfAllEvents();

  //virtual bool openFileAndLoadData(const char* filename, const char* treename = "tree");
  //virtual void closeFile();
//   //JPetTreeHeader* getHeaderClone() const;

  //virtual TObject* getObjectFromFile(const char* name);
  //virtual bool isOpen() const;

BOOST_AUTO_TEST_SUITE (JPetReaderTestSuite)

BOOST_AUTO_TEST_CASE (default_constructor)
{
  JPetReader reader;
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("Empty event"));
  BOOST_REQUIRE(!reader.isOpen());
  BOOST_REQUIRE(!reader.nextEvent());
  BOOST_REQUIRE(!reader.firstEvent());
  BOOST_REQUIRE(!reader.lastEvent());
  BOOST_REQUIRE(!reader.nthEvent(0));
  BOOST_REQUIRE(!reader.nthEvent(1));
  BOOST_REQUIRE(!reader.nthEvent(-1));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), -1);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 0);
  BOOST_REQUIRE(!reader.getHeaderClone());
  BOOST_REQUIRE(!reader.getObjectFromFile("testObj"));
}

BOOST_AUTO_TEST_CASE (bad_file)
{
  gErrorIgnoreLevel = 6000; /// we turn off the ROOT error messages
  JPetReader reader;
  /// not a ROOT file
  BOOST_REQUIRE(!reader.openFileAndLoadData("bad_file.txt", "tree"));
  BOOST_REQUIRE(!reader.isOpen());
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("Empty event"));
  BOOST_REQUIRE(!reader.nextEvent());
  BOOST_REQUIRE(!reader.firstEvent());
  BOOST_REQUIRE(!reader.lastEvent());
  BOOST_REQUIRE(!reader.nthEvent(0));
  BOOST_REQUIRE(!reader.nthEvent(1));
  BOOST_REQUIRE(!reader.nthEvent(-1));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), -1);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 0);
  BOOST_REQUIRE(!reader.getHeaderClone());
  BOOST_REQUIRE(!reader.getObjectFromFile("testObj"));
}

BOOST_AUTO_TEST_CASE (good_file_with_constructor)
{
  JPetReader reader("unitTestData/JPetReaderTest/timewindows_v2.root");
  BOOST_REQUIRE(reader.isOpen());
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("JPetTimeWindow"));
  BOOST_REQUIRE(reader.nextEvent());
  BOOST_REQUIRE(reader.firstEvent());
  BOOST_REQUIRE(reader.lastEvent());
  BOOST_REQUIRE(reader.nthEvent(0));
  BOOST_REQUIRE(reader.nthEvent(5));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), 5);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 10);
  BOOST_REQUIRE(reader.getHeaderClone());
}

BOOST_AUTO_TEST_CASE (good_file_getObject)
{
  JPetReader reader("unitTestData/JPetReaderTest/timewindows_v2.root");
  BOOST_REQUIRE(!reader.getObjectFromFile("nonExistentObj"));
  BOOST_REQUIRE(reader.getObjectFromFile("tree"));
}

BOOST_AUTO_TEST_CASE (good_file_openFileAndLoadData)
{
  JPetReader reader;
  BOOST_REQUIRE(reader.openFileAndLoadData("unitTestData/JPetReaderTest/timewindows_v2.root","tree"));
  BOOST_REQUIRE(reader.isOpen());
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("JPetTimeWindow"));
  BOOST_REQUIRE(reader.firstEvent());
  BOOST_REQUIRE(reader.nextEvent());
  BOOST_REQUIRE(reader.lastEvent());
  BOOST_REQUIRE(reader.nthEvent(0));
  BOOST_REQUIRE(reader.nthEvent(5));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), 5);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 10);
  BOOST_REQUIRE(reader.getHeaderClone());

}

BOOST_AUTO_TEST_CASE (good_file_closeFile)
{
  JPetReader reader;
  BOOST_REQUIRE(reader.openFileAndLoadData("unitTestData/JPetReaderTest/timewindows_v2.root","tree"));
  BOOST_REQUIRE(reader.isOpen());
  reader.closeFile();
  BOOST_REQUIRE(!reader.isOpen());
  BOOST_REQUIRE(std::string(reader.getCurrentEvent().GetName())==std::string("Empty event"));
  BOOST_REQUIRE(!reader.nextEvent());
  BOOST_REQUIRE(!reader.firstEvent());
  BOOST_REQUIRE(!reader.lastEvent());
  BOOST_REQUIRE(!reader.nthEvent(0));
  BOOST_REQUIRE(!reader.nthEvent(1));
  BOOST_REQUIRE(!reader.nthEvent(-1));
  BOOST_REQUIRE_EQUAL(reader.getCurrentEventNumber(), -1);
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 0);
  BOOST_REQUIRE(!reader.getHeaderClone());
  BOOST_REQUIRE(!reader.getObjectFromFile("testObj"));
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetWriterTest
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>  // for filesystem::remove
#include <TNamed.h>
#include "../JPetSigCh/JPetSigCh.h"
#include "../JPetTimeWindow/JPetTimeWindow.h"
#include "../JPetBaseSignal/JPetBaseSignal.h"
#include "../JPetRawSignal/JPetRawSignal.h"
#include "../JPetRecoSignal/JPetRecoSignal.h"
#include "../JPetPhysSignal/JPetPhysSignal.h"
#include "../JPetHit/JPetHit.h"
#include "../JPetLOR/JPetLOR.h"
#include "../JPetWriter/JPetWriter.h"
#include "../JPetReader/JPetReader.h"

//  JPetWriter(const char *p_fileName);
//  virtual ~JPetWriter(void);
//
//  template <class T>
//  bool Write(const T& obj);
//  //bool OpenFile(const char* filename);
//  void WriteHeader(TObject* header);
//  inline bool IsOpenFile() const {return fFile.IsOpen();}
//  void closeFile();
//
//  int WriteObject(const TObject* obj, const char* name){ return fFile.WriteObject(obj, name); }
//

BOOST_AUTO_TEST_SUITE(FirstSuite)

BOOST_AUTO_TEST_CASE( my_test1 )
{
  JPetWriter writer("test.root");
  BOOST_REQUIRE(writer.isOpen());
  writer.closeFile();
  BOOST_REQUIRE(!writer.isOpen());
}

BOOST_AUTO_TEST_CASE( my_test2 )
{
  std::string fileName = "test2.root";
  JPetWriter writer(fileName.c_str());
  TNamed obj("TNamed", "Title of this testObj");
  writer.write(obj);
  writer.closeFile();

  JPetReader reader(fileName.c_str());
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 1);
  TNamed& objOut = (TNamed&)reader.getCurrentEvent();
  BOOST_REQUIRE(std::string(objOut.GetName())=="TNamed");
  BOOST_REQUIRE(std::string(objOut.GetTitle())=="Title of this testObj");
}

/// a tree must have a name if not SetAutoSave makes it crash when when call Branch
BOOST_AUTO_TEST_CASE( my_helperTest_for_test3 )
{
  std::string fileName = "test3_bis.root";
  TFile file(fileName.c_str(), "RECREATE");
  TTree tree("tree", "tree");
  tree.SetAutoSave(1000);
  TNamed* filler = 0;
  tree.Branch("TNamed", "TNamed", &filler);
  const int kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    TNamed obj("TNamed", Form("Title of this testObj%d",i));
    filler = &obj;
    tree.Fill();
    tree.FlushBaskets();
  }
  std::cout <<std::endl;
  file.Close();
}

BOOST_AUTO_TEST_CASE( my_test3 )
{
  std::string fileName = "test3.root";
  JPetWriter writer(fileName.c_str());
  const int kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    TNamed obj("TNamed", Form("Title of this testObj%d",i));
    if (i%1000==0) std::cout<<"*"<<std::flush;
    writer.write(obj);
  }
  std::cout <<std::endl;
  writer.closeFile();

  JPetReader reader(fileName.c_str());
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), kHugeNumberOfObjects);
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    reader.nthEvent(i);
    TNamed& objOut = (TNamed&)reader.getCurrentEvent();
    BOOST_REQUIRE(std::string(objOut.GetName())=="TNamed");
    BOOST_REQUIRE(std::string(objOut.GetTitle())==Form("Title of this testObj%d",i));
  }
}

BOOST_AUTO_TEST_CASE( saving_different_objects1 )
{
  //JPetSigCh testJPetSigCh;
   auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetSigCh testJPetSigCh;
    writer.write(testJPetSigCh);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects2 )
{
  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetTimeWindow testJPetTimeWindow;
    writer.write(testJPetTimeWindow);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects3 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetBaseSignal testJPetBaseSignal;
    writer.write(testJPetBaseSignal);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects4 )
{
  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetRawSignal testJPetRawSignal;
    writer.write(testJPetRawSignal);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects5 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetRecoSignal testJPetRecoSignal;
    writer.write(testJPetRecoSignal);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects6 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetPhysSignal testJPetPhysSignal;
    writer.write(testJPetPhysSignal);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects7 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetHit testJPetHit;
    writer.write(testJPetHit);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects8 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetLOR testJPetLOR;
    writer.write(testJPetLOR);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Added cppcheck comment to JPetWriterTest.cpp to suppress null pointer error<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetWriterTest
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>  // for filesystem::remove
#include <TNamed.h>
#include "../JPetSigCh/JPetSigCh.h"
#include "../JPetTimeWindow/JPetTimeWindow.h"
#include "../JPetBaseSignal/JPetBaseSignal.h"
#include "../JPetRawSignal/JPetRawSignal.h"
#include "../JPetRecoSignal/JPetRecoSignal.h"
#include "../JPetPhysSignal/JPetPhysSignal.h"
#include "../JPetHit/JPetHit.h"
#include "../JPetLOR/JPetLOR.h"
#include "../JPetWriter/JPetWriter.h"
#include "../JPetReader/JPetReader.h"

//  JPetWriter(const char *p_fileName);
//  virtual ~JPetWriter(void);
//
//  template <class T>
//  bool Write(const T& obj);
//  //bool OpenFile(const char* filename);
//  void WriteHeader(TObject* header);
//  inline bool IsOpenFile() const {return fFile.IsOpen();}
//  void closeFile();
//
//  int WriteObject(const TObject* obj, const char* name){ return fFile.WriteObject(obj, name); }
//

BOOST_AUTO_TEST_SUITE(FirstSuite)

BOOST_AUTO_TEST_CASE( my_test1 )
{
  JPetWriter writer("test.root");
  BOOST_REQUIRE(writer.isOpen());
  writer.closeFile();
  BOOST_REQUIRE(!writer.isOpen());
}

BOOST_AUTO_TEST_CASE( my_test2 )
{
  std::string fileName = "test2.root";
  JPetWriter writer(fileName.c_str());
  TNamed obj("TNamed", "Title of this testObj");
  writer.write(obj);
  writer.closeFile();

  JPetReader reader(fileName.c_str());
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), 1);
  TNamed& objOut = (TNamed&)reader.getCurrentEvent();
  BOOST_REQUIRE(std::string(objOut.GetName())=="TNamed");
  BOOST_REQUIRE(std::string(objOut.GetTitle())=="Title of this testObj");
}

/// a tree must have a name if not SetAutoSave makes it crash when when call Branch
BOOST_AUTO_TEST_CASE( my_helperTest_for_test3 )
{
  std::string fileName = "test3_bis.root";
  TFile file(fileName.c_str(), "RECREATE");
  TTree tree("tree", "tree");
  tree.SetAutoSave(1000);
  TNamed* filler = 0;
  // cppcheck-suppress nullPointer
  tree.Branch("TNamed", "TNamed", &filler);
  const int kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    TNamed obj("TNamed", Form("Title of this testObj%d",i));
    filler = &obj;
    tree.Fill();
    tree.FlushBaskets();
  }
  std::cout <<std::endl;
  file.Close();
}

BOOST_AUTO_TEST_CASE( my_test3 )
{
  std::string fileName = "test3.root";
  JPetWriter writer(fileName.c_str());
  const int kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    TNamed obj("TNamed", Form("Title of this testObj%d",i));
    if (i%1000==0) std::cout<<"*"<<std::flush;
    writer.write(obj);
  }
  std::cout <<std::endl;
  writer.closeFile();

  JPetReader reader(fileName.c_str());
  BOOST_REQUIRE_EQUAL(reader.getNbOfAllEvents(), kHugeNumberOfObjects);
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    reader.nthEvent(i);
    TNamed& objOut = (TNamed&)reader.getCurrentEvent();
    BOOST_REQUIRE(std::string(objOut.GetName())=="TNamed");
    BOOST_REQUIRE(std::string(objOut.GetTitle())==Form("Title of this testObj%d",i));
  }
}

BOOST_AUTO_TEST_CASE( saving_different_objects1 )
{
  //JPetSigCh testJPetSigCh;
   auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetSigCh testJPetSigCh;
    writer.write(testJPetSigCh);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects2 )
{
  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetTimeWindow testJPetTimeWindow;
    writer.write(testJPetTimeWindow);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects3 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetBaseSignal testJPetBaseSignal;
    writer.write(testJPetBaseSignal);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects4 )
{
  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetRawSignal testJPetRawSignal;
    writer.write(testJPetRawSignal);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects5 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetRecoSignal testJPetRecoSignal;
    writer.write(testJPetRecoSignal);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects6 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetPhysSignal testJPetPhysSignal;
    writer.write(testJPetPhysSignal);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects7 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetHit testJPetHit;
    writer.write(testJPetHit);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_CASE( saving_different_objects8 )
{

  auto fileTest = "saving_different_objectsTest.root";
  JPetWriter writer(fileTest);
  const auto kHugeNumberOfObjects = 10000;
  for (int i = 0; i < kHugeNumberOfObjects; i++) {
    if (i%1000==0) std::cout<<"*"<<std::flush;
    JPetLOR testJPetLOR;
    writer.write(testJPetLOR);
  }
  if(boost::filesystem::exists(fileTest))
          boost::filesystem::remove(fileTest);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file ir_function_inlining.cpp
 *
 * Replaces calls to functions with the body of the function.
 */

#include <inttypes.h>
#include "ir.h"
#include "ir_visitor.h"
#include "ir_function_inlining.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"
#include "program/hash_table.h"

class ir_function_inlining_visitor : public ir_hierarchical_visitor {
public:
   ir_function_inlining_visitor()
   {
      progress = false;
   }

   virtual ~ir_function_inlining_visitor()
   {
      /* empty */
   }

   virtual ir_visitor_status visit_enter(ir_expression *);
   virtual ir_visitor_status visit_enter(ir_call *);
   virtual ir_visitor_status visit_enter(ir_assignment *);
   virtual ir_visitor_status visit_enter(ir_return *);
   virtual ir_visitor_status visit_enter(ir_texture *);
   virtual ir_visitor_status visit_enter(ir_swizzle *);

   bool progress;
};

bool
automatic_inlining_predicate(ir_instruction *ir)
{
   ir_call *call = ir->as_call();

   if (call && can_inline(call))
      return true;

   return false;
}

bool
do_function_inlining(exec_list *instructions)
{
   ir_function_inlining_visitor v;

   do_expression_flattening(instructions, automatic_inlining_predicate);

   v.run(instructions);

   return v.progress;
}

static void
replace_return_with_assignment(ir_instruction *ir, void *data)
{
   void *ctx = talloc_parent(ir);
   ir_variable *retval = (ir_variable *)data;
   ir_return *ret = ir->as_return();

   if (ret) {
      if (ret->value) {
	 ir_rvalue *lhs = new(ctx) ir_dereference_variable(retval);
	 ret->replace_with(new(ctx) ir_assignment(lhs, ret->value, NULL));
      } else {
	 /* un-valued return has to be the last return, or we shouldn't
	  * have reached here. (see can_inline()).
	  */
	 assert(!ret->next->is_tail_sentinel());
	 ret->remove();
      }
   }
}

ir_rvalue *
ir_call::generate_inline(ir_instruction *next_ir)
{
   void *ctx = talloc_parent(this);
   ir_variable **parameters;
   int num_parameters;
   int i;
   ir_variable *retval = NULL;
   struct hash_table *ht;

   ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);

   num_parameters = 0;
   foreach_iter(exec_list_iterator, iter_sig, this->callee->parameters)
      num_parameters++;

   parameters = new ir_variable *[num_parameters];

   /* Generate storage for the return value. */
   if (this->callee->return_type) {
      retval = new(ctx) ir_variable(this->callee->return_type, "__retval",
				    ir_var_auto);
      next_ir->insert_before(retval);
   }

   /* Generate the declarations for the parameters to our inlined code,
    * and set up the mapping of real function body variables to ours.
    */
   i = 0;
   exec_list_iterator sig_param_iter = this->callee->parameters.iterator();
   exec_list_iterator param_iter = this->actual_parameters.iterator();
   for (i = 0; i < num_parameters; i++) {
      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
      ir_rvalue *param = (ir_rvalue *) param_iter.get();

      /* Generate a new variable for the parameter. */
      if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
	 /* For samplers, we want the inlined sampler references
	  * referencing the passed in sampler variable, since that
	  * will have the location information, which an assignment of
	  * a sampler wouldn't.
	  */
	 parameters[i] = NULL;
	 hash_table_insert(ht, param->variable_referenced(), sig_param);
      } else {
	 parameters[i] = sig_param->clone(ctx, ht);
	 parameters[i]->mode = ir_var_auto;
	 next_ir->insert_before(parameters[i]);
      }

      /* Move the actual param into our param variable if it's an 'in' type. */
      if (parameters[i] && (sig_param->mode == ir_var_in ||
			    sig_param->mode == ir_var_inout)) {
	 ir_assignment *assign;

	 assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]),
					 param, NULL);
	 next_ir->insert_before(assign);
      }

      sig_param_iter.next();
      param_iter.next();
   }

   /* Generate the inlined body of the function. */
   foreach_iter(exec_list_iterator, iter, callee->body) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      ir_instruction *new_ir = ir->clone(ctx, ht);

      next_ir->insert_before(new_ir);
      visit_tree(new_ir, replace_return_with_assignment, retval);
   }

   /* Copy back the value of any 'out' parameters from the function body
    * variables to our own.
    */
   i = 0;
   param_iter = this->actual_parameters.iterator();
   sig_param_iter = this->callee->parameters.iterator();
   for (i = 0; i < num_parameters; i++) {
      ir_instruction *const param = (ir_instruction *) param_iter.get();
      const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get();

      /* Move our param variable into the actual param if it's an 'out' type. */
      if (parameters[i] && (sig_param->mode == ir_var_out ||
			    sig_param->mode == ir_var_inout)) {
	 ir_assignment *assign;

	 assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(),
					 new(ctx) ir_dereference_variable(parameters[i]),
					 NULL);
	 next_ir->insert_before(assign);
      }

      param_iter.next();
      sig_param_iter.next();
   }

   delete [] parameters;

   hash_table_dtor(ht);

   if (retval)
      return new(ctx) ir_dereference_variable(retval);
   else
      return NULL;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_expression *ir)
{
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_return *ir)
{
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_texture *ir)
{
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_swizzle *ir)
{
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_call *ir)
{
   if (can_inline(ir)) {
      /* If the call was part of some tree, then it should have been
       * flattened out or we shouldn't have seen it because of a
       * visit_continue_with_parent in this visitor.
       */
      assert(ir == base_ir);

      (void) ir->generate_inline(ir);
      ir->remove();
      this->progress = true;
   }

   return visit_continue;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_assignment *ir)
{
   ir_call *call = ir->rhs->as_call();
   if (!call || !can_inline(call))
      return visit_continue;

   /* generates the parameter setup, function body, and returns the return
    * value of the function
    */
   ir_rvalue *rhs = call->generate_inline(ir);
   assert(rhs);

   ir->rhs = rhs;
   this->progress = true;

   return visit_continue;
}
<commit_msg>glsl2: Fix inlining with sampler array or struct dereferences as arguments.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file ir_function_inlining.cpp
 *
 * Replaces calls to functions with the body of the function.
 */

#include <inttypes.h>
#include "ir.h"
#include "ir_visitor.h"
#include "ir_function_inlining.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"
#include "program/hash_table.h"

static void
do_sampler_replacement(exec_list *instructions,
		       ir_variable *sampler,
		       ir_dereference *deref);

class ir_function_inlining_visitor : public ir_hierarchical_visitor {
public:
   ir_function_inlining_visitor()
   {
      progress = false;
   }

   virtual ~ir_function_inlining_visitor()
   {
      /* empty */
   }

   virtual ir_visitor_status visit_enter(ir_expression *);
   virtual ir_visitor_status visit_enter(ir_call *);
   virtual ir_visitor_status visit_enter(ir_assignment *);
   virtual ir_visitor_status visit_enter(ir_return *);
   virtual ir_visitor_status visit_enter(ir_texture *);
   virtual ir_visitor_status visit_enter(ir_swizzle *);

   bool progress;
};

bool
automatic_inlining_predicate(ir_instruction *ir)
{
   ir_call *call = ir->as_call();

   if (call && can_inline(call))
      return true;

   return false;
}

bool
do_function_inlining(exec_list *instructions)
{
   ir_function_inlining_visitor v;

   do_expression_flattening(instructions, automatic_inlining_predicate);

   v.run(instructions);

   return v.progress;
}

static void
replace_return_with_assignment(ir_instruction *ir, void *data)
{
   void *ctx = talloc_parent(ir);
   ir_variable *retval = (ir_variable *)data;
   ir_return *ret = ir->as_return();

   if (ret) {
      if (ret->value) {
	 ir_rvalue *lhs = new(ctx) ir_dereference_variable(retval);
	 ret->replace_with(new(ctx) ir_assignment(lhs, ret->value, NULL));
      } else {
	 /* un-valued return has to be the last return, or we shouldn't
	  * have reached here. (see can_inline()).
	  */
	 assert(ret->next->is_tail_sentinel());
	 ret->remove();
      }
   }
}

ir_rvalue *
ir_call::generate_inline(ir_instruction *next_ir)
{
   void *ctx = talloc_parent(this);
   ir_variable **parameters;
   int num_parameters;
   int i;
   ir_variable *retval = NULL;
   struct hash_table *ht;

   ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);

   num_parameters = 0;
   foreach_iter(exec_list_iterator, iter_sig, this->callee->parameters)
      num_parameters++;

   parameters = new ir_variable *[num_parameters];

   /* Generate storage for the return value. */
   if (this->callee->return_type) {
      retval = new(ctx) ir_variable(this->callee->return_type, "__retval",
				    ir_var_auto);
      next_ir->insert_before(retval);
   }

   /* Generate the declarations for the parameters to our inlined code,
    * and set up the mapping of real function body variables to ours.
    */
   i = 0;
   exec_list_iterator sig_param_iter = this->callee->parameters.iterator();
   exec_list_iterator param_iter = this->actual_parameters.iterator();
   for (i = 0; i < num_parameters; i++) {
      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
      ir_rvalue *param = (ir_rvalue *) param_iter.get();

      /* Generate a new variable for the parameter. */
      if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
	 /* For samplers, we want the inlined sampler references
	  * referencing the passed in sampler variable, since that
	  * will have the location information, which an assignment of
	  * a sampler wouldn't.  Fix it up below.
	  */
	 parameters[i] = NULL;
      } else {
	 parameters[i] = sig_param->clone(ctx, ht);
	 parameters[i]->mode = ir_var_auto;
	 next_ir->insert_before(parameters[i]);
      }

      /* Move the actual param into our param variable if it's an 'in' type. */
      if (parameters[i] && (sig_param->mode == ir_var_in ||
			    sig_param->mode == ir_var_inout)) {
	 ir_assignment *assign;

	 assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]),
					 param, NULL);
	 next_ir->insert_before(assign);
      }

      sig_param_iter.next();
      param_iter.next();
   }

   exec_list new_instructions;

   /* Generate the inlined body of the function to a new list */
   foreach_iter(exec_list_iterator, iter, callee->body) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      ir_instruction *new_ir = ir->clone(ctx, ht);

      new_instructions.push_tail(new_ir);
      visit_tree(new_ir, replace_return_with_assignment, retval);
   }

   /* If any samplers were passed in, replace any deref of the sampler
    * with a deref of the sampler argument.
    */
   param_iter = this->actual_parameters.iterator();
   sig_param_iter = this->callee->parameters.iterator();
   for (i = 0; i < num_parameters; i++) {
      ir_instruction *const param = (ir_instruction *) param_iter.get();
      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();

      if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
	 ir_dereference *deref = param->as_dereference();

	 assert(deref);
	 do_sampler_replacement(&new_instructions, sig_param, deref);
      }
   }

   /* Now push those new instructions in. */
   foreach_iter(exec_list_iterator, iter, new_instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      next_ir->insert_before(ir);
   }

   /* Copy back the value of any 'out' parameters from the function body
    * variables to our own.
    */
   i = 0;
   param_iter = this->actual_parameters.iterator();
   sig_param_iter = this->callee->parameters.iterator();
   for (i = 0; i < num_parameters; i++) {
      ir_instruction *const param = (ir_instruction *) param_iter.get();
      const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get();

      /* Move our param variable into the actual param if it's an 'out' type. */
      if (parameters[i] && (sig_param->mode == ir_var_out ||
			    sig_param->mode == ir_var_inout)) {
	 ir_assignment *assign;

	 assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(),
					 new(ctx) ir_dereference_variable(parameters[i]),
					 NULL);
	 next_ir->insert_before(assign);
      }

      param_iter.next();
      sig_param_iter.next();
   }

   delete [] parameters;

   hash_table_dtor(ht);

   if (retval)
      return new(ctx) ir_dereference_variable(retval);
   else
      return NULL;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_expression *ir)
{
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_return *ir)
{
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_texture *ir)
{
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_swizzle *ir)
{
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_call *ir)
{
   if (can_inline(ir)) {
      /* If the call was part of some tree, then it should have been
       * flattened out or we shouldn't have seen it because of a
       * visit_continue_with_parent in this visitor.
       */
      assert(ir == base_ir);

      (void) ir->generate_inline(ir);
      ir->remove();
      this->progress = true;
   }

   return visit_continue;
}

ir_visitor_status
ir_function_inlining_visitor::visit_enter(ir_assignment *ir)
{
   ir_call *call = ir->rhs->as_call();
   if (!call || !can_inline(call))
      return visit_continue;

   /* generates the parameter setup, function body, and returns the return
    * value of the function
    */
   ir_rvalue *rhs = call->generate_inline(ir);
   assert(rhs);

   ir->rhs = rhs;
   this->progress = true;

   return visit_continue;
}

/**
 * Replaces references to the "sampler" variable with a clone of "deref."
 *
 * From the spec, samplers can appear in the tree as function
 * (non-out) parameters and as the result of array indexing and
 * structure field selection.  In our builtin implementation, they
 * also appear in the sampler field of an ir_tex instruction.
 */

class ir_sampler_replacement_visitor : public ir_hierarchical_visitor {
public:
   ir_sampler_replacement_visitor(ir_variable *sampler, ir_dereference *deref)
   {
      this->sampler = sampler;
      this->deref = deref;
   }

   virtual ~ir_sampler_replacement_visitor()
   {
   }

   virtual ir_visitor_status visit_leave(ir_call *);
   virtual ir_visitor_status visit_leave(ir_dereference_array *);
   virtual ir_visitor_status visit_leave(ir_dereference_record *);
   virtual ir_visitor_status visit_leave(ir_texture *);

   void replace_deref(ir_dereference **deref);
   void replace_rvalue(ir_rvalue **rvalue);

   ir_variable *sampler;
   ir_dereference *deref;
};

void
ir_sampler_replacement_visitor::replace_deref(ir_dereference **deref)
{
   ir_dereference_variable *deref_var = (*deref)->as_dereference_variable();
   if (deref_var && deref_var->var == this->sampler) {
      *deref = this->deref->clone(talloc_parent(*deref), NULL);
   }
}

void
ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue)
{
   if (!*rvalue)
      return;

   ir_dereference *deref = (*rvalue)->as_dereference();

   if (!deref)
      return;

   replace_deref(&deref);
   *rvalue = deref;
}

ir_visitor_status
ir_sampler_replacement_visitor::visit_leave(ir_texture *ir)
{
   replace_deref(&ir->sampler);

   return visit_continue;
}

ir_visitor_status
ir_sampler_replacement_visitor::visit_leave(ir_dereference_array *ir)
{
   replace_rvalue(&ir->array);
   return visit_continue;
}

ir_visitor_status
ir_sampler_replacement_visitor::visit_leave(ir_dereference_record *ir)
{
   replace_rvalue(&ir->record);
   return visit_continue;
}

ir_visitor_status
ir_sampler_replacement_visitor::visit_leave(ir_call *ir)
{
   foreach_iter(exec_list_iterator, iter, *ir) {
      ir_rvalue *param = (ir_rvalue *)iter.get();
      ir_rvalue *new_param = param;
      replace_rvalue(&new_param);

      if (new_param != param) {
	 param->replace_with(new_param);
      }
   }
   return visit_continue;
}

static void
do_sampler_replacement(exec_list *instructions,
		       ir_variable *sampler,
		       ir_dereference *deref)
{
   ir_sampler_replacement_visitor v(sampler, deref);

   visit_list_elements(&v, instructions);
}
<|endoftext|>


<commit_before>/* This file is part of VoltDB.
 * Copyright (C) 2008-2010 VoltDB L.L.C.
 *
 * VoltDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VoltDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef FATALEXCEPTION_HPP_
#define FATALEXCEPTION_HPP_

#include <string>
#include <string.h>
#include <execinfo.h>
#include <cxxabi.h>
#include <vector>
#include "boost/scoped_array.hpp"

#define throwFatalException(...) { char reallysuperbig_nonce_message[8192]; sprintf(reallysuperbig_nonce_message, __VA_ARGS__); throw voltdb::FatalException( reallysuperbig_nonce_message, __FILE__, __LINE__); }
namespace voltdb {
class FatalException {
public:
    FatalException(std::string message, const char *filename, unsigned long lineno) :
        m_reason(message), m_filename(filename), m_lineno(lineno) {
        void *traces[128];
        const int numTraces = backtrace( traces, 128);
        boost::scoped_array<char*> traceSymbols(backtrace_symbols( traces, 128));
        for (int ii = 0; ii < numTraces; ii++) {
            std::size_t sz = 200;
            char *function = static_cast<char*>(malloc(sz));
            char *begin = NULL, *end = NULL;
            //Find parens surrounding mangled name
            for (char *j = traceSymbols[ii]; *j; ++j) {
                if (*j == '(') {
                    begin = j;
                }
                else if (*j == '+') {
                    end = j;
                }
            }

            if (begin && end) {
                *begin++ = '\0';
                *end = '\0';

                int status;
                char *ret = abi::__cxa_demangle(begin, function, &sz, &status);
                if (ret) {
                    //return value may be a realloc of input
                    function = ret;
                } else {
                    // demangle failed, treat it like a C function with no args
                    strncpy(function, begin, sz);
                    strncat(function, "()", sz);
                    function[sz-1] = '\0';
                }
                m_traces.push_back(std::string(function));
            } else {
                //didn't find the mangled name in the trace
                m_traces.push_back(std::string(traceSymbols[ii]));
            }
            free(function);
        }
    }
    const std::string m_reason;
    const char *m_filename;
    const unsigned long m_lineno;
    std::vector<std::string> m_traces;
};
}
#endif /* FATALEXCEPTION_HPP_ */
<commit_msg>Add attribution to stack trace beautifying code.<commit_after>/* This file is part of VoltDB.
 * Copyright (C) 2008-2010 VoltDB L.L.C.
 *
 * VoltDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VoltDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef FATALEXCEPTION_HPP_
#define FATALEXCEPTION_HPP_

#include <string>
#include <string.h>
#include <execinfo.h>
#include <cxxabi.h>
#include <vector>
#include "boost/scoped_array.hpp"

#define throwFatalException(...) { char reallysuperbig_nonce_message[8192]; sprintf(reallysuperbig_nonce_message, __VA_ARGS__); throw voltdb::FatalException( reallysuperbig_nonce_message, __FILE__, __LINE__); }
namespace voltdb {
class FatalException {
public:
    /**
     * Stack trace code from http://tombarta.wordpress.com/2008/08/01/c-stack-traces-with-gcc/
     *
     */
    FatalException(std::string message, const char *filename, unsigned long lineno) :
        m_reason(message), m_filename(filename), m_lineno(lineno) {
        void *traces[128];
        const int numTraces = backtrace( traces, 128);
        boost::scoped_array<char*> traceSymbols(backtrace_symbols( traces, 128));
        for (int ii = 0; ii < numTraces; ii++) {
            std::size_t sz = 200;
            char *function = static_cast<char*>(malloc(sz));
            char *begin = NULL, *end = NULL;
            //Find parens surrounding mangled name
            for (char *j = traceSymbols[ii]; *j; ++j) {
                if (*j == '(') {
                    begin = j;
                }
                else if (*j == '+') {
                    end = j;
                }
            }

            if (begin && end) {
                *begin++ = '\0';
                *end = '\0';

                int status;
                char *ret = abi::__cxa_demangle(begin, function, &sz, &status);
                if (ret) {
                    //return value may be a realloc of input
                    function = ret;
                } else {
                    // demangle failed, treat it like a C function with no args
                    strncpy(function, begin, sz);
                    strncat(function, "()", sz);
                    function[sz-1] = '\0';
                }
                m_traces.push_back(std::string(function));
            } else {
                //didn't find the mangled name in the trace
                m_traces.push_back(std::string(traceSymbols[ii]));
            }
            free(function);
        }
    }
    const std::string m_reason;
    const char *m_filename;
    const unsigned long m_lineno;
    std::vector<std::string> m_traces;
};
}
#endif /* FATALEXCEPTION_HPP_ */
<|endoftext|>


<commit_before>#include "SkBlurDrawLooper.h"
#include "SkBlurMaskFilter.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkMaskFilter.h"

SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
                                   SkColor color)
    : fDx(dx), fDy(dy), fBlurColor(color)
{
    if (radius > 0)
        fBlur = SkBlurMaskFilter::Create(radius,
                                         SkBlurMaskFilter::kNormal_BlurStyle);
    else
        fBlur = NULL;
}

SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
{
    fDx = buffer.readScalar();
    fDy = buffer.readScalar();
    fBlurColor = buffer.readU32();
    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
}

SkBlurDrawLooper::~SkBlurDrawLooper()
{
    fBlur->safeUnref();
}

void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
{
    buffer.writeScalar(fDx);
    buffer.writeScalar(fDy);
    buffer.write32(fBlurColor);
    buffer.writeFlattenable(fBlur);
}

void SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
{
    // we do nothing if a maskfilter is already installed
    if (paint->getMaskFilter() != NULL)
        fState = kDone;
    else
    {
        fState = kBeforeEdge;
        fPaint = paint;
        fCanvas = canvas;
        fSaveCount = canvas->getSaveCount();
    }
}

bool SkBlurDrawLooper::next()
{
    switch (fState) {
    case kBeforeEdge:
        fSavedColor = fPaint->getColor();
        fPaint->setColor(fBlurColor);
        fPaint->setMaskFilter(fBlur);
        fCanvas->save(SkCanvas::kMatrix_SaveFlag);
        fCanvas->translate(fDx, fDy);
        fState = kAfterEdge;
        return true;
    case kAfterEdge:
        fPaint->setColor(fSavedColor);
        fPaint->setMaskFilter(NULL);
        fCanvas->restore(); // to remove the translate we did earlier
        fState = kDone;
        return true;
    default:
        SkASSERT(kDone == fState);
        return false;
    }
}

void SkBlurDrawLooper::restore()
{
    if (kAfterEdge == fState)
    {
        fPaint->setColor(fSavedColor);
        fPaint->setMaskFilter(NULL);
        fCanvas->restore(); // to remove the translate we did earlier
        fState = kDone;
    }
}

///////////////////////////////////////////////////////////////////////////////

static SkFlattenable::Registrar gReg("SkBlurDrawLooper",
                                     SkBlurDrawLooper::CreateProc);

<commit_msg>Applies the paint's alpha to drop shadows.<commit_after>#include "SkBlurDrawLooper.h"
#include "SkBlurMaskFilter.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkMaskFilter.h"

SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
                                   SkColor color)
    : fDx(dx), fDy(dy), fBlurColor(color)
{
    if (radius > 0)
        fBlur = SkBlurMaskFilter::Create(radius,
                                         SkBlurMaskFilter::kNormal_BlurStyle);
    else
        fBlur = NULL;
}

SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
{
    fDx = buffer.readScalar();
    fDy = buffer.readScalar();
    fBlurColor = buffer.readU32();
    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
}

SkBlurDrawLooper::~SkBlurDrawLooper()
{
    fBlur->safeUnref();
}

void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer)
{
    buffer.writeScalar(fDx);
    buffer.writeScalar(fDy);
    buffer.write32(fBlurColor);
    buffer.writeFlattenable(fBlur);
}

void SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint)
{
    // we do nothing if a maskfilter is already installed
    if (paint->getMaskFilter() != NULL)
        fState = kDone;
    else
    {
        fState = kBeforeEdge;
        fPaint = paint;
        fCanvas = canvas;
        fSaveCount = canvas->getSaveCount();
    }
}

bool SkBlurDrawLooper::next()
{
    SkColor blurColor;
    SkAlpha alpha;
    switch (fState) {
    case kBeforeEdge:
        fSavedColor = fPaint->getColor();
        blurColor = fBlurColor;
        alpha = SkColorGetA(blurColor);
        if (alpha == 255) {
            blurColor = SkColorSetA(blurColor, fPaint->getAlpha());
        }
        fPaint->setColor(blurColor);
        fPaint->setMaskFilter(fBlur);
        fCanvas->save(SkCanvas::kMatrix_SaveFlag);
        fCanvas->translate(fDx, fDy);
        fState = kAfterEdge;
        return true;
    case kAfterEdge:
        fPaint->setColor(fSavedColor);
        fPaint->setMaskFilter(NULL);
        fCanvas->restore(); // to remove the translate we did earlier
        fState = kDone;
        return true;
    default:
        SkASSERT(kDone == fState);
        return false;
    }
}

void SkBlurDrawLooper::restore()
{
    if (kAfterEdge == fState)
    {
        fPaint->setColor(fSavedColor);
        fPaint->setMaskFilter(NULL);
        fCanvas->restore(); // to remove the translate we did earlier
        fState = kDone;
    }
}

///////////////////////////////////////////////////////////////////////////////

static SkFlattenable::Registrar gReg("SkBlurDrawLooper",
                                     SkBlurDrawLooper::CreateProc);

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <serialize/binary-i-serializer.hh>

#include <libport/finally.hh>

#include <ast/nary.hh>
#include <ast/stmt.hh>

#include <libport/debug.hh>

#include <urbi/object/lobby.hh>
#include <urbi/object/object.hh>
#include <urbi/object/tag.hh>

#include <urbi/uvalue-serialize.hh>

#include <object/system.hh>

#include <ast/print.hh>
#include <kernel/uconnection.hh>
#include <kernel/uobject.hh>
#include <kernel/userver.hh>
#include <parser/transform.hh>
#include <parser/uparser.hh>
#include <runner/exception.hh>
#include <runner/shell.hh>

#include <sched/job.hh>
#include <sched/scheduler.hh>

namespace runner
{
  GD_CATEGORY(Urbi.Shell);

  Shell::Shell(const rLobby& lobby,
	       sched::Scheduler& scheduler,
	       const std::string& name,
               std::istream& input)
    : Interpreter(lobby, scheduler, ast::rConstAst(), name)
    , executing_(false)
    , input_(input)
    , stop_(false)
    , binary_mode_(false)
    , parser_(new parser::UParser(input_))
  {
    GD_FINFO_TRACE("new shell: %s %p", name_get(), this);
  }

  Shell::~Shell()
  {
    GD_FINFO_TRACE("dying shell: %s %p", name_get(), this);
    if (serializationJob_)
      serializationJob_->terminate_asap();
    delete parser_;
  }

  void
  Shell::eval_print_(const ast::Exp* exp)
  {
    // Visual Studio on Windows does not rewind the stack before the
    // end of a "try/catch" block, "catch" included. It means that we
    // cannot display the exception in the "catch" block in case this
    // is a scheduling error due to stack exhaustion, as we may need
    // the stack. The following objects will be set if we have an
    // exception to show, and it will be printed after the "catch"
    // block, or if we have an exception to rethrow.
    boost::scoped_ptr<object::UrbiException> exception_to_show;

    try
    {
      object::rObject res = operator()(exp);

      // We need to keep checking for void here because it
      // cannot be passed to the << function.
      if (res && res != object::void_class)
      {
        // Display the value using the topLevel channel.  If it is not
        // (yet) defined, do nothing, unless this environment variable
        // is set.
        static bool toplevel_debug = getenv("URBI_TOPLEVEL");

        rSlot topLevel =
          lobby_get()->slot_locate(SYMBOL(topLevel), false).second;
       if (topLevel)
         topLevel->value()->call(SYMBOL(LT_LT), res);
        else if (toplevel_debug)
        {
          try
          {
            rObject result = res->call(SYMBOL(asToplevelPrintable));
            std::ostringstream os;
            result->print(os);
            lobby_->connection_get().send(os.str());
            lobby_->connection_get().endline();
          }
          catch (object::UrbiException&)
          {
            // nothing
          }
        }
      }
    }
    // Catch and print unhandled exceptions
    catch (object::UrbiException& e)
    {
      exception_to_show.reset(new object::UrbiException(e.value_get(),
                                                        e.backtrace_get()));
    }
    // When we receive the exception fired by "connectionTag.stop",
    // kill the jobs, not the shell.
    catch (const sched::StopException& e)
    {
      GD_FINFO_DUMP("StopException ignored: %s", e.what());
    }
    catch (const sched::TerminateException&)
    {
      GD_INFO_DUMP("TerminateException");
      throw;
    }
    // Stop invalid exceptions thrown by primitives
    catch (const std::exception& e)
    {
      Exception::warn(exp->location_get(),
                      libport::format("invalid exception caught: %s",
                                      e.what()));
    }
    catch (...)
    {
      Exception::warn(exp->location_get(), "unknown exception caught");
    }

    if (exception_to_show.get())
      show_exception(*exception_to_show);
  }

  void
  Shell::handle_command_(ast::rConstExp exp, bool canYield)
  {
    LIBPORT_SCOPE_SET(executing_, true);
    const ast::Stmt* stmt = dynamic_cast<const ast::Stmt*>(exp.get());

    if (stmt && stmt->flavor_get() == ast::flavor_comma)
    {
      GD_FPUSH_TRACE("%s: executing command in background.", name_get());
      GD_FINFO_DUMP("%s: command: %s", name_get(), *exp);
      sched::rJob subrunner =
        new Interpreter(*this, stmt->expression_get().get(),
                        libport::Symbol::fresh_string(name_get()));
      jobs_ <<  subrunner;
      subrunner->start_job();
      if (canYield && !input_.eof())
        yield();
    }
    else
    {
      GD_FPUSH_TRACE("%s: executing command (%s).", name_get(), stmt);
      GD_FINFO_DUMP("%s: command: %s", name_get(), *exp);
      eval_print_(exp.get());
      if (canYield && !input_.eof())
        yield();
    }

    if (non_interruptible_get())
    {
      send_message("error", "the toplevel cannot be non-interruptible");
      non_interruptible_set(false);
    }
  }

  static
  void collect_connection(kernel::UConnection* c)
  {
    GD_FPUSH_DUMP("closing connection %p", c);
    aver(c);
    kernel::server().connection_remove(*c);
  }

  void
  Shell::handle_command_end_()
  {
    if (input_.eof())
    {
      stop();
    }
  }

  void
  Shell::work()
  {
    while (!stop_)
    {
      try
      {
        work_();
      }
      // Don't kill the shell when we receive the exception
      // fired by "connectionTag.stop".
      catch (const sched::StopException& e)
      {
        GD_FINFO_DUMP("StopException ignored: %s", e.what());
      }
    }

    foreach (const sched::rJob& job, jobs_)
      job->terminate_now();
    yield_until_terminated(jobs_);
  }

  void
  Shell::work_()
  {
    while (!stop_)
    {
      try
      {
        parser::parse_result_type res;
        {
          GD_FPUSH_TRACE("%s: reading command.", name_get());
          // It once happened that parser_ was null here.  The
          // scenario is that an remote UObject in binary mode sends a
          // message that is too big to fit into the stream buffer,
          // and as a result the message was incomplete.  This caused
          // processSerializedMessages to end in an unexpected way,
          // and control returned here, with !stop_.  So we returned
          // in the regular processing flow, although there is no
          // parser around.
          //
          // To work around this, the buffer size was increased (from
          // 1k to 8k on OS X).
          assert(parser_);
          res = parser_->parse();
        }
        ast::rExp ast = parser::transform(ast::rConstExp(res));
        handle_command_(ast);
        handle_command_end_();
      }
      catch (const Exception& e)
      {
        GD_FINFO_TRACE("%s: command is invalid, printing errors.",
                       name_get());
        e.print(*this);
      }
      for (jobs_type::iterator it = jobs_.begin();
           it != jobs_.end();
           /* nothing */)
        if ((*it)->terminated())
          it = jobs_.erase(it);
        else
          ++it;
    }
  }

  void
  Shell::processSerializedMessages()
  {
    GD_CATEGORY(Urbi.Shell.Serialize);
    GD_INFO_TRACE("Entering processSerializedMessages");
    libport::serialize::BinaryISerializer deserializer(input_);
    while (binary_mode_ && !stop_)
    {
      try
      {
        GD_INFO_DEBUG("Reading new serialized message type");
        char msgType;
        deserializer >> msgType;
        GD_FINFO_DEBUG("Processing serialized message of type %s",
                       (int)msgType);
        std::string code
          = urbi::uobjects::processSerializedMessage(msgType, deserializer);
        GD_FINFO_DEBUG("Got value '%s'", code);
        if (!code.empty())
        {
          // We must parse and execute synchronously, but honor ',': this is
          // toplevel code.
          yy::location loc;
          parser::UParser p(code, &loc);
          p.oneshot_set(false);
          ast::rConstExp e = p.parse();
          ast::rConstExp ast = parser::transform(e);
          handle_command_(ast::rConstExp(ast), false);
        }
        handle_command_end_();
      }
      // Catch and print unhandled exceptions
      catch (object::UrbiException& e)
      {
        show_exception(object::UrbiException(e.value_get(),
                                             e.backtrace_get()));
      }
      catch (const Exception& e)
      {
        GD_FINFO_TRACE("%s: command is invalid, printing errors.",
                       name_get());
        e.print(*this);
      }
      catch (const sched::StopException& e)
      {
        GD_FINFO_DUMP("StopException ignored: %s", e.what());
      }
      catch (const std::runtime_error& re)
      {
        GD_FINFO_TRACE("Serialized message error: %s", re.what());
        Exception e;
        e.err(ast::loc(), re.what());
        e.print(*this);
      }
      catch (const std::exception& e)
      {
        GD_FWARN("Unexpected error '%s' caught in processSerializedMessages",
                 e.what());
        throw;
      }
      catch(...)
      {
        GD_WARN("Unknown error caught in processSerializedMessages");
        throw;
      }
      for (jobs_type::iterator it = jobs_.begin();
           it != jobs_.end();
           /* nothing */)
        if ((*it)->terminated())
          it = jobs_.erase(it);
        else
          ++it;
    }
  }

  void
  Shell::setSerializationMode(bool m, const std::string& tag)
  {
    GD_CATEGORY(Urbi.Shell.serialize);
    GD_FINFO_TRACE("setSerializationMode %s", m);
    if (m == binary_mode_)
      return;
    if (!m && binary_mode_)
      throw std::runtime_error("There is no turning back from serialized mode");
    delete parser_;
    parser_ = 0;
    lobby_get()->send("1", tag);
    binary_mode_ = m;
    if (binary_mode_)
      processSerializedMessages();
  }

  bool
  Shell::pending_command_get() const
  {
    return executing_ || !commands_.empty();
  }

  void
  Shell::pending_commands_clear()
  {
    commands_.clear();
  }

  void
  Shell::stop()
  {
    if (stop_)
      return;
    GD_FPUSH_TRACE("%s: end reached.", name_get());
    if (&kernel::urbiserver->ghost_connection_get() !=
        &lobby_get()->connection_get())
    {
      // Asynchronous destruction of the connection is necessary
      // otherwise the connection destructor (which is stopping the
      // connection tag) will raise a Stop exception.  In addition, the
      // UConnection is supposed to hold the last reference on this
      // Shell once the work function has ended, thus scheduling the
      // ansynchronous destruction will destroy the lobby and the shell.
      // The UConnection should be fetch before disconnecting the lobby,
      // because the lobby will lose it's reference on the connection.
      GD_FPUSH_DUMP("%s: schedule connection destruction.", name_get());
      aver(&lobby_get()->connection_get());
      kernel::server().schedule(
                                SYMBOL(collect_connection),
                                boost::bind(collect_connection, &lobby_get()->connection_get())
                                );
      GD_FPUSH_DUMP("%s: disconnecting.", name_get());
      lobby_get()->disconnect();
      stop_ = true;
    }
    // Force interruption of work_
    lobby_get()->tag_get()->stop();
  }
} // namespace runner
<commit_msg>Shell: don't report TerminateException as unexpected.<commit_after>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <serialize/binary-i-serializer.hh>

#include <libport/finally.hh>

#include <ast/nary.hh>
#include <ast/stmt.hh>

#include <libport/debug.hh>

#include <urbi/object/lobby.hh>
#include <urbi/object/object.hh>
#include <urbi/object/tag.hh>

#include <urbi/uvalue-serialize.hh>

#include <object/system.hh>

#include <ast/print.hh>
#include <kernel/uconnection.hh>
#include <kernel/uobject.hh>
#include <kernel/userver.hh>
#include <parser/transform.hh>
#include <parser/uparser.hh>
#include <runner/exception.hh>
#include <runner/shell.hh>

#include <sched/job.hh>
#include <sched/scheduler.hh>

namespace runner
{
  GD_CATEGORY(Urbi.Shell);

  Shell::Shell(const rLobby& lobby,
	       sched::Scheduler& scheduler,
	       const std::string& name,
               std::istream& input)
    : Interpreter(lobby, scheduler, ast::rConstAst(), name)
    , executing_(false)
    , input_(input)
    , stop_(false)
    , binary_mode_(false)
    , parser_(new parser::UParser(input_))
  {
    GD_FINFO_TRACE("new shell: %s %p", name_get(), this);
  }

  Shell::~Shell()
  {
    GD_FINFO_TRACE("dying shell: %s %p", name_get(), this);
    if (serializationJob_)
      serializationJob_->terminate_asap();
    delete parser_;
  }

  void
  Shell::eval_print_(const ast::Exp* exp)
  {
    // Visual Studio on Windows does not rewind the stack before the
    // end of a "try/catch" block, "catch" included. It means that we
    // cannot display the exception in the "catch" block in case this
    // is a scheduling error due to stack exhaustion, as we may need
    // the stack. The following objects will be set if we have an
    // exception to show, and it will be printed after the "catch"
    // block, or if we have an exception to rethrow.
    boost::scoped_ptr<object::UrbiException> exception_to_show;

    try
    {
      object::rObject res = operator()(exp);

      // We need to keep checking for void here because it
      // cannot be passed to the << function.
      if (res && res != object::void_class)
      {
        // Display the value using the topLevel channel.  If it is not
        // (yet) defined, do nothing, unless this environment variable
        // is set.
        static bool toplevel_debug = getenv("URBI_TOPLEVEL");

        rSlot topLevel =
          lobby_get()->slot_locate(SYMBOL(topLevel), false).second;
       if (topLevel)
         topLevel->value()->call(SYMBOL(LT_LT), res);
        else if (toplevel_debug)
        {
          try
          {
            rObject result = res->call(SYMBOL(asToplevelPrintable));
            std::ostringstream os;
            result->print(os);
            lobby_->connection_get().send(os.str());
            lobby_->connection_get().endline();
          }
          catch (object::UrbiException&)
          {
            // nothing
          }
        }
      }
    }
    // Catch and print unhandled exceptions
    catch (object::UrbiException& e)
    {
      exception_to_show.reset(new object::UrbiException(e.value_get(),
                                                        e.backtrace_get()));
    }
    // When we receive the exception fired by "connectionTag.stop",
    // kill the jobs, not the shell.
    catch (const sched::StopException& e)
    {
      GD_FINFO_DUMP("StopException ignored: %s", e.what());
    }
    catch (const sched::TerminateException&)
    {
      GD_INFO_DUMP("TerminateException");
      throw;
    }
    // Stop invalid exceptions thrown by primitives
    catch (const std::exception& e)
    {
      Exception::warn(exp->location_get(),
                      libport::format("invalid exception caught: %s",
                                      e.what()));
    }
    catch (...)
    {
      Exception::warn(exp->location_get(), "unknown exception caught");
    }

    if (exception_to_show.get())
      show_exception(*exception_to_show);
  }

  void
  Shell::handle_command_(ast::rConstExp exp, bool canYield)
  {
    LIBPORT_SCOPE_SET(executing_, true);
    const ast::Stmt* stmt = dynamic_cast<const ast::Stmt*>(exp.get());

    if (stmt && stmt->flavor_get() == ast::flavor_comma)
    {
      GD_FPUSH_TRACE("%s: executing command in background.", name_get());
      GD_FINFO_DUMP("%s: command: %s", name_get(), *exp);
      sched::rJob subrunner =
        new Interpreter(*this, stmt->expression_get().get(),
                        libport::Symbol::fresh_string(name_get()));
      jobs_ <<  subrunner;
      subrunner->start_job();
      if (canYield && !input_.eof())
        yield();
    }
    else
    {
      GD_FPUSH_TRACE("%s: executing command (%s).", name_get(), stmt);
      GD_FINFO_DUMP("%s: command: %s", name_get(), *exp);
      eval_print_(exp.get());
      if (canYield && !input_.eof())
        yield();
    }

    if (non_interruptible_get())
    {
      send_message("error", "the toplevel cannot be non-interruptible");
      non_interruptible_set(false);
    }
  }

  static
  void collect_connection(kernel::UConnection* c)
  {
    GD_FPUSH_DUMP("closing connection %p", c);
    aver(c);
    kernel::server().connection_remove(*c);
  }

  void
  Shell::handle_command_end_()
  {
    if (input_.eof())
    {
      stop();
    }
  }

  void
  Shell::work()
  {
    while (!stop_)
    {
      try
      {
        work_();
      }
      // Don't kill the shell when we receive the exception
      // fired by "connectionTag.stop".
      catch (const sched::StopException& e)
      {
        GD_FINFO_DUMP("StopException ignored: %s", e.what());
      }
    }

    foreach (const sched::rJob& job, jobs_)
      job->terminate_now();
    yield_until_terminated(jobs_);
  }

  void
  Shell::work_()
  {
    while (!stop_)
    {
      try
      {
        parser::parse_result_type res;
        {
          GD_FPUSH_TRACE("%s: reading command.", name_get());
          // It once happened that parser_ was null here.  The
          // scenario is that an remote UObject in binary mode sends a
          // message that is too big to fit into the stream buffer,
          // and as a result the message was incomplete.  This caused
          // processSerializedMessages to end in an unexpected way,
          // and control returned here, with !stop_.  So we returned
          // in the regular processing flow, although there is no
          // parser around.
          //
          // To work around this, the buffer size was increased (from
          // 1k to 8k on OS X).
          assert(parser_);
          res = parser_->parse();
        }
        ast::rExp ast = parser::transform(ast::rConstExp(res));
        handle_command_(ast);
        handle_command_end_();
      }
      catch (const Exception& e)
      {
        GD_FINFO_TRACE("%s: command is invalid, printing errors.",
                       name_get());
        e.print(*this);
      }
      for (jobs_type::iterator it = jobs_.begin();
           it != jobs_.end();
           /* nothing */)
        if ((*it)->terminated())
          it = jobs_.erase(it);
        else
          ++it;
    }
  }

  void
  Shell::processSerializedMessages()
  {
    GD_CATEGORY(Urbi.Shell.Serialize);
    GD_INFO_TRACE("Entering processSerializedMessages");
    libport::serialize::BinaryISerializer deserializer(input_);
    while (binary_mode_ && !stop_)
    {
      try
      {
        GD_INFO_DEBUG("Reading new serialized message type");
        char msgType;
        deserializer >> msgType;
        GD_FINFO_DEBUG("Processing serialized message of type %s",
                       (int)msgType);
        std::string code
          = urbi::uobjects::processSerializedMessage(msgType, deserializer);
        GD_FINFO_DEBUG("Got value '%s'", code);
        if (!code.empty())
        {
          // We must parse and execute synchronously, but honor ',': this is
          // toplevel code.
          yy::location loc;
          parser::UParser p(code, &loc);
          p.oneshot_set(false);
          ast::rConstExp e = p.parse();
          ast::rConstExp ast = parser::transform(e);
          handle_command_(ast::rConstExp(ast), false);
        }
        handle_command_end_();
      }
      // Catch and print unhandled exceptions
      catch (object::UrbiException& e)
      {
        show_exception(object::UrbiException(e.value_get(),
                                             e.backtrace_get()));
      }
      catch (const Exception& e)
      {
        GD_FINFO_TRACE("%s: command is invalid, printing errors.",
                       name_get());
        e.print(*this);
      }
      catch (const sched::StopException& e)
      {
        GD_FINFO_DUMP("StopException ignored: %s", e.what());
      }
      catch (const sched::TerminateException&)
      {
        GD_INFO_DUMP("TerminateException");
        throw;
      }
      catch (const std::runtime_error& re)
      {
        GD_FINFO_TRACE("Serialized message error: %s", re.what());
        Exception e;
        e.err(ast::loc(), re.what());
        e.print(*this);
      }
      catch (const std::exception& e)
      {
        GD_FWARN("Unexpected error '%s' caught in processSerializedMessages",
                 e.what());
        throw;
      }
      catch(...)
      {
        GD_WARN("Unknown error caught in processSerializedMessages");
        throw;
      }
      for (jobs_type::iterator it = jobs_.begin();
           it != jobs_.end();
           /* nothing */)
        if ((*it)->terminated())
          it = jobs_.erase(it);
        else
          ++it;
    }
  }

  void
  Shell::setSerializationMode(bool m, const std::string& tag)
  {
    GD_CATEGORY(Urbi.Shell.serialize);
    GD_FINFO_TRACE("setSerializationMode %s", m);
    if (m == binary_mode_)
      return;
    if (!m && binary_mode_)
      throw std::runtime_error("There is no turning back from serialized mode");
    delete parser_;
    parser_ = 0;
    lobby_get()->send("1", tag);
    binary_mode_ = m;
    if (binary_mode_)
      processSerializedMessages();
  }

  bool
  Shell::pending_command_get() const
  {
    return executing_ || !commands_.empty();
  }

  void
  Shell::pending_commands_clear()
  {
    commands_.clear();
  }

  void
  Shell::stop()
  {
    if (stop_)
      return;
    GD_FPUSH_TRACE("%s: end reached.", name_get());
    if (&kernel::urbiserver->ghost_connection_get() !=
        &lobby_get()->connection_get())
    {
      // Asynchronous destruction of the connection is necessary
      // otherwise the connection destructor (which is stopping the
      // connection tag) will raise a Stop exception.  In addition, the
      // UConnection is supposed to hold the last reference on this
      // Shell once the work function has ended, thus scheduling the
      // ansynchronous destruction will destroy the lobby and the shell.
      // The UConnection should be fetch before disconnecting the lobby,
      // because the lobby will lose it's reference on the connection.
      GD_FPUSH_DUMP("%s: schedule connection destruction.", name_get());
      aver(&lobby_get()->connection_get());
      kernel::server().schedule(
                                SYMBOL(collect_connection),
                                boost::bind(collect_connection, &lobby_get()->connection_get())
                                );
      GD_FPUSH_DUMP("%s: disconnecting.", name_get());
      lobby_get()->disconnect();
      stop_ = true;
    }
    // Force interruption of work_
    lobby_get()->tag_get()->stop();
  }
} // namespace runner
<|endoftext|>


<commit_before>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <ctime>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <utils.hpp>
#include <SNR.hpp>

typedef float dataType;
std::string typeName("float");

int main(int argc, char *argv[]) {
  bool print = false;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
  unsigned int nrDMsPerBlock = 0;
  unsigned int nrPeriodsPerBlock = 0;
  unsigned int nrDMsPerThread = 0;
  unsigned int nrPeriodsPerThread = 0;
	long long unsigned int wrongSamples = 0;
	AstroData::Observation observation;

	try {
    isa::utils::ArgumentList args(argc, argv);
    print = args.getSwitch("-print");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    nrDMsPerBlock = args.getSwitchArgument< unsigned int >("-db");
    nrPeriodsPerBlock = args.getSwitchArgument< unsigned int >("-pb");
    nrDMsPerThread = args.getSwitchArgument< unsigned int >("-dt");
    nrPeriodsPerThread = args.getSwitchArgument< unsigned int >("-pt");
		observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), 0.0, 0.0);
    observation.setPeriodRange(args.getSwitchArgument< unsigned int >("-periods"), 0, 0);
    observation.setNrBins(args.getSwitchArgument< unsigned int >("-bins"));
	} catch  ( isa::utils::SwitchNotFound &err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }catch ( std::exception &err ) {
    std::cerr << "Usage: " << argv[0] << " [-print] -opencl_platform ... -opencl_device ... -padding ... -db ... -pb ... -dt ... -pt ... -dms ... -periods ... -bins ..." << std::endl;
		return 1;
	}

	// Initialize OpenCL
	cl::Context * clContext = new cl::Context();
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();

  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
  std::vector< dataType > foldedData = std::vector< dataType >(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedDMs());
  cl::Buffer foldedData_d;
  std::vector< dataType > snrs = std::vector< dataType >(observation.getNrPeriods() * observation.getNrPaddedDMs());
  std::vector< dataType > snrs_c = std::vector< dataType >(observation.getNrPeriods() * observation.getNrPaddedDMs());
  cl::Buffer snrs_d;
  try {
    foldedData_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, foldedData.size() * sizeof(dataType), NULL, NULL);
    snrs_d = cl::Buffer(*clContext, CL_MEM_WRITE_ONLY, snrs.size() * sizeof(dataType), NULL, NULL);
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error allocating memory: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

	srand(time(NULL));
  for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
    for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
      for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
        foldedData[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + DM] = static_cast< dataType >(rand() % 10);
      }
    }
	}
  std::fill(snrs.begin(), snrs.end(), static_cast< dataType >(0));
  std::fill(snrs_c.begin(), snrs_c.end(), static_cast< dataType >(0));

  // Copy data structures to device
  try {
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(foldedData_d, CL_FALSE, 0, foldedData.size() * sizeof(dataType), reinterpret_cast< void * >(foldedData.data()));
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(snrs_d, CL_FALSE, 0, snrs.size() * sizeof(dataType), reinterpret_cast< void * >(snrs.data()));
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error H2D transfer: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

  // Generate kernel
  cl::Kernel * kernel;
  std::string * code = PulsarSearch::getSNROpenCL(nrDMsPerBlock, nrPeriodsPerBlock, nrDMsPerThread, nrPeriodsPerThread, typeName, observation);
  if ( print ) {
    std::cout << *code << std::endl;
  }

  try {
    kernel = isa::OpenCL::compile("snr", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
  } catch ( isa::OpenCL::OpenCLError &err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  // Run OpenCL kernel and CPU control
  try {
    cl::NDRange global(observation.getNrPaddedDMs() / nrDMsPerThread, observation.getNrPeriods() / nrPeriodsPerThread);
    cl::NDRange local(nrDMsPerBlock, nrPeriodsPerBlock);

    kernel->setArg(0, foldedData_d);
    kernel->setArg(1, snrs_d);

    clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, NULL, NULL);
    PulsarSearch::snrFoldedTS(observation, foldedData, snrs_c);
    clQueues->at(clDeviceID)[0].enqueueReadBuffer(snrs_d, CL_TRUE, 0, snrs.size() * sizeof(dataType), reinterpret_cast< void * >(snrs.data()));
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

  for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
    for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
      if ( ! isa::utils::same(snrs_c[(period * observation.getNrPaddedDMs()) + dm], snrs[(period * observation.getNrPaddedDMs()) + dm]) ) {
        wrongSamples++;
      }
    }
  }

  if ( wrongSamples > 0 ) {
    std::cout << "Wrong samples: " << wrongSamples << " (" << (wrongSamples * 100.0) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods()) << "%)." << std::endl;
  } else {
    std::cout << "TEST PASSED." << std::endl;
  }

	return 0;
}

<commit_msg>Updated the tests.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <ctime>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <utils.hpp>
#include <SNR.hpp>

typedef float dataType;
std::string typeName("float");

int main(int argc, char *argv[]) {
  bool print = false;
  bool dSNR = false;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
  unsigned int nrDMsPerBlock = 0;
  unsigned int nrPeriodsPerBlock = 0;
  unsigned int nrDMsPerThread = 0;
  unsigned int nrPeriodsPerThread = 0;
	long long unsigned int wrongSamples = 0;
	AstroData::Observation observation;

	try {
    isa::utils::ArgumentList args(argc, argv);
    print = args.getSwitch("-print");
    dSNR = args.getSwitch("-dedispersed");
    bool fSNR = args.getSwitch("-folded");
    if ( (dSNR && fSNR) || (!dSNR && ! fSNR) ) {
      throw std::exception();
    }
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    nrDMsPerBlock = args.getSwitchArgument< unsigned int >("-db");
    nrPeriodsPerBlock = args.getSwitchArgument< unsigned int >("-pb");
    nrDMsPerThread = args.getSwitchArgument< unsigned int >("-dt");
    if ( fSNR ) {
      nrPeriodsPerBlock = args.getSwitchArgument< unsigned int >("-pb");
      nrPeriodsPerThread = args.getSwitchArgument< unsigned int >("-pt");
    } else {
      observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    }
		observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), 0.0, 0.0);
    if ( fSNR ) {
      observation.setPeriodRange(args.getSwitchArgument< unsigned int >("-periods"), 0, 0);
      observation.setNrBins(args.getSwitchArgument< unsigned int >("-bins"));
    }
	} catch  ( isa::utils::SwitchNotFound &err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  } catch ( std::exception &err ) {
    std::cerr << "Usage: " << argv[0] << " [-dedispersed | -folded] [-print] -opencl_platform ... -opencl_device ... -padding ... -db ... -dt ... -dms ..." << std::endl;
    std::cerr << "\t -dedispersed -samples ..." << std::endl;
    std::cerr << "\t -folded -pb ... -pt ... -periods .... -bins ..." << std::endl;
		return 1;
	}

	// Initialize OpenCL
	cl::Context * clContext = new cl::Context();
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();

  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
  std::vector< dataType > foldedData, snrs, snrs_c;
  std::vector< dataType > transposedData, maxS, meanS, rmsS, maxS_c, meanS_c, rmsS_c;
  cl::Buffer foldedData_d, snrs_d;
  cl::Buffer tranposedData_d, maxS_d, meanS_d, rmsS_d;
  if ( dSNR ) {
    foldedData.resize(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedBins());
    snrs.resize(observation.getNrPeriods() * observation.getNrPaddedDMs());
    snrs_c.resize(observation.getNrPeriods() * observation.getNrPaddedDMs());
  } else {
    tranposedData.resize(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
    maxS.resize(observation.getNrPaddedDMs());
    meanS.resize(observation.getNrPaddedDMs());
    rmsS.resize(observation.getNrPaddedDMs());
    maxS_c.resize(observation.getNrPaddedDMs());
    meanS_c.resize(observation.getNrPaddedDMs());
    rmsS_c.resize(observation.getNrPaddedDMs());
  }
  try {
    if ( dSNR ) {
      transposedData_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, transposedData.size() * sizeof(dataType), 0, 0);
      maxS_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, maxS.size() * sizeof(dataType), 0, 0);
      meanS_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, meanS.size() * sizeof(dataType), 0, 0);
      rmsS_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, rmsS.size() * sizeof(dataType), 0, 0);
    } else {
      foldedData_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, foldedData.size() * sizeof(dataType), 0, 0);
      snrs_d = cl::Buffer(*clContext, CL_MEM_WRITE_ONLY, snrs.size() * sizeof(dataType), 0, 0);
    }
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error allocating memory: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

	srand(time(0));
  if ( dSNR ) {
    for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
      for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
        transposedData[(sample * observation.getNrPaddedDMs()) + dm] = static_cast< dataType >(rand() % 10);
      }
    }
    std::fill(maxS.begin(), maxS.end(), static_cast< dataType >(0));
    std::fill(meanS.begin(), meanS.end(), static_cast< dataType >(0));
    std::fill(rmsS.begin(), rmsS.end(), static_cast< dataType >(0));
    std::fill(maxS_c.begin(), maxS_c.end(), static_cast< dataType >(0));
    std::fill(meanS_c.begin(), meanS_c.end(), static_cast< dataType >(0));
    std::fill(rmsS_c.begin(), rmsS_c.end(), static_cast< dataType >(0));
  } else {
    for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
      for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
        for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
          foldedData[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + DM] = static_cast< dataType >(rand() % 10);
        }
      }
    }
    std::fill(snrs.begin(), snrs.end(), static_cast< dataType >(0));
    std::fill(snrs_c.begin(), snrs_c.end(), static_cast< dataType >(0));
  }

  // Copy data structures to device
  try {
    if ( dSNR ) {
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(transposedData_d, CL_FALSE, 0, transposedData.size() * sizeof(dataType), reinterpret_cast< void * >(transposedData.data()));
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(maxS_d, CL_FALSE, 0, maxS.size() * sizeof(dataType), reinterpret_cast< void * >(maxS.data()));
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(meanS_d, CL_FALSE, 0, meanS.size() * sizeof(dataType), reinterpret_cast< void * >(meanS.data()));
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(rmsS_d, CL_FALSE, 0, rmsS.size() * sizeof(dataType), reinterpret_cast< void * >(rmsS.data()));
    } else {
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(foldedData_d, CL_FALSE, 0, foldedData.size() * sizeof(dataType), reinterpret_cast< void * >(foldedData.data()));
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(snrs_d, CL_FALSE, 0, snrs.size() * sizeof(dataType), reinterpret_cast< void * >(snrs.data()));
    }
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error H2D transfer: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

  // Generate kernel
  cl::Kernel * kernel;
  std::string * code;
  if ( dSNR ) {
    code = PulsarSearch::getSNRDedispersedOpenCL(nrDMsPerBlock, nrDMsPerThread, typeName, observation);
  } else {
    code = PulsarSearch::getSNRFoldedOpenCL(nrDMsPerBlock, nrPeriodsPerBlock, nrDMsPerThread, nrPeriodsPerThread, typeName, observation);
  }
  if ( print ) {
    std::cout << *code << std::endl;
  }

  try {
    if ( dSNR ) {
      kernel = isa::OpenCL::compile("snrDedispersed", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
    } else {
      kernel = isa::OpenCL::compile("snrFolded", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
    }
  } catch ( isa::OpenCL::OpenCLError &err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  // Run OpenCL kernel and CPU control
  try {
    cl::NDRange global;
    cl::NDRange local;
    if ( dSNR ) {
      cl::NDRange global(observation.getNrPaddedDMs() / nrDMsPerThread);
      cl::NDRange local(nrDMsPerBlock);

      kernel->setArg(0, 0);
      kernel->setArg(1, transposedData_d);
      kernel->setArg(2, maxS_d);
      kernel->setArg(3, meanS_d);
      kernel->setArg(4, rmsS_d);
    } else {
      cl::NDRange global(observation.getNrPaddedDMs() / nrDMsPerThread, observation.getNrPeriods() / nrPeriodsPerThread);
      cl::NDRange local(nrDMsPerBlock, nrPeriodsPerBlock);

      kernel->setArg(0, foldedData_d);
      kernel->setArg(1, snrs_d);
    }

    clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, 0);
    if ( dSNR ) {
      PulsarSearch::snrDedispersedTS(0, observation, transposedData, maxS_c, meanS_c, rmsS_c);
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(maxS_d, CL_TRUE, 0, maxS.size() * sizeof(dataType), reinterpret_cast< void * >(maxS.data()));
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(meanS_d, CL_TRUE, 0, meanS.size() * sizeof(dataType), reinterpret_cast< void * >(meanS.data()));
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(rmsS_d, CL_TRUE, 0, rmsS.size() * sizeof(dataType), reinterpret_cast< void * >(rmsS.data()));
    } else {
      PulsarSearch::snrFoldedTS(observation, foldedData, snrs_c);
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(snrs_d, CL_TRUE, 0, snrs.size() * sizeof(dataType), reinterpret_cast< void * >(snrs.data()));
    }
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

  if ( dSNR) {
    for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
      dataType snr = (maxS[dm] - meanS[dm]) / std::sqrt(rmsS[dm]);
      dataType snr_c = (maxS_c[dm] - meanS_c[dm]) / std::sqrt(rmsS_c[dm]);
      if ( ! isa::utils::same(snr, snr_c) ) {
        wrongSamples++;
      }
    }
  } else {
    for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
      for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
        if ( ! isa::utils::same(snrs_c[(period * observation.getNrPaddedDMs()) + dm], snrs[(period * observation.getNrPaddedDMs()) + dm]) ) {
          wrongSamples++;
        }
      }
    }
  }

  if ( wrongSamples > 0 ) {
    if ( dSNR ) {
      std::cout << "Wrong samples: " << wrongSamples << " (" << (wrongSamples * 100.0) / static_cast< long long unsigned int >(observation.getNrDMs()) << "%)." << std::endl;
    } else {
      std::cout << "Wrong samples: " << wrongSamples << " (" << (wrongSamples * 100.0) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods()) << "%)." << std::endl;
    }
  } else {
    std::cout << "TEST PASSED." << std::endl;
  }

	return 0;
}

<|endoftext|>