<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
***************************************************************************/
///////////////////////////////////////////////////////////////////////////
//  Class to generate decays of particles generated by a                 //
//  previous generator. It works as a generator, but pratically it       //
//  performs only decays. It works with this scheme: first loops over    //
//  particles on the stack, selects those to be decayed, decays them     //
//  and then pushes the decay products on the stack.                     //
//                                                                       //
//  Giuseppe E. Bruno            &    Fiorella Fionda                    //
//  (Giuseppe.Bruno@ba.infn.it)       (Fiorella.Fionda@ba.infn.it)       //
///////////////////////////////////////////////////////////////////////////

#include "AliStack.h"
#include "AliGenEvtGen.h"
#include "AliRun.h"
#include <TParticle.h>

ClassImp(AliGenEvtGen)
///////////////////////////////////////////////////////////////////////////
AliGenEvtGen::AliGenEvtGen():
  fStack(0x0),
  fDecayer(0x0),
  fForceDecay(kAll),
  fSwitchOff(kBeautyPart),
  fUserDecay(kFALSE),
  fUserDecayTablePath(0x0)
  {
  //
  // Default Construction
  //
  }
///////////////////////////////////////////////////////////////////////////////////////////
AliGenEvtGen::~AliGenEvtGen()
  {
  //
  // Standard Destructor
  //
  if(fStack) {delete fStack;}
  fStack = 0;
  if(fDecayer) {delete fDecayer;}
  fDecayer = 0;
  if(fUserDecayTablePath) {delete fUserDecayTablePath;}
  fUserDecayTablePath = 0;
  }
///////////////////////////////////////////////////////////////////////////////////////////

void AliGenEvtGen::Init()
  {
  //
  // Standard AliGenerator Initializer - no input
  // 1) initialize EvtGen with default decay and particle table
  // 2) set the decay mode to force particle
  // 3) set a user decay table if defined
  //
  if(fDecayer)
  {
  AliWarning("AliGenEvtGen already initialized!!!");
  return;
  }
  fDecayer = new AliDecayerEvtGen();
  fDecayer->Init(); //read the default decay table DECAY.DEC and particle table

  //if is set a decay mode: default decay mode is kAll
  fDecayer->SetForceDecay(fForceDecay);
  fDecayer->ForceDecay();

  //if is defined a user decay table
  if(fUserDecay)
    {
    fDecayer->SetDecayTablePath(fUserDecayTablePath);
    fDecayer->ReadDecayTable();
    }
  }

/////////////////////////////////////////////////////////////////////////////////////////////
void AliGenEvtGen::Generate()
  {
  //
  //Generate method - Input none - Output none
  //For each event:
  //1)return the stack of the previous generator and select particles to be decayed by EvtGen
  //2)decay particles selected and put the decay products on the stack
  //
  //
  Float_t polar[3]= {0,0,0};  // Polarisation of daughter particles
  Float_t origin0[3];         // Origin of the parent particle
  Float_t pc[3], och[3]; // Momentum and origin of the children particles from EvtGen
  Int_t nt;
  Float_t tof;
  Int_t nPrimsPythia;
  TLorentzVector *mom=new TLorentzVector();
  static TClonesArray *particles;
  if(!particles) particles = new TClonesArray("TParticle",1000);
  fStack = AliRunLoader::Instance()->Stack();
  if(!fStack) {Info("Generate","Error: No stack found!"); return;}
  nPrimsPythia = fStack->GetNprimary();
  AliDebug(1,Form("nPrimsPythia = %d \n",nPrimsPythia));
  for (Int_t iTrack = 0; iTrack < nPrimsPythia; ++iTrack) {
  TParticle *part = fStack->Particle(iTrack);
  Int_t pdg=part->GetPdgCode();

  AliDebug(1,Form("GetFlavour = %d e pdg = %d \n",GetFlavour(pdg),pdg));

  switch(fSwitchOff)
  {
  case kAllPart:
  break;
  case kBeautyPart:
  if(GetFlavour(pdg)!=5) continue;
  break;
  case kCharmPart:
  if(GetFlavour(pdg)!=4) continue;
  break;
  }

  //check if particle is already decayed by Pythia
  if(part->GetStatusCode() != 1 || part->GetNDaughters()>0)
    {
    Info("AliGenEvtGen","Attention: particle %d is already decayed by Pythia!",pdg);
    continue;
    }

  part->SetStatusCode(11); //Set particle as decayed : change the status code

  mom->SetPxPyPzE(part->Px(),part->Py(),part->Pz(),part->Energy());
  Int_t np;

   do{
     fDecayer->Decay(part->GetPdgCode(),mom);
     np = fDecayer->ImportParticles(particles);
     }while(np<0);

  Int_t* trackIt    = new Int_t[np];
  Int_t* pParent   = new Int_t[np];
  AliDebug(1,Form("np = %d \n",np));

  for (int i = 0; i < np; i++) {
             pParent[i]   = -1;
             trackIt[i]   =  0;
         }
  //select trackable particle
  if (np >1) {
  TParticle* iparticle =  (TParticle *) particles->At(0);//parent particle
   for (int i = 1; i<np ; i++) {
     iparticle = (TParticle*) particles->At(i);
     Int_t ks = iparticle->GetStatusCode();

     //track last decay products
     if(ks==1) trackIt[i]=1;

     }//decay particles loop

  }// if decay products

  origin0[0]=part->Vx(); //[cm]
  origin0[1]=part->Vy(); //[cm]
  origin0[2]=part->Vz(); //[cm]
  //
  // Put decay products on the stack
  //
  for (int i = 1; i < np; i++) {
         TParticle* iparticle = (TParticle *) particles->At(i);
         Int_t kf   = iparticle->GetPdgCode();
         Int_t ksc  = iparticle->GetStatusCode();
         Int_t jpa  = iparticle->GetFirstMother()-1; //jpa = 0 for daughters of beauty particles
         Int_t iparent = (jpa > 0) ? pParent[jpa] : iTrack;

         och[0] = origin0[0]+iparticle->Vx()/10; //[cm]
         och[1] = origin0[1]+iparticle->Vy()/10; //[cm]
         och[2] = origin0[2]+iparticle->Vz()/10; //[cm]
         pc[0]  = iparticle->Px(); //[GeV/c]
         pc[1]  = iparticle->Py(); //[GeV/c]
         pc[2]  = iparticle->Pz(); //[GeV/c]
         tof = part->T()+kconv*iparticle->T();

         AliDebug(1,Form("FirstMother = %d e indicePart = %d e pdg = %d \n",jpa,i,kf));

         PushTrack(trackIt[i], iparent, kf, pc, och, polar,tof, kPDecay, nt, 1., ksc);
         if(trackIt[i]==1) AliDebug(1,Form("Trackable particles: %d e pdg %d \n",i,kf));
         pParent[i] = nt;
         KeepTrack(nt);
         SetHighWaterMark(nt);
         }// Particle loop
         particles->Clear();
     	 if (trackIt)    delete[] trackIt;
         if (pParent)    delete[] pParent;
       }
  Info("Generate","AliGenEvtGen DONE");
  }

//////////////////////////////////////////////////////////////////////////////////////////
Int_t AliGenEvtGen::GetFlavour(Int_t pdgCode)
  {
  //
  // return the flavour of a particle
  // input: pdg code of the particle
  // output: Int_t
  //         3 in case of strange (open and hidden)
  //         4 in case of charm (")
  //         5 in case of beauty (")
  //
  Int_t pdg = TMath::Abs(pdgCode);
  //Resonance
  if (pdg > 100000) pdg %= 100000;
  if(pdg > 10000)  pdg %= 10000;
  // meson ?
  if(pdg > 10) pdg/=100;
  // baryon ?
  if(pdg > 10) pdg/=10;
  return pdg;
  }

/////////////////////////////////////////////////////////////////////////////////////////
Bool_t AliGenEvtGen::SetUserDecayTable(Char_t *path)
  {
  //
  //Set the path of user decay table if it is defined
  //
  //put a comment to control if path exists
  if(gSystem->AccessPathName(path))
    {
    AliWarning("Attention: This path not exist!\n");
    return kFALSE;
    }
  fUserDecayTablePath = path;
  fUserDecay = kTRUE;
  return kTRUE;
  }
<commit_msg>include file added Zaida<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
***************************************************************************/
///////////////////////////////////////////////////////////////////////////
//  Class to generate decays of particles generated by a                 //
//  previous generator. It works as a generator, but pratically it       //
//  performs only decays. It works with this scheme: first loops over    //
//  particles on the stack, selects those to be decayed, decays them     //
//  and then pushes the decay products on the stack.                     //
//                                                                       //
//  Giuseppe E. Bruno            &    Fiorella Fionda                    //
//  (Giuseppe.Bruno@ba.infn.it)       (Fiorella.Fionda@ba.infn.it)       //
///////////////////////////////////////////////////////////////////////////

#include "AliStack.h"
#include "AliGenEvtGen.h"
#include "AliRun.h"
#include "AliLog.h"
#include <TParticle.h>

ClassImp(AliGenEvtGen)
///////////////////////////////////////////////////////////////////////////
AliGenEvtGen::AliGenEvtGen():
  fStack(0x0),
  fDecayer(0x0),
  fForceDecay(kAll),
  fSwitchOff(kBeautyPart),
  fUserDecay(kFALSE),
  fUserDecayTablePath(0x0)
  {
  //
  // Default Construction
  //
  }
///////////////////////////////////////////////////////////////////////////////////////////
AliGenEvtGen::~AliGenEvtGen()
  {
  //
  // Standard Destructor
  //
  if(fStack) {delete fStack;}
  fStack = 0;
  if(fDecayer) {delete fDecayer;}
  fDecayer = 0;
  if(fUserDecayTablePath) {delete fUserDecayTablePath;}
  fUserDecayTablePath = 0;
  }
///////////////////////////////////////////////////////////////////////////////////////////

void AliGenEvtGen::Init()
  {
  //
  // Standard AliGenerator Initializer - no input
  // 1) initialize EvtGen with default decay and particle table
  // 2) set the decay mode to force particle
  // 3) set a user decay table if defined
  //
  if(fDecayer)
  {
  AliWarning("AliGenEvtGen already initialized!!!");
  return;
  }
  fDecayer = new AliDecayerEvtGen();
  fDecayer->Init(); //read the default decay table DECAY.DEC and particle table

  //if is set a decay mode: default decay mode is kAll
  fDecayer->SetForceDecay(fForceDecay);
  fDecayer->ForceDecay();

  //if is defined a user decay table
  if(fUserDecay)
    {
    fDecayer->SetDecayTablePath(fUserDecayTablePath);
    fDecayer->ReadDecayTable();
    }
  }

/////////////////////////////////////////////////////////////////////////////////////////////
void AliGenEvtGen::Generate()
  {
  //
  //Generate method - Input none - Output none
  //For each event:
  //1)return the stack of the previous generator and select particles to be decayed by EvtGen
  //2)decay particles selected and put the decay products on the stack
  //
  //
  Float_t polar[3]= {0,0,0};  // Polarisation of daughter particles
  Float_t origin0[3];         // Origin of the parent particle
  Float_t pc[3], och[3]; // Momentum and origin of the children particles from EvtGen
  Int_t nt;
  Float_t tof;
  Int_t nPrimsPythia;
  TLorentzVector *mom=new TLorentzVector();
  static TClonesArray *particles;
  if(!particles) particles = new TClonesArray("TParticle",1000);
  fStack = AliRunLoader::Instance()->Stack();
  if(!fStack) {Info("Generate","Error: No stack found!"); return;}
  nPrimsPythia = fStack->GetNprimary();
  AliDebug(1,Form("nPrimsPythia = %d \n",nPrimsPythia));
  for (Int_t iTrack = 0; iTrack < nPrimsPythia; ++iTrack) {
  TParticle *part = fStack->Particle(iTrack);
  Int_t pdg=part->GetPdgCode();

  AliDebug(1,Form("GetFlavour = %d e pdg = %d \n",GetFlavour(pdg),pdg));

  switch(fSwitchOff)
  {
  case kAllPart:
  break;
  case kBeautyPart:
  if(GetFlavour(pdg)!=5) continue;
  break;
  case kCharmPart:
  if(GetFlavour(pdg)!=4) continue;
  break;
  }

  //check if particle is already decayed by Pythia
  if(part->GetStatusCode() != 1 || part->GetNDaughters()>0)
    {
    Info("AliGenEvtGen","Attention: particle %d is already decayed by Pythia!",pdg);
    continue;
    }

  part->SetStatusCode(11); //Set particle as decayed : change the status code

  mom->SetPxPyPzE(part->Px(),part->Py(),part->Pz(),part->Energy());
  Int_t np;

   do{
     fDecayer->Decay(part->GetPdgCode(),mom);
     np = fDecayer->ImportParticles(particles);
     }while(np<0);

  Int_t* trackIt    = new Int_t[np];
  Int_t* pParent   = new Int_t[np];
  AliDebug(1,Form("np = %d \n",np));

  for (int i = 0; i < np; i++) {
             pParent[i]   = -1;
             trackIt[i]   =  0;
         }
  //select trackable particle
  if (np >1) {
  TParticle* iparticle =  (TParticle *) particles->At(0);//parent particle
   for (int i = 1; i<np ; i++) {
     iparticle = (TParticle*) particles->At(i);
     Int_t ks = iparticle->GetStatusCode();

     //track last decay products
     if(ks==1) trackIt[i]=1;

     }//decay particles loop

  }// if decay products

  origin0[0]=part->Vx(); //[cm]
  origin0[1]=part->Vy(); //[cm]
  origin0[2]=part->Vz(); //[cm]
  //
  // Put decay products on the stack
  //
  for (int i = 1; i < np; i++) {
         TParticle* iparticle = (TParticle *) particles->At(i);
         Int_t kf   = iparticle->GetPdgCode();
         Int_t ksc  = iparticle->GetStatusCode();
         Int_t jpa  = iparticle->GetFirstMother()-1; //jpa = 0 for daughters of beauty particles
         Int_t iparent = (jpa > 0) ? pParent[jpa] : iTrack;

         och[0] = origin0[0]+iparticle->Vx()/10; //[cm]
         och[1] = origin0[1]+iparticle->Vy()/10; //[cm]
         och[2] = origin0[2]+iparticle->Vz()/10; //[cm]
         pc[0]  = iparticle->Px(); //[GeV/c]
         pc[1]  = iparticle->Py(); //[GeV/c]
         pc[2]  = iparticle->Pz(); //[GeV/c]
         tof = part->T()+kconv*iparticle->T();

         AliDebug(1,Form("FirstMother = %d e indicePart = %d e pdg = %d \n",jpa,i,kf));

         PushTrack(trackIt[i], iparent, kf, pc, och, polar,tof, kPDecay, nt, 1., ksc);
         if(trackIt[i]==1) AliDebug(1,Form("Trackable particles: %d e pdg %d \n",i,kf));
         pParent[i] = nt;
         KeepTrack(nt);
         SetHighWaterMark(nt);
         }// Particle loop
         particles->Clear();
     	 if (trackIt)    delete[] trackIt;
         if (pParent)    delete[] pParent;
       }
  Info("Generate","AliGenEvtGen DONE");
  }

//////////////////////////////////////////////////////////////////////////////////////////
Int_t AliGenEvtGen::GetFlavour(Int_t pdgCode)
  {
  //
  // return the flavour of a particle
  // input: pdg code of the particle
  // output: Int_t
  //         3 in case of strange (open and hidden)
  //         4 in case of charm (")
  //         5 in case of beauty (")
  //
  Int_t pdg = TMath::Abs(pdgCode);
  //Resonance
  if (pdg > 100000) pdg %= 100000;
  if(pdg > 10000)  pdg %= 10000;
  // meson ?
  if(pdg > 10) pdg/=100;
  // baryon ?
  if(pdg > 10) pdg/=10;
  return pdg;
  }

/////////////////////////////////////////////////////////////////////////////////////////
Bool_t AliGenEvtGen::SetUserDecayTable(Char_t *path)
  {
  //
  //Set the path of user decay table if it is defined
  //
  //put a comment to control if path exists
  if(gSystem->AccessPathName(path))
    {
    AliWarning("Attention: This path not exist!\n");
    return kFALSE;
    }
  fUserDecayTablePath = path;
  fUserDecay = kTRUE;
  return kTRUE;
  }
<|endoftext|>


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

#include "base/command_line.h"
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "base/test/trace_event_analyzer.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/test_switches.h"
#include "chrome/test/base/tracing.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/perf/browser_perf_test.h"
#include "chrome/test/perf/perf_test.h"
#include "content/public/common/content_switches.h"
#include "googleurl/src/gurl.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/gl/gl_switches.h"

namespace {

enum ThroughputTestFlags {
  kNone = 0,
  kInternal = 1 << 0 // Test uses internal test data.
};

const int kSpinUpTimeMs = 5 * 1000;
const int kRunTimeMs = 10 * 1000;
const int kIgnoreSomeFrames = 3;

class ThroughputTest : public BrowserPerfTest {
 public:
  explicit ThroughputTest(bool use_gpu) : use_gpu_(use_gpu) {}

  bool IsGpuAvailable() const {
    return CommandLine::ForCurrentProcess()->HasSwitch("enable-gpu");
  }

  GURL GetURLFromCommandLine() {
    CommandLine::StringType extra_chrome_flags =
        CommandLine::ForCurrentProcess()->GetSwitchValueNative(
            switches::kExtraChromeFlags);
    return GURL(extra_chrome_flags);
  }

  void AllowExternalDNS() {
    net::RuleBasedHostResolverProc* resolver =
        new net::RuleBasedHostResolverProc(host_resolver());
    resolver->AllowDirectLookup("*");
    host_resolver_override_.reset(
        new net::ScopedDefaultHostResolverProc(resolver));
  }

  void ResetAllowExternalDNS() {
    host_resolver_override_.reset();
  }

  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    BrowserPerfTest::SetUpCommandLine(command_line);
    // We are measuring throughput, so we don't want any FPS throttling.
    command_line->AppendSwitch(switches::kDisableGpuVsync);
    // Default behavior is to thumbnail the tab after 0.5 seconds, causing
    // a nasty frame hitch and disturbing the latency test. Fix that:
    command_line->AppendSwitch(switches::kEnableInBrowserThumbnailing);
    command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
    // Enable or disable GPU acceleration.
    if (use_gpu_) {
      command_line->AppendSwitch(switches::kEnableAccelerated2dCanvas);
      command_line->AppendSwitch(switches::kForceCompositingMode);
    } else {
      command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
      command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
      command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
    }
  }

  void Wait(int ms) {
    MessageLoop::current()->PostDelayedTask(
        FROM_HERE, MessageLoop::QuitClosure(), ms);
    ui_test_utils::RunMessageLoop();
  }

  void RunTest(const std::string& test_name, ThroughputTestFlags flags) {
    // Set path to test html.
    FilePath test_path;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_path));
    test_path = test_path.Append(FILE_PATH_LITERAL("perf"));
    if (flags & kInternal)
      test_path = test_path.Append(FILE_PATH_LITERAL("private"));
    test_path = test_path.Append(FILE_PATH_LITERAL("rendering"));
    test_path = test_path.Append(FILE_PATH_LITERAL("throughput"));
    test_path = test_path.AppendASCII(test_name);
    test_path = test_path.Append(FILE_PATH_LITERAL("index.html"));
    ASSERT_TRUE(file_util::PathExists(test_path))
        << "Missing test file: " << test_path.value();

    RunTestWithURL(test_name, net::FilePathToFileURL(test_path));
  }

  void RunTestWithURL(const std::string& test_name, const GURL& gurl) {
    using trace_analyzer::Query;
    using trace_analyzer::TraceAnalyzer;
    using trace_analyzer::TraceEventVector;

    if (use_gpu_ && !IsGpuAvailable()) {
      LOG(WARNING) << "Test skipped: requires gpu. Pass --enable-gpu on the "
                      "command line if use of GPU is desired.\n";
      return;
    }

    std::string json_events;
    TraceEventVector events_sw, events_gpu;
    scoped_ptr<TraceAnalyzer> analyzer;

    LOG(INFO) << gurl.possibly_invalid_spec();
    ui_test_utils::NavigateToURLWithDisposition(
        browser(), gurl, CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);

    // Let the test spin up.
    LOG(INFO) << "Spinning up test...\n";
    ASSERT_TRUE(tracing::BeginTracing("test_gpu"));
    Wait(kSpinUpTimeMs);
    ASSERT_TRUE(tracing::EndTracing(&json_events));

    // Check if GPU is rendering:
    analyzer.reset(TraceAnalyzer::Create(json_events));
    bool ran_on_gpu = (analyzer->FindEvents(Query::EventName() ==
        Query::String("SwapBuffers"), &events_gpu) > 0u);
    LOG(INFO) << "Mode: " << (ran_on_gpu ? "GPU" : "Software");
    EXPECT_EQ(use_gpu_, ran_on_gpu);

    // Let the test run for a while.
    LOG(INFO) << "Running test...\n";
    ASSERT_TRUE(tracing::BeginTracing("test_fps"));
    Wait(kRunTimeMs);
    ASSERT_TRUE(tracing::EndTracing(&json_events));

    // Search for frame ticks. We look for both SW and GPU frame ticks so that
    // the test can verify that only one or the other are found.
    analyzer.reset(TraceAnalyzer::Create(json_events));
    Query query_sw = Query::EventName() == Query::String("TestFrameTickSW");
    Query query_gpu = Query::EventName() == Query::String("TestFrameTickGPU");
    analyzer->FindEvents(query_sw, &events_sw);
    analyzer->FindEvents(query_gpu, &events_gpu);
    TraceEventVector* frames = NULL;
    if (use_gpu_) {
      frames = &events_gpu;
      EXPECT_EQ(0u, events_sw.size());
    } else {
      frames = &events_sw;
      EXPECT_EQ(0u, events_gpu.size());
    }
    printf("Frame tick events: %d\n", static_cast<int>(frames->size()));
    ASSERT_GT(frames->size(), 20u);
    // Cull a few leading and trailing events as they might be unreliable.
    TraceEventVector rate_events(frames->begin() + kIgnoreSomeFrames,
                                 frames->end() - kIgnoreSomeFrames);
    trace_analyzer::RateStats stats;
    ASSERT_TRUE(GetRateStats(rate_events, &stats));
    printf("FPS = %f\n", 1000000.0 / stats.mean_us);

    // Print perf results.
    double mean_ms = stats.mean_us / 1000.0;
    double std_dev_ms = stats.standard_deviation_us / 1000.0 / 1000.0;
    std::string trace_name = ran_on_gpu ? "gpu" : "software";
    std::string mean_and_error = base::StringPrintf("%f,%f", mean_ms,
                                                    std_dev_ms);
    perf_test::PrintResultMeanAndError(test_name, "", trace_name,
                                       mean_and_error, "frame_time", true);
  }

 private:
  bool use_gpu_;
  scoped_ptr<net::ScopedDefaultHostResolverProc> host_resolver_override_;
};

// For running tests on GPU:
class ThroughputTestGPU : public ThroughputTest {
 public:
  ThroughputTestGPU() : ThroughputTest(true) {}
};

// For running tests on Software:
class ThroughputTestSW : public ThroughputTest {
 public:
  ThroughputTestSW() : ThroughputTest(false) {}
};

////////////////////////////////////////////////////////////////////////////////
/// Tests

// Run this test with a URL on the command line:
// performance_browser_tests --gtest_also_run_disabled_tests --enable-gpu
//     --gtest_filter=ThroughputTest*URL --extra-chrome-flags=http://...
IN_PROC_BROWSER_TEST_F(ThroughputTestSW, DISABLED_TestURL) {
  AllowExternalDNS();
  RunTestWithURL("URL", GetURLFromCommandLine());
  ResetAllowExternalDNS();
}

IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, DISABLED_TestURL) {
  AllowExternalDNS();
  RunTestWithURL("URL", GetURLFromCommandLine());
  ResetAllowExternalDNS();
}

IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, Particles) {
  RunTest("particles", kInternal);
}

IN_PROC_BROWSER_TEST_F(ThroughputTestSW, CanvasDemoSW) {
  RunTest("canvas-demo", kInternal);
}

IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, CanvasDemoGPU) {
  RunTest("canvas-demo", kInternal);
}

}  // namespace
<commit_msg>Make throughput test wait for page to load before starting.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "base/test/trace_event_analyzer.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/test_switches.h"
#include "chrome/test/base/tracing.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/perf/browser_perf_test.h"
#include "chrome/test/perf/perf_test.h"
#include "content/public/common/content_switches.h"
#include "googleurl/src/gurl.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/gl/gl_switches.h"

namespace {

enum ThroughputTestFlags {
  kNone = 0,
  kInternal = 1 << 0 // Test uses internal test data.
};

const int kSpinUpTimeMs = 4 * 1000;
const int kRunTimeMs = 10 * 1000;
const int kIgnoreSomeFrames = 3;

class ThroughputTest : public BrowserPerfTest {
 public:
  explicit ThroughputTest(bool use_gpu) : use_gpu_(use_gpu) {}

  bool IsGpuAvailable() const {
    return CommandLine::ForCurrentProcess()->HasSwitch("enable-gpu");
  }

  GURL GetURLFromCommandLine() {
    CommandLine::StringType extra_chrome_flags =
        CommandLine::ForCurrentProcess()->GetSwitchValueNative(
            switches::kExtraChromeFlags);
    return GURL(extra_chrome_flags);
  }

  void AllowExternalDNS() {
    net::RuleBasedHostResolverProc* resolver =
        new net::RuleBasedHostResolverProc(host_resolver());
    resolver->AllowDirectLookup("*");
    host_resolver_override_.reset(
        new net::ScopedDefaultHostResolverProc(resolver));
  }

  void ResetAllowExternalDNS() {
    host_resolver_override_.reset();
  }

  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    BrowserPerfTest::SetUpCommandLine(command_line);
    // We are measuring throughput, so we don't want any FPS throttling.
    command_line->AppendSwitch(switches::kDisableGpuVsync);
    // Default behavior is to thumbnail the tab after 0.5 seconds, causing
    // a nasty frame hitch and disturbing the latency test. Fix that:
    command_line->AppendSwitch(switches::kEnableInBrowserThumbnailing);
    command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
    // Enable or disable GPU acceleration.
    if (use_gpu_) {
      command_line->AppendSwitch(switches::kEnableAccelerated2dCanvas);
      command_line->AppendSwitch(switches::kForceCompositingMode);
    } else {
      command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
      command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
      command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
    }
  }

  void Wait(int ms) {
    MessageLoop::current()->PostDelayedTask(
        FROM_HERE, MessageLoop::QuitClosure(), ms);
    ui_test_utils::RunMessageLoop();
  }

  void RunTest(const std::string& test_name, ThroughputTestFlags flags) {
    // Set path to test html.
    FilePath test_path;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_path));
    test_path = test_path.Append(FILE_PATH_LITERAL("perf"));
    if (flags & kInternal)
      test_path = test_path.Append(FILE_PATH_LITERAL("private"));
    test_path = test_path.Append(FILE_PATH_LITERAL("rendering"));
    test_path = test_path.Append(FILE_PATH_LITERAL("throughput"));
    test_path = test_path.AppendASCII(test_name);
    test_path = test_path.Append(FILE_PATH_LITERAL("index.html"));
    ASSERT_TRUE(file_util::PathExists(test_path))
        << "Missing test file: " << test_path.value();

    RunTestWithURL(test_name, net::FilePathToFileURL(test_path));
  }

  void RunTestWithURL(const std::string& test_name, const GURL& gurl) {
    using trace_analyzer::Query;
    using trace_analyzer::TraceAnalyzer;
    using trace_analyzer::TraceEventVector;

    if (use_gpu_ && !IsGpuAvailable()) {
      LOG(WARNING) << "Test skipped: requires gpu. Pass --enable-gpu on the "
                      "command line if use of GPU is desired.\n";
      return;
    }

    std::string json_events;
    TraceEventVector events_sw, events_gpu;
    scoped_ptr<TraceAnalyzer> analyzer;

    LOG(INFO) << gurl.possibly_invalid_spec();
    ui_test_utils::NavigateToURLWithDisposition(
        browser(), gurl, CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
    ui_test_utils::WaitForLoadStop(browser()->GetSelectedWebContents());

    // Let the test spin up.
    LOG(INFO) << "Spinning up test...\n";
    ASSERT_TRUE(tracing::BeginTracing("test_gpu"));
    Wait(kSpinUpTimeMs);
    ASSERT_TRUE(tracing::EndTracing(&json_events));

    // Check if GPU is rendering:
    analyzer.reset(TraceAnalyzer::Create(json_events));
    bool ran_on_gpu = (analyzer->FindEvents(Query::EventName() ==
        Query::String("SwapBuffers"), &events_gpu) > 0u);
    LOG(INFO) << "Mode: " << (ran_on_gpu ? "GPU" : "Software");
    EXPECT_EQ(use_gpu_, ran_on_gpu);

    // Let the test run for a while.
    LOG(INFO) << "Running test...\n";
    ASSERT_TRUE(tracing::BeginTracing("test_fps"));
    Wait(kRunTimeMs);
    ASSERT_TRUE(tracing::EndTracing(&json_events));

    // Search for frame ticks. We look for both SW and GPU frame ticks so that
    // the test can verify that only one or the other are found.
    analyzer.reset(TraceAnalyzer::Create(json_events));
    Query query_sw = Query::EventName() == Query::String("TestFrameTickSW");
    Query query_gpu = Query::EventName() == Query::String("TestFrameTickGPU");
    analyzer->FindEvents(query_sw, &events_sw);
    analyzer->FindEvents(query_gpu, &events_gpu);
    TraceEventVector* frames = NULL;
    if (use_gpu_) {
      frames = &events_gpu;
      EXPECT_EQ(0u, events_sw.size());
    } else {
      frames = &events_sw;
      EXPECT_EQ(0u, events_gpu.size());
    }
    printf("Frame tick events: %d\n", static_cast<int>(frames->size()));
    ASSERT_GT(frames->size(), 20u);
    // Cull a few leading and trailing events as they might be unreliable.
    TraceEventVector rate_events(frames->begin() + kIgnoreSomeFrames,
                                 frames->end() - kIgnoreSomeFrames);
    trace_analyzer::RateStats stats;
    ASSERT_TRUE(GetRateStats(rate_events, &stats));
    printf("FPS = %f\n", 1000000.0 / stats.mean_us);

    // Print perf results.
    double mean_ms = stats.mean_us / 1000.0;
    double std_dev_ms = stats.standard_deviation_us / 1000.0 / 1000.0;
    std::string trace_name = ran_on_gpu ? "gpu" : "software";
    std::string mean_and_error = base::StringPrintf("%f,%f", mean_ms,
                                                    std_dev_ms);
    perf_test::PrintResultMeanAndError(test_name, "", trace_name,
                                       mean_and_error, "frame_time", true);
  }

 private:
  bool use_gpu_;
  scoped_ptr<net::ScopedDefaultHostResolverProc> host_resolver_override_;
};

// For running tests on GPU:
class ThroughputTestGPU : public ThroughputTest {
 public:
  ThroughputTestGPU() : ThroughputTest(true) {}
};

// For running tests on Software:
class ThroughputTestSW : public ThroughputTest {
 public:
  ThroughputTestSW() : ThroughputTest(false) {}
};

////////////////////////////////////////////////////////////////////////////////
/// Tests

// Run this test with a URL on the command line:
// performance_browser_tests --gtest_also_run_disabled_tests --enable-gpu
//     --gtest_filter=ThroughputTest*URL --extra-chrome-flags=http://...
IN_PROC_BROWSER_TEST_F(ThroughputTestSW, DISABLED_TestURL) {
  AllowExternalDNS();
  RunTestWithURL("URL", GetURLFromCommandLine());
  ResetAllowExternalDNS();
}

IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, DISABLED_TestURL) {
  AllowExternalDNS();
  RunTestWithURL("URL", GetURLFromCommandLine());
  ResetAllowExternalDNS();
}

IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, Particles) {
  RunTest("particles", kInternal);
}

IN_PROC_BROWSER_TEST_F(ThroughputTestSW, CanvasDemoSW) {
  RunTest("canvas-demo", kInternal);
}

IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, CanvasDemoGPU) {
  RunTest("canvas-demo", kInternal);
}

}  // namespace
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cfgservices.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 02:48:50 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _CPPUHELPER_FACTORY_HXX_
#include <cppuhelper/factory.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef CFG_REGHELPER_HXX
#include "cfg_reghelper.hxx"
#endif

/********************************************************************************************/

using namespace ::rtl;
using namespace ::dbacfg;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

//***************************************************************************************
//
// registry functions
extern "C" void SAL_CALL createRegistryInfo_OCfgImport();

//***************************************************************************************
extern "C" void SAL_CALL createRegistryInfo_dbacfg()
{
    static sal_Bool bInit = sal_False;
    if (!bInit)
    {
        createRegistryInfo_OCfgImport();
        bInit = sal_True;
    }
}

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
                const sal_Char  **ppEnvTypeName,
                uno_Environment **/*ppEnv*/
            )
{
    createRegistryInfo_dbacfg();
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//---------------------------------------------------------------------------------------
extern "C" sal_Bool SAL_CALL component_writeInfo(
                void* pServiceManager,
                void* pRegistryKey
            )
{
    if (pRegistryKey)
    try
    {
        return ::dbacfg::OModuleRegistration::writeComponentInfos(
            static_cast<XMultiServiceFactory*>(pServiceManager),
            static_cast<XRegistryKey*>(pRegistryKey));
    }
    catch (InvalidRegistryException& )
    {
        OSL_ENSURE(sal_False, "DBA::component_writeInfo : could not create a registry key ! ## InvalidRegistryException !");
    }

    return sal_False;
}

//---------------------------------------------------------------------------------------
extern "C" void* SAL_CALL component_getFactory(
                    const sal_Char* pImplementationName,
                    void* pServiceManager,
                    void* /*pRegistryKey*/)
{
    Reference< XInterface > xRet;
    if (pServiceManager && pImplementationName)
    {
        xRet = ::dbacfg::OModuleRegistration::getComponentFactory(
            ::rtl::OUString::createFromAscii(pImplementationName),
            static_cast< XMultiServiceFactory* >(pServiceManager));
    }

    if (xRet.is())
        xRet->acquire();
    return xRet.get();
};

<commit_msg>INTEGRATION: CWS pchfix02 (1.4.52); FILE MERGED 2006/09/01 17:24:12 kaib 1.4.52.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cfgservices.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 06:44:31 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"

#ifndef _CPPUHELPER_FACTORY_HXX_
#include <cppuhelper/factory.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef CFG_REGHELPER_HXX
#include "cfg_reghelper.hxx"
#endif

/********************************************************************************************/

using namespace ::rtl;
using namespace ::dbacfg;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

//***************************************************************************************
//
// registry functions
extern "C" void SAL_CALL createRegistryInfo_OCfgImport();

//***************************************************************************************
extern "C" void SAL_CALL createRegistryInfo_dbacfg()
{
    static sal_Bool bInit = sal_False;
    if (!bInit)
    {
        createRegistryInfo_OCfgImport();
        bInit = sal_True;
    }
}

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
                const sal_Char  **ppEnvTypeName,
                uno_Environment **/*ppEnv*/
            )
{
    createRegistryInfo_dbacfg();
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//---------------------------------------------------------------------------------------
extern "C" sal_Bool SAL_CALL component_writeInfo(
                void* pServiceManager,
                void* pRegistryKey
            )
{
    if (pRegistryKey)
    try
    {
        return ::dbacfg::OModuleRegistration::writeComponentInfos(
            static_cast<XMultiServiceFactory*>(pServiceManager),
            static_cast<XRegistryKey*>(pRegistryKey));
    }
    catch (InvalidRegistryException& )
    {
        OSL_ENSURE(sal_False, "DBA::component_writeInfo : could not create a registry key ! ## InvalidRegistryException !");
    }

    return sal_False;
}

//---------------------------------------------------------------------------------------
extern "C" void* SAL_CALL component_getFactory(
                    const sal_Char* pImplementationName,
                    void* pServiceManager,
                    void* /*pRegistryKey*/)
{
    Reference< XInterface > xRet;
    if (pServiceManager && pImplementationName)
    {
        xRet = ::dbacfg::OModuleRegistration::getComponentFactory(
            ::rtl::OUString::createFromAscii(pImplementationName),
            static_cast< XMultiServiceFactory* >(pServiceManager));
    }

    if (xRet.is())
        xRet->acquire();
    return xRet.get();
};

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cfgservices.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-26 14:41:37 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"

#ifndef _CPPUHELPER_FACTORY_HXX_
#include <cppuhelper/factory.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef CFG_REGHELPER_HXX
#include "cfg_reghelper.hxx"
#endif

/********************************************************************************************/

using namespace ::dbacfg;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

//***************************************************************************************
//
// registry functions
extern "C" void SAL_CALL createRegistryInfo_OCfgImport();

//***************************************************************************************
extern "C" void SAL_CALL createRegistryInfo_dbacfg()
{
    static sal_Bool bInit = sal_False;
    if (!bInit)
    {
        createRegistryInfo_OCfgImport();
        bInit = sal_True;
    }
}

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
                const sal_Char  **ppEnvTypeName,
                uno_Environment **
            )
{
    createRegistryInfo_dbacfg();
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//---------------------------------------------------------------------------------------
extern "C" sal_Bool SAL_CALL component_writeInfo(
                void* pServiceManager,
                void* pRegistryKey
            )
{
    if (pRegistryKey)
    try
    {
        return ::dbacfg::OModuleRegistration::writeComponentInfos(
            static_cast<XMultiServiceFactory*>(pServiceManager),
            static_cast<XRegistryKey*>(pRegistryKey));
    }
    catch (InvalidRegistryException& )
    {
        OSL_ENSURE(sal_False, "DBA::component_writeInfo : could not create a registry key ! ## InvalidRegistryException !");
    }

    return sal_False;
}

//---------------------------------------------------------------------------------------
extern "C" void* SAL_CALL component_getFactory(
                    const sal_Char* pImplementationName,
                    void* pServiceManager,
                    void* /*pRegistryKey*/)
{
    Reference< XInterface > xRet;
    if (pServiceManager && pImplementationName)
    {
        xRet = ::dbacfg::OModuleRegistration::getComponentFactory(
            ::rtl::OUString::createFromAscii(pImplementationName),
            static_cast< XMultiServiceFactory* >(pServiceManager));
    }

    if (xRet.is())
        xRet->acquire();
    return xRet.get();
};

<commit_msg>INTEGRATION: CWS changefileheader (1.7.120); FILE MERGED 2008/03/31 13:26:53 rt 1.7.120.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: cfgservices.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"

#ifndef _CPPUHELPER_FACTORY_HXX_
#include <cppuhelper/factory.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef CFG_REGHELPER_HXX
#include "cfg_reghelper.hxx"
#endif

/********************************************************************************************/

using namespace ::dbacfg;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

//***************************************************************************************
//
// registry functions
extern "C" void SAL_CALL createRegistryInfo_OCfgImport();

//***************************************************************************************
extern "C" void SAL_CALL createRegistryInfo_dbacfg()
{
    static sal_Bool bInit = sal_False;
    if (!bInit)
    {
        createRegistryInfo_OCfgImport();
        bInit = sal_True;
    }
}

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
                const sal_Char  **ppEnvTypeName,
                uno_Environment **
            )
{
    createRegistryInfo_dbacfg();
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//---------------------------------------------------------------------------------------
extern "C" sal_Bool SAL_CALL component_writeInfo(
                void* pServiceManager,
                void* pRegistryKey
            )
{
    if (pRegistryKey)
    try
    {
        return ::dbacfg::OModuleRegistration::writeComponentInfos(
            static_cast<XMultiServiceFactory*>(pServiceManager),
            static_cast<XRegistryKey*>(pRegistryKey));
    }
    catch (InvalidRegistryException& )
    {
        OSL_ENSURE(sal_False, "DBA::component_writeInfo : could not create a registry key ! ## InvalidRegistryException !");
    }

    return sal_False;
}

//---------------------------------------------------------------------------------------
extern "C" void* SAL_CALL component_getFactory(
                    const sal_Char* pImplementationName,
                    void* pServiceManager,
                    void* /*pRegistryKey*/)
{
    Reference< XInterface > xRet;
    if (pServiceManager && pImplementationName)
    {
        xRet = ::dbacfg::OModuleRegistration::getComponentFactory(
            ::rtl::OUString::createFromAscii(pImplementationName),
            static_cast< XMultiServiceFactory* >(pServiceManager));
    }

    if (xRet.is())
        xRet->acquire();
    return xRet.get();
};

<|endoftext|>


<commit_before>// Copyright (c) 2017 Pierre Fourgeaud
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "drivers/xml/serializablecodec_xml.h"
#include "core/enginecontext.h"
#include "core/fileaccess.h"
#include "core/resourceloader.h"
#include "core/serializable.h"
#include "core/type_traits/attributeaccessor.h"
#include "core/type_traits/objectdefinition.h"
#include "core/utils.h"
#include <cstring>
#include <logger.h>

namespace CodeHero {

// Standard parsing
bool ParseBool(const std::string& iInput) {
    bool res = false;

    if (iInput == "true") {
        res = true;
    } else if (iInput == "false") {
        res = false;
    } else {
        LOGE << "[SerializableCodecXML]: Faile to parse bool argument: '" << iInput << "' is not valid." << std::endl;
    }

    return res;
}

float ParseFloat(const std::string& iInput) {
    float res = 0.0f;
    try {
        res = std::stof(iInput);
    } catch (const std::exception& e) {
        LOGE << "XML: Fail to parse float argument, got: " << e.what() << std::endl;
    }

    return res;
}

Vector2 ParseVector2(const std::string& iInput) {
    Vector2 res;
    auto nums = Split(iInput, ' ');
    if (nums.size() != 2) {
        LOGE << "[SerializableCodexXML]: Fail to parse Vector2 argument. Got " << nums.size() << " members, expected 2." << std::endl;
        return res;
    }
    try {
        res.SetX(ParseFloat(nums[0]));
        res.SetY(ParseFloat(nums[1]));
    } catch (const std::exception& e) {
        LOGE << "[SerializableCodexXML]: Fail to parse Vector2 argument, got: " << e.what() << std::endl;
    }

    return res;
}

Vector3 ParseVector3(const std::string& iInput) {
    Vector3 res;
    auto nums = Split(iInput, ' ');
    if (nums.size() != 3) {
        LOGE << "XML: Fail to parse Vector3 argument. Got " << nums.size() << " members, expected 3." << std::endl;
        return res;
    }
    try {
        res.SetX(ParseFloat(nums[0]));
        res.SetY(ParseFloat(nums[1]));
        res.SetZ(ParseFloat(nums[2]));
    } catch (const std::exception& e) {
        LOGE << "XML: Fail to parse Vector3 argument, got: " << e.what() << std::endl;
    }

    return res;
}

Quaternion ParseQuaternion(const std::string& iInput) {
    Quaternion res;
    auto nums = Split(iInput, ' ');
    if (nums.size() == 3) {
        try {
            res.FromEulerAngles(ParseFloat(nums[0]), ParseFloat(nums[1]), ParseFloat(nums[2]));
        } catch (const std::exception& e) {
            LOGE << "[SerializableCodexXML]: Fail to parse Quaternion argument, got: " << e.what() << std::endl;
        }
    } else {
        LOGE << "[SerializableCodexXML]: Fail to parse Quaternion argument. Got " << nums.size() << " members." << std::endl;
    }

    return res;
}

VariantArray ParseArray(const pugi::xml_object_range<pugi::xml_node_iterator>& iChildren) {
    VariantArray res;

    for (pugi::xml_node_iterator it = iChildren.begin(); it != iChildren.end(); ++it) {
        if (std::strcmp(it->name(), "subattribute") == 0) {
            std::string attrVal = it->attribute("value").as_string();

            res.push_back(attrVal);
        } else {
            LOGE << "[SerializableCodeXML]: Failed to parse array attribute with name '" << it->name() << "'" << std::endl;
        }
    }

    return std::move(res);
}

VariantHashMap ParseHashMap(const pugi::xml_object_range<pugi::xml_node_iterator>& iChildren) {
    VariantHashMap res;

    for (pugi::xml_node_iterator it = iChildren.begin(); it != iChildren.end(); ++it) {
        if (std::strcmp(it->name(), "subattribute") == 0) {
            std::string attr = it->attribute("name").as_string();
            std::string attrVal = it->attribute("value").as_string();

            res[attr] = attrVal;
        } else {
            LOGE << "[SerializableCodeXML]: Failed to parse hashmap attribute with name '" << it->name() << "'" << std::endl;
        }
    }

    return std::move(res);
}

SerializableCodecXML::SerializableCodecXML(const std::shared_ptr<EngineContext>& iContext)
    : ResourceCodec<Serializable>(iContext) {
    std::vector<std::string> ext{"xml"};
    for (auto& e : ext) {
        _AddExtension(e);
    }
}

SerializableCodecXML::~SerializableCodecXML() {}

std::shared_ptr<Serializable> SerializableCodecXML::Load(FileAccess& iF, const std::string& iTypeName) {
    std::string content = iF.ReadAll();

    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load_string(content.c_str());

    if (!result) {
        LOGE << "XML [" << content << "] parsed with errors, attr value: [" << doc.child("node").attribute("attr").value() << "]" << std::endl;
        LOGE << "Error description: " << result.description() << std::endl;
        LOGE << "Error offset: " << result.offset << " (error at [..." << (&content[result.offset]) << "]" << std::endl;
        return nullptr;
    }

    pugi::xml_node root = doc.child(iTypeName.c_str());

    if (!root) {
        LOGE << "SerializableCodecXML: Failed to find node " << iTypeName << ". Object not imported." << std::endl;
        return nullptr;
    }

    auto rootDef = Object::GetDefinition(iTypeName);
    if (!rootDef) {
        LOGE << "SerializableCodecXML: No definition was declared for object '" << iTypeName
             << "'. Object not imported." << std::endl;
        return nullptr;
    }

    return _Load(rootDef, root);
}

std::shared_ptr<Serializable> SerializableCodecXML::_Load(const std::shared_ptr<ObjectDefinition>& iDefinition,
                                                          const pugi::xml_node& iNode) const {
    // TODO(pierre) At that point we are fairly confident the obj is Serializable,
    // we should make it more sure in the future.
    auto obj = std::static_pointer_cast<Serializable>(iDefinition->Create());
    obj->BeginLoad();

    for (pugi::xml_node_iterator it = iNode.begin(); it != iNode.end(); ++it) {
        // If the current node is attribute, then it is an attribute for the current object
        if (std::strcmp(it->name(), "attribute") == 0) {
            // No need to check for neither if name or value exists, the GetAttribe and then the parsers will fail
            // if no value where passed
            std::string attr = it->attribute("name").as_string();
            std::string attrVal = it->attribute("value").as_string();
            auto attrInfo = iDefinition->GetAttribute(attr);
            if (attrInfo.IsNull()) {
                LOGE << "SerializableCodecXML: Attribute '" << attr << "' not registered for object '"
                     << iDefinition->GetName() << "', ignored." << std::endl;
            } else {
                switch (attrInfo.GetType()) {
                case Variant::Value::VVT_Bool:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseBool(attrVal)));
                    break;
                case Variant::Value::VVT_Float:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseFloat(attrVal)));
                    break;
                case Variant::Value::VVT_String:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(std::string(attrVal)));
                    break;
                case Variant::Value::VVT_Vector2:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseVector2(attrVal)));
                    break;
                case Variant::Value::VVT_Vector3:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseVector3(attrVal)));
                    break;
                case Variant::Value::VVT_Quaternion:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseQuaternion(attrVal)));
                    break;
                case Variant::Value::VVT_Array:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseArray(it->children())));
                    break;
                case Variant::Value::VVT_HashMap:
                    // HashMap in variant for now does support only <string, string>
                    // When the type will evolve in a more complicated/complete version
                    // we will need to revise this parsing
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseHashMap(it->children())));
                    break;
                case Variant::Value::VVT_SerializablePtr:
                    // If the tag is attribute and the type is shared_ptr<Serializable>
                    // we consider that we expect a collection of SerializablePtr object
                    // the attribute tag being a way to group those elements together
                    if (_ParseCollection(it->children(), attrInfo, *obj) != Error::OK) {
                        LOGE << "[SerializableCodeXML]: Failed to parse collection '" << attr << "'." << std::endl;
                    }
                    break;
                default:
                    // Should not be here...
                    CH_ASSERT(false);
                    break;
                }
            }
        } else {
            auto attrInfo = iDefinition->GetAttribute(it->name());
            if (attrInfo.IsNull()) {
                LOGE << "SerializableCodecXML: Attribute '" << it->name() << "' not registered for object '"
                     << iDefinition->GetName() << "', ignored." << std::endl;
                continue;
            }

            _LoadObject(it, attrInfo, *obj);
        }
    }

    obj->EndLoad();

    return obj;
}

Error SerializableCodecXML::_ParseCollection(const pugi::xml_object_range<pugi::xml_node_iterator>& iChildren,
                                             const AttributeInfo& iAttrInfo,
                                             Serializable& oObject) const {
    Error ret = Error::OK;

    for (pugi::xml_node_iterator it = iChildren.begin(); it != iChildren.end(); ++it) {
        ret = _LoadObject(it, iAttrInfo, oObject);
        if (ret != Error::OK) {
            LOGE << "[SerializableCodecXML]: Failed to load object '" << it->name() << "'." << std::endl;
            break;
        }
    }

    return ret;
}

Error SerializableCodecXML::_LoadObject(const pugi::xml_node_iterator& iNode, const AttributeInfo& iAttrInfo, Serializable& oObject) const {
    auto def = Object::GetDefinition(iNode->name());
    if (!def) {
        LOGE << "[SerializableCodecXML]: No definition was declared for object '" << iNode->name()
             << "'. Object not imported." << std::endl;
        return Error::ERR_PARSING_FAILED;
    }

    auto attr = iNode->attribute("path");

    // Whatever path we take next, we will need this object
    std::shared_ptr<Serializable> obj;

    // If it has a path to file, we use the resource loader
    if (attr) {
        obj = m_pContext->GetSubsystem<ResourceLoader<Serializable>>()->Load(attr.as_string(), iNode->name());
    } else { // Or we load it here
        // TODO(pierre) All object here can be serializable
        // but we should add a test. We can at least do a IsA (to be added soon)
        obj = _Load(def, *iNode);
        if (obj == nullptr) {
            LOGE << "[SerializableCodecXML]: Failed to import " << iNode->name() << " object. Continuing..."
                 << std::endl;
            return Error::FAILED;
        }
    }

    iAttrInfo.GetAccessor()->Set(&oObject, Variant(obj));

    return Error::OK;
}

}  // namespace CodeHero
<commit_msg>Just cosmetic change on a too long line in xml codec<commit_after>// Copyright (c) 2017 Pierre Fourgeaud
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "drivers/xml/serializablecodec_xml.h"
#include "core/enginecontext.h"
#include "core/fileaccess.h"
#include "core/resourceloader.h"
#include "core/serializable.h"
#include "core/type_traits/attributeaccessor.h"
#include "core/type_traits/objectdefinition.h"
#include "core/utils.h"
#include <cstring>
#include <logger.h>

namespace CodeHero {

// Standard parsing
bool ParseBool(const std::string& iInput) {
    bool res = false;

    if (iInput == "true") {
        res = true;
    } else if (iInput == "false") {
        res = false;
    } else {
        LOGE << "[SerializableCodecXML]: Faile to parse bool argument: '" << iInput << "' is not valid." << std::endl;
    }

    return res;
}

float ParseFloat(const std::string& iInput) {
    float res = 0.0f;
    try {
        res = std::stof(iInput);
    } catch (const std::exception& e) {
        LOGE << "XML: Fail to parse float argument, got: " << e.what() << std::endl;
    }

    return res;
}

Vector2 ParseVector2(const std::string& iInput) {
    Vector2 res;
    auto nums = Split(iInput, ' ');
    if (nums.size() != 2) {
        LOGE << "[SerializableCodexXML]: Fail to parse Vector2 argument. Got " << nums.size() << " members, expected 2." << std::endl;
        return res;
    }
    try {
        res.SetX(ParseFloat(nums[0]));
        res.SetY(ParseFloat(nums[1]));
    } catch (const std::exception& e) {
        LOGE << "[SerializableCodexXML]: Fail to parse Vector2 argument, got: " << e.what() << std::endl;
    }

    return res;
}

Vector3 ParseVector3(const std::string& iInput) {
    Vector3 res;
    auto nums = Split(iInput, ' ');
    if (nums.size() != 3) {
        LOGE << "XML: Fail to parse Vector3 argument. Got " << nums.size() << " members, expected 3." << std::endl;
        return res;
    }
    try {
        res.SetX(ParseFloat(nums[0]));
        res.SetY(ParseFloat(nums[1]));
        res.SetZ(ParseFloat(nums[2]));
    } catch (const std::exception& e) {
        LOGE << "XML: Fail to parse Vector3 argument, got: " << e.what() << std::endl;
    }

    return res;
}

Quaternion ParseQuaternion(const std::string& iInput) {
    Quaternion res;
    auto nums = Split(iInput, ' ');
    if (nums.size() == 3) {
        try {
            res.FromEulerAngles(ParseFloat(nums[0]), ParseFloat(nums[1]), ParseFloat(nums[2]));
        } catch (const std::exception& e) {
            LOGE << "[SerializableCodexXML]: Fail to parse Quaternion argument, got: " << e.what() << std::endl;
        }
    } else {
        LOGE << "[SerializableCodexXML]: Fail to parse Quaternion argument. Got " << nums.size() << " members." << std::endl;
    }

    return res;
}

VariantArray ParseArray(const pugi::xml_object_range<pugi::xml_node_iterator>& iChildren) {
    VariantArray res;

    for (pugi::xml_node_iterator it = iChildren.begin(); it != iChildren.end(); ++it) {
        if (std::strcmp(it->name(), "subattribute") == 0) {
            std::string attrVal = it->attribute("value").as_string();

            res.push_back(attrVal);
        } else {
            LOGE << "[SerializableCodeXML]: Failed to parse array attribute with name '" << it->name() << "'" << std::endl;
        }
    }

    return std::move(res);
}

VariantHashMap ParseHashMap(const pugi::xml_object_range<pugi::xml_node_iterator>& iChildren) {
    VariantHashMap res;

    for (pugi::xml_node_iterator it = iChildren.begin(); it != iChildren.end(); ++it) {
        if (std::strcmp(it->name(), "subattribute") == 0) {
            std::string attr = it->attribute("name").as_string();
            std::string attrVal = it->attribute("value").as_string();

            res[attr] = attrVal;
        } else {
            LOGE << "[SerializableCodeXML]: Failed to parse hashmap attribute with name '" << it->name() << "'" << std::endl;
        }
    }

    return std::move(res);
}

SerializableCodecXML::SerializableCodecXML(const std::shared_ptr<EngineContext>& iContext)
    : ResourceCodec<Serializable>(iContext) {
    std::vector<std::string> ext{"xml"};
    for (auto& e : ext) {
        _AddExtension(e);
    }
}

SerializableCodecXML::~SerializableCodecXML() {}

std::shared_ptr<Serializable> SerializableCodecXML::Load(FileAccess& iF, const std::string& iTypeName) {
    std::string content = iF.ReadAll();

    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load_string(content.c_str());

    if (!result) {
        LOGE << "XML [" << content << "] parsed with errors, attr value: ["
             << doc.child("node").attribute("attr").value() << "]" << std::endl;
        LOGE << "Error description: " << result.description() << std::endl;
        LOGE << "Error offset: " << result.offset << " (error at [..." << (&content[result.offset]) << "]" << std::endl;
        return nullptr;
    }

    pugi::xml_node root = doc.child(iTypeName.c_str());

    if (!root) {
        LOGE << "SerializableCodecXML: Failed to find node " << iTypeName << ". Object not imported." << std::endl;
        return nullptr;
    }

    auto rootDef = Object::GetDefinition(iTypeName);
    if (!rootDef) {
        LOGE << "SerializableCodecXML: No definition was declared for object '" << iTypeName
             << "'. Object not imported." << std::endl;
        return nullptr;
    }

    return _Load(rootDef, root);
}

std::shared_ptr<Serializable> SerializableCodecXML::_Load(const std::shared_ptr<ObjectDefinition>& iDefinition,
                                                          const pugi::xml_node& iNode) const {
    // TODO(pierre) At that point we are fairly confident the obj is Serializable,
    // we should make it more sure in the future.
    auto obj = std::static_pointer_cast<Serializable>(iDefinition->Create());
    obj->BeginLoad();

    for (pugi::xml_node_iterator it = iNode.begin(); it != iNode.end(); ++it) {
        // If the current node is attribute, then it is an attribute for the current object
        if (std::strcmp(it->name(), "attribute") == 0) {
            // No need to check for neither if name or value exists, the GetAttribe and then the parsers will fail
            // if no value where passed
            std::string attr = it->attribute("name").as_string();
            std::string attrVal = it->attribute("value").as_string();
            auto attrInfo = iDefinition->GetAttribute(attr);
            if (attrInfo.IsNull()) {
                LOGE << "SerializableCodecXML: Attribute '" << attr << "' not registered for object '"
                     << iDefinition->GetName() << "', ignored." << std::endl;
            } else {
                switch (attrInfo.GetType()) {
                case Variant::Value::VVT_Bool:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseBool(attrVal)));
                    break;
                case Variant::Value::VVT_Float:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseFloat(attrVal)));
                    break;
                case Variant::Value::VVT_String:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(std::string(attrVal)));
                    break;
                case Variant::Value::VVT_Vector2:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseVector2(attrVal)));
                    break;
                case Variant::Value::VVT_Vector3:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseVector3(attrVal)));
                    break;
                case Variant::Value::VVT_Quaternion:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseQuaternion(attrVal)));
                    break;
                case Variant::Value::VVT_Array:
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseArray(it->children())));
                    break;
                case Variant::Value::VVT_HashMap:
                    // HashMap in variant for now does support only <string, string>
                    // When the type will evolve in a more complicated/complete version
                    // we will need to revise this parsing
                    attrInfo.GetAccessor()->Set(obj.get(), Variant(ParseHashMap(it->children())));
                    break;
                case Variant::Value::VVT_SerializablePtr:
                    // If the tag is attribute and the type is shared_ptr<Serializable>
                    // we consider that we expect a collection of SerializablePtr object
                    // the attribute tag being a way to group those elements together
                    if (_ParseCollection(it->children(), attrInfo, *obj) != Error::OK) {
                        LOGE << "[SerializableCodeXML]: Failed to parse collection '" << attr << "'." << std::endl;
                    }
                    break;
                default:
                    // Should not be here...
                    CH_ASSERT(false);
                    break;
                }
            }
        } else {
            auto attrInfo = iDefinition->GetAttribute(it->name());
            if (attrInfo.IsNull()) {
                LOGE << "SerializableCodecXML: Attribute '" << it->name() << "' not registered for object '"
                     << iDefinition->GetName() << "', ignored." << std::endl;
                continue;
            }

            _LoadObject(it, attrInfo, *obj);
        }
    }

    obj->EndLoad();

    return obj;
}

Error SerializableCodecXML::_ParseCollection(const pugi::xml_object_range<pugi::xml_node_iterator>& iChildren,
                                             const AttributeInfo& iAttrInfo,
                                             Serializable& oObject) const {
    Error ret = Error::OK;

    for (pugi::xml_node_iterator it = iChildren.begin(); it != iChildren.end(); ++it) {
        ret = _LoadObject(it, iAttrInfo, oObject);
        if (ret != Error::OK) {
            LOGE << "[SerializableCodecXML]: Failed to load object '" << it->name() << "'." << std::endl;
            break;
        }
    }

    return ret;
}

Error SerializableCodecXML::_LoadObject(const pugi::xml_node_iterator& iNode, const AttributeInfo& iAttrInfo, Serializable& oObject) const {
    auto def = Object::GetDefinition(iNode->name());
    if (!def) {
        LOGE << "[SerializableCodecXML]: No definition was declared for object '" << iNode->name()
             << "'. Object not imported." << std::endl;
        return Error::ERR_PARSING_FAILED;
    }

    auto attr = iNode->attribute("path");

    // Whatever path we take next, we will need this object
    std::shared_ptr<Serializable> obj;

    // If it has a path to file, we use the resource loader
    if (attr) {
        obj = m_pContext->GetSubsystem<ResourceLoader<Serializable>>()->Load(attr.as_string(), iNode->name());
    } else { // Or we load it here
        // TODO(pierre) All object here can be serializable
        // but we should add a test. We can at least do a IsA (to be added soon)
        obj = _Load(def, *iNode);
        if (obj == nullptr) {
            LOGE << "[SerializableCodecXML]: Failed to import " << iNode->name() << " object. Continuing..."
                 << std::endl;
            return Error::FAILED;
        }
    }

    iAttrInfo.GetAccessor()->Set(&oObject, Variant(obj));

    return Error::OK;
}

}  // namespace CodeHero
<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

// Reference implementation of timer functions.  Platforms are not required to
// implement these timer methods, but they are required to enable profiling.

// On platforms that have a POSIX stack or C library, it can be written using
// methods from <sys/time.h> or clock() from <time.h>.

// To add an equivalent function for your own platform, create your own
// implementation file, and place it in a subfolder with named after the OS
// you're targeting. For example, see the Cortex M bare metal version in
// tensorflow/lite/micro/bluepill/micro_time.cc or the mbed one on
// tensorflow/lite/micro/mbed/micro_time.cc.

#include "tensorflow/lite/micro/micro_time.h"

#if defined(TF_LITE_USE_CTIME)
#include <ctime>
#endif

namespace tflite {

#if !defined(TF_LITE_USE_CTIME)

// Reference implementation of the ticks_per_second() function that's required
// for a platform to support Tensorflow Lite for Microcontrollers profiling.
// This returns 0 by default because timing is an optional feature that builds
// without errors on platforms that do not need it.
int32_t ticks_per_second() { return 0; }

// Reference implementation of the GetCurrentTimeTicks() function that's
// required for a platform to support Tensorflow Lite for Microcontrollers
// profiling. This returns 0 by default because timing is an optional feature
// that builds without errors on platforms that do not need it.
int32_t GetCurrentTimeTicks() { return 0; }

#else  // defined(TF_LITE_USE_CTIME)

// For platforms that support ctime, we implment the micro_time interface in
// this central location.
int32_t ticks_per_second() { return CLOCKS_PER_SEC; }

int32_t GetCurrentTimeTicks() { return clock(); }
#endif

}  // namespace tflite
<commit_msg>micro_time.cc: Re-add previous functionality<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/micro/micro_time.h"

static inline unsigned get_mcycle() {
  unsigned result;
  asm volatile("csrr %0, mcycle" : "=r"(result));
  return result;
}

static inline void set_mcycle(unsigned cyc) {
  asm volatile("csrw mcycle, %0" ::"r"(cyc));
}

namespace tflite {

// Assumes 100 MHz
int32_t ticks_per_second() { return 100000000; }

// WARNING (from tcal) -- very susceptible to wrap-around (happens every 40s)
//   --> need to get mcycleh, and shift/divide down
//
int32_t GetCurrentTimeTicks() { return (int32_t)get_mcycle(); }

}  // namespace tflite
<|endoftext|>