<commit_before>////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// AliFemtoCutMonitorParticlePID - the cut monitor for particles to study     //
// various aspects of the PID determination                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
#include "AliFemtoCutMonitorParticlePID.h"
#include "AliFemtoModelHiddenInfo.h"
#include <TH1D.h>
#include <TH2D.h>
#include <TList.h>
#include <TMath.h>

AliFemtoCutMonitorParticlePID::AliFemtoCutMonitorParticlePID():
  AliFemtoCutMonitor()
  , fTOFParticle(0)
  , fIfUsePt(false)
  , fTPCdEdx(nullptr)
  , fTOFTime(nullptr)
  , fTOFNSigma(nullptr)
  , fTPCNSigma(nullptr)
  , fTPCTOFNSigma(nullptr)
  , fTPCvsTOFNSigma(nullptr)
  , fParticleOrigin(nullptr)
  , fParticleId(nullptr)
{
  // Default constructor
  fTPCdEdx        = new TH2D("TPCdEdx", "TPC dEdx vs. momentum", 100, 0.0, 5.0, 250, 0.0, 500.0);
  fTOFTime        = new TH2D("TOFTime", "TOF Time vs. momentum", 100, 0.1, 5.0, 400, -4000.0, 4000.0);
  fTOFNSigma      = new TH2D("TOFNSigma","TOF NSigma vs. momentum", 100, 0.0, 5.0, 100, -5.0, 5.0);
  fTPCNSigma      = new TH2D("TPCNSigma","TPC NSigma vs. momentum", 100, 0.0, 5.0, 100, -5.0, 5.0);
  fTPCTOFNSigma   = new TH2D("TPCTOFNSigma","TPC & TOF NSigma vs. momentum", 100, 0.0, 5.0, 100, 0.0, 10.0);
  fTPCvsTOFNSigma = new TH2D("TPCvsTOFNSigma","TPC vs TOF Nsigma",100, -5.0, 5.0, 100, -5.0, 5.0);
  fParticleOrigin = new TH1D("POrigin", "Mothers PDG Codes", 6000, 0.0, 6000.0);
  fParticleId     = new TH1D("PId", "Particle PDG Codes", 6000, 0.0, 6000.0);

}

AliFemtoCutMonitorParticlePID::AliFemtoCutMonitorParticlePID(const char *aName, Int_t aTOFParticle, Double_t yTOFTimeMin, Double_t yTOFTimeMax):
  AliFemtoCutMonitor()
  , fTOFParticle(aTOFParticle)
  , fIfUsePt(false)
  , fTPCdEdx(nullptr)
  , fTOFTime(nullptr)
  , fTOFNSigma(nullptr)
  , fTPCNSigma(nullptr)
  , fTPCTOFNSigma(nullptr)
  , fTPCvsTOFNSigma(nullptr)
  , fParticleOrigin(nullptr)
  , fParticleId(nullptr)
{
  // Normal constructor
  fTPCdEdx        = new TH2D(TString::Format("TPCdEdx%s", aName), "TPC dEdx vs. momentum", 200, 0.1, 4.0, 250, 0.0, 500.0);
  fTOFTime        = new TH2D(TString::Format("TOFTime%s", aName), "TOF Time vs. momentum", 100, 0.1, 5.0, 400, yTOFTimeMin, yTOFTimeMax);
  fTOFNSigma      = new TH2D(TString::Format("TOFNSigma%s", aName), "TOF NSigma vs. momentum", 100, 0.0, 5.0, 100, -5.0, 5.0);
  fTPCNSigma      = new TH2D(TString::Format("TPCNSigma%s", aName), "TPC NSigma vs. momentum", 100, 0.0, 5.0, 100, -5.0, 5.0);
  fTPCTOFNSigma   = new TH2D(TString::Format("TPCTOFNSigma%s", aName), "TPC & TOF NSigma vs. momentum", 100, 0.0, 5.0, 100, 0.0, 10.0);
  fTPCvsTOFNSigma = new TH2D(TString::Format("TPCvsTOFNSigma%s", aName), "TPC vs TOF Nsigma",100, -5.0, 5.0, 100, -5.0, 5.0);
  fParticleOrigin = new TH1D(TString::Format("POrigin%s", aName), "Mothers PDG Codes", 6000, 0.0, 6000.0);
  fParticleId     = new TH1D(TString::Format("PId%s", aName), "Particle PDG Codes", 6000, 0.0, 6000.0);
}

AliFemtoCutMonitorParticlePID::AliFemtoCutMonitorParticlePID(const AliFemtoCutMonitorParticlePID &aCut):
  AliFemtoCutMonitor(aCut)
  , fTOFParticle(aCut.fTOFParticle)
  , fIfUsePt(aCut.fIfUsePt)
  , fTPCdEdx(new TH2D(*aCut.fTPCdEdx))
  , fTOFTime(new TH2D(*aCut.fTOFTime))
  , fTOFNSigma(new TH2D(*aCut.fTOFNSigma))
  , fTPCNSigma(new TH2D(*aCut.fTPCNSigma))
  , fTPCTOFNSigma(new TH2D(*aCut.fTPCTOFNSigma))
  , fTPCvsTOFNSigma(new TH2D(*aCut.fTPCvsTOFNSigma))
  , fParticleOrigin(new TH1D(*aCut.fParticleOrigin))
  , fParticleId(new TH1D(*aCut.fParticleId))
{
  // copy constructor
}

AliFemtoCutMonitorParticlePID::~AliFemtoCutMonitorParticlePID()
{
  // Destructor
  delete fTPCdEdx;
  delete fTOFTime;
  delete fTOFNSigma;
  delete fTPCNSigma;
  delete fTPCTOFNSigma;
  delete fTPCvsTOFNSigma;
  delete fParticleOrigin;
  delete fParticleId;
}

AliFemtoCutMonitorParticlePID& AliFemtoCutMonitorParticlePID::operator=(const AliFemtoCutMonitorParticlePID& aCut)
{
  // assignment operator
  if (this == &aCut)
    return *this;

  AliFemtoCutMonitor::operator=(aCut);

  fTOFParticle = aCut.fTOFParticle;
  fIfUsePt = aCut.fIfUsePt;

  *fTPCdEdx = *aCut.fTPCdEdx;
  *fTOFTime = *aCut.fTOFTime;
  *fTOFNSigma = *aCut.fTOFNSigma;
  *fTPCNSigma = *aCut.fTPCNSigma;
  *fTPCTOFNSigma = *aCut.fTPCTOFNSigma;
  *fTPCvsTOFNSigma = *aCut.fTPCvsTOFNSigma;
  *fParticleOrigin = *aCut.fParticleOrigin;
  *fParticleId = *aCut.fParticleId;

  return *this;
}

AliFemtoString AliFemtoCutMonitorParticlePID::Report()
{
  // Prepare report from the execution
  TString report = "*** AliFemtoCutMonitorParticlePID report";
  return AliFemtoString(report.Data());
}

void AliFemtoCutMonitorParticlePID::Fill(const AliFemtoTrack* aTrack)
{
  // Fill in the monitor histograms with the values from the current track
  float tMom = (fIfUsePt) ? aTrack->Pt() : aTrack->P().Mag();
  float tdEdx = aTrack->TPCsignal();
  float tTOF = 0.0;
  //  short tchg = aTrack->Charge();
  if (fTOFParticle == 0) tTOF = aTrack->TOFpionTime();
  if (fTOFParticle == 1) tTOF = aTrack->TOFkaonTime();
  if (fTOFParticle == 2) tTOF = aTrack->TOFprotonTime();
  if (fTOFParticle == 3) {tTOF = aTrack->TOFdeuteronTime();
  }

  fTPCdEdx->Fill(tMom, tdEdx);
  fTOFTime->Fill(tMom, tTOF);

  AliFemtoModelHiddenInfo *tInfo = (AliFemtoModelHiddenInfo*)aTrack->GetHiddenInfo();
  if(tInfo!=NULL) {
    Int_t partID = TMath::Abs(tInfo->GetPDGPid());
    Int_t motherID = TMath::Abs(tInfo->GetMotherPdgCode());

    fParticleId->Fill(partID);
    fParticleOrigin->Fill(motherID);
  }
  //  float vp= aTrack->VTOF();
  //     if (vp > 0.) {
  //         fTOFTime->Fill(tMom, tTOF);
  //         if (fTOFParticle == 0) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFPi());
  //         if (fTOFParticle == 1) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFK());
  //         if (fTOFParticle == 2) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFP());
  // }

    if (fTOFParticle == 0) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFPi());
    if (fTOFParticle == 1) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFK());
    if (fTOFParticle == 2) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFP());
    if (fTOFParticle == 3) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFD());

    if (fTOFParticle == 0) fTPCNSigma->Fill(tMom, aTrack->NSigmaTPCPi());
    if (fTOFParticle == 1) fTPCNSigma->Fill(tMom, aTrack->NSigmaTPCK());
    if (fTOFParticle == 2) fTPCNSigma->Fill(tMom, aTrack->NSigmaTPCP());
    if (fTOFParticle == 3) fTPCNSigma->Fill(tMom, aTrack->NSigmaTPCD());

    if (fTOFParticle == 0) fTPCTOFNSigma->Fill(tMom, TMath::Hypot( aTrack->NSigmaTPCPi(), aTrack->NSigmaTOFPi() ) );
    if (fTOFParticle == 1) fTPCTOFNSigma->Fill(tMom, TMath::Hypot( aTrack->NSigmaTPCK(), aTrack->NSigmaTOFK() ) );
    if (fTOFParticle == 2) fTPCTOFNSigma->Fill(tMom, TMath::Hypot( aTrack->NSigmaTPCP(), aTrack->NSigmaTOFP() ) );
    if (fTOFParticle == 3) fTPCTOFNSigma->Fill(tMom, TMath::Hypot( aTrack->NSigmaTPCD(), aTrack->NSigmaTOFD() ) );

    if (fTOFParticle == 0) fTPCvsTOFNSigma->Fill(aTrack->NSigmaTPCPi(), aTrack->NSigmaTOFPi());
    if (fTOFParticle == 1) fTPCvsTOFNSigma->Fill(aTrack->NSigmaTPCK(), aTrack->NSigmaTOFK());
    if (fTOFParticle == 2) fTPCvsTOFNSigma->Fill(aTrack->NSigmaTPCP(), aTrack->NSigmaTOFP());
    if (fTOFParticle == 3) fTPCvsTOFNSigma->Fill(aTrack->NSigmaTPCD(), aTrack->NSigmaTOFD());

}

void AliFemtoCutMonitorParticlePID::Write()
{
  // Write out the relevant histograms
  fTPCdEdx->Write();
  fTOFTime->Write();
  fTOFNSigma->Write();
  fTPCNSigma->Write();
  fTPCTOFNSigma->Write();
  fTPCvsTOFNSigma->Write();
  fParticleId->Write();
  fParticleOrigin->Write();
}

TList *AliFemtoCutMonitorParticlePID::GetOutputList()
{
  TList *tOutputList = new TList();
  tOutputList->Add(fTPCdEdx);
  tOutputList->Add(fTOFTime);
  tOutputList->Add(fTOFNSigma);
  tOutputList->Add(fTPCNSigma);
  tOutputList->Add(fTPCTOFNSigma);
  tOutputList->Add(fTPCvsTOFNSigma);
  tOutputList->Add(fParticleId);
  tOutputList->Add(fParticleOrigin);

  return tOutputList;
}
<commit_msg>Change TOFTime binning to be consistent with dE/dx<commit_after>////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// AliFemtoCutMonitorParticlePID - the cut monitor for particles to study     //
// various aspects of the PID determination                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
#include "AliFemtoCutMonitorParticlePID.h"
#include "AliFemtoModelHiddenInfo.h"
#include <TH1D.h>
#include <TH2D.h>
#include <TList.h>
#include <TMath.h>

AliFemtoCutMonitorParticlePID::AliFemtoCutMonitorParticlePID():
  AliFemtoCutMonitor()
  , fTOFParticle(0)
  , fIfUsePt(false)
  , fTPCdEdx(nullptr)
  , fTOFTime(nullptr)
  , fTOFNSigma(nullptr)
  , fTPCNSigma(nullptr)
  , fTPCTOFNSigma(nullptr)
  , fTPCvsTOFNSigma(nullptr)
  , fParticleOrigin(nullptr)
  , fParticleId(nullptr)
{
  // Default constructor
  fTPCdEdx        = new TH2D("TPCdEdx", "TPC dEdx vs. momentum", 100, 0.0, 5.0, 250, 0.0, 500.0);
  fTOFTime        = new TH2D("TOFTime", "TOF Time vs. momentum", 100, 0.0, 5.0, 400, -4000.0, 4000.0);//to be consistent with dE/dx
  //fTOFTime        = new TH2D("TOFTime", "TOF Time vs. momentum", 100, 0.1, 5.0, 400, -4000.0, 4000.0);
  fTOFNSigma      = new TH2D("TOFNSigma","TOF NSigma vs. momentum", 100, 0.0, 5.0, 100, -5.0, 5.0);
  fTPCNSigma      = new TH2D("TPCNSigma","TPC NSigma vs. momentum", 100, 0.0, 5.0, 100, -5.0, 5.0);
  fTPCTOFNSigma   = new TH2D("TPCTOFNSigma","TPC & TOF NSigma vs. momentum", 100, 0.0, 5.0, 100, 0.0, 10.0);
  fTPCvsTOFNSigma = new TH2D("TPCvsTOFNSigma","TPC vs TOF Nsigma",100, -5.0, 5.0, 100, -5.0, 5.0);
  fParticleOrigin = new TH1D("POrigin", "Mothers PDG Codes", 6000, 0.0, 6000.0);
  fParticleId     = new TH1D("PId", "Particle PDG Codes", 6000, 0.0, 6000.0);

}

AliFemtoCutMonitorParticlePID::AliFemtoCutMonitorParticlePID(const char *aName, Int_t aTOFParticle, Double_t yTOFTimeMin, Double_t yTOFTimeMax):
  AliFemtoCutMonitor()
  , fTOFParticle(aTOFParticle)
  , fIfUsePt(false)
  , fTPCdEdx(nullptr)
  , fTOFTime(nullptr)
  , fTOFNSigma(nullptr)
  , fTPCNSigma(nullptr)
  , fTPCTOFNSigma(nullptr)
  , fTPCvsTOFNSigma(nullptr)
  , fParticleOrigin(nullptr)
  , fParticleId(nullptr)
{
  // Normal constructor
  fTPCdEdx        = new TH2D(TString::Format("TPCdEdx%s", aName), "TPC dEdx vs. momentum", 200, 0.1, 4.0, 250, 0.0, 500.0);
  fTOFTime        = new TH2D(TString::Format("TOFTime%s", aName), "TOF Time vs. momentum", 200, 0.1, 4.0, 400, yTOFTimeMin, yTOFTimeMax);//to be consistent with dE/dx
  //fTOFTime        = new TH2D(TString::Format("TOFTime%s", aName), "TOF Time vs. momentum", 100, 0.1, 5.0, 400, yTOFTimeMin, yTOFTimeMax);
  fTOFNSigma      = new TH2D(TString::Format("TOFNSigma%s", aName), "TOF NSigma vs. momentum", 100, 0.0, 5.0, 100, -5.0, 5.0);
  fTPCNSigma      = new TH2D(TString::Format("TPCNSigma%s", aName), "TPC NSigma vs. momentum", 100, 0.0, 5.0, 100, -5.0, 5.0);
  fTPCTOFNSigma   = new TH2D(TString::Format("TPCTOFNSigma%s", aName), "TPC & TOF NSigma vs. momentum", 100, 0.0, 5.0, 100, 0.0, 10.0);
  fTPCvsTOFNSigma = new TH2D(TString::Format("TPCvsTOFNSigma%s", aName), "TPC vs TOF Nsigma",100, -5.0, 5.0, 100, -5.0, 5.0);
  fParticleOrigin = new TH1D(TString::Format("POrigin%s", aName), "Mothers PDG Codes", 6000, 0.0, 6000.0);
  fParticleId     = new TH1D(TString::Format("PId%s", aName), "Particle PDG Codes", 6000, 0.0, 6000.0);
}

AliFemtoCutMonitorParticlePID::AliFemtoCutMonitorParticlePID(const AliFemtoCutMonitorParticlePID &aCut):
  AliFemtoCutMonitor(aCut)
  , fTOFParticle(aCut.fTOFParticle)
  , fIfUsePt(aCut.fIfUsePt)
  , fTPCdEdx(new TH2D(*aCut.fTPCdEdx))
  , fTOFTime(new TH2D(*aCut.fTOFTime))
  , fTOFNSigma(new TH2D(*aCut.fTOFNSigma))
  , fTPCNSigma(new TH2D(*aCut.fTPCNSigma))
  , fTPCTOFNSigma(new TH2D(*aCut.fTPCTOFNSigma))
  , fTPCvsTOFNSigma(new TH2D(*aCut.fTPCvsTOFNSigma))
  , fParticleOrigin(new TH1D(*aCut.fParticleOrigin))
  , fParticleId(new TH1D(*aCut.fParticleId))
{
  // copy constructor
}

AliFemtoCutMonitorParticlePID::~AliFemtoCutMonitorParticlePID()
{
  // Destructor
  delete fTPCdEdx;
  delete fTOFTime;
  delete fTOFNSigma;
  delete fTPCNSigma;
  delete fTPCTOFNSigma;
  delete fTPCvsTOFNSigma;
  delete fParticleOrigin;
  delete fParticleId;
}

AliFemtoCutMonitorParticlePID& AliFemtoCutMonitorParticlePID::operator=(const AliFemtoCutMonitorParticlePID& aCut)
{
  // assignment operator
  if (this == &aCut)
    return *this;

  AliFemtoCutMonitor::operator=(aCut);

  fTOFParticle = aCut.fTOFParticle;
  fIfUsePt = aCut.fIfUsePt;

  *fTPCdEdx = *aCut.fTPCdEdx;
  *fTOFTime = *aCut.fTOFTime;
  *fTOFNSigma = *aCut.fTOFNSigma;
  *fTPCNSigma = *aCut.fTPCNSigma;
  *fTPCTOFNSigma = *aCut.fTPCTOFNSigma;
  *fTPCvsTOFNSigma = *aCut.fTPCvsTOFNSigma;
  *fParticleOrigin = *aCut.fParticleOrigin;
  *fParticleId = *aCut.fParticleId;

  return *this;
}

AliFemtoString AliFemtoCutMonitorParticlePID::Report()
{
  // Prepare report from the execution
  TString report = "*** AliFemtoCutMonitorParticlePID report";
  return AliFemtoString(report.Data());
}

void AliFemtoCutMonitorParticlePID::Fill(const AliFemtoTrack* aTrack)
{
  // Fill in the monitor histograms with the values from the current track
  float tMom = (fIfUsePt) ? aTrack->Pt() : aTrack->P().Mag();
  float tdEdx = aTrack->TPCsignal();
  float tTOF = 0.0;
  //  short tchg = aTrack->Charge();
  if (fTOFParticle == 0) tTOF = aTrack->TOFpionTime();
  if (fTOFParticle == 1) tTOF = aTrack->TOFkaonTime();
  if (fTOFParticle == 2) tTOF = aTrack->TOFprotonTime();
  if (fTOFParticle == 3) {tTOF = aTrack->TOFdeuteronTime();
  }

  fTPCdEdx->Fill(tMom, tdEdx);
  fTOFTime->Fill(tMom, tTOF);

  AliFemtoModelHiddenInfo *tInfo = (AliFemtoModelHiddenInfo*)aTrack->GetHiddenInfo();
  if(tInfo!=NULL) {
    Int_t partID = TMath::Abs(tInfo->GetPDGPid());
    Int_t motherID = TMath::Abs(tInfo->GetMotherPdgCode());

    fParticleId->Fill(partID);
    fParticleOrigin->Fill(motherID);
  }
  //  float vp= aTrack->VTOF();
  //     if (vp > 0.) {
  //         fTOFTime->Fill(tMom, tTOF);
  //         if (fTOFParticle == 0) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFPi());
  //         if (fTOFParticle == 1) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFK());
  //         if (fTOFParticle == 2) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFP());
  // }

    if (fTOFParticle == 0) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFPi());
    if (fTOFParticle == 1) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFK());
    if (fTOFParticle == 2) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFP());
    if (fTOFParticle == 3) fTOFNSigma->Fill(tMom, aTrack->NSigmaTOFD());

    if (fTOFParticle == 0) fTPCNSigma->Fill(tMom, aTrack->NSigmaTPCPi());
    if (fTOFParticle == 1) fTPCNSigma->Fill(tMom, aTrack->NSigmaTPCK());
    if (fTOFParticle == 2) fTPCNSigma->Fill(tMom, aTrack->NSigmaTPCP());
    if (fTOFParticle == 3) fTPCNSigma->Fill(tMom, aTrack->NSigmaTPCD());

    if (fTOFParticle == 0) fTPCTOFNSigma->Fill(tMom, TMath::Hypot( aTrack->NSigmaTPCPi(), aTrack->NSigmaTOFPi() ) );
    if (fTOFParticle == 1) fTPCTOFNSigma->Fill(tMom, TMath::Hypot( aTrack->NSigmaTPCK(), aTrack->NSigmaTOFK() ) );
    if (fTOFParticle == 2) fTPCTOFNSigma->Fill(tMom, TMath::Hypot( aTrack->NSigmaTPCP(), aTrack->NSigmaTOFP() ) );
    if (fTOFParticle == 3) fTPCTOFNSigma->Fill(tMom, TMath::Hypot( aTrack->NSigmaTPCD(), aTrack->NSigmaTOFD() ) );

    if (fTOFParticle == 0) fTPCvsTOFNSigma->Fill(aTrack->NSigmaTPCPi(), aTrack->NSigmaTOFPi());
    if (fTOFParticle == 1) fTPCvsTOFNSigma->Fill(aTrack->NSigmaTPCK(), aTrack->NSigmaTOFK());
    if (fTOFParticle == 2) fTPCvsTOFNSigma->Fill(aTrack->NSigmaTPCP(), aTrack->NSigmaTOFP());
    if (fTOFParticle == 3) fTPCvsTOFNSigma->Fill(aTrack->NSigmaTPCD(), aTrack->NSigmaTOFD());

}

void AliFemtoCutMonitorParticlePID::Write()
{
  // Write out the relevant histograms
  fTPCdEdx->Write();
  fTOFTime->Write();
  fTOFNSigma->Write();
  fTPCNSigma->Write();
  fTPCTOFNSigma->Write();
  fTPCvsTOFNSigma->Write();
  fParticleId->Write();
  fParticleOrigin->Write();
}

TList *AliFemtoCutMonitorParticlePID::GetOutputList()
{
  TList *tOutputList = new TList();
  tOutputList->Add(fTPCdEdx);
  tOutputList->Add(fTOFTime);
  tOutputList->Add(fTOFNSigma);
  tOutputList->Add(fTPCNSigma);
  tOutputList->Add(fTPCTOFNSigma);
  tOutputList->Add(fTPCvsTOFNSigma);
  tOutputList->Add(fParticleId);
  tOutputList->Add(fParticleOrigin);

  return tOutputList;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// This file contains the WebRTC suppressions for ThreadSanitizer.
// Please refer to
// http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for more info.

#if defined(THREAD_SANITIZER)

// Please make sure the code below declares a single string variable
// kTSanDefaultSuppressions contains TSan suppressions delimited by newlines.
// See http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for the instructions on writing suppressions.
char kTSanDefaultSuppressions[] =

// WebRTC specific suppressions.

// Split up suppressions covered previously by thread.cc and messagequeue.cc.
"race:vp8cx_remove_encoder_threads\n"
"race:third_party/libvpx/source/libvpx/vp9/common/vp9_scan.h\n"

// Usage of trace callback and trace level is racy in rtc_media_unittests.
// https://code.google.com/p/webrtc/issues/detail?id=3372
"race:webrtc::TraceImpl::WriteToFile\n"
"race:webrtc::VideoEngine::SetTraceFilter\n"
"race:webrtc::VoiceEngine::SetTraceFilter\n"
"race:webrtc::Trace::set_level_filter\n"
"race:webrtc::GetStaticInstance<webrtc::TraceImpl>\n"

// Race in pulse initialization.
// https://code.google.com/p/webrtc/issues/detail?id=5152
"race:webrtc::AudioDeviceLinuxPulse::Init\n"

// rtc_unittests
// https://code.google.com/p/webrtc/issues/detail?id=3911 for details.
"race:rtc::MessageQueueManager::Clear\n"
"race:rtc::Thread::Clear\n"
// https://code.google.com/p/webrtc/issues/detail?id=2080
"race:webrtc/base/logging.cc\n"
"race:webrtc/base/sharedexclusivelock_unittest.cc\n"
"race:webrtc/base/signalthread_unittest.cc\n"
// https://code.google.com/p/webrtc/issues/detail?id=4456
"deadlock:rtc::MessageQueueManager::Clear\n"
"deadlock:rtc::MessageQueueManager::ClearInternal\n"

// rtc_pc_unittests
// https://code.google.com/p/webrtc/issues/detail?id=2079
"race:webrtc/base/testclient.cc\n"
"race:webrtc/base/virtualsocketserver.cc\n"
"race:talk/p2p/base/stunserver_unittest.cc\n"

// third_party/usrsctp
// TODO(jiayl): https://code.google.com/p/webrtc/issues/detail?id=3492
"race:user_sctp_timer_iterate\n"

// https://code.google.com/p/webrtc/issues/detail?id=5151
"race:sctp_close\n"

// Potential deadlocks detected after roll in r6516.
// https://code.google.com/p/webrtc/issues/detail?id=3509
"deadlock:webrtc::test::UdpSocketManagerPosixImpl::RemoveSocket\n"

// TODO(pbos): Trace events are racy due to lack of proper POD atomics.
// https://code.google.com/p/webrtc/issues/detail?id=2497
"race:*trace_event_unique_catstatic*\n"

// https://code.google.com/p/webrtc/issues/detail?id=4719
"race:webrtc::voe::TransmitMixer::PrepareDemux\n"
"race:webrtc::voe::TransmitMixer::EnableStereoChannelSwapping\n"

// Race between InitCpuFlags and TestCpuFlag in libyuv.
// https://code.google.com/p/libyuv/issues/detail?id=508
"race:InitCpuFlags\n"

// End of suppressions.
;  // Please keep this semicolon.

#endif  // THREAD_SANITIZER
<commit_msg>Adding suppression for race in stats collector test.<commit_after>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// This file contains the WebRTC suppressions for ThreadSanitizer.
// Please refer to
// http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for more info.

#if defined(THREAD_SANITIZER)

// Please make sure the code below declares a single string variable
// kTSanDefaultSuppressions contains TSan suppressions delimited by newlines.
// See http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for the instructions on writing suppressions.
char kTSanDefaultSuppressions[] =

// WebRTC specific suppressions.

// Split up suppressions covered previously by thread.cc and messagequeue.cc.
"race:vp8cx_remove_encoder_threads\n"
"race:third_party/libvpx/source/libvpx/vp9/common/vp9_scan.h\n"

// Usage of trace callback and trace level is racy in rtc_media_unittests.
// https://code.google.com/p/webrtc/issues/detail?id=3372
"race:webrtc::TraceImpl::WriteToFile\n"
"race:webrtc::VideoEngine::SetTraceFilter\n"
"race:webrtc::VoiceEngine::SetTraceFilter\n"
"race:webrtc::Trace::set_level_filter\n"
"race:webrtc::GetStaticInstance<webrtc::TraceImpl>\n"

// Race in pulse initialization.
// https://code.google.com/p/webrtc/issues/detail?id=5152
"race:webrtc::AudioDeviceLinuxPulse::Init\n"

// rtc_unittests
// https://code.google.com/p/webrtc/issues/detail?id=3911 for details.
"race:rtc::MessageQueueManager::Clear\n"
"race:rtc::Thread::Clear\n"
// https://code.google.com/p/webrtc/issues/detail?id=2080
"race:webrtc/base/logging.cc\n"
"race:webrtc/base/sharedexclusivelock_unittest.cc\n"
"race:webrtc/base/signalthread_unittest.cc\n"
// https://code.google.com/p/webrtc/issues/detail?id=4456
"deadlock:rtc::MessageQueueManager::Clear\n"
"deadlock:rtc::MessageQueueManager::ClearInternal\n"

// rtc_pc_unittests
// https://code.google.com/p/webrtc/issues/detail?id=2079
"race:webrtc/base/testclient.cc\n"
"race:webrtc/base/virtualsocketserver.cc\n"
"race:talk/p2p/base/stunserver_unittest.cc\n"

// third_party/usrsctp
// TODO(jiayl): https://code.google.com/p/webrtc/issues/detail?id=3492
"race:user_sctp_timer_iterate\n"

// https://code.google.com/p/webrtc/issues/detail?id=5151
"race:sctp_close\n"

// Potential deadlocks detected after roll in r6516.
// https://code.google.com/p/webrtc/issues/detail?id=3509
"deadlock:webrtc::test::UdpSocketManagerPosixImpl::RemoveSocket\n"

// TODO(pbos): Trace events are racy due to lack of proper POD atomics.
// https://code.google.com/p/webrtc/issues/detail?id=2497
"race:*trace_event_unique_catstatic*\n"

// https://code.google.com/p/webrtc/issues/detail?id=4719
"race:webrtc::voe::TransmitMixer::PrepareDemux\n"
"race:webrtc::voe::TransmitMixer::EnableStereoChannelSwapping\n"

// Race between InitCpuFlags and TestCpuFlag in libyuv.
// https://code.google.com/p/libyuv/issues/detail?id=508
"race:InitCpuFlags\n"

// Test-only race due to PeerConnection::session() being virtual for testing.
// The stats collector may call session() before or after the destructor begins
// executing, which modifies the vtable.
"race:*RTCStatsIntegrationTest_GetsStatsWhileDestroyingPeerConnections_Test::TestBody\n"

// End of suppressions.
;  // Please keep this semicolon.

#endif  // THREAD_SANITIZER
<|endoftext|>


<commit_before>// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     -T semihosted.lds \
// RUN:     -L some/directory/user/asked/for \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-C %s
// CHECK-V6M-C: "[[PREFIX_DIR:.*]]/bin/clang" "-cc1" "-triple" "thumbv6m-none--eabi"
// CHECK-V6M-C-SAME: "-resource-dir" "[[PREFIX_DIR]]/lib/clang/[[VERSION:[^"]*]]"
// CHECK-V6M-C-SAME: "-isysroot" "[[SYSROOT:[^"]*]]"
// CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]/include/c++/v1"
// CHECk-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]/include"
// CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp"
// CHECK-V6M-C-NEXT: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-C-SAME: "-L[[PREFIX_DIR]]/lib/clang/[[VERSION]]/lib/baremetal"
// CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome/directory/user/asked/for"
// CHECK-V6M-C-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
// CHECK-V6M-C-SAME: "-o" "{{.*}}.o"

// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     -nostdlibinc -nobuiltininc \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBINC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     -nostdinc \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBINC %s
// CHECK-V6M-LIBINC-NOT: "-internal-isystem"

// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-DEFAULTCXX %s
// CHECK-V6M-DEFAULTCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}/lib/clang/{{.*}}/lib/baremetal"
// CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
// CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
// CHECK-V6M-DEFAULTCXX-SAME: "-o" "{{.*}}.o"

// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:     -stdlib=libc++ \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBCXX %s
// CHECK-V6M-LIBCXX-NOT: "-internal-isystem" "{{[^"]+}}/include/c++/{{[^v].*}}"
// CHECK-V6M-LIBCXX: "-internal-isystem" "{{[^"]+}}/include/c++/v1"
// CHECK-V6M-LIBCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-LIBCXX-SAME: "-L{{[^"]*}}/lib/clang/{{.*}}/lib/baremetal"
// CHECK-V6M-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
// CHECK-V6M-LIBCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
// CHECK-V6M-LIBCXX-SAME: "-o" "{{.*}}.o"

// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:     -stdlib=libstdc++ \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBSTDCXX %s
// CHECK-V6M-LIBSTDCXX-NOT: "-internal-isystem" "{{[^"]+}}/include/c++/v1"
// CHECK-V6M-LIBSTDCXX: "-internal-isystem" "{{[^"]+}}/include/c++/6.0.0"
// CHECK-V6M-LIBSTDCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-LIBSTDCXX-SAME: "-L{{[^"]*}}/lib/clang/{{.*}}/lib/baremetal"
// CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind"
// CHECK-V6M-LIBSTDCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
// CHECK-V6M-LIBSTDCXX-SAME: "-o" "{{.*}}.o"

// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:     -nodefaultlibs \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-NDL %s
// CHECK-V6M-NDL: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-NDL-SAME: "-L{{[^"]*}}/lib/clang/{{.*}}/lib/baremetal" "-o" "{{.*}}.o"

// RUN: %clangxx -target arm-none-eabi -v 2>&1 \
// RUN:   | FileCheck %s --check-prefix=CHECK-THREAD-MODEL
// CHECK-THREAD-MODEL: Thread model: single
<commit_msg>Make test/Driver/baremetal.cpp pass on Windows<commit_after>// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     -T semihosted.lds \
// RUN:     -L some/directory/user/asked/for \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-C %s
// CHECK-V6M-C: "[[PREFIX_DIR:.*]]{{[/\\]+}}bin{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "thumbv6m-none--eabi"
// CHECK-V6M-C-SAME: "-resource-dir" "[[PREFIX_DIR]]{{[/\\]+}}lib{{[/\\]+}}clang{{[/\\]+}}[[VERSION:[^"]*]]"
// CHECK-V6M-C-SAME: "-isysroot" "[[SYSROOT:[^"]*]]"
// CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
// CHECk-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include"
// CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp"
// CHECK-V6M-C-NEXT: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-C-SAME: "-L[[PREFIX_DIR]]{{[/\\]+}}lib{{[/\\]+}}clang{{[/\\]+}}[[VERSION]]{{[/\\]+}}lib{{[/\\]+}}baremetal"
// CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for"
// CHECK-V6M-C-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
// CHECK-V6M-C-SAME: "-o" "{{.*}}.o"

// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     -nostdlibinc -nobuiltininc \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBINC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     -nostdinc \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBINC %s
// CHECK-V6M-LIBINC-NOT: "-internal-isystem"

// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-DEFAULTCXX %s
// CHECK-V6M-DEFAULTCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal"
// CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
// CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
// CHECK-V6M-DEFAULTCXX-SAME: "-o" "{{.*}}.o"

// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:     -stdlib=libc++ \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBCXX %s
// CHECK-V6M-LIBCXX-NOT: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}{{[^v].*}}"
// CHECK-V6M-LIBCXX: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
// CHECK-V6M-LIBCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal"
// CHECK-V6M-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
// CHECK-V6M-LIBCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
// CHECK-V6M-LIBCXX-SAME: "-o" "{{.*}}.o"

// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:     -stdlib=libstdc++ \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBSTDCXX %s
// CHECK-V6M-LIBSTDCXX-NOT: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
// CHECK-V6M-LIBSTDCXX: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}6.0.0"
// CHECK-V6M-LIBSTDCXX: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal"
// CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind"
// CHECK-V6M-LIBSTDCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
// CHECK-V6M-LIBSTDCXX-SAME: "-o" "{{.*}}.o"

// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN:     -target armv6m-none-eabi \
// RUN:     --sysroot=%S/Inputs/baremetal_arm \
// RUN:     -nodefaultlibs \
// RUN:   | FileCheck --check-prefix=CHECK-V6M-NDL %s
// CHECK-V6M-NDL: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic"
// CHECK-V6M-NDL-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal" "-o" "{{.*}}.o"

// RUN: %clangxx -target arm-none-eabi -v 2>&1 \
// RUN:   | FileCheck %s --check-prefix=CHECK-THREAD-MODEL
// CHECK-THREAD-MODEL: Thread model: single
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2017, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "ThreadLocalSSLContextProvider.h"

#include <unordered_map>

#include <folly/Hash.h>
#include <folly/Singleton.h>
#include <folly/io/async/SSLContext.h>
#include <wangle/client/persistence/SharedMutexCacheLockGuard.h>
#include <wangle/client/ssl/SSLSessionCacheData.h>
#include <wangle/client/ssl/SSLSessionPersistentCache.h>
#include <wangle/ssl/SSLCacheOptions.h>
#include <wangle/ssl/SSLContextConfig.h>
#include <wangle/ssl/SSLSessionCacheManager.h>
#include <wangle/ssl/ServerSSLContext.h>
#include <wangle/ssl/TLSTicketKeyManager.h>
#include <wangle/ssl/TLSTicketKeySeeds.h>

#include "mcrouter/lib/fbi/cpp/LogFailure.h"

using folly::SSLContext;

namespace facebook {
namespace memcache {

namespace {

/* Sessions are valid for upto 24 hours */
constexpr size_t kSessionLifeTime = 86400;

struct CertPaths {
  folly::StringPiece pemCertPath;
  folly::StringPiece pemKeyPath;
  folly::StringPiece pemCaPath;
  bool isClient;

  bool operator==(const CertPaths& other) const {
    return pemCertPath == other.pemCertPath && pemKeyPath == other.pemKeyPath &&
        pemCaPath == other.pemCaPath && isClient == other.isClient;
  }
};

struct ContextInfo {
  std::string pemCertPath;
  std::string pemKeyPath;
  std::string pemCaPath;

  std::shared_ptr<SSLContext> context;

  std::chrono::time_point<std::chrono::steady_clock> lastLoadTime;
};

struct CertPathsHasher {
  size_t operator()(const CertPaths& paths) const {
    return folly::Hash()(
        paths.pemCertPath, paths.pemKeyPath, paths.pemCaPath, paths.isClient);
  }
};

void logCertFailure(
    folly::StringPiece name,
    folly::StringPiece path,
    const std::exception& ex) {
  LOG_FAILURE(
      "SSLCert",
      failure::Category::kBadEnvironment,
      "Failed to load {} from \"{}\", ex: {}",
      name,
      path,
      ex.what());
}

bool configureSSLContext(
    folly::SSLContext& sslContext,
    folly::StringPiece pemCertPath,
    folly::StringPiece pemKeyPath,
    folly::StringPiece pemCaPath) {
  // Load certificate.
  try {
    sslContext.loadCertificate(pemCertPath.begin());
  } catch (const std::exception& ex) {
    logCertFailure("certificate", pemCertPath, ex);
    return false;
  }

  // Load private key.
  try {
    sslContext.loadPrivateKey(pemKeyPath.begin());
  } catch (const std::exception& ex) {
    logCertFailure("private key", pemKeyPath, ex);
    return false;
  }

  // Load trusted certificates.
  try {
    sslContext.loadTrustedCertificates(pemCaPath.begin());
  } catch (const std::exception& ex) {
    logCertFailure("trusted certificates", pemCaPath, ex);
    return false;
  }

  // Load client CA list.
  try {
    sslContext.loadClientCAList(pemCaPath.begin());
  } catch (const std::exception& ex) {
    logCertFailure("client CA list", pemCaPath, ex);
    return false;
  }

// Try to disable compression if possible to reduce CPU and memory usage.
#ifdef SSL_OP_NO_COMPRESSION
  try {
    sslContext.setOptions(SSL_OP_NO_COMPRESSION);
  } catch (const std::runtime_error& ex) {
    LOG_FAILURE(
        "SSLCert",
        failure::Category::kSystemError,
        "Failed to apply SSL_OP_NO_COMPRESSION flag onto SSLContext "
        "with files: pemCertPath='{}', pemKeyPath='{}', pemCaPath='{}'",
        pemCertPath,
        pemKeyPath,
        pemCaPath);
    // We failed to disable compression, but the SSLContext itself is good to
    // use.
  }
#endif
  return true;
}

using TicketCacheLayer = wangle::LRUPersistentCache<
    std::string,
    wangle::SSLSessionCacheData,
    folly::SharedMutex>;

// a SSL session cache that keys off string
class SSLTicketCache
    : public wangle::SSLSessionPersistentCacheBase<std::string> {
 public:
  explicit SSLTicketCache(std::shared_ptr<TicketCacheLayer> cache)
      : wangle::SSLSessionPersistentCacheBase<std::string>(std::move(cache)) {}

 protected:
  std::string getKey(const std::string& identity) const override {
    return identity;
  }
};

// global thread safe ticket cache
folly::Singleton<SSLTicketCache> ticketCache([] {
  // create cache layer of max size 100;
  auto cacheLayer = std::make_shared<TicketCacheLayer>(100);
  return new SSLTicketCache(std::move(cacheLayer));
});

std::shared_ptr<SSLContext> createServerSSLContext(
    folly::StringPiece pemCertPath,
    folly::StringPiece pemKeyPath,
    folly::StringPiece pemCaPath,
    folly::Optional<wangle::TLSTicketKeySeeds> ticketKeySeeds) {
  wangle::SSLContextConfig cfg;
  // don't need to set any certs on the cfg since the context is configured
  // in configureSSLContext;
  cfg.sessionTicketEnabled = true;
  cfg.sessionCacheEnabled = true;
  cfg.sessionContext = "async-server";

  // we'll use our own internal session cache instead of openssl's
  wangle::SSLCacheOptions cacheOpts;
  cacheOpts.sslCacheTimeout = std::chrono::seconds(kSessionLifeTime);
  // defaults from wangle/acceptor/ServerSocketConfig.h
  cacheOpts.maxSSLCacheSize = 20480;
  cacheOpts.sslCacheFlushSize = 200;
  auto sslContext = std::make_shared<wangle::ServerSSLContext>();
  if (!configureSSLContext(*sslContext, pemCertPath, pemKeyPath, pemCaPath)) {
    return nullptr;
  }
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
  // ServerSSLContext handles null
  sslContext->setupTicketManager(ticketKeySeeds.get_pointer(), cfg, nullptr);
#endif
  sslContext->setupSessionCache(
      cfg,
      cacheOpts,
      nullptr, // external cache
      "", // common name
      nullptr); // SSL Stats

#ifdef SSL_CTRL_SET_MAX_SEND_FRAGMENT
  // reduce send fragment size
  SSL_CTX_set_max_send_fragment(sslContext->getSSLCtx(), 8000);
#endif
  return sslContext;
}

std::shared_ptr<SSLContext> createClientSSLContext(
    folly::StringPiece pemCertPath,
    folly::StringPiece pemKeyPath,
    folly::StringPiece pemCaPath) {
  auto context = std::make_shared<ClientSSLContext>();
  if (!configureSSLContext(*context, pemCertPath, pemKeyPath, pemCaPath)) {
    return nullptr;
  }
  auto sessionCache = ticketCache.try_get();
  if (sessionCache) {
    context->attachToCache(sessionCache);
  }
  return context;
}

} // anonymous

std::shared_ptr<SSLContext> getSSLContext(
    folly::StringPiece pemCertPath,
    folly::StringPiece pemKeyPath,
    folly::StringPiece pemCaPath,
    folly::Optional<wangle::TLSTicketKeySeeds> ticketKeySeeds,
    bool clientContext) {
  static constexpr std::chrono::minutes kSslReloadInterval{30};
  thread_local std::unordered_map<CertPaths, ContextInfo, CertPathsHasher>
      localContexts;

  CertPaths paths;
  paths.pemCertPath = pemCertPath;
  paths.pemKeyPath = pemKeyPath;
  paths.pemCaPath = pemCaPath;
  paths.isClient = clientContext;

  auto iter = localContexts.find(paths);
  if (localContexts.find(paths) == localContexts.end()) {
    // Copy strings.
    ContextInfo info;
    info.pemCertPath = pemCertPath.toString();
    info.pemKeyPath = pemKeyPath.toString();
    info.pemCaPath = pemCaPath.toString();
    // Point all StringPiece's to our own strings.
    paths.pemCertPath = info.pemCertPath;
    paths.pemKeyPath = info.pemKeyPath;
    paths.pemCaPath = info.pemCaPath;
    iter = localContexts.insert(std::make_pair(paths, std::move(info))).first;
  }

  auto& contextInfo = iter->second;

  auto now = std::chrono::steady_clock::now();
  if (contextInfo.context == nullptr ||
      now - contextInfo.lastLoadTime > kSslReloadInterval) {
    auto updated = clientContext
        ? createClientSSLContext(pemCertPath, pemKeyPath, pemCaPath)
        : createServerSSLContext(
              pemCertPath, pemKeyPath, pemCaPath, std::move(ticketKeySeeds));
    if (updated) {
      contextInfo.lastLoadTime = now;
      contextInfo.context = std::move(updated);
    }
  }

  return contextInfo.context;
}

} // memcache
} // facebook
<commit_msg>Pass async-server as the session id context explicitly<commit_after>/*
 *  Copyright (c) 2017, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "ThreadLocalSSLContextProvider.h"

#include <unordered_map>

#include <folly/Hash.h>
#include <folly/Singleton.h>
#include <folly/io/async/SSLContext.h>
#include <wangle/client/persistence/SharedMutexCacheLockGuard.h>
#include <wangle/client/ssl/SSLSessionCacheData.h>
#include <wangle/client/ssl/SSLSessionPersistentCache.h>
#include <wangle/ssl/SSLCacheOptions.h>
#include <wangle/ssl/SSLContextConfig.h>
#include <wangle/ssl/SSLSessionCacheManager.h>
#include <wangle/ssl/ServerSSLContext.h>
#include <wangle/ssl/TLSTicketKeyManager.h>
#include <wangle/ssl/TLSTicketKeySeeds.h>

#include "mcrouter/lib/fbi/cpp/LogFailure.h"

using folly::SSLContext;

namespace facebook {
namespace memcache {

namespace {

/* Sessions are valid for upto 24 hours */
constexpr size_t kSessionLifeTime = 86400;

struct CertPaths {
  folly::StringPiece pemCertPath;
  folly::StringPiece pemKeyPath;
  folly::StringPiece pemCaPath;
  bool isClient;

  bool operator==(const CertPaths& other) const {
    return pemCertPath == other.pemCertPath && pemKeyPath == other.pemKeyPath &&
        pemCaPath == other.pemCaPath && isClient == other.isClient;
  }
};

struct ContextInfo {
  std::string pemCertPath;
  std::string pemKeyPath;
  std::string pemCaPath;

  std::shared_ptr<SSLContext> context;

  std::chrono::time_point<std::chrono::steady_clock> lastLoadTime;
};

struct CertPathsHasher {
  size_t operator()(const CertPaths& paths) const {
    return folly::Hash()(
        paths.pemCertPath, paths.pemKeyPath, paths.pemCaPath, paths.isClient);
  }
};

void logCertFailure(
    folly::StringPiece name,
    folly::StringPiece path,
    const std::exception& ex) {
  LOG_FAILURE(
      "SSLCert",
      failure::Category::kBadEnvironment,
      "Failed to load {} from \"{}\", ex: {}",
      name,
      path,
      ex.what());
}

bool configureSSLContext(
    folly::SSLContext& sslContext,
    folly::StringPiece pemCertPath,
    folly::StringPiece pemKeyPath,
    folly::StringPiece pemCaPath) {
  // Load certificate.
  try {
    sslContext.loadCertificate(pemCertPath.begin());
  } catch (const std::exception& ex) {
    logCertFailure("certificate", pemCertPath, ex);
    return false;
  }

  // Load private key.
  try {
    sslContext.loadPrivateKey(pemKeyPath.begin());
  } catch (const std::exception& ex) {
    logCertFailure("private key", pemKeyPath, ex);
    return false;
  }

  // Load trusted certificates.
  try {
    sslContext.loadTrustedCertificates(pemCaPath.begin());
  } catch (const std::exception& ex) {
    logCertFailure("trusted certificates", pemCaPath, ex);
    return false;
  }

  // Load client CA list.
  try {
    sslContext.loadClientCAList(pemCaPath.begin());
  } catch (const std::exception& ex) {
    logCertFailure("client CA list", pemCaPath, ex);
    return false;
  }

// Try to disable compression if possible to reduce CPU and memory usage.
#ifdef SSL_OP_NO_COMPRESSION
  try {
    sslContext.setOptions(SSL_OP_NO_COMPRESSION);
  } catch (const std::runtime_error& ex) {
    LOG_FAILURE(
        "SSLCert",
        failure::Category::kSystemError,
        "Failed to apply SSL_OP_NO_COMPRESSION flag onto SSLContext "
        "with files: pemCertPath='{}', pemKeyPath='{}', pemCaPath='{}'",
        pemCertPath,
        pemKeyPath,
        pemCaPath);
    // We failed to disable compression, but the SSLContext itself is good to
    // use.
  }
#endif
  return true;
}

using TicketCacheLayer = wangle::LRUPersistentCache<
    std::string,
    wangle::SSLSessionCacheData,
    folly::SharedMutex>;

// a SSL session cache that keys off string
class SSLTicketCache
    : public wangle::SSLSessionPersistentCacheBase<std::string> {
 public:
  explicit SSLTicketCache(std::shared_ptr<TicketCacheLayer> cache)
      : wangle::SSLSessionPersistentCacheBase<std::string>(std::move(cache)) {}

 protected:
  std::string getKey(const std::string& identity) const override {
    return identity;
  }
};

// global thread safe ticket cache
folly::Singleton<SSLTicketCache> ticketCache([] {
  // create cache layer of max size 100;
  auto cacheLayer = std::make_shared<TicketCacheLayer>(100);
  return new SSLTicketCache(std::move(cacheLayer));
});

std::shared_ptr<SSLContext> createServerSSLContext(
    folly::StringPiece pemCertPath,
    folly::StringPiece pemKeyPath,
    folly::StringPiece pemCaPath,
    folly::Optional<wangle::TLSTicketKeySeeds> ticketKeySeeds) {
  wangle::SSLContextConfig cfg;
  // don't need to set any certs on the cfg since the context is configured
  // in configureSSLContext;
  cfg.sessionTicketEnabled = true;
  cfg.sessionCacheEnabled = true;
  cfg.sessionContext = "async-server";

  // we'll use our own internal session cache instead of openssl's
  wangle::SSLCacheOptions cacheOpts;
  cacheOpts.sslCacheTimeout = std::chrono::seconds(kSessionLifeTime);
  // defaults from wangle/acceptor/ServerSocketConfig.h
  cacheOpts.maxSSLCacheSize = 20480;
  cacheOpts.sslCacheFlushSize = 200;
  auto sslContext = std::make_shared<wangle::ServerSSLContext>();
  if (!configureSSLContext(*sslContext, pemCertPath, pemKeyPath, pemCaPath)) {
    return nullptr;
  }
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
  // ServerSSLContext handles null
  sslContext->setupTicketManager(ticketKeySeeds.get_pointer(), cfg, nullptr);
#endif
  sslContext->setupSessionCache(
      cfg,
      cacheOpts,
      nullptr, // external cache
      "async-server", // session context
      nullptr); // SSL Stats

#ifdef SSL_CTRL_SET_MAX_SEND_FRAGMENT
  // reduce send fragment size
  SSL_CTX_set_max_send_fragment(sslContext->getSSLCtx(), 8000);
#endif
  return sslContext;
}

std::shared_ptr<SSLContext> createClientSSLContext(
    folly::StringPiece pemCertPath,
    folly::StringPiece pemKeyPath,
    folly::StringPiece pemCaPath) {
  auto context = std::make_shared<ClientSSLContext>();
  if (!configureSSLContext(*context, pemCertPath, pemKeyPath, pemCaPath)) {
    return nullptr;
  }
  auto sessionCache = ticketCache.try_get();
  if (sessionCache) {
    context->attachToCache(sessionCache);
  }
  return context;
}

} // anonymous

std::shared_ptr<SSLContext> getSSLContext(
    folly::StringPiece pemCertPath,
    folly::StringPiece pemKeyPath,
    folly::StringPiece pemCaPath,
    folly::Optional<wangle::TLSTicketKeySeeds> ticketKeySeeds,
    bool clientContext) {
  static constexpr std::chrono::minutes kSslReloadInterval{30};
  thread_local std::unordered_map<CertPaths, ContextInfo, CertPathsHasher>
      localContexts;

  CertPaths paths;
  paths.pemCertPath = pemCertPath;
  paths.pemKeyPath = pemKeyPath;
  paths.pemCaPath = pemCaPath;
  paths.isClient = clientContext;

  auto iter = localContexts.find(paths);
  if (localContexts.find(paths) == localContexts.end()) {
    // Copy strings.
    ContextInfo info;
    info.pemCertPath = pemCertPath.toString();
    info.pemKeyPath = pemKeyPath.toString();
    info.pemCaPath = pemCaPath.toString();
    // Point all StringPiece's to our own strings.
    paths.pemCertPath = info.pemCertPath;
    paths.pemKeyPath = info.pemKeyPath;
    paths.pemCaPath = info.pemCaPath;
    iter = localContexts.insert(std::make_pair(paths, std::move(info))).first;
  }

  auto& contextInfo = iter->second;

  auto now = std::chrono::steady_clock::now();
  if (contextInfo.context == nullptr ||
      now - contextInfo.lastLoadTime > kSslReloadInterval) {
    auto updated = clientContext
        ? createClientSSLContext(pemCertPath, pemKeyPath, pemCaPath)
        : createServerSSLContext(
              pemCertPath, pemKeyPath, pemCaPath, std::move(ticketKeySeeds));
    if (updated) {
      contextInfo.lastLoadTime = now;
      contextInfo.context = std::move(updated);
    }
  }

  return contextInfo.context;
}

} // memcache
} // facebook
<|endoftext|>


<commit_before>// soundmgr.cxx -- Sound effect management class
//
// Sound manager initially written by David Findlay
// <david_j_findlay@yahoo.com.au> 2001
//
// C++-ified by Curtis Olson, started March 2001.
//
// Copyright (C) 2001  Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$

#include <iostream>

#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>

#include "soundmgr.hxx"

#define SOUND_SAFETY_MULT 3
#define MAX_SOUND_SAFETY ( 1.0 / SOUND_SAFETY_MULT )

//
// SGSimpleSound
//

// constructor
SGSimpleSound::SGSimpleSound( const char *path, const char *file )
  : sample(NULL),
    pitch_envelope(NULL),
    volume_envelope(NULL),
    pitch(1.0),
    volume(1.0)
{
    SGPath slfile( path );
    if ( file )
       slfile.append( file );

    sample = new slSample ( slfile.c_str() );
    pitch_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
    volume_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
    pitch_envelope->setStep ( 0, 0.01, 1.0 );
    volume_envelope->setStep ( 0, 0.01, 1.0 );
}

SGSimpleSound::SGSimpleSound( unsigned char *buffer, int len )
  : pitch(1.0),
    volume(1.0)
{
    sample = new slSample ( buffer, len );
    pitch_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
    volume_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
    pitch_envelope->setStep ( 0, 0.01, 1.0 );
    volume_envelope->setStep ( 0, 0.01, 1.0 );
}

// destructor
SGSimpleSound::~SGSimpleSound() {
    delete pitch_envelope;
    delete volume_envelope;
    delete sample;
}

void SGSimpleSound::play( slScheduler *sched, bool looped ) {

    // make sure sound isn't already playing
    if ( sample->getPlayCount() > 0 ) {
       sched->stopSample(sample);
    //   return;
    }

    if ( looped ) {
        sched->loopSample(sample);
    } else {
        sched->playSample(sample);
    }

    sched->addSampleEnvelope(sample, 0, 0, pitch_envelope, SL_PITCH_ENVELOPE);
    sched->addSampleEnvelope(sample, 0, 1, volume_envelope, SL_VOLUME_ENVELOPE);
}

void SGSimpleSound::stop( slScheduler *sched, bool quick ) {

    sched->stopSample( sample );
}

//
// Sound Manager
//

// constructor
SGSoundMgr::SGSoundMgr() {
    audio_sched = new slScheduler( 8000 );
    if ( audio_sched->notWorking() ) {
	SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
    } else {
	audio_sched -> setMaxConcurrent ( 6 );

	audio_mixer = new smMixer;

	SG_LOG( SG_GENERAL, SG_INFO,
		"Rate = " << audio_sched->getRate()
		<< "  Bps = " << audio_sched->getBps()
		<< "  Stereo = " << audio_sched->getStereo() );
    }
}

// destructor

SGSoundMgr::~SGSoundMgr() {

    //
    // Remove the samples from the sample manager.
    //
    sample_map_iterator sample_current = samples.begin();
    sample_map_iterator sample_end = samples.end();
    for ( ; sample_current != sample_end; ++sample_current ) {
	sample_ref *sr = sample_current->second;

        audio_sched->stopSample(sr->sample);
	delete sr->sample;
	delete sr;
    }

    //
    // Remove the sounds from the sound manager.
    //
    sound_map_iterator sound_current = sounds.begin();
    sound_map_iterator sound_end = sounds.end();
    for ( ; sound_current != sound_end; ++sound_current ) {
        SGSimpleSound *s = sound_current->second;

        audio_sched->stopSample(s->get_sample());
        delete s->get_sample();
        delete s;
    }

    delete audio_sched;
    delete audio_mixer;
}

// initialize the sound manager
void SGSoundMgr::init() {
    safety = MAX_SOUND_SAFETY;

    // audio_mixer -> setMasterVolume ( 80 ) ;  /* 80% of max volume. */
    audio_sched -> setSafetyMargin ( SOUND_SAFETY_MULT * safety ) ;

    //
    // Remove the samples from the sample manager.
    //
    sample_map_iterator sample_current = samples.begin();
    sample_map_iterator sample_end = samples.end();
    for ( ; sample_current != sample_end; ++sample_current ) {
        sample_ref *sr = sample_current->second;

        audio_sched->stopSample(sr->sample);
        delete sr->sample;
        delete sr;
    }
    samples.clear();

    //
    // Remove the sounds from the sound manager.
    //
    sound_map_iterator sound_current = sounds.begin();
    sound_map_iterator sound_end = sounds.end();
    for ( ; sound_current != sound_end; ++sound_current ) {
	SGSimpleSound *s = sound_current->second;

        audio_sched->stopSample(s->get_sample());
	delete s->get_sample();
	delete s;
    }
    sounds.clear();

}

void SGSoundMgr::bind ()
{
  // no properties yet
}

void SGSoundMgr::unbind ()
{
  // no properties yet
}

// run the audio scheduler
void SGSoundMgr::update( double dt ) {
    if ( dt > safety ) {
	safety = dt;
    } else {
	safety = safety * 0.99 + dt * 0.01;
    }
    if ( safety > MAX_SOUND_SAFETY ) {
	safety = MAX_SOUND_SAFETY;
    }
    // cout << "safety = " << safety << endl;
    audio_sched -> setSafetyMargin ( SOUND_SAFETY_MULT * safety ) ;

    if ( !audio_sched->not_working() )
	audio_sched -> update();
}

void
SGSoundMgr::pause ()
{
  audio_sched->pauseSample(0, 0);
}

void
SGSoundMgr::resume ()
{
  audio_sched->resumeSample(0, 0);
}

// add a sound effect, return true if successful
bool SGSoundMgr::add( SGSimpleSound *sound, const string& refname ) {

    sound_map_iterator sound_it = sounds.find( refname );
    if ( sound_it != sounds.end() ) {
        // sound already exists
        return false;
    }

    sample_map_iterator sample_it = samples.find( refname );
    if ( sample_it != samples.end() ) {
        // this sound has existed in the past and it's sample is still
        // here, delete the sample so we can replace it.
        samples.erase( sample_it );
    }

    sample_ref *sr = new sample_ref;

    sr->n=1;
    sr->sample = sound->get_sample();
    samples[refname] = sr;

    sounds[refname] = sound;

    return true;
}

// add a sound from a file, return the sample if successful, else return NULL
SGSimpleSound *SGSoundMgr::add( const string &refname,
                            const char *path, const char *file ) {
     SGSimpleSound *sound;

    SGPath slfile( path );
    if ( file )
       slfile.append( file );

    if ( slfile.str().empty() )
       return NULL;

    sample_map_iterator it = samples.find(slfile.str());
    if (it == samples.end()) {

       sound = new SGSimpleSound(slfile.c_str());
       sounds[refname] = sound;

       sample_ref *sr = new sample_ref;

       sr->n=1;
       sr->sample = sound->get_sample();
       samples[slfile.str()] = sr;

    } else {
       sample_ref *sr = it->second;

       sr->n++;
       sound =
           new SGSimpleSound(sr->sample->getBuffer(), sr->sample->getLength());
       sounds[refname] = sound;

    }

    return sound;
}

// remove a sound effect, return true if successful
bool SGSoundMgr::remove( const string &refname ) {

    sound_map_iterator it = sounds.find( refname );
    if ( it != sounds.end() ) {
	// first stop the sound from playing (so we don't bomb the
	// audio scheduler)
	SGSimpleSound *sample = it->second;

	// cout << "Playing " << sample->get_sample()->getPlayCount()
	//      << " instances!" << endl;

	audio_sched->stopSample( sample->get_sample() );
	audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0,
					NULL,
					SL_PITCH_ENVELOPE );
	audio_sched->addSampleEnvelope( sample->get_sample(), 0, 1,
					NULL,
					SL_VOLUME_ENVELOPE );

	// must call audio_sched->update() after stopping the sound
	// but before deleting it.
	audio_sched -> update();
	// cout << "Still playing " << sample->get_sample()->getPlayCount()
	//      << " instances!" << endl;

        //
        // FIXME:
        // Due to the change in the sound manager, samples live
	// until the sound manager gets removed.
        //
	// delete sample;
        sounds.erase( it );

        // cout << "sndmgr: removed -> " << refname << endl;
	return true;
    } else {
        // cout << "sndmgr: failed remove -> " << refname << endl;
        return false;
    }
}

// return true of the specified sound exists in the sound manager system
bool SGSoundMgr::exists( const string &refname ) {
    sound_map_iterator it = sounds.find( refname );
    if ( it != sounds.end() ) {
	return true;
   } else {
	return false;
    }
}

// return a pointer to the SGSimpleSound if the specified sound exists
// in the sound manager system, otherwise return NULL
SGSimpleSound *SGSoundMgr::find( const string &refname ) {
    sound_map_iterator it = sounds.find( refname );
    if ( it != sounds.end() ) {
	return it->second;
    } else {
	return NULL;
    }
}

// tell the scheduler to play the indexed sample in a continuous
// loop
bool SGSoundMgr::play_looped( const string &refname ) {
   SGSimpleSound *sample;

    if ((sample = find( refname )) == NULL)
       return false;

    sample->play(audio_sched, true);
    return true;
}

// tell the scheduler to play the indexed sample once
bool SGSoundMgr::play_once( const string& refname ) {
    SGSimpleSound *sample;

    if ((sample = find( refname )) == NULL)
       return false;

    sample->play(audio_sched, false);
    return true;
}

// return true of the specified sound is currently being played
bool SGSoundMgr::is_playing( const string& refname ) {
    SGSimpleSound *sample;

    if ((sample = find( refname )) == NULL)
       return false;

    return (sample->get_sample()->getPlayCount() > 0 );
}

// immediate stop playing the sound
bool SGSoundMgr::stop( const string& refname ) {
    SGSimpleSound *sample;

    if ((sample = find( refname )) == NULL)
       return false;

    audio_sched->stopSample( sample->get_sample() );
    return true;
}
<commit_msg>Remove an unused variable<commit_after>// soundmgr.cxx -- Sound effect management class
//
// Sound manager initially written by David Findlay
// <david_j_findlay@yahoo.com.au> 2001
//
// C++-ified by Curtis Olson, started March 2001.
//
// Copyright (C) 2001  Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$

#include <iostream>

#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>

#include "soundmgr.hxx"

#define SOUND_SAFETY_MULT 3
#define MAX_SOUND_SAFETY ( 1.0 / SOUND_SAFETY_MULT )

//
// SGSimpleSound
//

// constructor
SGSimpleSound::SGSimpleSound( const char *path, const char *file )
  : sample(NULL),
    pitch_envelope(NULL),
    volume_envelope(NULL),
    pitch(1.0),
    volume(1.0)
{
    SGPath slfile( path );
    if ( file )
       slfile.append( file );

    sample = new slSample ( slfile.c_str() );
    pitch_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
    volume_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
    pitch_envelope->setStep ( 0, 0.01, 1.0 );
    volume_envelope->setStep ( 0, 0.01, 1.0 );
}

SGSimpleSound::SGSimpleSound( unsigned char *buffer, int len )
  : pitch(1.0),
    volume(1.0)
{
    sample = new slSample ( buffer, len );
    pitch_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
    volume_envelope = new slEnvelope( 1, SL_SAMPLE_ONE_SHOT );
    pitch_envelope->setStep ( 0, 0.01, 1.0 );
    volume_envelope->setStep ( 0, 0.01, 1.0 );
}

// destructor
SGSimpleSound::~SGSimpleSound() {
    delete pitch_envelope;
    delete volume_envelope;
    delete sample;
}

void SGSimpleSound::play( slScheduler *sched, bool looped ) {

    // make sure sound isn't already playing
    if ( sample->getPlayCount() > 0 ) {
       sched->stopSample(sample);
    //   return;
    }

    if ( looped ) {
        sched->loopSample(sample);
    } else {
        sched->playSample(sample);
    }

    sched->addSampleEnvelope(sample, 0, 0, pitch_envelope, SL_PITCH_ENVELOPE);
    sched->addSampleEnvelope(sample, 0, 1, volume_envelope, SL_VOLUME_ENVELOPE);
}

void SGSimpleSound::stop( slScheduler *sched ) {

    sched->stopSample( sample );
}

//
// Sound Manager
//

// constructor
SGSoundMgr::SGSoundMgr() {
    audio_sched = new slScheduler( 8000 );
    if ( audio_sched->notWorking() ) {
	SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
    } else {
	audio_sched -> setMaxConcurrent ( 6 );

	audio_mixer = new smMixer;

	SG_LOG( SG_GENERAL, SG_INFO,
		"Rate = " << audio_sched->getRate()
		<< "  Bps = " << audio_sched->getBps()
		<< "  Stereo = " << audio_sched->getStereo() );
    }
}

// destructor

SGSoundMgr::~SGSoundMgr() {

    //
    // Remove the samples from the sample manager.
    //
    sample_map_iterator sample_current = samples.begin();
    sample_map_iterator sample_end = samples.end();
    for ( ; sample_current != sample_end; ++sample_current ) {
	sample_ref *sr = sample_current->second;

        audio_sched->stopSample(sr->sample);
	delete sr->sample;
	delete sr;
    }

    //
    // Remove the sounds from the sound manager.
    //
    sound_map_iterator sound_current = sounds.begin();
    sound_map_iterator sound_end = sounds.end();
    for ( ; sound_current != sound_end; ++sound_current ) {
        SGSimpleSound *s = sound_current->second;

        audio_sched->stopSample(s->get_sample());
        delete s->get_sample();
        delete s;
    }

    delete audio_sched;
    delete audio_mixer;
}

// initialize the sound manager
void SGSoundMgr::init() {
    safety = MAX_SOUND_SAFETY;

    // audio_mixer -> setMasterVolume ( 80 ) ;  /* 80% of max volume. */
    audio_sched -> setSafetyMargin ( SOUND_SAFETY_MULT * safety ) ;

    //
    // Remove the samples from the sample manager.
    //
    sample_map_iterator sample_current = samples.begin();
    sample_map_iterator sample_end = samples.end();
    for ( ; sample_current != sample_end; ++sample_current ) {
        sample_ref *sr = sample_current->second;

        audio_sched->stopSample(sr->sample);
        delete sr->sample;
        delete sr;
    }
    samples.clear();

    //
    // Remove the sounds from the sound manager.
    //
    sound_map_iterator sound_current = sounds.begin();
    sound_map_iterator sound_end = sounds.end();
    for ( ; sound_current != sound_end; ++sound_current ) {
	SGSimpleSound *s = sound_current->second;

        audio_sched->stopSample(s->get_sample());
	delete s->get_sample();
	delete s;
    }
    sounds.clear();

}

void SGSoundMgr::bind ()
{
  // no properties yet
}

void SGSoundMgr::unbind ()
{
  // no properties yet
}

// run the audio scheduler
void SGSoundMgr::update( double dt ) {
    if ( dt > safety ) {
	safety = dt;
    } else {
	safety = safety * 0.99 + dt * 0.01;
    }
    if ( safety > MAX_SOUND_SAFETY ) {
	safety = MAX_SOUND_SAFETY;
    }
    // cout << "safety = " << safety << endl;
    audio_sched -> setSafetyMargin ( SOUND_SAFETY_MULT * safety ) ;

    if ( !audio_sched->not_working() )
	audio_sched -> update();
}

void
SGSoundMgr::pause ()
{
  audio_sched->pauseSample(0, 0);
}

void
SGSoundMgr::resume ()
{
  audio_sched->resumeSample(0, 0);
}

// add a sound effect, return true if successful
bool SGSoundMgr::add( SGSimpleSound *sound, const string& refname ) {

    sound_map_iterator sound_it = sounds.find( refname );
    if ( sound_it != sounds.end() ) {
        // sound already exists
        return false;
    }

    sample_map_iterator sample_it = samples.find( refname );
    if ( sample_it != samples.end() ) {
        // this sound has existed in the past and it's sample is still
        // here, delete the sample so we can replace it.
        samples.erase( sample_it );
    }

    sample_ref *sr = new sample_ref;

    sr->n=1;
    sr->sample = sound->get_sample();
    samples[refname] = sr;

    sounds[refname] = sound;

    return true;
}

// add a sound from a file, return the sample if successful, else return NULL
SGSimpleSound *SGSoundMgr::add( const string &refname,
                            const char *path, const char *file ) {
     SGSimpleSound *sound;

    SGPath slfile( path );
    if ( file )
       slfile.append( file );

    if ( slfile.str().empty() )
       return NULL;

    sample_map_iterator it = samples.find(slfile.str());
    if (it == samples.end()) {

       sound = new SGSimpleSound(slfile.c_str());
       sounds[refname] = sound;

       sample_ref *sr = new sample_ref;

       sr->n=1;
       sr->sample = sound->get_sample();
       samples[slfile.str()] = sr;

    } else {
       sample_ref *sr = it->second;

       sr->n++;
       sound =
           new SGSimpleSound(sr->sample->getBuffer(), sr->sample->getLength());
       sounds[refname] = sound;

    }

    return sound;
}

// remove a sound effect, return true if successful
bool SGSoundMgr::remove( const string &refname ) {

    sound_map_iterator it = sounds.find( refname );
    if ( it != sounds.end() ) {
	// first stop the sound from playing (so we don't bomb the
	// audio scheduler)
	SGSimpleSound *sample = it->second;

	// cout << "Playing " << sample->get_sample()->getPlayCount()
	//      << " instances!" << endl;

	audio_sched->stopSample( sample->get_sample() );
	audio_sched->addSampleEnvelope( sample->get_sample(), 0, 0,
					NULL,
					SL_PITCH_ENVELOPE );
	audio_sched->addSampleEnvelope( sample->get_sample(), 0, 1,
					NULL,
					SL_VOLUME_ENVELOPE );

	// must call audio_sched->update() after stopping the sound
	// but before deleting it.
	audio_sched -> update();
	// cout << "Still playing " << sample->get_sample()->getPlayCount()
	//      << " instances!" << endl;

        //
        // FIXME:
        // Due to the change in the sound manager, samples live
	// until the sound manager gets removed.
        //
	// delete sample;
        sounds.erase( it );

        // cout << "sndmgr: removed -> " << refname << endl;
	return true;
    } else {
        // cout << "sndmgr: failed remove -> " << refname << endl;
        return false;
    }
}

// return true of the specified sound exists in the sound manager system
bool SGSoundMgr::exists( const string &refname ) {
    sound_map_iterator it = sounds.find( refname );
    if ( it != sounds.end() ) {
	return true;
   } else {
	return false;
    }
}

// return a pointer to the SGSimpleSound if the specified sound exists
// in the sound manager system, otherwise return NULL
SGSimpleSound *SGSoundMgr::find( const string &refname ) {
    sound_map_iterator it = sounds.find( refname );
    if ( it != sounds.end() ) {
	return it->second;
    } else {
	return NULL;
    }
}

// tell the scheduler to play the indexed sample in a continuous
// loop
bool SGSoundMgr::play_looped( const string &refname ) {
   SGSimpleSound *sample;

    if ((sample = find( refname )) == NULL)
       return false;

    sample->play(audio_sched, true);
    return true;
}

// tell the scheduler to play the indexed sample once
bool SGSoundMgr::play_once( const string& refname ) {
    SGSimpleSound *sample;

    if ((sample = find( refname )) == NULL)
       return false;

    sample->play(audio_sched, false);
    return true;
}

// return true of the specified sound is currently being played
bool SGSoundMgr::is_playing( const string& refname ) {
    SGSimpleSound *sample;

    if ((sample = find( refname )) == NULL)
       return false;

    return (sample->get_sample()->getPlayCount() > 0 );
}

// immediate stop playing the sound
bool SGSoundMgr::stop( const string& refname ) {
    SGSimpleSound *sample;

    if ((sample = find( refname )) == NULL)
       return false;

    audio_sched->stopSample( sample->get_sample() );
    return true;
}
<|endoftext|>


<commit_before>#ifndef INTERPOLATOR_HPP
#define INTERPOLATOR_HPP

#include <cmath>
#include <list>
#include <time.h>
#include <sys/time.h>
#include "InterpolatorInfo.hpp"
#include "MovementQuadruple.hpp"
#include "Position6DOF.hpp"
#include "ros/ros.h"
#include "../matlab/profiling.hpp"
#define MAX_NUMBER_QUADCOPTER_HIGH 10	// TODO equals MAX_NUMBER_QUADCOPTER
#define MIN_TIME_TO_WAIT 500000000 	// in ns, only for rpy-values
#define PREDICT_FUTURE_POSITION_TIME 200000000	// in ns
#define PREDICT_FUTURE_POSITION_STEPS 1 	// Interpolate with ? number of latest positions (unused)

#define ROTATIONAL_CORRECTION 0	// 0-no correction; 1-always take new value; linear in between wouldn't work
#define POSITIONED_NORTH_AT_START 0	// 0 or 1, used as bool, North means pitch+ -> y+

#define REACHING_TARGET_DIFF 0.6 // Factor 0 <= x <= 1
#define REACHING_HEIGHT_DIFF 0.6 // Factor 0 <= x <= 1

#define SPEED_MIN_INCLINING 20 	// in mm/s
#define SPEED_MAX_INCLINING 500 	// in mm/s
#define SPEED_MIN_DECLINING -20 	// in mm/s
#define SPEED_MAX_DECLINING -500 	// in mm/s
#define SPEED_MIN_PLANE 80		// in mm/s
#define SPEED_MAX_PLANE 300		// in mm/s

#define DISTANCE_CLOSE_TO_TARGET 50 	// in mm

#define TEST_ROLL_PITCH 0

/*
 * tuesday
 * TODO hold
 * TODO Coordinatesystem
 * TODO roll/pitch-test QC
 * TODO flight of circles, rotation, ...
 *
 *
 * TODO test of speed, either optimize or save data-to-sent in advance
 *
 * TODO list future movement - fix
 * TODO use of timestamps
 * TODO ROS_INFO, ROS_WARN, ROS_ERROR, ROS_DEBUG - correct use
 * TODO convertMovement (Controller)
 */

class Interpolator {
public:
	Interpolator();
	//MovementQuadruple calibrate(int id, std::list<MovementQuadruple> sentQuadruples);
	MovementQuadruple calculateNextMQ(std::list<MovementQuadruple> &sentQuadruples, std::list<Position6DOF> &positions, Position6DOF &target, int id);
	MovementQuadruple calculateHold(std::list<MovementQuadruple> &sentQuadruples, std::list<Position6DOF> &positions, int id);

protected:
	void checkState( int id );

private:
	InterpolatorInfo status[MAX_NUMBER_QUADCOPTER_HIGH];
	double stepSizeOfChange; 	// depends on the distance of position to target
	long int timeDiff1;
	long int timeDiff2;
	long int timeDiff3;

	int aTimeSwitch;

};

#endif // INTERPOLATOR_HPP
<commit_msg>thrust min/max speed<commit_after>#ifndef INTERPOLATOR_HPP
#define INTERPOLATOR_HPP

#include <cmath>
#include <list>
#include <time.h>
#include <sys/time.h>
#include "InterpolatorInfo.hpp"
#include "MovementQuadruple.hpp"
#include "Position6DOF.hpp"
#include "ros/ros.h"
#include "../matlab/profiling.hpp"
#define MAX_NUMBER_QUADCOPTER_HIGH 10	// TODO equals MAX_NUMBER_QUADCOPTER
#define MIN_TIME_TO_WAIT 500000000 	// in ns, only for rpy-values
#define PREDICT_FUTURE_POSITION_TIME 200000000	// in ns
#define PREDICT_FUTURE_POSITION_STEPS 1 	// Interpolate with ? number of latest positions (unused)

#define ROTATIONAL_CORRECTION 0	// 0-no correction; 1-always take new value; linear in between wouldn't work
#define POSITIONED_NORTH_AT_START 0	// 0 or 1, used as bool, North means pitch+ -> y+

#define REACHING_TARGET_DIFF 0.6 // Factor 0 <= x <= 1
#define REACHING_HEIGHT_DIFF 0.6 // Factor 0 <= x <= 1

#define SPEED_MIN_INCLINING 0 	// in mm/s
#define SPEED_MAX_INCLINING 8000 	// in mm/s
#define SPEED_MIN_DECLINING -0 	// in mm/s
#define SPEED_MAX_DECLINING -8000 	// in mm/s
#define SPEED_MIN_PLANE 80		// in mm/s
#define SPEED_MAX_PLANE 300		// in mm/s

#define DISTANCE_CLOSE_TO_TARGET 50 	// in mm

#define TEST_ROLL_PITCH 0

/*
 * tuesday
 * TODO hold
 * TODO Coordinatesystem
 * TODO roll/pitch-test QC
 * TODO flight of circles, rotation, ...
 *
 *
 * TODO test of speed, either optimize or save data-to-sent in advance
 *
 * TODO list future movement - fix
 * TODO use of timestamps
 * TODO ROS_INFO, ROS_WARN, ROS_ERROR, ROS_DEBUG - correct use
 * TODO convertMovement (Controller)
 */

class Interpolator {
public:
	Interpolator();
	//MovementQuadruple calibrate(int id, std::list<MovementQuadruple> sentQuadruples);
	MovementQuadruple calculateNextMQ(std::list<MovementQuadruple> &sentQuadruples, std::list<Position6DOF> &positions, Position6DOF &target, int id);
	MovementQuadruple calculateHold(std::list<MovementQuadruple> &sentQuadruples, std::list<Position6DOF> &positions, int id);

protected:
	void checkState( int id );

private:
	InterpolatorInfo status[MAX_NUMBER_QUADCOPTER_HIGH];
	double stepSizeOfChange; 	// depends on the distance of position to target
	long int timeDiff1;
	long int timeDiff2;
	long int timeDiff3;

	int aTimeSwitch;

};

#endif // INTERPOLATOR_HPP
<|endoftext|>


<commit_before>/*
 * Scope Guard
 * Copyright (C) 2017  offa
 *
 * This file is part of Scope Guard.
 *
 * Scope Guard 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.
 *
 * Scope Guard 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 Scope Guard.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "scope_success.h"
#include <catch.hpp>
#include <trompeloeil.hpp>

using namespace trompeloeil;

namespace
{
    struct CallMock
    {
        MAKE_MOCK0(deleter, void());
    };

    struct ThrowOnCopyMock
    {
        ThrowOnCopyMock() {  }

        ThrowOnCopyMock(const ThrowOnCopyMock&)
        {
            throw std::exception{};
        }

        MAKE_CONST_MOCK0(deleter, void());

        void operator()() const
        {
            this->deleter();
        }

        ThrowOnCopyMock& operator=(const ThrowOnCopyMock&)
        {
            throw std::exception{};
        }
    };

    struct NotNothrowMoveMock
    {
        NotNothrowMoveMock(CallMock* m) : m_mock(m) { }
        NotNothrowMoveMock(const NotNothrowMoveMock& other) : m_mock(other.m_mock)  { }
        NotNothrowMoveMock(NotNothrowMoveMock&& other) noexcept(false) : m_mock(other.m_mock) { }

        void operator()() const
        {
            m_mock->deleter();
        }

        NotNothrowMoveMock& operator=(const NotNothrowMoveMock&)
        {
            throw "Not implemented";
        }

        NotNothrowMoveMock& operator=(NotNothrowMoveMock&&)
        {
            throw "Not implemented";
        }

        CallMock* m_mock;

    };

    CallMock m;

    void deleter()
    {
        m.deleter();
    }
}

TEST_CASE("deleter called on destruction", "[ScopeSuccess]")
{
    REQUIRE_CALL(m, deleter());
    auto guard = sr::make_scope_success(deleter);
    static_cast<void>(guard);
}

TEST_CASE("deleter lambda called on destruction", "[ScopeSuccess]")
{
    CallMock cm;
    REQUIRE_CALL(cm, deleter());
    auto guard = sr::make_scope_success([&cm] { cm.deleter(); });
    static_cast<void>(guard);
}

TEST_CASE("deleter not called and rethrow on copy exception", "[ScopeSuccess]")
{
    REQUIRE_THROWS([] {
        const ThrowOnCopyMock noMove;
        sr::scope_success<decltype(noMove)> guard{noMove};
        }());
}

TEST_CASE("deleter is not called if released", "[ScopeSuccess]")
{
   REQUIRE_CALL(m, deleter()).TIMES(0);
   auto guard = sr::make_scope_success(deleter);
   guard.release();
}

TEST_CASE("move releases moved-from object", "[ScopeSuccess]")
{
    REQUIRE_CALL(m, deleter());
    auto movedFrom = sr::make_scope_success(deleter);
    auto guard = std::move(movedFrom);
    static_cast<void>(guard);
}

TEST_CASE("move with copy init releases moved-from object", "[ScopeSuccess]")
{
    CallMock mock;
    const NotNothrowMoveMock notNothrow{&mock};
    REQUIRE_CALL(mock, deleter());
    sr::scope_success<decltype(notNothrow)> movedFrom{notNothrow};
    auto guard = std::move(movedFrom);
}

TEST_CASE("move transfers state", "[ScopeSuccess]")
{
    REQUIRE_CALL(m, deleter());
    auto movedFrom = sr::make_scope_success(deleter);
    auto guard = std::move(movedFrom);
    static_cast<void>(guard);
}

TEST_CASE("move transfers state if released", "[ScopeSuccess]")
{
    REQUIRE_CALL(m, deleter()).TIMES(0);
    auto movedFrom = sr::make_scope_success(deleter);
    movedFrom.release();
    auto guard = std::move(movedFrom);
    static_cast<void>(guard);
}

<commit_msg>Test case added (#47).<commit_after>/*
 * Scope Guard
 * Copyright (C) 2017  offa
 *
 * This file is part of Scope Guard.
 *
 * Scope Guard 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.
 *
 * Scope Guard 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 Scope Guard.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "scope_success.h"
#include <catch.hpp>
#include <trompeloeil.hpp>

using namespace trompeloeil;

namespace
{
    struct CallMock
    {
        MAKE_MOCK0(deleter, void());
    };

    struct ThrowOnCopyMock
    {
        ThrowOnCopyMock() {  }

        ThrowOnCopyMock(const ThrowOnCopyMock&)
        {
            throw std::exception{};
        }

        MAKE_CONST_MOCK0(deleter, void());

        void operator()() const
        {
            this->deleter();
        }

        ThrowOnCopyMock& operator=(const ThrowOnCopyMock&)
        {
            throw std::exception{};
        }
    };

    struct NotNothrowMoveMock
    {
        NotNothrowMoveMock(CallMock* m) : m_mock(m) { }
        NotNothrowMoveMock(const NotNothrowMoveMock& other) : m_mock(other.m_mock)  { }
        NotNothrowMoveMock(NotNothrowMoveMock&& other) noexcept(false) : m_mock(other.m_mock) { }

        void operator()() const
        {
            m_mock->deleter();
        }

        NotNothrowMoveMock& operator=(const NotNothrowMoveMock&)
        {
            throw "Not implemented";
        }

        NotNothrowMoveMock& operator=(NotNothrowMoveMock&&)
        {
            throw "Not implemented";
        }

        CallMock* m_mock;

    };

    CallMock m;

    void deleter()
    {
        m.deleter();
    }
}

TEST_CASE("deleter called on destruction", "[ScopeSuccess]")
{
    REQUIRE_CALL(m, deleter());
    auto guard = sr::make_scope_success(deleter);
    static_cast<void>(guard);
}

TEST_CASE("deleter lambda called on destruction", "[ScopeSuccess]")
{
    CallMock cm;
    REQUIRE_CALL(cm, deleter());
    auto guard = sr::make_scope_success([&cm] { cm.deleter(); });
    static_cast<void>(guard);
}

TEST_CASE("deleter not called and rethrow on copy exception", "[ScopeSuccess]")
{
    REQUIRE_THROWS([] {
        const ThrowOnCopyMock noMove;
        sr::scope_success<decltype(noMove)> guard{noMove};
        }());
}

TEST_CASE("deleter is not called if released", "[ScopeSuccess]")
{
   REQUIRE_CALL(m, deleter()).TIMES(0);
   auto guard = sr::make_scope_success(deleter);
   guard.release();
}

TEST_CASE("move releases moved-from object", "[ScopeSuccess]")
{
    REQUIRE_CALL(m, deleter());
    auto movedFrom = sr::make_scope_success(deleter);
    auto guard = std::move(movedFrom);
    static_cast<void>(guard);
}

TEST_CASE("move with copy init releases moved-from object", "[ScopeSuccess]")
{
    CallMock mock;
    const NotNothrowMoveMock notNothrow{&mock};
    REQUIRE_CALL(mock, deleter());
    sr::scope_success<decltype(notNothrow)> movedFrom{notNothrow};
    auto guard = std::move(movedFrom);
}

TEST_CASE("move transfers state", "[ScopeSuccess]")
{
    REQUIRE_CALL(m, deleter());
    auto movedFrom = sr::make_scope_success(deleter);
    auto guard = std::move(movedFrom);
    static_cast<void>(guard);
}

TEST_CASE("move transfers state if released", "[ScopeSuccess]")
{
    REQUIRE_CALL(m, deleter()).TIMES(0);
    auto movedFrom = sr::make_scope_success(deleter);
    movedFrom.release();
    auto guard = std::move(movedFrom);
    static_cast<void>(guard);
}

TEST_CASE("deleter not called on exception", "[ScopeFail]")
{
    try
    {
        auto guard = sr::make_scope_success(deleter);
        throw 3;
    }
    catch( ... )
    {
    }
}

TEST_CASE("deleter called on pending exception", "[ScopeFail]")
{
    try
    {
        throw 3;
    }
    catch( ... )
    {
        REQUIRE_CALL(m, deleter());
        auto guard = sr::make_scope_success(deleter);
    }
}

<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkConjugateGradientOptimizerTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkConjugateGradientOptimizer.h>
#include <vnl/vnl_math.h>

/**
 *  The objectif function is the quadratic form:
 *
 *  1/2 x^T A x - b^T x
 *
 *  Where A is represented as an itkMatrix and
 *  b is represented as a itkVector
 *
 *  The system in this example is:
 *
 *     | 3  2 ||x|   | 2|   |0|
 *     | 2  6 ||y| + |-8| = |0|
 *
 *
 *   the solution is the vector | 2 -2 |
 *
 */
class conjugateCostFunction : public itk::SingleValuedCostFunction
{
public:

  typedef conjugateCostFunction                    Self;
  typedef itk::SingleValuedCostFunction     Superclass;
  typedef itk::SmartPointer<Self>           Pointer;
  typedef itk::SmartPointer<const Self>     ConstPointer;
  itkNewMacro( Self );
  itkTypeMacro( conjugateCostFunction, SingleValuedCostFunction );

  enum { SpaceDimension=2 };

  typedef Superclass::ParametersType              ParametersType;
  typedef Superclass::DerivativeType              DerivativeType;

  typedef vnl_vector<double>                      VectorType;
  typedef vnl_matrix<double>                      MatrixType;

  typedef double MeasureType ;

  conjugateCostFunction()
  {
  }

  double GetValue( const ParametersType & position ) const
  {

    double x = position[0];
    double y = position[1];

    std::cout << "GetValue ( " ;
    std::cout << x << " , " << y;
    std::cout << ") = ";

    double val = 0.5*(3*x*x+4*x*y+6*y*y) - 2*x + 8*y;

    std::cout << val << std::endl;

    return val;
  }

  void GetDerivative( const ParametersType & position,
                            DerivativeType & derivative ) const
  {

    double x = position[0];
    double y = position[1];

    std::cout << "GetDerivative ( " ;
    std::cout << x << " , " << y;
    std::cout << ") = ";

    derivative = DerivativeType(SpaceDimension);
    derivative[0] = 3*x + 2*y -2;
    derivative[1] = 2*x + 6*y +8;
    std::cout << "(" ;
    std::cout << derivative[0] <<" , ";
    std::cout << derivative[1] << ")" << std::endl;
  }

  unsigned int GetNumberOfParameters(void) const
    {
    return SpaceDimension;
    }

private:

};

int itkConjugateGradientOptimizerTest(int, char* [] )
{
  std::cout << "Conjugate Gradient Optimizer Test \n \n";

  typedef  itk::ConjugateGradientOptimizer  OptimizerType;

  typedef  OptimizerType::InternalOptimizerType  vnlOptimizerType;

  // Declaration of a itkOptimizer
  OptimizerType::Pointer  itkOptimizer = OptimizerType::New();

  // Declaration of the CostFunction adaptor
  conjugateCostFunction::Pointer costFunction = conjugateCostFunction::New();

  itkOptimizer->SetCostFunction( costFunction.GetPointer() );

  vnlOptimizerType * vnlOptimizer = itkOptimizer->GetOptimizer();

  const double F_Tolerance      = 1e-3;  // Function value tolerance
  const double G_Tolerance      = 1e-4;  // Gradient magnitude tolerance
  const double X_Tolerance      = 1e-8;  // Search space tolerance
  const double Epsilon_Function = 1e-10; // Step
  const int    Max_Iterations   =   100; // Maximum number of iterations

  vnlOptimizer->set_f_tolerance( F_Tolerance );
  vnlOptimizer->set_g_tolerance( G_Tolerance );
  vnlOptimizer->set_x_tolerance( X_Tolerance );
  vnlOptimizer->set_epsilon_function( Epsilon_Function );
  vnlOptimizer->set_max_function_evals( Max_Iterations );

  vnlOptimizer->set_check_derivatives( 3 );

  OptimizerType::ParametersType initialValue(2);       // constructor requires vector size
  // We start not so far from  | 2 -2 |
  initialValue[0] =  100;
  initialValue[1] = -100;

  OptimizerType::ParametersType currentValue(2);

  currentValue = initialValue;

  itkOptimizer->SetInitialPosition( currentValue );

  try
    {
    itkOptimizer->StartOptimization();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cout << "Exception thrown ! " << std::endl;
    std::cout << "An error ocurred during Optimization" << std::endl;
    std::cout << "Location    = " << e.GetLocation()    << std::endl;
    std::cout << "Description = " << e.GetDescription() << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Number of iters = " << itkOptimizer->GetCurrentIteration()  << std::endl;
  std::cout << "Number of evals = " << vnlOptimizer->get_num_evaluations() << std::endl;

  std::cout << "Report from vnl optimizer: " << std::endl;
  vnlOptimizer->diagnose_outcome( std::cout );

  std::cout << std::endl;

  //
  // check results to see if it is within range
  //

  OptimizerType::ParametersType finalPosition;
  finalPosition = itkOptimizer->GetCurrentPosition();

  std::cout << "Solution        = (";
  std::cout << finalPosition[0] << "," ;
  std::cout << finalPosition[1] << ")" << std::endl;

  bool pass = true;
  double trueParameters[2] = { 2, -2 };
  for( unsigned int j = 0; j < 2; j++ )
    {
    if( vnl_math_abs( finalPosition[j] - trueParameters[j] ) > 0.01 )
      pass = false;
    }

  if( !pass )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  // Get the final value of the optimizer
  std::cout << "Testing GetValue() : ";
  OptimizerType::MeasureType finalValue = itkOptimizer->GetValue();
  if(fabs(finalValue+10.0)>0.01)
    {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
    }
  else
    {
    std::cout << "[SUCCESS]" << std::endl;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;

}

<commit_msg>ENH: Added test for the command observer on the ConjugateGradientOptimizer.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkConjugateGradientOptimizerTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkConjugateGradientOptimizer.h>
#include <vnl/vnl_math.h>

/**
 *  The objectif function is the quadratic form:
 *
 *  1/2 x^T A x - b^T x
 *
 *  Where A is represented as an itkMatrix and
 *  b is represented as a itkVector
 *
 *  The system in this example is:
 *
 *     | 3  2 ||x|   | 2|   |0|
 *     | 2  6 ||y| + |-8| = |0|
 *
 *
 *   the solution is the vector | 2 -2 |
 *
 */
class conjugateCostFunction : public itk::SingleValuedCostFunction
{
public:

  typedef conjugateCostFunction                    Self;
  typedef itk::SingleValuedCostFunction     Superclass;
  typedef itk::SmartPointer<Self>           Pointer;
  typedef itk::SmartPointer<const Self>     ConstPointer;
  itkNewMacro( Self );
  itkTypeMacro( conjugateCostFunction, SingleValuedCostFunction );

  enum { SpaceDimension=2 };

  typedef Superclass::ParametersType              ParametersType;
  typedef Superclass::DerivativeType              DerivativeType;

  typedef vnl_vector<double>                      VectorType;
  typedef vnl_matrix<double>                      MatrixType;

  typedef double MeasureType ;

  conjugateCostFunction()
  {
  }

  double GetValue( const ParametersType & position ) const
  {

    double x = position[0];
    double y = position[1];

    std::cout << "GetValue ( " ;
    std::cout << x << " , " << y;
    std::cout << ") = ";

    double val = 0.5*(3*x*x+4*x*y+6*y*y) - 2*x + 8*y;

    std::cout << val << std::endl;

    return val;
  }

  void GetDerivative( const ParametersType & position,
                            DerivativeType & derivative ) const
  {

    double x = position[0];
    double y = position[1];

    std::cout << "GetDerivative ( " ;
    std::cout << x << " , " << y;
    std::cout << ") = ";

    derivative = DerivativeType(SpaceDimension);
    derivative[0] = 3*x + 2*y -2;
    derivative[1] = 2*x + 6*y +8;
    std::cout << "(" ;
    std::cout << derivative[0] <<" , ";
    std::cout << derivative[1] << ")" << std::endl;
  }

  unsigned int GetNumberOfParameters(void) const
    {
    return SpaceDimension;
    }

private:

};

class CommandIterationUpdateConjugateGradient : public itk::Command
{
public:
  typedef  CommandIterationUpdateConjugateGradient   Self;
  typedef  itk::Command             Superclass;
  typedef itk::SmartPointer<Self>  Pointer;
  itkNewMacro( Self );
protected:
  CommandIterationUpdateConjugateGradient()
  {
    m_IterationNumber=0;
  }
public:
  typedef itk::ConjugateGradientOptimizer   OptimizerType;
  typedef   const OptimizerType   *    OptimizerPointer;

  void Execute(itk::Object *caller, const itk::EventObject & event)
    {
      Execute( (const itk::Object *)caller, event);
    }

  void Execute(const itk::Object * object, const itk::EventObject & event)
    {
      OptimizerPointer optimizer =
        dynamic_cast< OptimizerPointer >( object );
      if( typeid( event ) == typeid( itk::FunctionEvaluationIterationEvent() ) )
        {
        std::cout << m_IterationNumber++ << "   ";
        std::cout << optimizer->GetCachedValue() << "   ";
        std::cout << optimizer->GetCachedCurrentPosition() << std::endl;
        }
      else if( typeid( event ) == typeid( itk::GradientEvaluationIterationEvent() ) )
        {
        std::cout << "Gradient " << optimizer->GetCachedDerivative() << "   ";
        }

    }
private:
  unsigned long m_IterationNumber;
};

int itkConjugateGradientOptimizerTest(int, char* [] )
{
  std::cout << "Conjugate Gradient Optimizer Test \n \n";

  typedef  itk::ConjugateGradientOptimizer  OptimizerType;

  typedef  OptimizerType::InternalOptimizerType  vnlOptimizerType;

  // Declaration of a itkOptimizer
  OptimizerType::Pointer  itkOptimizer = OptimizerType::New();

  // Declaration of the CostFunction adaptor
  conjugateCostFunction::Pointer costFunction = conjugateCostFunction::New();

  itkOptimizer->SetCostFunction( costFunction.GetPointer() );

  vnlOptimizerType * vnlOptimizer = itkOptimizer->GetOptimizer();

  const double F_Tolerance      = 1e-3;  // Function value tolerance
  const double G_Tolerance      = 1e-4;  // Gradient magnitude tolerance
  const double X_Tolerance      = 1e-8;  // Search space tolerance
  const double Epsilon_Function = 1e-10; // Step
  const int    Max_Iterations   =   100; // Maximum number of iterations

  vnlOptimizer->set_f_tolerance( F_Tolerance );
  vnlOptimizer->set_g_tolerance( G_Tolerance );
  vnlOptimizer->set_x_tolerance( X_Tolerance );
  vnlOptimizer->set_epsilon_function( Epsilon_Function );
  vnlOptimizer->set_max_function_evals( Max_Iterations );

  vnlOptimizer->set_check_derivatives( 3 );

  OptimizerType::ParametersType initialValue(2);       // constructor requires vector size
  // We start not so far from  | 2 -2 |
  initialValue[0] =  100;
  initialValue[1] = -100;

  OptimizerType::ParametersType currentValue(2);

  currentValue = initialValue;

  itkOptimizer->SetInitialPosition( currentValue );

  CommandIterationUpdateConjugateGradient::Pointer observer =
    CommandIterationUpdateConjugateGradient::New();
  itkOptimizer->AddObserver( itk::IterationEvent(), observer );
  itkOptimizer->AddObserver( itk::FunctionEvaluationIterationEvent(), observer );

  try
    {
    itkOptimizer->StartOptimization();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cout << "Exception thrown ! " << std::endl;
    std::cout << "An error ocurred during Optimization" << std::endl;
    std::cout << "Location    = " << e.GetLocation()    << std::endl;
    std::cout << "Description = " << e.GetDescription() << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Number of iters = " << itkOptimizer->GetCurrentIteration()  << std::endl;
  std::cout << "Number of evals = " << vnlOptimizer->get_num_evaluations() << std::endl;

  std::cout << "Report from vnl optimizer: " << std::endl;
  vnlOptimizer->diagnose_outcome( std::cout );

  std::cout << std::endl;

  //
  // check results to see if it is within range
  //

  OptimizerType::ParametersType finalPosition;
  finalPosition = itkOptimizer->GetCurrentPosition();

  std::cout << "Solution        = (";
  std::cout << finalPosition[0] << "," ;
  std::cout << finalPosition[1] << ")" << std::endl;

  bool pass = true;
  double trueParameters[2] = { 2, -2 };
  for( unsigned int j = 0; j < 2; j++ )
    {
    if( vnl_math_abs( finalPosition[j] - trueParameters[j] ) > 0.01 )
      pass = false;
    }

  if( !pass )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  // Get the final value of the optimizer
  std::cout << "Testing GetValue() : ";
  OptimizerType::MeasureType finalValue = itkOptimizer->GetValue();
  if(fabs(finalValue+10.0)>0.01)
    {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
    }
  else
    {
    std::cout << "[SUCCESS]" << std::endl;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;

}

<|endoftext|>