<commit_before>#include <DuiApplicationWindow>
#include <DuiApplication>
#include <QDBusInterface>
#include <QDebug>

#include "lockscreenui.h"
#include "lockscreenbusinesslogic.h"

LockScreenBusinessLogic::LockScreenBusinessLogic(QObject* parent) :
        QObject(parent),
        display(NULL),
        lockUI(NULL)
{
    qDebug() << Q_FUNC_INFO;

    display = new QmDisplayState(this);
    lockUI = new LockScreenUI();

    connect(display, SIGNAL(displayStateChanged(Maemo::QmDisplayState::DisplayState)),
            this, SLOT(displayStateChanged(Maemo::QmDisplayState::DisplayState)));
    connect(lockUI, SIGNAL(unlocked()), this, SLOT(unlockScreen()));

    /*
    dbusIf = new QDBusInterface("org.maemo.dui.NotificationManager", "/systemui",
                                "org.maemo.dui.NotificationManager.MissedEvents",
                                QDBusConnection::sessionBus(), this);
    connect(dbusIf, SIGNAL(missedEventAmountsChanged(int, int, int, int)),
            this, SLOT(updateMissedEventAmounts(int, int, int, int)));
    dbusIf->call(QDBus::NoBlock, QString("missedEventAmountsRequired"));
    */
    shortPowerKeyPressOccured();
}

LockScreenBusinessLogic::~LockScreenBusinessLogic()
{
    //delete eventEater;
    //eventEater = NULL;
    delete lockUI;
}

void LockScreenBusinessLogic::shortPowerKeyPressOccured()
{
    qDebug() << Q_FUNC_INFO;
    switch (display->get()) {
    case Maemo::QmDisplayState::Off:
        toggleScreenLockUI(true); //make sure the UI is on
        toggleKeyPadLock(false);
        display->set(Maemo::QmDisplayState::On);
        break;
    case Maemo::QmDisplayState::On:
    case Maemo::QmDisplayState::Dimmed:
        toggleKeyPadLock(true);
        display->set(Maemo::QmDisplayState::Off);
        toggleScreenLockUI(true);
        break;
    }
}

void LockScreenBusinessLogic::displayStateChanged(Maemo::QmDisplayState::DisplayState state)
{
    qDebug() << Q_FUNC_INFO << state;
    switch (state) {
    case Maemo::QmDisplayState::Off:
        toggleKeyPadLock(true); //lock the keypad
        toggleScreenLockUI(true); //show UI
        break;
    case Maemo::QmDisplayState::On:
        toggleKeyPadLock(false); //unlock the keypad
        break;
    default:
        break;
    }
}

void LockScreenBusinessLogic::unlockScreen()
{
    qDebug() << Q_FUNC_INFO;
    toggleScreenLockUI(false); //turn off the UI
    toggleKeyPadLock(false); //unlock the keypad
}

void LockScreenBusinessLogic::updateMissedEventAmounts(int a, int b, int c, int d)
{
    qDebug() << "LockScreenBusinessLogic::updateMissedEventAmounts("
    << a << ", " << b << ", " << c << ", " << d << ")";
    lockUI->updateMissedEventAmounts(a, b, c, d);
}

void LockScreenBusinessLogic::toggleKeyPadLock(bool toggle)
{
    qDebug() << Q_FUNC_INFO << toggle;
    QmLocks::State newState = (toggle ? QmLocks::Locked : QmLocks::Unlocked);
    QmLocks touchPadLocker;
    touchPadLocker.setState(QmLocks::TouchAndKeyboard, newState);
}

void LockScreenBusinessLogic::toggleScreenLockUI(bool toggle)
{
    qDebug() << Q_FUNC_INFO << toggle;
    if (toggle) {
        DuiApplication::activeApplicationWindow()->show();
        lockUI->appear();
    } else {
        DuiApplication::activeApplicationWindow()->hide();
    }
}

<commit_msg>Removing test code, once again<commit_after>#include <DuiApplicationWindow>
#include <DuiApplication>
#include <QDBusInterface>
#include <QDebug>

#include "lockscreenui.h"
#include "lockscreenbusinesslogic.h"

LockScreenBusinessLogic::LockScreenBusinessLogic(QObject* parent) :
        QObject(parent),
        display(NULL),
        lockUI(NULL)
{
    qDebug() << Q_FUNC_INFO;

    display = new QmDisplayState(this);
    lockUI = new LockScreenUI();

    connect(display, SIGNAL(displayStateChanged(Maemo::QmDisplayState::DisplayState)),
            this, SLOT(displayStateChanged(Maemo::QmDisplayState::DisplayState)));
    connect(lockUI, SIGNAL(unlocked()), this, SLOT(unlockScreen()));

    /*
    dbusIf = new QDBusInterface("org.maemo.dui.NotificationManager", "/systemui",
                                "org.maemo.dui.NotificationManager.MissedEvents",
                                QDBusConnection::sessionBus(), this);
    connect(dbusIf, SIGNAL(missedEventAmountsChanged(int, int, int, int)),
            this, SLOT(updateMissedEventAmounts(int, int, int, int)));
    dbusIf->call(QDBus::NoBlock, QString("missedEventAmountsRequired"));
    */
}

LockScreenBusinessLogic::~LockScreenBusinessLogic()
{
    //delete eventEater;
    //eventEater = NULL;
    delete lockUI;
}

void LockScreenBusinessLogic::shortPowerKeyPressOccured()
{
    qDebug() << Q_FUNC_INFO;
    switch (display->get()) {
    case Maemo::QmDisplayState::Off:
        toggleScreenLockUI(true); //make sure the UI is on
        toggleKeyPadLock(false);
        display->set(Maemo::QmDisplayState::On);
        break;
    case Maemo::QmDisplayState::On:
    case Maemo::QmDisplayState::Dimmed:
        toggleKeyPadLock(true);
        display->set(Maemo::QmDisplayState::Off);
        toggleScreenLockUI(true);
        break;
    }
}

void LockScreenBusinessLogic::displayStateChanged(Maemo::QmDisplayState::DisplayState state)
{
    qDebug() << Q_FUNC_INFO << state;
    switch (state) {
    case Maemo::QmDisplayState::Off:
        toggleKeyPadLock(true); //lock the keypad
        toggleScreenLockUI(true); //show UI
        break;
    case Maemo::QmDisplayState::On:
        toggleKeyPadLock(false); //unlock the keypad
        break;
    default:
        break;
    }
}

void LockScreenBusinessLogic::unlockScreen()
{
    qDebug() << Q_FUNC_INFO;
    toggleScreenLockUI(false); //turn off the UI
    toggleKeyPadLock(false); //unlock the keypad
}

void LockScreenBusinessLogic::updateMissedEventAmounts(int a, int b, int c, int d)
{
    qDebug() << "LockScreenBusinessLogic::updateMissedEventAmounts("
    << a << ", " << b << ", " << c << ", " << d << ")";
    lockUI->updateMissedEventAmounts(a, b, c, d);
}

void LockScreenBusinessLogic::toggleKeyPadLock(bool toggle)
{
    qDebug() << Q_FUNC_INFO << toggle;
    QmLocks::State newState = (toggle ? QmLocks::Locked : QmLocks::Unlocked);
    QmLocks touchPadLocker;
    touchPadLocker.setState(QmLocks::TouchAndKeyboard, newState);
}

void LockScreenBusinessLogic::toggleScreenLockUI(bool toggle)
{
    qDebug() << Q_FUNC_INFO << toggle;
    if (toggle) {
        DuiApplication::activeApplicationWindow()->show();
        lockUI->appear();
    } else {
        DuiApplication::activeApplicationWindow()->hide();
    }
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef INTERRUPTS_H
#define INTERRUPTS_H

#include "stl/types.hpp"

namespace interrupt {

constexpr const size_t SYSCALL_FIRST = 50;
constexpr const size_t SYSCALL_MAX = 10;

struct fault_regs {
    uint64_t error_no;
    uint64_t error_code;
    uint64_t rip;
    uint64_t rflags;
    uint64_t cs;
    uint64_t rsp;
    uint64_t ss;
} __attribute__((packed));

struct syscall_regs {
    uint64_t data_segment;
    uint64_t rax;
    uint64_t rbx;
    uint64_t rcx;
    uint64_t rdx;
    uint64_t rsi;
    uint64_t rdi;
    uint64_t r8;
    uint64_t r9;
    uint64_t r10;
    uint64_t r11;
    uint64_t r12;
    uint64_t code;
} __attribute__((packed));

void setup_interrupts();

void register_irq_handler(size_t irq, void (*handler)());
void register_syscall_handler(size_t irq, void (*handler)(const syscall_regs&));

} //end of interrupt namespace

#endif
<commit_msg>Get reference to the values that are pushed on the stack by int<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef INTERRUPTS_H
#define INTERRUPTS_H

#include "stl/types.hpp"

namespace interrupt {

constexpr const size_t SYSCALL_FIRST = 50;
constexpr const size_t SYSCALL_MAX = 10;

struct fault_regs {
    uint64_t error_no;
    uint64_t error_code;
    uint64_t rip;
    uint64_t rflags;
    uint64_t cs;
    uint64_t rsp;
    uint64_t ss;
} __attribute__((packed));

struct syscall_regs {
    uint64_t data_segment;
    uint64_t rax;
    uint64_t rbx;
    uint64_t rcx;
    uint64_t rdx;
    uint64_t rsi;
    uint64_t rdi;
    uint64_t r8;
    uint64_t r9;
    uint64_t r10;
    uint64_t r11;
    uint64_t r12;
    uint64_t rbp;
    uint64_t rsp;
    uint64_t code;
    uint64_t rip;
    uint64_t cs;
    uint64_t rflags;
    uint64_t rsp;
} __attribute__((packed));

void setup_interrupts();

void register_irq_handler(size_t irq, void (*handler)());
void register_syscall_handler(size_t irq, void (*handler)(const syscall_regs&));

} //end of interrupt namespace

#endif
<|endoftext|>


<commit_before>#if !defined( __CINT__) || defined(__MAKECINT__)
#include <AliRun.h>
#include <AliStack.h>
#include <AliLoader.h>
#include <AliRunLoader.h>

#include "AliRICH.h"
#include "AliRICHDisplFast.h"
#endif

//globals for easy manual manipulations
AliRun *a;    AliStack *s;  AliRunLoader *al;
AliRICH   *r; AliLoader    *rl,*vl;

//__________________________________________________________________________________________________
void pp(int tid)
{
  if(!al) return;
  al->LoadHeader();  al->LoadKinematics();

  if(tid<0||tid>=al->Stack()->GetNtrack())
    cout<<"Valid tid number is 0-"<<al->Stack()->GetNtrack()-1<<" for this event.\n";
  else
    PrintParticleInfo(tid);

  al->UnloadKinematics();  al->UnloadHeader();
}
//__________________________________________________________________________________________________
void PrintParticleInfo(int tid)
{
// Prints particle info for a given TID
  TParticle *p=al->Stack()->Particle(tid);
  cout<<p->GetName()<<"("<<tid<<")";
  if(!p->IsPrimary()){cout<<" from "; PrintParticleInfo(p->GetFirstMother());}
  else                   {cout<<endl;}
}
//__________________________________________________________________________________________________
Int_t mother(Int_t tid)
{
// Who is the mother of given track TID?
  al->LoadHeader();  al->LoadKinematics();

  if(tid<0||tid>=al->Stack()->GetNtrack())
    cout<<"Valid tid number is 0-"<<al->Stack()->GetNtrack()-1<<" for this event.\n";
  else
    while(1){
      TParticle *p=al->Stack()->Particle(tid);
      if(p->IsPrimary()) break;
      tid=p->GetFirstMother();
    }

  al->UnloadKinematics();  al->UnloadHeader();
  return tid;
}
//__________________________________________________________________________________________________

Bool_t AliceRead()
{
  Info("ReadAlice","Tring to read ALICE from SIMULATED FILE...");
  if(gAlice){
    delete gAlice->GetRunLoader();
    delete gAlice;
  }

  if(gSystem->Exec("ls galice.root>/dev/null")==256){//there is no galice.root in current directory
    AliceNew();
    RichGet();
    return kFALSE; //new session
  }else{
    if(!(al=AliRunLoader::Open())){//if not possible to read from galice.root, then remove grabage and reinvoke AliceRead()
      gSystem->Exec("rm -rf *.root *.dat");
      AliceRead();
    }
    al->LoadgAlice();//before this gAlice is 0;
    if(!gAlice) Fatal("menu.C::ReadAlice","No gAlice in file");
    a=al->GetAliRun();//provides pointer to AliRun object
    Info("AliceRead","Run contains %i event(s)",a->GetEventsPerRun());
    RichGet();
    return kTRUE;   //old session opened from file
  }
}//AliceRead()
//__________________________________________________________________________________________________
void AliceNew()
{
  Info("AliceNew","Init new session");
  new AliRun("gAlice","Alice experiment system");  gAlice->Init(); a=gAlice; al=gAlice->GetRunLoader();
}//AliceNew()
//__________________________________________________________________________________________________
void RichGet()
{
  if(!(r=r()))     Warning("RICH/menu.C::ReadAlice","No RICH in file");
  if(!(rl=rl()))   Warning("RICH/menu.C::ReadAlice","No RICH loader in file");
}

//__________________________________________________________________________________________________
void MenuRich()
{
  TControlBar *pMenu = new TControlBar("vertical","RICH");
  pMenu->AddButton("Display single chambers"          ,"r->Display();"  , "Display Fast");
  pMenu->AddButton("Display ALL chambers"          ,"r->DisplayEvent(0,0);"  , "Display Fast");
  pMenu->AddButton("Print hits"       ,"r->HitsPrint();"      ,"????");
  pMenu->AddButton("Print sdigits"    ,"r->SDigitsPrint();"   ,"????");
  pMenu->AddButton("Print digits"     ,"r->DigitsPrint();"    ,"????");
  pMenu->AddButton("Print clusters"   ,"r->ClustersPrint();"  ,"????");
  pMenu->AddButton("Print occupancy"  ,"r->OccupancyPrint();" ,"????");
  pMenu->AddButton("Event Summary  "  ,"r->SummaryOfEvent();" ,"????");
  pMenu->AddButton("Hits plots"       ,"r->ControlPlots()"    ,"????");
  pMenu->AddButton("Recon with stack" ,"r->CheckPR()"                                           , "Create RSR.root with ntuple hn");
  pMenu->Show();
}//TestMenu()
//__________________________________________________________________________________________________
void RichMenu()
{
  TControlBar *pMenu = new TControlBar("vertical","MAIN");

  if(AliceRead()){//it's from file, show some info
    if(r) pMenu->AddButton("RICH submenu"    , "MenuRich()"               , "Show RICH submenu"       );
  }else{//it's aliroot, simulate
    pMenu->AddButton("Debug ON",     "DebugON();",   "Switch debug on-off");
    pMenu->AddButton("Debug OFF",    "DebugOFF();",  "Switch debug on-off");
    pMenu->AddButton("Run",          "a()->Run(1)",  "Process!");
  }
  pMenu->AddButton("Test segmentation"  ,"rp->TestSeg()"  ,"Test AliRICHParam segmentation methods"     );
  pMenu->AddButton("Test response"      ,"rp->TestResp()" ,"Test AliRICHParam response methods"         );
  pMenu->AddButton("Test transformation","rp->TestTrans()","Test AliRICHParam transformation methods"   );
  pMenu->AddButton("Test opticals"      ,".x Opticals.h"  ,"Test optical properties"                    );
  pMenu->AddButton("Geo GUI"            ,"GeomGui()"      ,"Shows geometry"                             );
  pMenu->AddButton("Browser"            ,"new TBrowser;"  ,"Start ROOT TBrowser"                        );
  pMenu->AddButton("Quit"               ,".q"             ,"Close session"                              );
  pMenu->Show();
}//menu()
//__________________________________________________________________________________________________
void DebugOFF(){  Info("DebugOFF","");  AliLog::SetGlobalDebugLevel(0);}
void DebugON() {  Info("DebugON","");   AliLog::SetGlobalDebugLevel(AliLog::kDebug);}
//__________________________________________________________________________________________________
void GeomGui()
{
  if(gGeoManager){
    gGeoManager->GetTopVolume()->Draw();
    AliRICHParam::DrawAxis();
  }else
    new G3GeometryGUI;
}

AliRun    *a() {return al->GetAliRun();}                         //provides pointer to main AliRun object (aka gAlice)
AliRICH   *r() {return (AliRICH*)  a()->GetDetector("RICH");}    //provides pointer to RICH detector
AliLoader *rl(){return             al->GetLoader("RICHLoader");}

void rt(Int_t event=0)    {r->PrintTracks  (event);}                                                       //utility print tracks
Int_t nem(Int_t event=0)  {AliRICH::Nparticles(kElectron  ,event,al);} //utility number of electrons
Int_t nep(Int_t event=0)  {AliRICH::Nparticles(kPositron  ,event,al);} //utility number of positrons
Int_t nmup(Int_t event=0) {AliRICH::Nparticles(kMuonPlus  ,event,al);} //utility number of positive muons
Int_t nmum(Int_t event=0) {AliRICH::Nparticles(kMuonMinus ,event,al);} //utility number of negative muons
Int_t npi0(Int_t event=0) {AliRICH::Nparticles(kPi0       ,event,al);} //utility number of neutral pions
Int_t npip(Int_t event=0) {AliRICH::Nparticles(kPiPlus    ,event,al);} //utility number of positive pions
Int_t npim(Int_t event=0) {AliRICH::Nparticles(kPiMinus   ,event,al);} //utility number of negative pions
Int_t nk0(Int_t event=0)  {AliRICH::Nparticles(kK0        ,event,al);} //utility number of neutral kaons
Int_t nkp(Int_t event=0)  {AliRICH::Nparticles(kKPlus     ,event,al);} //utility number of positive kaons
Int_t nkm(Int_t event=0)  {AliRICH::Nparticles(kKMinus    ,event,al);} //utility number of negative kaons
Int_t npp(Int_t event=0)  {AliRICH::Nparticles(kProton    ,event,al);} //utility number of protons
Int_t npm(Int_t event=0)  {AliRICH::Nparticles(kProtonBar ,event,al);} //utility number of antiprotons
<commit_msg>Minor change<commit_after>#if !defined( __CINT__) || defined(__MAKECINT__)
#include <AliRun.h>
#include <AliStack.h>
#include <AliLoader.h>
#include <AliRunLoader.h>

#include "AliRICH.h"
#include "AliRICHDisplFast.h"
#endif

//globals for easy manual manipulations
AliRun *a;    AliStack *s;  AliRunLoader *al;
AliRICH   *r; AliLoader    *rl,*vl;

//__________________________________________________________________________________________________
void pp(int tid)
{
  if(!al) return;
  al->LoadHeader();  al->LoadKinematics();

  if(tid<0||tid>=al->Stack()->GetNtrack())
    cout<<"Valid tid number is 0-"<<al->Stack()->GetNtrack()-1<<" for this event.\n";
  else
    PrintParticleInfo(tid);

  al->UnloadKinematics();  al->UnloadHeader();
}
//__________________________________________________________________________________________________
void PrintParticleInfo(int tid)
{
// Prints particle info for a given TID
  TParticle *p=al->Stack()->Particle(tid);
  cout<<p->GetName()<<"("<<tid<<")";
  if(!p->IsPrimary()){cout<<" from "; PrintParticleInfo(p->GetFirstMother());}
  else                   {cout<<endl;}
}
//__________________________________________________________________________________________________
Int_t mother(Int_t tid)
{
// Who is the mother of given track TID?
  al->LoadHeader();  al->LoadKinematics();

  if(tid<0||tid>=al->Stack()->GetNtrack())
    cout<<"Valid tid number is 0-"<<al->Stack()->GetNtrack()-1<<" for this event.\n";
  else
    while(1){
      TParticle *p=al->Stack()->Particle(tid);
      if(p->IsPrimary()) break;
      tid=p->GetFirstMother();
    }

  al->UnloadKinematics();  al->UnloadHeader();
  return tid;
}
//__________________________________________________________________________________________________

Bool_t AliceRead()
{
  Info("ReadAlice","Tring to read ALICE from SIMULATED FILE...");
  if(gAlice){
    delete gAlice->GetRunLoader();
    delete gAlice;
  }

  if(gSystem->Exec("ls galice.root>/dev/null")==256){//there is no galice.root in current directory
    AliceNew();
    RichGet();
    return kFALSE; //new session
  }else{
    if(!(al=AliRunLoader::Open())){//if not possible to read from galice.root, then remove grabage and reinvoke AliceRead()
      gSystem->Exec("rm -rf *.root *.dat");
      AliceRead();
    }
    al->LoadgAlice();//before this gAlice is 0;
    if(!gAlice) Fatal("menu.C::ReadAlice","No gAlice in file");
    a=al->GetAliRun();//provides pointer to AliRun object
    Info("AliceRead","Run contains %i event(s)",a->GetEventsPerRun());
    RichGet();
    return kTRUE;   //old session opened from file
  }
}//AliceRead()
//__________________________________________________________________________________________________
void AliceNew()
{
  Info("AliceNew","Init new session");
  new AliRun("gAlice","Alice experiment system");  gAlice->Init(); a=gAlice; al=gAlice->GetRunLoader();
}//AliceNew()
//__________________________________________________________________________________________________
void RichGet()
{
  if(!(r=r()))     Warning("RICH/menu.C::ReadAlice","No RICH in file");
  if(!(rl=rl()))   Warning("RICH/menu.C::ReadAlice","No RICH loader in file");
}

//__________________________________________________________________________________________________
void MenuRich()
{
  TControlBar *pMenu = new TControlBar("vertical","RICH");
  pMenu->AddButton("Display single chambers"          ,"r->Display();"  , "Display Fast");
  pMenu->AddButton("Display ALL chambers"          ,"r->DisplayEvent(0,0);"  , "Display Fast");
  pMenu->AddButton("Print hits"       ,"r->HitsPrint();"      ,"????");
  pMenu->AddButton("Print sdigits"    ,"r->SDigitsPrint();"   ,"????");
  pMenu->AddButton("Print digits"     ,"r->DigitsPrint();"    ,"????");
  pMenu->AddButton("Print clusters"   ,"r->ClustersPrint();"  ,"????");
  pMenu->AddButton("Print occupancy"  ,"r->OccupancyPrint(-1);" ,"????");
  pMenu->AddButton("Event Summary  "  ,"r->SummaryOfEvent();" ,"????");
  pMenu->AddButton("Hits plots"       ,"r->ControlPlots()"    ,"????");
  pMenu->AddButton("Recon with stack" ,"r->CheckPR()"                                           , "Create RSR.root with ntuple hn");
  pMenu->Show();
}//TestMenu()
//__________________________________________________________________________________________________
void RichMenu()
{
  TControlBar *pMenu = new TControlBar("vertical","MAIN");

  if(AliceRead()){//it's from file, show some info
    if(r) pMenu->AddButton("RICH submenu"    , "MenuRich()"               , "Show RICH submenu"       );
  }else{//it's aliroot, simulate
    pMenu->AddButton("Debug ON",     "DebugON();",   "Switch debug on-off");
    pMenu->AddButton("Debug OFF",    "DebugOFF();",  "Switch debug on-off");
    pMenu->AddButton("Run",          "a()->Run(1)",  "Process!");
  }
  pMenu->AddButton("Test segmentation"  ,"rp->TestSeg()"  ,"Test AliRICHParam segmentation methods"     );
  pMenu->AddButton("Test response"      ,"rp->TestResp()" ,"Test AliRICHParam response methods"         );
  pMenu->AddButton("Test transformation","rp->TestTrans()","Test AliRICHParam transformation methods"   );
  pMenu->AddButton("Test opticals"      ,".x Opticals.h"  ,"Test optical properties"                    );
  pMenu->AddButton("Geo GUI"            ,"GeomGui()"      ,"Shows geometry"                             );
  pMenu->AddButton("Browser"            ,"new TBrowser;"  ,"Start ROOT TBrowser"                        );
  pMenu->AddButton("Quit"               ,".q"             ,"Close session"                              );
  pMenu->Show();
}//menu()
//__________________________________________________________________________________________________
void DebugOFF(){  Info("DebugOFF","");  AliLog::SetGlobalDebugLevel(0);}
void DebugON() {  Info("DebugON","");   AliLog::SetGlobalDebugLevel(AliLog::kDebug);}
//__________________________________________________________________________________________________
void GeomGui()
{
  if(gGeoManager){
    gGeoManager->GetTopVolume()->Draw();
    AliRICHParam::DrawAxis();
  }else
    new G3GeometryGUI;
}

AliRun    *a() {return al->GetAliRun();}                         //provides pointer to main AliRun object (aka gAlice)
AliRICH   *r() {return (AliRICH*)  a()->GetDetector("RICH");}    //provides pointer to RICH detector
AliLoader *rl(){return             al->GetLoader("RICHLoader");}

void rt(Int_t event=0)    {r->PrintTracks  (event);}                                                       //utility print tracks
Int_t nem(Int_t event=0)  {AliRICH::Nparticles(kElectron  ,event,al);} //utility number of electrons
Int_t nep(Int_t event=0)  {AliRICH::Nparticles(kPositron  ,event,al);} //utility number of positrons
Int_t nmup(Int_t event=0) {AliRICH::Nparticles(kMuonPlus  ,event,al);} //utility number of positive muons
Int_t nmum(Int_t event=0) {AliRICH::Nparticles(kMuonMinus ,event,al);} //utility number of negative muons
Int_t npi0(Int_t event=0) {AliRICH::Nparticles(kPi0       ,event,al);} //utility number of neutral pions
Int_t npip(Int_t event=0) {AliRICH::Nparticles(kPiPlus    ,event,al);} //utility number of positive pions
Int_t npim(Int_t event=0) {AliRICH::Nparticles(kPiMinus   ,event,al);} //utility number of negative pions
Int_t nk0(Int_t event=0)  {AliRICH::Nparticles(kK0        ,event,al);} //utility number of neutral kaons
Int_t nkp(Int_t event=0)  {AliRICH::Nparticles(kKPlus     ,event,al);} //utility number of positive kaons
Int_t nkm(Int_t event=0)  {AliRICH::Nparticles(kKMinus    ,event,al);} //utility number of negative kaons
Int_t npp(Int_t event=0)  {AliRICH::Nparticles(kProton    ,event,al);} //utility number of protons
Int_t npm(Int_t event=0)  {AliRICH::Nparticles(kProtonBar ,event,al);} //utility number of antiprotons
<|endoftext|>


<commit_before>/*
 * Asynchronous local file access.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "istream_file.hxx"
#include "istream_buffer.hxx"
#include "buffered_io.hxx"
#include "system/fd_util.h"
#include "gerrno.h"
#include "pool.hxx"
#include "fb_pool.hxx"
#include "SliceFifoBuffer.hxx"
#include "util/Cast.hxx"

#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>

#include <event.h>

/**
 * If EAGAIN occurs (on NFS), we try again after 100ms.  We can't
 * check EV_READ, because the kernel always indicates VFS files as
 * "readable without blocking".
 */
static const struct timeval file_retry_timeout = {
    .tv_sec = 0,
    .tv_usec = 100000,
};

struct FileIstream {
    struct istream stream;
    int fd;

    FdType fd_type;

    /**
     * A timer to retry reading after EAGAIN.
     */
    struct event event;

    off_t rest;
    SliceFifoBuffer buffer;
    const char *path;
};

static void
file_close(FileIstream *file)
{
    if (file->fd >= 0) {
        evtimer_del(&file->event);

        close(file->fd);
        file->fd = -1;
    }
}

static void
file_destroy(FileIstream *file)
{
    file_close(file);

    file->buffer.FreeIfDefined(fb_pool_get());
}

static void
file_abort(FileIstream *file, GError *error)
{
    file_destroy(file);

    istream_deinit_abort(&file->stream, error);
}

/**
 * @return the number of bytes still in the buffer
 */
static size_t
istream_file_invoke_data(FileIstream *file)
{
    return istream_buffer_consume(&file->stream, file->buffer);
}

static void
istream_file_eof_detected(FileIstream *file)
{
    assert(file->fd >= 0);

    file_destroy(file);

    istream_deinit_eof(&file->stream);
}

static inline size_t
istream_file_max_read(const FileIstream *file)
{
    if (file->rest != (off_t)-1 && file->rest < (off_t)INT_MAX)
        return (size_t)file->rest;
    else
        return INT_MAX;
}

static void
istream_file_try_data(FileIstream *file)
{
    size_t rest = 0;

    if (file->buffer.IsNull()) {
        if (file->rest != 0)
            file->buffer.Allocate(fb_pool_get());
    } else {
        const size_t available = file->buffer.GetAvailable();
        if (available > 0) {
            rest = istream_file_invoke_data(file);
            if (rest == available)
                /* not a single byte was consumed: we may have been
                   closed, and we must bail out now */
                return;
        }
    }

    if (file->rest == 0) {
        if (rest == 0)
            istream_file_eof_detected(file);
        return;
    }

    ForeignFifoBuffer<uint8_t> &buffer = file->buffer;
    ssize_t nbytes = read_to_buffer(file->fd, buffer,
                                    istream_file_max_read(file));
    if (nbytes == 0) {
        if (file->rest == (off_t)-1) {
            file->rest = 0;
            if (rest == 0)
                istream_file_eof_detected(file);
        } else {
            GError *error =
                g_error_new(g_file_error_quark(), 0,
                            "premature end of file in '%s'", file->path);
            file_abort(file, error);
        }
        return;
    } else if (nbytes == -1) {
        GError *error =
            g_error_new(errno_quark(), errno,
                        "failed to read from '%s': %s",
                        file->path, strerror(errno));
        file_abort(file, error);
        return;
    } else if (nbytes > 0 && file->rest != (off_t)-1) {
        file->rest -= (off_t)nbytes;
        assert(file->rest >= 0);
    }

    assert(!file->buffer.IsEmpty());

    rest = istream_file_invoke_data(file);
    if (rest == 0 && file->rest == 0)
        istream_file_eof_detected(file);
}

static void
istream_file_try_direct(FileIstream *file)
{
    assert(file->stream.handler->direct != nullptr);

    /* first consume the rest of the buffer */
    if (istream_file_invoke_data(file) > 0)
        return;

    if (file->rest == 0) {
        istream_file_eof_detected(file);
        return;
    }

    ssize_t nbytes = istream_invoke_direct(&file->stream,
                                           file->fd_type, file->fd,
                                           istream_file_max_read(file));
    if (nbytes == ISTREAM_RESULT_CLOSED)
        /* this stream was closed during the direct() callback */
        return;

    if (nbytes > 0 || nbytes == ISTREAM_RESULT_BLOCKING) {
        /* -2 means the callback wasn't able to consume any data right
           now */
        if (nbytes > 0 && file->rest != (off_t)-1) {
            file->rest -= (off_t)nbytes;
            assert(file->rest >= 0);
            if (file->rest == 0)
                istream_file_eof_detected(file);
        }
    } else if (nbytes == ISTREAM_RESULT_EOF) {
        if (file->rest == (off_t)-1) {
            istream_file_eof_detected(file);
        } else {
            GError *error =
                g_error_new(g_file_error_quark(), 0,
                            "premature end of file in '%s'", file->path);
            file_abort(file, error);
        }
    } else if (errno == EAGAIN) {
        /* this should only happen for splice(SPLICE_F_NONBLOCK) from
           NFS files - unfortunately we cannot use EV_READ here, so we
           just install a timer which retries after 100ms */

        evtimer_add(&file->event, &file_retry_timeout);
    } else {
        /* XXX */
        GError *error =
            g_error_new(errno_quark(), errno,
                        "failed to read from '%s': %s",
                        file->path, strerror(errno));
        file_abort(file, error);
    }
}

static void
file_try_read(FileIstream *file)
{
    if (istream_check_direct(&file->stream, file->fd_type))
        istream_file_try_direct(file);
    else
        istream_file_try_data(file);
}

static void
file_event_callback(gcc_unused int fd, gcc_unused short event,
                    void *ctx)
{
    FileIstream *file = (FileIstream *)ctx;

    file_try_read(file);
}

/*
 * istream implementation
 *
 */

static inline FileIstream *
istream_to_file(struct istream *istream)
{
    return &ContainerCast2(*istream, &FileIstream::stream);
}

static off_t
istream_file_available(struct istream *istream, bool partial)
{
    FileIstream *file = istream_to_file(istream);
    off_t available = 0;

    if (file->rest != (off_t)-1)
        available = file->rest;
    else if (!partial)
        return (off_t)-1;
    else
        available = 0;

    available += file->buffer.GetAvailable();
    return available;
}

static off_t
istream_file_skip(struct istream *istream, off_t length)
{
    FileIstream *file = istream_to_file(istream);

    evtimer_del(&file->event);

    if (file->rest == (off_t)-1)
        return (off_t)-1;

    if (length == 0)
        return 0;

    /* clear the buffer; later we could optimize this function by
       flushing only the skipped number of bytes */
    file->buffer.Clear();

    if (length >= file->rest) {
        /* skip beyond EOF */

        length = file->rest;
        file->rest = 0;
    } else {
        /* seek the file descriptor */

        off_t ret = lseek(file->fd, length, SEEK_CUR);
        if (ret < 0)
            return -1;
        file->rest -= length;
    }

    return length;
}

static void
istream_file_read(struct istream *istream)
{
    FileIstream *file = istream_to_file(istream);

    assert(file->stream.handler != nullptr);

    evtimer_del(&file->event);

    file_try_read(file);
}

static int
istream_file_as_fd(struct istream *istream)
{
    FileIstream *file = istream_to_file(istream);
    int fd = file->fd;

    evtimer_del(&file->event);
    istream_deinit(&file->stream);

    return fd;
}

static void
istream_file_close(struct istream *istream)
{
    FileIstream *file = istream_to_file(istream);

    file_destroy(file);

    istream_deinit(&file->stream);
}

static const struct istream_class istream_file = {
    .available = istream_file_available,
    .skip = istream_file_skip,
    .read = istream_file_read,
    .as_fd = istream_file_as_fd,
    .close = istream_file_close,
};

/*
 * constructor and public methods
 *
 */

struct istream *
istream_file_fd_new(struct pool *pool, const char *path,
                    int fd, FdType fd_type, off_t length)
{
    assert(fd >= 0);
    assert(length >= -1);

    auto file = NewFromPool<FileIstream>(*pool);
    istream_init(&file->stream, &istream_file, pool);
    file->fd = fd;
    file->fd_type = fd_type;
    file->rest = length;
    file->buffer.SetNull();
    file->path = path;

    evtimer_set(&file->event, file_event_callback, file);

    return &file->stream;
}

struct istream *
istream_file_stat_new(struct pool *pool, const char *path, struct stat *st,
                      GError **error_r)
{
    assert(path != nullptr);
    assert(st != nullptr);

    int fd = open_cloexec(path, O_RDONLY|O_NOCTTY, 0);
    if (fd < 0) {
        set_error_errno(error_r);
        g_prefix_error(error_r, "Failed to open %s: ", path);
        return nullptr;
    }

    if (fstat(fd, st) < 0) {
        set_error_errno(error_r);
        g_prefix_error(error_r, "Failed to stat %s: ", path);
        close(fd);
        return nullptr;
    }

    FdType fd_type = FdType::FD_FILE;
    off_t size = st->st_size;

    if (S_ISCHR(st->st_mode)) {
        fd_type = FdType::FD_CHARDEV;
        size = -1;
    }

    return istream_file_fd_new(pool, path, fd, fd_type, size);
}

struct istream *
istream_file_new(struct pool *pool, const char *path, off_t length,
                 GError **error_r)
{
    assert(length >= -1);

    int fd = open_cloexec(path, O_RDONLY|O_NOCTTY, 0);
    if (fd < 0) {
        set_error_errno(error_r);
        g_prefix_error(error_r, "Failed to open %s: ", path);
        return nullptr;
    }

    return istream_file_fd_new(pool, path, fd, FdType::FD_FILE, length);
}

int
istream_file_fd(struct istream *istream)
{
    assert(istream != nullptr);
    assert(istream->cls == &istream_file);

    FileIstream *file = istream_to_file(istream);

    assert(file->fd >= 0);

    return file->fd;
}

bool
istream_file_set_range(struct istream *istream, off_t start, off_t end)
{
    assert(istream != nullptr);
    assert(istream->cls == &istream_file);
    assert(start >= 0);
    assert(end >= start);

    FileIstream *file = istream_to_file(istream);
    assert(file->fd >= 0);
    assert(file->rest >= 0);
    assert(file->buffer.IsNull());
    assert(end <= file->rest);

    if (start > 0 && lseek(file->fd, start, SEEK_CUR) < 0)
        return false;

    file->rest = end - start;
    return true;
}
<commit_msg>istream_file: rename "rest" to "buffer_rest"<commit_after>/*
 * Asynchronous local file access.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "istream_file.hxx"
#include "istream_buffer.hxx"
#include "buffered_io.hxx"
#include "system/fd_util.h"
#include "gerrno.h"
#include "pool.hxx"
#include "fb_pool.hxx"
#include "SliceFifoBuffer.hxx"
#include "util/Cast.hxx"

#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>

#include <event.h>

/**
 * If EAGAIN occurs (on NFS), we try again after 100ms.  We can't
 * check EV_READ, because the kernel always indicates VFS files as
 * "readable without blocking".
 */
static const struct timeval file_retry_timeout = {
    .tv_sec = 0,
    .tv_usec = 100000,
};

struct FileIstream {
    struct istream stream;
    int fd;

    FdType fd_type;

    /**
     * A timer to retry reading after EAGAIN.
     */
    struct event event;

    off_t rest;
    SliceFifoBuffer buffer;
    const char *path;
};

static void
file_close(FileIstream *file)
{
    if (file->fd >= 0) {
        evtimer_del(&file->event);

        close(file->fd);
        file->fd = -1;
    }
}

static void
file_destroy(FileIstream *file)
{
    file_close(file);

    file->buffer.FreeIfDefined(fb_pool_get());
}

static void
file_abort(FileIstream *file, GError *error)
{
    file_destroy(file);

    istream_deinit_abort(&file->stream, error);
}

/**
 * @return the number of bytes still in the buffer
 */
static size_t
istream_file_invoke_data(FileIstream *file)
{
    return istream_buffer_consume(&file->stream, file->buffer);
}

static void
istream_file_eof_detected(FileIstream *file)
{
    assert(file->fd >= 0);

    file_destroy(file);

    istream_deinit_eof(&file->stream);
}

static inline size_t
istream_file_max_read(const FileIstream *file)
{
    if (file->rest != (off_t)-1 && file->rest < (off_t)INT_MAX)
        return (size_t)file->rest;
    else
        return INT_MAX;
}

static void
istream_file_try_data(FileIstream *file)
{
    size_t buffer_rest = 0;

    if (file->buffer.IsNull()) {
        if (file->rest != 0)
            file->buffer.Allocate(fb_pool_get());
    } else {
        const size_t available = file->buffer.GetAvailable();
        if (available > 0) {
            buffer_rest = istream_file_invoke_data(file);
            if (buffer_rest == available)
                /* not a single byte was consumed: we may have been
                   closed, and we must bail out now */
                return;
        }
    }

    if (file->rest == 0) {
        if (buffer_rest == 0)
            istream_file_eof_detected(file);
        return;
    }

    ForeignFifoBuffer<uint8_t> &buffer = file->buffer;
    ssize_t nbytes = read_to_buffer(file->fd, buffer,
                                    istream_file_max_read(file));
    if (nbytes == 0) {
        if (file->rest == (off_t)-1) {
            file->rest = 0;
            if (buffer_rest == 0)
                istream_file_eof_detected(file);
        } else {
            GError *error =
                g_error_new(g_file_error_quark(), 0,
                            "premature end of file in '%s'", file->path);
            file_abort(file, error);
        }
        return;
    } else if (nbytes == -1) {
        GError *error =
            g_error_new(errno_quark(), errno,
                        "failed to read from '%s': %s",
                        file->path, strerror(errno));
        file_abort(file, error);
        return;
    } else if (nbytes > 0 && file->rest != (off_t)-1) {
        file->rest -= (off_t)nbytes;
        assert(file->rest >= 0);
    }

    assert(!file->buffer.IsEmpty());

    buffer_rest = istream_file_invoke_data(file);
    if (buffer_rest == 0 && file->rest == 0)
        istream_file_eof_detected(file);
}

static void
istream_file_try_direct(FileIstream *file)
{
    assert(file->stream.handler->direct != nullptr);

    /* first consume the rest of the buffer */
    if (istream_file_invoke_data(file) > 0)
        return;

    if (file->rest == 0) {
        istream_file_eof_detected(file);
        return;
    }

    ssize_t nbytes = istream_invoke_direct(&file->stream,
                                           file->fd_type, file->fd,
                                           istream_file_max_read(file));
    if (nbytes == ISTREAM_RESULT_CLOSED)
        /* this stream was closed during the direct() callback */
        return;

    if (nbytes > 0 || nbytes == ISTREAM_RESULT_BLOCKING) {
        /* -2 means the callback wasn't able to consume any data right
           now */
        if (nbytes > 0 && file->rest != (off_t)-1) {
            file->rest -= (off_t)nbytes;
            assert(file->rest >= 0);
            if (file->rest == 0)
                istream_file_eof_detected(file);
        }
    } else if (nbytes == ISTREAM_RESULT_EOF) {
        if (file->rest == (off_t)-1) {
            istream_file_eof_detected(file);
        } else {
            GError *error =
                g_error_new(g_file_error_quark(), 0,
                            "premature end of file in '%s'", file->path);
            file_abort(file, error);
        }
    } else if (errno == EAGAIN) {
        /* this should only happen for splice(SPLICE_F_NONBLOCK) from
           NFS files - unfortunately we cannot use EV_READ here, so we
           just install a timer which retries after 100ms */

        evtimer_add(&file->event, &file_retry_timeout);
    } else {
        /* XXX */
        GError *error =
            g_error_new(errno_quark(), errno,
                        "failed to read from '%s': %s",
                        file->path, strerror(errno));
        file_abort(file, error);
    }
}

static void
file_try_read(FileIstream *file)
{
    if (istream_check_direct(&file->stream, file->fd_type))
        istream_file_try_direct(file);
    else
        istream_file_try_data(file);
}

static void
file_event_callback(gcc_unused int fd, gcc_unused short event,
                    void *ctx)
{
    FileIstream *file = (FileIstream *)ctx;

    file_try_read(file);
}

/*
 * istream implementation
 *
 */

static inline FileIstream *
istream_to_file(struct istream *istream)
{
    return &ContainerCast2(*istream, &FileIstream::stream);
}

static off_t
istream_file_available(struct istream *istream, bool partial)
{
    FileIstream *file = istream_to_file(istream);
    off_t available = 0;

    if (file->rest != (off_t)-1)
        available = file->rest;
    else if (!partial)
        return (off_t)-1;
    else
        available = 0;

    available += file->buffer.GetAvailable();
    return available;
}

static off_t
istream_file_skip(struct istream *istream, off_t length)
{
    FileIstream *file = istream_to_file(istream);

    evtimer_del(&file->event);

    if (file->rest == (off_t)-1)
        return (off_t)-1;

    if (length == 0)
        return 0;

    /* clear the buffer; later we could optimize this function by
       flushing only the skipped number of bytes */
    file->buffer.Clear();

    if (length >= file->rest) {
        /* skip beyond EOF */

        length = file->rest;
        file->rest = 0;
    } else {
        /* seek the file descriptor */

        off_t ret = lseek(file->fd, length, SEEK_CUR);
        if (ret < 0)
            return -1;
        file->rest -= length;
    }

    return length;
}

static void
istream_file_read(struct istream *istream)
{
    FileIstream *file = istream_to_file(istream);

    assert(file->stream.handler != nullptr);

    evtimer_del(&file->event);

    file_try_read(file);
}

static int
istream_file_as_fd(struct istream *istream)
{
    FileIstream *file = istream_to_file(istream);
    int fd = file->fd;

    evtimer_del(&file->event);
    istream_deinit(&file->stream);

    return fd;
}

static void
istream_file_close(struct istream *istream)
{
    FileIstream *file = istream_to_file(istream);

    file_destroy(file);

    istream_deinit(&file->stream);
}

static const struct istream_class istream_file = {
    .available = istream_file_available,
    .skip = istream_file_skip,
    .read = istream_file_read,
    .as_fd = istream_file_as_fd,
    .close = istream_file_close,
};

/*
 * constructor and public methods
 *
 */

struct istream *
istream_file_fd_new(struct pool *pool, const char *path,
                    int fd, FdType fd_type, off_t length)
{
    assert(fd >= 0);
    assert(length >= -1);

    auto file = NewFromPool<FileIstream>(*pool);
    istream_init(&file->stream, &istream_file, pool);
    file->fd = fd;
    file->fd_type = fd_type;
    file->rest = length;
    file->buffer.SetNull();
    file->path = path;

    evtimer_set(&file->event, file_event_callback, file);

    return &file->stream;
}

struct istream *
istream_file_stat_new(struct pool *pool, const char *path, struct stat *st,
                      GError **error_r)
{
    assert(path != nullptr);
    assert(st != nullptr);

    int fd = open_cloexec(path, O_RDONLY|O_NOCTTY, 0);
    if (fd < 0) {
        set_error_errno(error_r);
        g_prefix_error(error_r, "Failed to open %s: ", path);
        return nullptr;
    }

    if (fstat(fd, st) < 0) {
        set_error_errno(error_r);
        g_prefix_error(error_r, "Failed to stat %s: ", path);
        close(fd);
        return nullptr;
    }

    FdType fd_type = FdType::FD_FILE;
    off_t size = st->st_size;

    if (S_ISCHR(st->st_mode)) {
        fd_type = FdType::FD_CHARDEV;
        size = -1;
    }

    return istream_file_fd_new(pool, path, fd, fd_type, size);
}

struct istream *
istream_file_new(struct pool *pool, const char *path, off_t length,
                 GError **error_r)
{
    assert(length >= -1);

    int fd = open_cloexec(path, O_RDONLY|O_NOCTTY, 0);
    if (fd < 0) {
        set_error_errno(error_r);
        g_prefix_error(error_r, "Failed to open %s: ", path);
        return nullptr;
    }

    return istream_file_fd_new(pool, path, fd, FdType::FD_FILE, length);
}

int
istream_file_fd(struct istream *istream)
{
    assert(istream != nullptr);
    assert(istream->cls == &istream_file);

    FileIstream *file = istream_to_file(istream);

    assert(file->fd >= 0);

    return file->fd;
}

bool
istream_file_set_range(struct istream *istream, off_t start, off_t end)
{
    assert(istream != nullptr);
    assert(istream->cls == &istream_file);
    assert(start >= 0);
    assert(end >= start);

    FileIstream *file = istream_to_file(istream);
    assert(file->fd >= 0);
    assert(file->rest >= 0);
    assert(file->buffer.IsNull());
    assert(end <= file->rest);

    if (start > 0 && lseek(file->fd, start, SEEK_CUR) < 0)
        return false;

    file->rest = end - start;
    return true;
}
<|endoftext|>


<commit_before>#include "memory.hpp"
#include "memory/immix_collector.hpp"
#include "memory/immix_marker.hpp"

#include "capi/handles.hpp"
#include "capi/tag.hpp"
#include "object_watch.hpp"

#include "configuration.hpp"

#include "instruments/timing.hpp"

#include "util/logger.hpp"

#ifdef ENABLE_LLVM
#include "llvm/state.hpp"
#endif

namespace rubinius {
namespace memory {
  void ImmixGC::Diagnostics::log() {
    if(!modified_p()) return;

    diagnostics::Diagnostics::log();

    utilities::logger::write("immix: diagnostics: " \
        "collections: %ld, " \
        "objects: %ld, " \
        "bytes: %ld, " \
        "total_bytes: %ld, " \
        "chunks: %ld, " \
        "holes: %ld, " \
        "percentage: %f",
        collections_, objects_, bytes_, total_bytes_,
        chunks_, holes_, percentage_);
  }

  void ImmixGC::ObjectDescriber::added_chunk(int count) {
    if(object_memory_) {
      object_memory_->vm()->metrics().memory.immix_chunks++;

      if(gc_->dec_chunks_left() <= 0) {
        gc_->reset_chunks_left();
      }
    }
  }

  /**
   * This means we're getting low on memory! Time to schedule a garbage
   * collection.
   */
  void ImmixGC::ObjectDescriber::last_block() {
    if(object_memory_) {
      object_memory_->schedule_full_collection();
    }
  }

  void ImmixGC::ObjectDescriber::set_forwarding_pointer(memory::Address from, memory::Address to) {
    from.as<Object>()->set_forward(to.as<Object>());
  }

  ImmixGC::ImmixGC(Memory* om)
    : GarbageCollector(om)
    , allocator_(gc_.block_allocator())
    , memory_(om)
    , marker_(NULL)
    , chunks_left_(0)
    , chunks_before_collection_(10)
    , diagnostics_(Diagnostics())
  {
    gc_.describer().set_object_memory(om, this);
    reset_chunks_left();
  }

  ImmixGC::~ImmixGC() {
    if(marker_) {
      delete marker_;
    }
  }

  memory::Address ImmixGC::ObjectDescriber::copy(memory::Address original,
      ImmixAllocator& alloc) {
    Object* orig = original.as<Object>();

    bool collect_flag = false;

    memory::Address copy_addr = alloc.allocate(
        orig->size_in_bytes(object_memory_->vm()),
        collect_flag);

    if(collect_flag) {
      object_memory_->schedule_full_collection();
    }

    Object* copy = copy_addr.as<Object>();

    copy->initialize_full_state(object_memory_->vm(), orig, 0);

    copy->set_zone(MatureObjectZone);
    copy->set_in_immix();

    return copy_addr;
  }

  int ImmixGC::ObjectDescriber::size(memory::Address addr) {
    return addr.as<Object>()->size_in_bytes(object_memory_->vm());
  }

  Address ImmixGC::ObjectDescriber::update_pointer(Address addr) {
    Object* obj = addr.as<Object>();
    if(!obj) return Address::null();
    if(obj->young_object_p()) {
      if(obj->forwarded_p()) return obj->forward();
      return Address::null();
    } else {
      // we must remember this because it might
      // contain references to young gen objects
      object_memory_->remember_object(obj);
    }
    return addr;
  }

  bool ImmixGC::ObjectDescriber::mark_address(Address addr, MarkStack& ms, bool push) {
    Object* obj = addr.as<Object>();

    if(obj->marked_p(object_memory_->mark())) return false;
    obj->mark(object_memory_, object_memory_->mark());

    if(push) ms.push_back(addr);
    // If this is a young object, let the GC know not to try and mark
    // the block it's in.
    return obj->in_immix_p();
  }

  Object* ImmixGC::allocate(uint32_t bytes, bool& collect_now) {
    if(bytes > cMaxObjectSize) return 0;

    Object* obj = allocator_.allocate(bytes, collect_now).as<Object>();
    obj->init_header(MatureObjectZone, InvalidType);
    obj->set_in_immix();

    return obj;
  }

  Object* ImmixGC::move_object(Object* orig, uint32_t bytes, bool& collect_now) {
    if(bytes > cMaxObjectSize) return 0;

    Object* obj = allocator_.allocate(bytes, collect_now).as<Object>();

    memcpy(obj, orig, bytes);

    obj->set_zone(MatureObjectZone);
    obj->set_in_immix();

    orig->set_forward(obj);

    return obj;
  }

  Object* ImmixGC::saw_object(Object* obj) {
#ifdef ENABLE_OBJECT_WATCH
    if(watched_p(obj)) {
      std::cout << "detected " << obj << " during immix scanning.\n";
    }
#endif

    if(!obj->reference_p()) return NULL;

    memory::Address fwd = gc_.mark_address(memory::Address(obj), allocator_);
    Object* copy = fwd.as<Object>();

    // Check and update an inflated header
    if(copy && copy != obj) {
      obj->set_forward(copy);
      return copy;
    }

    // Always return NULL for non moved objects
    return NULL;
  }

  void ImmixGC::scanned_object(Object* obj) {
    obj->scanned();
  }

  bool ImmixGC::mature_gc_in_progress() {
    return object_memory_->mature_gc_in_progress();
  }

  ObjectPosition ImmixGC::validate_object(Object* obj) {
    if(gc_.allocated_address(memory::Address(obj))) {
      if(obj->in_immix_p()) {
        return cInImmix;
      } else {
        return cInImmixCorruptHeader;
      }
    }

    return cUnknown;
  }

  /**
   * Performs a garbage collection of the immix space.
   */
  void ImmixGC::collect(GCData* data) {
    gc_.clear_marks();
  }

  void ImmixGC::collect_start(GCData* data) {
    gc_.clear_marks();
    collect_scan(data);
    marker_->concurrent_mark(data);
  }

  void ImmixGC::collect_scan(GCData* data) {
    for(Roots::Iterator i(data->roots()); i.more(); i.advance()) {
      if(Object* fwd = saw_object(i->get())) {
        i->set(fwd);
      }
    }

    {
      utilities::thread::SpinLock::LockGuard guard(data->thread_nexus()->threads_lock());

      for(ThreadList::iterator i = data->thread_nexus()->threads()->begin();
          i != data->thread_nexus()->threads()->end();
          ++i)
      {
        scan(*i, false);
      }
    }

    for(Allocator<capi::Handle>::Iterator i(data->handles()->allocator()); i.more(); i.advance()) {
      if(i->in_use_p() && !i->weak_p()) {
        if(Object* fwd = saw_object(i->object())) {
          i->set_object(fwd);
        }
      }
    }

    std::list<capi::GlobalHandle*>* gh = data->global_handle_locations();

    if(gh) {
      for(std::list<capi::GlobalHandle*>::iterator i = gh->begin();
          i != gh->end();
          ++i) {
        capi::Handle** loc = (*i)->handle();
        if(capi::Handle* hdl = *loc) {
          if(!REFERENCE_P(hdl)) continue;
          if(hdl->valid_p()) {
            Object* obj = hdl->object();
            if(obj && obj->reference_p()) {
              if(Object* fwd = saw_object(obj)) {
                hdl->set_object(fwd);
              }
            }
          } else {
            std::cerr << "Detected bad handle checking global capi handles\n";
          }
        }
      }
    }

#ifdef ENABLE_LLVM
    if(LLVMState* ls = data->llvm_state()) ls->gc_scan(this);
#endif
  }

  void ImmixGC::collect_finish(GCData* data) {
    collect_scan(data);
    process_mark_stack();

    ObjectArray* marked_set = object_memory_->swap_marked_set();
    for(ObjectArray::iterator oi = marked_set->begin();
        oi != marked_set->end();
        ++oi) {
      Object* obj = *oi;
      if(obj) {
        if(Object* fwd = saw_object(obj)) {
          *oi = fwd;
        }
      }
    }
    delete marked_set;

    // Users manipulate values accessible from the data* within an
    // RData without running a write barrier. Thusly if we see any rdata
    // we must always scan it again here because it could contain new pointers.
    //
    // We do this in a loop because the scanning might generate new entries
    // on the mark stack.
    do {
      for(Allocator<capi::Handle>::Iterator i(data->handles()->allocator());
          i.more();
          i.advance())
      {
        capi::Handle* hdl = i.current();
        if(!hdl->in_use_p()) continue;
        if(hdl->is_rdata()) {
          Object* obj = hdl->object();
          if(obj->marked_p(object_memory_->mark())) {
            scan_object(obj);
          }
        }
      }
    } while(process_mark_stack());

    // We've now finished marking the entire object graph.
    // Clean weakrefs before keeping additional objects alive
    // for finalization, so people don't get a hold of finalized
    // objects through weakrefs.
    clean_weakrefs();

    // Marking objects to be Finalized can cause more things to continue to
    // live, so we must check the mark_stack again.
    do {
      walk_finalizers();
      scan_fibers(data, true);
    } while(process_mark_stack());

    // Remove unreachable locked objects still in the list
    {
      utilities::thread::SpinLock::LockGuard guard(data->thread_nexus()->threads_lock());

      for(ThreadList::iterator i = data->thread_nexus()->threads()->begin();
          i != data->thread_nexus()->threads()->end();
          ++i)
      {
        clean_locked_objects(*i, false);
      }
    }

    // Clear unreachable objects from the various remember sets
    unsigned int mark = object_memory_->mark();
    object_memory_->unremember_objects(mark);
  }

  void ImmixGC::sweep() {
    // Copy marks for use in new allocations
    gc_.copy_marks();

    // Sweep up the garbage
    gc_.sweep_blocks();

    // This resets the allocator state to sync it up with the BlockAllocator
    // properly.
    allocator_.get_new_block();

    {
      timer::StopWatch<timer::microseconds> timer(
          vm()->metrics().gc.immix_diagnostics_us);

      diagnostics_ = Diagnostics(diagnostics_.collections_);

      // Now, calculate how much space we're still using.
      Chunks& chunks = gc_.block_allocator().chunks();
      AllBlockIterator iter(chunks);

      diagnostics_.chunks_ = chunks.size();

      while(Block* block = iter.next()) {
        diagnostics_.holes_ += block->holes();
        diagnostics_.objects_ += block->objects();
        diagnostics_.bytes_ += block->object_bytes();
        diagnostics_.total_bytes_ += cBlockSize;
      }

      diagnostics_.percentage_ =
        (double)diagnostics_.bytes_ / (double)diagnostics_.total_bytes_;

      diagnostics_.collections_++;
      diagnostics_.modify();
    }

    if(diagnostics_.percentage_ >= 0.90) {
      gc_.block_allocator().add_chunk();
    }
  }

  void ImmixGC::start_marker(STATE) {
    if(!marker_) {
      marker_ = new ImmixMarker(state, this);
    }
  }

  bool ImmixGC::process_mark_stack() {
    bool exit = false;
    return gc_.process_mark_stack(allocator_, exit);
  }

  bool ImmixGC::process_mark_stack(bool& exit) {
    return gc_.process_mark_stack(allocator_, exit);
  }

  MarkStack& ImmixGC::mark_stack() {
    return gc_.mark_stack();
  }

  void ImmixGC::walk_finalizers() {
    FinalizerThread* fh = object_memory_->finalizer_handler();
    if(!fh) return;

    for(FinalizerThread::iterator i = fh->begin();
        !i.end();
        /* advance is handled in the loop */)
    {
      FinalizeObject& fi = i.current();

      bool live = fi.object->marked_p(object_memory_->mark());

      if(fi.ruby_finalizer) {
        if(Object* fwd = saw_object(fi.ruby_finalizer)) {
          fi.ruby_finalizer = fwd;
        }
      }

      if(Object* fwd = saw_object(fi.object)) {
        fi.object = fwd;
      }

      i.next(live);
    }
  }
}
}
<commit_msg>Fixed namespaced references to Address.<commit_after>#include "memory.hpp"
#include "memory/immix_collector.hpp"
#include "memory/immix_marker.hpp"

#include "capi/handles.hpp"
#include "capi/tag.hpp"
#include "object_watch.hpp"

#include "configuration.hpp"

#include "instruments/timing.hpp"

#include "util/logger.hpp"

#ifdef ENABLE_LLVM
#include "llvm/state.hpp"
#endif

namespace rubinius {
namespace memory {
  void ImmixGC::Diagnostics::log() {
    if(!modified_p()) return;

    diagnostics::Diagnostics::log();

    utilities::logger::write("immix: diagnostics: " \
        "collections: %ld, " \
        "objects: %ld, " \
        "bytes: %ld, " \
        "total_bytes: %ld, " \
        "chunks: %ld, " \
        "holes: %ld, " \
        "percentage: %f",
        collections_, objects_, bytes_, total_bytes_,
        chunks_, holes_, percentage_);
  }

  void ImmixGC::ObjectDescriber::added_chunk(int count) {
    if(object_memory_) {
      object_memory_->vm()->metrics().memory.immix_chunks++;

      if(gc_->dec_chunks_left() <= 0) {
        gc_->reset_chunks_left();
      }
    }
  }

  /**
   * This means we're getting low on memory! Time to schedule a garbage
   * collection.
   */
  void ImmixGC::ObjectDescriber::last_block() {
    if(object_memory_) {
      object_memory_->schedule_full_collection();
    }
  }

  void ImmixGC::ObjectDescriber::set_forwarding_pointer(Address from, Address to) {
    from.as<Object>()->set_forward(to.as<Object>());
  }

  ImmixGC::ImmixGC(Memory* om)
    : GarbageCollector(om)
    , allocator_(gc_.block_allocator())
    , memory_(om)
    , marker_(NULL)
    , chunks_left_(0)
    , chunks_before_collection_(10)
    , diagnostics_(Diagnostics())
  {
    gc_.describer().set_object_memory(om, this);
    reset_chunks_left();
  }

  ImmixGC::~ImmixGC() {
    if(marker_) {
      delete marker_;
    }
  }

  Address ImmixGC::ObjectDescriber::copy(Address original,
      ImmixAllocator& alloc) {
    Object* orig = original.as<Object>();

    bool collect_flag = false;

    Address copy_addr = alloc.allocate(
        orig->size_in_bytes(object_memory_->vm()),
        collect_flag);

    if(collect_flag) {
      object_memory_->schedule_full_collection();
    }

    Object* copy = copy_addr.as<Object>();

    copy->initialize_full_state(object_memory_->vm(), orig, 0);

    copy->set_zone(MatureObjectZone);
    copy->set_in_immix();

    return copy_addr;
  }

  int ImmixGC::ObjectDescriber::size(Address addr) {
    return addr.as<Object>()->size_in_bytes(object_memory_->vm());
  }

  Address ImmixGC::ObjectDescriber::update_pointer(Address addr) {
    Object* obj = addr.as<Object>();
    if(!obj) return Address::null();
    if(obj->young_object_p()) {
      if(obj->forwarded_p()) return obj->forward();
      return Address::null();
    } else {
      // we must remember this because it might
      // contain references to young gen objects
      object_memory_->remember_object(obj);
    }
    return addr;
  }

  bool ImmixGC::ObjectDescriber::mark_address(Address addr, MarkStack& ms, bool push) {
    Object* obj = addr.as<Object>();

    if(obj->marked_p(object_memory_->mark())) return false;
    obj->mark(object_memory_, object_memory_->mark());

    if(push) ms.push_back(addr);
    // If this is a young object, let the GC know not to try and mark
    // the block it's in.
    return obj->in_immix_p();
  }

  Object* ImmixGC::allocate(uint32_t bytes, bool& collect_now) {
    if(bytes > cMaxObjectSize) return 0;

    Object* obj = allocator_.allocate(bytes, collect_now).as<Object>();
    obj->init_header(MatureObjectZone, InvalidType);
    obj->set_in_immix();

    return obj;
  }

  Object* ImmixGC::move_object(Object* orig, uint32_t bytes, bool& collect_now) {
    if(bytes > cMaxObjectSize) return 0;

    Object* obj = allocator_.allocate(bytes, collect_now).as<Object>();

    memcpy(obj, orig, bytes);

    obj->set_zone(MatureObjectZone);
    obj->set_in_immix();

    orig->set_forward(obj);

    return obj;
  }

  Object* ImmixGC::saw_object(Object* obj) {
#ifdef ENABLE_OBJECT_WATCH
    if(watched_p(obj)) {
      std::cout << "detected " << obj << " during immix scanning.\n";
    }
#endif

    if(!obj->reference_p()) return NULL;

    Address fwd = gc_.mark_address(Address(obj), allocator_);
    Object* copy = fwd.as<Object>();

    // Check and update an inflated header
    if(copy && copy != obj) {
      obj->set_forward(copy);
      return copy;
    }

    // Always return NULL for non moved objects
    return NULL;
  }

  void ImmixGC::scanned_object(Object* obj) {
    obj->scanned();
  }

  bool ImmixGC::mature_gc_in_progress() {
    return object_memory_->mature_gc_in_progress();
  }

  ObjectPosition ImmixGC::validate_object(Object* obj) {
    if(gc_.allocated_address(Address(obj))) {
      if(obj->in_immix_p()) {
        return cInImmix;
      } else {
        return cInImmixCorruptHeader;
      }
    }

    return cUnknown;
  }

  /**
   * Performs a garbage collection of the immix space.
   */
  void ImmixGC::collect(GCData* data) {
    gc_.clear_marks();
  }

  void ImmixGC::collect_start(GCData* data) {
    gc_.clear_marks();
    collect_scan(data);
    marker_->concurrent_mark(data);
  }

  void ImmixGC::collect_scan(GCData* data) {
    for(Roots::Iterator i(data->roots()); i.more(); i.advance()) {
      if(Object* fwd = saw_object(i->get())) {
        i->set(fwd);
      }
    }

    {
      utilities::thread::SpinLock::LockGuard guard(data->thread_nexus()->threads_lock());

      for(ThreadList::iterator i = data->thread_nexus()->threads()->begin();
          i != data->thread_nexus()->threads()->end();
          ++i)
      {
        scan(*i, false);
      }
    }

    for(Allocator<capi::Handle>::Iterator i(data->handles()->allocator()); i.more(); i.advance()) {
      if(i->in_use_p() && !i->weak_p()) {
        if(Object* fwd = saw_object(i->object())) {
          i->set_object(fwd);
        }
      }
    }

    std::list<capi::GlobalHandle*>* gh = data->global_handle_locations();

    if(gh) {
      for(std::list<capi::GlobalHandle*>::iterator i = gh->begin();
          i != gh->end();
          ++i) {
        capi::Handle** loc = (*i)->handle();
        if(capi::Handle* hdl = *loc) {
          if(!REFERENCE_P(hdl)) continue;
          if(hdl->valid_p()) {
            Object* obj = hdl->object();
            if(obj && obj->reference_p()) {
              if(Object* fwd = saw_object(obj)) {
                hdl->set_object(fwd);
              }
            }
          } else {
            std::cerr << "Detected bad handle checking global capi handles\n";
          }
        }
      }
    }

#ifdef ENABLE_LLVM
    if(LLVMState* ls = data->llvm_state()) ls->gc_scan(this);
#endif
  }

  void ImmixGC::collect_finish(GCData* data) {
    collect_scan(data);
    process_mark_stack();

    ObjectArray* marked_set = object_memory_->swap_marked_set();
    for(ObjectArray::iterator oi = marked_set->begin();
        oi != marked_set->end();
        ++oi) {
      Object* obj = *oi;
      if(obj) {
        if(Object* fwd = saw_object(obj)) {
          *oi = fwd;
        }
      }
    }
    delete marked_set;

    // Users manipulate values accessible from the data* within an
    // RData without running a write barrier. Thusly if we see any rdata
    // we must always scan it again here because it could contain new pointers.
    //
    // We do this in a loop because the scanning might generate new entries
    // on the mark stack.
    do {
      for(Allocator<capi::Handle>::Iterator i(data->handles()->allocator());
          i.more();
          i.advance())
      {
        capi::Handle* hdl = i.current();
        if(!hdl->in_use_p()) continue;
        if(hdl->is_rdata()) {
          Object* obj = hdl->object();
          if(obj->marked_p(object_memory_->mark())) {
            scan_object(obj);
          }
        }
      }
    } while(process_mark_stack());

    // We've now finished marking the entire object graph.
    // Clean weakrefs before keeping additional objects alive
    // for finalization, so people don't get a hold of finalized
    // objects through weakrefs.
    clean_weakrefs();

    // Marking objects to be Finalized can cause more things to continue to
    // live, so we must check the mark_stack again.
    do {
      walk_finalizers();
      scan_fibers(data, true);
    } while(process_mark_stack());

    // Remove unreachable locked objects still in the list
    {
      utilities::thread::SpinLock::LockGuard guard(data->thread_nexus()->threads_lock());

      for(ThreadList::iterator i = data->thread_nexus()->threads()->begin();
          i != data->thread_nexus()->threads()->end();
          ++i)
      {
        clean_locked_objects(*i, false);
      }
    }

    // Clear unreachable objects from the various remember sets
    unsigned int mark = object_memory_->mark();
    object_memory_->unremember_objects(mark);
  }

  void ImmixGC::sweep() {
    // Copy marks for use in new allocations
    gc_.copy_marks();

    // Sweep up the garbage
    gc_.sweep_blocks();

    // This resets the allocator state to sync it up with the BlockAllocator
    // properly.
    allocator_.get_new_block();

    {
      timer::StopWatch<timer::microseconds> timer(
          vm()->metrics().gc.immix_diagnostics_us);

      diagnostics_ = Diagnostics(diagnostics_.collections_);

      // Now, calculate how much space we're still using.
      Chunks& chunks = gc_.block_allocator().chunks();
      AllBlockIterator iter(chunks);

      diagnostics_.chunks_ = chunks.size();

      while(Block* block = iter.next()) {
        diagnostics_.holes_ += block->holes();
        diagnostics_.objects_ += block->objects();
        diagnostics_.bytes_ += block->object_bytes();
        diagnostics_.total_bytes_ += cBlockSize;
      }

      diagnostics_.percentage_ =
        (double)diagnostics_.bytes_ / (double)diagnostics_.total_bytes_;

      diagnostics_.collections_++;
      diagnostics_.modify();
    }

    if(diagnostics_.percentage_ >= 0.90) {
      gc_.block_allocator().add_chunk();
    }
  }

  void ImmixGC::start_marker(STATE) {
    if(!marker_) {
      marker_ = new ImmixMarker(state, this);
    }
  }

  bool ImmixGC::process_mark_stack() {
    bool exit = false;
    return gc_.process_mark_stack(allocator_, exit);
  }

  bool ImmixGC::process_mark_stack(bool& exit) {
    return gc_.process_mark_stack(allocator_, exit);
  }

  MarkStack& ImmixGC::mark_stack() {
    return gc_.mark_stack();
  }

  void ImmixGC::walk_finalizers() {
    FinalizerThread* fh = object_memory_->finalizer_handler();
    if(!fh) return;

    for(FinalizerThread::iterator i = fh->begin();
        !i.end();
        /* advance is handled in the loop */)
    {
      FinalizeObject& fi = i.current();

      bool live = fi.object->marked_p(object_memory_->mark());

      if(fi.ruby_finalizer) {
        if(Object* fwd = saw_object(fi.ruby_finalizer)) {
          fi.ruby_finalizer = fwd;
        }
      }

      if(Object* fwd = saw_object(fi.object)) {
        fi.object = fwd;
      }

      i.next(live);
    }
  }
}
}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include "PlacemarkManager.h"

#include <QtCore/QBuffer>
#include <QtCore/QByteArray>
#include <QtCore/QDataStream>
#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtXml/QXmlInputSource>
#include <QtXml/QXmlSimpleReader>

#include "KmlFileViewItem.h"
#include "FileViewModel.h"
#include "MarbleDirs.h"
#include "MarblePlacemarkModel.h"
#include "MarbleGeometryModel.h"
#include "PlacemarkContainer.h"
#include "PlacemarkLoader.h"

#include "GeoDataDocument.h"
#include "GeoDataParser.h"
#include "GeoDataPlacemark.h"

using namespace Marble;

namespace Marble {
class PlacemarkManagerPrivate
{
    public:
        PlacemarkManagerPrivate( QObject* parent )
        : m_model( 0 )
        , m_geomodel( new MarbleGeometryModel() )
        , m_target( QString() )
        , m_finalized( true )
        , m_fileViewModel( new FileViewModel(parent ) )
        {
        };

        MarblePlacemarkModel* m_model;
        MarbleGeometryModel* m_geomodel;
        QList<PlacemarkLoader*> m_loaderList;
        FileViewModel* m_fileViewModel;

        bool m_finalized;
        QString m_target;
};
}

PlacemarkManager::PlacemarkManager( QObject *parent )
    : QObject( parent )
    , d( new PlacemarkManagerPrivate( parent ) )
{

}

PlacemarkManager::~PlacemarkManager()
{
    foreach( PlacemarkLoader *loader, d->m_loaderList ) {
        if ( loader ) {
            loader->wait();
        }
    }

    delete d->m_model;
    delete d->m_fileViewModel;
    delete d;
    /* do not delete the d->m_geomodel here
     * it is not this models property
     */
}

MarblePlacemarkModel* PlacemarkManager::model() const
{
    return d->m_model;
}

FileViewModel* PlacemarkManager::fileViewModel() const
{
    return d->m_fileViewModel;
}

MarbleGeometryModel* PlacemarkManager::geomodel() const
{
    return d->m_geomodel;
}

void PlacemarkManager::setGeoModel( MarbleGeometryModel * model )
{
    d->m_geomodel = model;
}

void PlacemarkManager::setPlacemarkModel( MarblePlacemarkModel *model )
{
    d->m_model = model;
}

void PlacemarkManager::clearPlacemarks()
{
    d->m_model->clearPlacemarks();
}

void PlacemarkManager::addPlacemarkFile( const QString& filepath, bool finalized )
{
    if( !(d->m_model->containers().contains( filepath ) ) ) {
        qDebug() << "adding container:" << filepath << finalized;
        PlacemarkLoader* loader = new PlacemarkLoader( this, filepath, finalized );
        connect (   loader, SIGNAL( placemarksLoaded( PlacemarkLoader*, PlacemarkContainer * ) ),
                    this, SLOT( loadPlacemarkContainer( PlacemarkLoader*, PlacemarkContainer * ) ) );
        connect (   loader, SIGNAL( placemarkLoaderFailed( PlacemarkLoader* ) ),
                    this, SLOT( cleanupLoader( PlacemarkLoader* ) ) );
        connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                    this, SIGNAL( geoDataDocumentAdded( GeoDataDocument* ) ) );
        connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                    this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
        d->m_loaderList.append( loader );
        loader->start();
    }
}

void PlacemarkManager::addGeoDataDocument( GeoDataDocument* document )
{
    AbstractFileViewItem* item = new KmlFileViewItem( *this,
                                                      *document );

    d->m_fileViewModel->append( item );
}

void PlacemarkManager::addPlacemarkData( const QString& data, const QString& key )
{
    loadKmlFromData( data, key, false );
}

void PlacemarkManager::removePlacemarkKey( const QString& key )
{
    QString nkey = key;
    qDebug() << "trying to remove file:" << key;
    for( int i = 0; i < d->m_fileViewModel->rowCount(); ++i )
    {
        if(nkey.remove(".kml").remove(".cache") == d->m_fileViewModel->data(d->m_fileViewModel->index(i, 0)).toString().remove(".kml").remove(".cache")) {
            d->m_fileViewModel->remove(d->m_fileViewModel->index(i, 0));
        }
    };
}

void PlacemarkManager::cleanupLoader( PlacemarkLoader* loader )
{
    d->m_loaderList.removeAll( loader );
    if ( loader->isFinished() ) {
         delete loader;
    }
}

void PlacemarkManager::loadPlacemarkContainer( PlacemarkLoader* loader, PlacemarkContainer * container )
{
    qDebug() << "Containername:" << container->name() << "to be finalized:" << loader->finalize() << d->m_loaderList.size();
    d->m_loaderList.removeAll( loader );
    if ( container )
    {
        d->m_model->addPlacemarks( *container, false, d->m_finalized && d->m_loaderList.isEmpty() );
    }

    if( 0 == d->m_loaderList.size() )
        emit finalize();
    if ( loader->isFinished() ) {
         delete loader;
    }
}

void PlacemarkManager::loadKml( const QString& filename, bool clearPrevious )
{
    addPlacemarkFile( filename, true );
}

void PlacemarkManager::loadKmlFromData( const QString& data, const QString& key, bool finalize )
{
    Q_ASSERT( d->m_model != 0 && "You have called loadKmlFromData before creating a model!" );

    PlacemarkContainer container;

    d->m_finalized = true;
    qDebug() << "adding container:" << key;
    PlacemarkLoader* loader = new PlacemarkLoader( this, data, key );
    connect (   loader, SIGNAL( placemarksLoaded( PlacemarkLoader*, PlacemarkContainer * ) ),
                this, SLOT( loadPlacemarkContainer( PlacemarkLoader*, PlacemarkContainer * ) ) );
    connect (   loader, SIGNAL( placemarkLoaderFailed( PlacemarkLoader* ) ),
                this, SLOT( cleanupLoader( PlacemarkLoader* ) ) );
    connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                this, SIGNAL( geoDataDocumentAdded( GeoDataDocument* ) ) );
    connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
    d->m_loaderList.append( loader );
    loader->start();
}

#include "PlacemarkManager.moc"
<commit_msg>use isEmpty() instead of compairing sizes<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include "PlacemarkManager.h"

#include <QtCore/QBuffer>
#include <QtCore/QByteArray>
#include <QtCore/QDataStream>
#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtXml/QXmlInputSource>
#include <QtXml/QXmlSimpleReader>

#include "KmlFileViewItem.h"
#include "FileViewModel.h"
#include "MarbleDirs.h"
#include "MarblePlacemarkModel.h"
#include "MarbleGeometryModel.h"
#include "PlacemarkContainer.h"
#include "PlacemarkLoader.h"

#include "GeoDataDocument.h"
#include "GeoDataParser.h"
#include "GeoDataPlacemark.h"

using namespace Marble;

namespace Marble {
class PlacemarkManagerPrivate
{
    public:
        PlacemarkManagerPrivate( QObject* parent )
        : m_model( 0 )
        , m_geomodel( new MarbleGeometryModel() )
        , m_target( QString() )
        , m_finalized( true )
        , m_fileViewModel( new FileViewModel(parent ) )
        {
        };

        MarblePlacemarkModel* m_model;
        MarbleGeometryModel* m_geomodel;
        QList<PlacemarkLoader*> m_loaderList;
        FileViewModel* m_fileViewModel;

        bool m_finalized;
        QString m_target;
};
}

PlacemarkManager::PlacemarkManager( QObject *parent )
    : QObject( parent )
    , d( new PlacemarkManagerPrivate( parent ) )
{

}

PlacemarkManager::~PlacemarkManager()
{
    foreach( PlacemarkLoader *loader, d->m_loaderList ) {
        if ( loader ) {
            loader->wait();
        }
    }

    delete d->m_model;
    delete d->m_fileViewModel;
    delete d;
    /* do not delete the d->m_geomodel here
     * it is not this models property
     */
}

MarblePlacemarkModel* PlacemarkManager::model() const
{
    return d->m_model;
}

FileViewModel* PlacemarkManager::fileViewModel() const
{
    return d->m_fileViewModel;
}

MarbleGeometryModel* PlacemarkManager::geomodel() const
{
    return d->m_geomodel;
}

void PlacemarkManager::setGeoModel( MarbleGeometryModel * model )
{
    d->m_geomodel = model;
}

void PlacemarkManager::setPlacemarkModel( MarblePlacemarkModel *model )
{
    d->m_model = model;
}

void PlacemarkManager::clearPlacemarks()
{
    d->m_model->clearPlacemarks();
}

void PlacemarkManager::addPlacemarkFile( const QString& filepath, bool finalized )
{
    if( !(d->m_model->containers().contains( filepath ) ) ) {
        qDebug() << "adding container:" << filepath << finalized;
        PlacemarkLoader* loader = new PlacemarkLoader( this, filepath, finalized );
        connect (   loader, SIGNAL( placemarksLoaded( PlacemarkLoader*, PlacemarkContainer * ) ),
                    this, SLOT( loadPlacemarkContainer( PlacemarkLoader*, PlacemarkContainer * ) ) );
        connect (   loader, SIGNAL( placemarkLoaderFailed( PlacemarkLoader* ) ),
                    this, SLOT( cleanupLoader( PlacemarkLoader* ) ) );
        connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                    this, SIGNAL( geoDataDocumentAdded( GeoDataDocument* ) ) );
        connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                    this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
        d->m_loaderList.append( loader );
        loader->start();
    }
}

void PlacemarkManager::addGeoDataDocument( GeoDataDocument* document )
{
    AbstractFileViewItem* item = new KmlFileViewItem( *this,
                                                      *document );

    d->m_fileViewModel->append( item );
}

void PlacemarkManager::addPlacemarkData( const QString& data, const QString& key )
{
    loadKmlFromData( data, key, false );
}

void PlacemarkManager::removePlacemarkKey( const QString& key )
{
    QString nkey = key;
    qDebug() << "trying to remove file:" << key;
    for( int i = 0; i < d->m_fileViewModel->rowCount(); ++i )
    {
        if(nkey.remove(".kml").remove(".cache") == d->m_fileViewModel->data(d->m_fileViewModel->index(i, 0)).toString().remove(".kml").remove(".cache")) {
            d->m_fileViewModel->remove(d->m_fileViewModel->index(i, 0));
        }
    };
}

void PlacemarkManager::cleanupLoader( PlacemarkLoader* loader )
{
    d->m_loaderList.removeAll( loader );
    if ( loader->isFinished() ) {
         delete loader;
    }
}

void PlacemarkManager::loadPlacemarkContainer( PlacemarkLoader* loader, PlacemarkContainer * container )
{
    qDebug() << "Containername:" << container->name() << "to be finalized:" << (d->m_loaderList.size() == 1) << d->m_loaderList.size();
    d->m_loaderList.removeAll( loader );
    if ( container )
    {
        d->m_model->addPlacemarks( *container, false, d->m_finalized && d->m_loaderList.isEmpty() );
    }

    if( d->m_loaderList.isEmpty() ) {
        emit finalize();
    }

    if ( loader->isFinished() ) {
         delete loader;
    }
}

void PlacemarkManager::loadKml( const QString& filename, bool clearPrevious )
{
    addPlacemarkFile( filename, true );
}

void PlacemarkManager::loadKmlFromData( const QString& data, const QString& key, bool finalize )
{
    Q_ASSERT( d->m_model != 0 && "You have called loadKmlFromData before creating a model!" );

    PlacemarkContainer container;

    d->m_finalized = true;
    qDebug() << "adding container:" << key;
    PlacemarkLoader* loader = new PlacemarkLoader( this, data, key );
    connect (   loader, SIGNAL( placemarksLoaded( PlacemarkLoader*, PlacemarkContainer * ) ),
                this, SLOT( loadPlacemarkContainer( PlacemarkLoader*, PlacemarkContainer * ) ) );
    connect (   loader, SIGNAL( placemarkLoaderFailed( PlacemarkLoader* ) ),
                this, SLOT( cleanupLoader( PlacemarkLoader* ) ) );
    connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                this, SIGNAL( geoDataDocumentAdded( GeoDataDocument* ) ) );
    connect (   loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
                this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
    d->m_loaderList.append( loader );
    loader->start();
}

#include "PlacemarkManager.moc"
<|endoftext|>


<commit_before>#include "shape/sphere.h"

namespace AT_NAME
{
	static AT_DEVICE_API void getUV(real& u, real& v, const aten::vec3& p)
	{
		auto phi = aten::asin(p.y);
		auto theta = aten::atan(p.x / p.z);

		u = (theta + AT_MATH_PI_HALF) / AT_MATH_PI;
		v = (phi + AT_MATH_PI_HALF) / AT_MATH_PI;
	}

	sphere::sphere(const aten::vec3& center, real radius, material* mtrl)
		: m_param(center, radius, mtrl)
	{
		auto _min = center - radius;
		auto _max = center + radius;

		m_aabb.init(_min, _max);
	}

	bool sphere::hit(
		const aten::ray& r,
		real t_min, real t_max,
		aten::Intersection& isect) const
	{
		bool isHit = hit(&m_param, r, t_min, t_max, &isect);

		if (isHit) {
			isect.objid = id();
			isect.mtrlid = ((material*)m_param.mtrl.ptr)->id();
		}

		return isHit;
	}

	bool AT_DEVICE_API sphere::hit(
		const aten::ShapeParameter* param,
		const aten::ray& r,
		real t_min, real t_max,
		aten::Intersection* isect)
	{
		// NOTE
		// https://www.slideshare.net/h013/edupt-kaisetsu-22852235
		// p52 - p58

		const aten::vec3 p_o = param->center - r.org;
		const real b = dot(p_o, r.dir);

		// ʎ.
		const real D4 = b * b - dot(p_o, p_o) + param->radius * param->radius;

		if (D4 < real(0)) {
			return false;
		}

		const real sqrt_D4 = aten::sqrt(D4);
		const real t1 = b - sqrt_D4;
		const real t2 = b + sqrt_D4;

#if 0
		if (t1 > AT_MATH_EPSILON) {
			isect->t = t1;
		}
		else if (t2 > AT_MATH_EPSILON) {
			isect->t = t2;
		}
		else {
			return false;
		}
#elif 1
		bool close = aten::isClose(aten::abs(b), sqrt_D4, 25000);

		if (t1 > AT_MATH_EPSILON && !close) {
			isect->t = t1;
		}
		else if (t2 > AT_MATH_EPSILON && !close) {
			isect->t = t2;
		}
		else {
			return false;
		}
#else
		if (t1 < 0 && t2 < 0) {
			return false;
		}
		else if (t1 > 0 && t2 > 0) {
			isect->t = aten::cmpMin(t1, t2);
		}
		else {
			isect->t = aten::cmpMax(t1, t2);
		}
#endif

		return true;
	}

	void sphere::evalHitResult(
		const aten::ray& r,
		aten::hitrecord& rec,
		const aten::Intersection& isect) const
	{
		evalHitResult(&m_param, r, aten::mat4(), &rec, &isect);
	}

	void sphere::evalHitResult(
		const aten::ray& r,
		const aten::mat4& mtxL2W,
		aten::hitrecord& rec,
		const aten::Intersection& isect) const
	{
		evalHitResult(&m_param, r, mtxL2W, &rec, &isect);
	}

	void sphere::evalHitResult(
		const aten::ShapeParameter* param,
		const aten::ray& r,
		aten::hitrecord* rec,
		const aten::Intersection* isect)
	{
		evalHitResult(param, r, aten::mat4(), rec, isect);
	}

	void sphere::evalHitResult(
		const aten::ShapeParameter* param,
		const aten::ray& r,
		const aten::mat4& mtxL2W,
		aten::hitrecord* rec,
		const aten::Intersection* isect)
	{
		rec->p = r.org + isect->t * r.dir;
		rec->normal = (rec->p - param->center) / param->radius; // KĖ@𓾂

		rec->objid = isect->objid;
		rec->mtrlid = isect->mtrlid;

		{
			auto tmp = param->center + aten::vec3(param->radius, 0, 0);

			auto center = mtxL2W.apply(param->center);
			tmp = mtxL2W.apply(tmp);

			auto radius = length(tmp - center);

			rec->area = 4 * AT_MATH_PI * radius * radius;
		}

		getUV(rec->u, rec->v, rec->normal);
	}

	void sphere::getSamplePosNormalArea(
		aten::hitable::SamplePosNormalPdfResult* result,
		aten::sampler* sampler) const
	{
		return getSamplePosNormalArea(result, aten::mat4::Identity, sampler);
	}

	AT_DEVICE_API void sphere::getSamplePosNormalArea(
		aten::hitable::SamplePosNormalPdfResult* result,
		const aten::ShapeParameter* param,
		aten::sampler* sampler)
	{
		getSamplePosNormalArea(result, param, aten::mat4(), sampler);
	}

	void sphere::getSamplePosNormalArea(
		aten::hitable::SamplePosNormalPdfResult* result,
		const aten::mat4& mtxL2W,
		aten::sampler* sampler) const
	{
		getSamplePosNormalArea(result, &m_param, mtxL2W, sampler);
	}

	void sphere::getSamplePosNormalArea(
		aten::hitable::SamplePosNormalPdfResult* result,
		const aten::ShapeParameter* param,
		const aten::mat4& mtxL2W,
		aten::sampler* sampler)
	{
		auto r1 = sampler->nextSample();
		auto r2 = sampler->nextSample();

		auto r = param->radius;

		auto z = real(2) * r1 - real(1); // [0,1] -> [-1, 1]

		auto sin_theta = aten::sqrt(1 - z * z);
		auto phi = 2 * AT_MATH_PI * r2;

		auto x = aten::cos(phi) * sin_theta;
		auto y = aten::sin(phi) * sin_theta;

		aten::vec3 dir = aten::vec3(x, y, z);
		dir = normalize(dir);

		auto p = dir * (r + AT_MATH_EPSILON);

		result->pos = param->center + p;

		result->nml = normalize(result->pos - param->center);

		result->area = real(1);
		{
			auto tmp = param->center + aten::vec3(param->radius, 0, 0);

			auto center = mtxL2W.apply(param->center);
			tmp = mtxL2W.apply(tmp);

			auto radius = length(tmp - center);

			result->area = 4 * AT_MATH_PI * radius * radius;
		}
	}
}
<commit_msg>Modify threshold to hit test for sphere.<commit_after>#include "shape/sphere.h"

namespace AT_NAME
{
	static AT_DEVICE_API void getUV(real& u, real& v, const aten::vec3& p)
	{
		auto phi = aten::asin(p.y);
		auto theta = aten::atan(p.x / p.z);

		u = (theta + AT_MATH_PI_HALF) / AT_MATH_PI;
		v = (phi + AT_MATH_PI_HALF) / AT_MATH_PI;
	}

	sphere::sphere(const aten::vec3& center, real radius, material* mtrl)
		: m_param(center, radius, mtrl)
	{
		auto _min = center - radius;
		auto _max = center + radius;

		m_aabb.init(_min, _max);
	}

	bool sphere::hit(
		const aten::ray& r,
		real t_min, real t_max,
		aten::Intersection& isect) const
	{
		bool isHit = hit(&m_param, r, t_min, t_max, &isect);

		if (isHit) {
			isect.objid = id();
			isect.mtrlid = ((material*)m_param.mtrl.ptr)->id();
		}

		return isHit;
	}

	bool AT_DEVICE_API sphere::hit(
		const aten::ShapeParameter* param,
		const aten::ray& r,
		real t_min, real t_max,
		aten::Intersection* isect)
	{
		// NOTE
		// https://www.slideshare.net/h013/edupt-kaisetsu-22852235
		// p52 - p58

		const aten::vec3 p_o = param->center - r.org;
		const real b = dot(p_o, r.dir);

		// ʎ.
		const real D4 = b * b - dot(p_o, p_o) + param->radius * param->radius;

		if (D4 < real(0)) {
			return false;
		}

		const real sqrt_D4 = aten::sqrt(D4);
		const real t1 = b - sqrt_D4;
		const real t2 = b + sqrt_D4;

#if 0
		if (t1 > AT_MATH_EPSILON) {
			isect->t = t1;
		}
		else if (t2 > AT_MATH_EPSILON) {
			isect->t = t2;
		}
		else {
			return false;
		}
#elif 1
		bool close = aten::isClose(aten::abs(b), sqrt_D4, 2500);

		if (t1 > AT_MATH_EPSILON && !close) {
			isect->t = t1;
		}
		else if (t2 > AT_MATH_EPSILON && !close) {
			isect->t = t2;
		}
		else {
			return false;
		}
#else
		if (t1 < 0 && t2 < 0) {
			return false;
		}
		else if (t1 > 0 && t2 > 0) {
			isect->t = aten::cmpMin(t1, t2);
		}
		else {
			isect->t = aten::cmpMax(t1, t2);
		}
#endif

		return true;
	}

	void sphere::evalHitResult(
		const aten::ray& r,
		aten::hitrecord& rec,
		const aten::Intersection& isect) const
	{
		evalHitResult(&m_param, r, aten::mat4(), &rec, &isect);
	}

	void sphere::evalHitResult(
		const aten::ray& r,
		const aten::mat4& mtxL2W,
		aten::hitrecord& rec,
		const aten::Intersection& isect) const
	{
		evalHitResult(&m_param, r, mtxL2W, &rec, &isect);
	}

	void sphere::evalHitResult(
		const aten::ShapeParameter* param,
		const aten::ray& r,
		aten::hitrecord* rec,
		const aten::Intersection* isect)
	{
		evalHitResult(param, r, aten::mat4(), rec, isect);
	}

	void sphere::evalHitResult(
		const aten::ShapeParameter* param,
		const aten::ray& r,
		const aten::mat4& mtxL2W,
		aten::hitrecord* rec,
		const aten::Intersection* isect)
	{
		rec->p = r.org + isect->t * r.dir;
		rec->normal = (rec->p - param->center) / param->radius; // KĖ@𓾂

		rec->objid = isect->objid;
		rec->mtrlid = isect->mtrlid;

		{
			auto tmp = param->center + aten::vec3(param->radius, 0, 0);

			auto center = mtxL2W.apply(param->center);
			tmp = mtxL2W.apply(tmp);

			auto radius = length(tmp - center);

			rec->area = 4 * AT_MATH_PI * radius * radius;
		}

		getUV(rec->u, rec->v, rec->normal);
	}

	void sphere::getSamplePosNormalArea(
		aten::hitable::SamplePosNormalPdfResult* result,
		aten::sampler* sampler) const
	{
		return getSamplePosNormalArea(result, aten::mat4::Identity, sampler);
	}

	AT_DEVICE_API void sphere::getSamplePosNormalArea(
		aten::hitable::SamplePosNormalPdfResult* result,
		const aten::ShapeParameter* param,
		aten::sampler* sampler)
	{
		getSamplePosNormalArea(result, param, aten::mat4(), sampler);
	}

	void sphere::getSamplePosNormalArea(
		aten::hitable::SamplePosNormalPdfResult* result,
		const aten::mat4& mtxL2W,
		aten::sampler* sampler) const
	{
		getSamplePosNormalArea(result, &m_param, mtxL2W, sampler);
	}

	void sphere::getSamplePosNormalArea(
		aten::hitable::SamplePosNormalPdfResult* result,
		const aten::ShapeParameter* param,
		const aten::mat4& mtxL2W,
		aten::sampler* sampler)
	{
		auto r1 = sampler->nextSample();
		auto r2 = sampler->nextSample();

		auto r = param->radius;

		auto z = real(2) * r1 - real(1); // [0,1] -> [-1, 1]

		auto sin_theta = aten::sqrt(1 - z * z);
		auto phi = 2 * AT_MATH_PI * r2;

		auto x = aten::cos(phi) * sin_theta;
		auto y = aten::sin(phi) * sin_theta;

		aten::vec3 dir = aten::vec3(x, y, z);
		dir = normalize(dir);

		auto p = dir * (r + AT_MATH_EPSILON);

		result->pos = param->center + p;

		result->nml = normalize(result->pos - param->center);

		result->area = real(1);
		{
			auto tmp = param->center + aten::vec3(param->radius, 0, 0);

			auto center = mtxL2W.apply(param->center);
			tmp = mtxL2W.apply(tmp);

			auto radius = length(tmp - center);

			result->area = 4 * AT_MATH_PI * radius * radius;
		}
	}
}
<|endoftext|>


<commit_before>#include <iostream>

#include "SDL.h"
#include "fxgl_controllerinput.h"

SDL_GameController* controllers[10];
int num_controllers = 0;

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    getBackendVersion
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_getBackendVersion
(JNIEnv* env, jclass clazz) {

    SDL_version linked;

    SDL_GetVersion(&linked);

    return (int)linked.patch;
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    connectControllers
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_connectControllers
(JNIEnv* env, jclass clazz) {

    SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);

    for (int i = 0; i < SDL_NumJoysticks(); ++i) {
        if (SDL_IsGameController(i)) {
            controller = SDL_GameControllerOpen(i);
            if (controller) {
                controllers[num_controllers++] = controller;
            } else {
                // TODO: add a callback with SDL_GetError() to say failed to access game controller
            }
        }
    }
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    updateState
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_updateState
(JNIEnv* env, jclass clazz, jint controller_id) {

    SDL_GameControllerUpdate();
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    isButtonPressed
 * Signature: (II)Z
 */
JNIEXPORT jboolean JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_isButtonPressed
(JNIEnv* env, jclass clazz, jint controller_id, jint button_id) {

    if (controller_id >= num_controllers) {
        return JNI_FALSE;
    }

    SDL_GameControllerButton btn = static_cast<SDL_GameControllerButton>(button_id);

    if (SDL_GameControllerGetButton(controllers[controller_id], btn)) {
        return JNI_TRUE;
    }

    return JNI_FALSE;
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    getAxis
 * Signature: (II)D
 */
JNIEXPORT jdouble JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_getAxis
(JNIEnv* env, jclass clazz, jint controller_id, jint axis_id) {

    if (controller_id >= num_controllers) {
        return 0.0;
    }

    SDL_GameControllerAxis axis = static_cast<SDL_GameControllerAxis>(axis_id);

    return (jdouble)SDL_GameControllerGetAxis(controllers[controller_id], axis);
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    disconnectControllers
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_disconnectControllers
(JNIEnv* env, jclass clazz) {

    for (int i = 0; i < num_controllers; i++) {
        SDL_GameControllerClose(controllers[i]);
    }

    SDL_Quit();
}<commit_msg>fixed not declared<commit_after>#include <iostream>

#include "SDL.h"
#include "fxgl_controllerinput.h"

SDL_GameController* controllers[10];
int num_controllers = 0;

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    getBackendVersion
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_getBackendVersion
(JNIEnv* env, jclass clazz) {

    SDL_version linked;

    SDL_GetVersion(&linked);

    return (int)linked.patch;
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    connectControllers
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_connectControllers
(JNIEnv* env, jclass clazz) {

    SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);

    for (int i = 0; i < SDL_NumJoysticks(); ++i) {
        if (SDL_IsGameController(i)) {
            SDL_GameController* controller = SDL_GameControllerOpen(i);
            if (controller) {
                controllers[num_controllers++] = controller;
            } else {
                // TODO: add a callback with SDL_GetError() to say failed to access game controller
            }
        }
    }
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    updateState
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_updateState
(JNIEnv* env, jclass clazz, jint controller_id) {

    SDL_GameControllerUpdate();
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    isButtonPressed
 * Signature: (II)Z
 */
JNIEXPORT jboolean JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_isButtonPressed
(JNIEnv* env, jclass clazz, jint controller_id, jint button_id) {

    if (controller_id >= num_controllers) {
        return JNI_FALSE;
    }

    SDL_GameControllerButton btn = static_cast<SDL_GameControllerButton>(button_id);

    if (SDL_GameControllerGetButton(controllers[controller_id], btn)) {
        return JNI_TRUE;
    }

    return JNI_FALSE;
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    getAxis
 * Signature: (II)D
 */
JNIEXPORT jdouble JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_getAxis
(JNIEnv* env, jclass clazz, jint controller_id, jint axis_id) {

    if (controller_id >= num_controllers) {
        return 0.0;
    }

    SDL_GameControllerAxis axis = static_cast<SDL_GameControllerAxis>(axis_id);

    return (jdouble)SDL_GameControllerGetAxis(controllers[controller_id], axis);
}

/*
 * Class:     com_almasb_fxgl_controllerinput_impl_GameControllerImpl
 * Method:    disconnectControllers
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_almasb_fxgl_controllerinput_impl_GameControllerImpl_disconnectControllers
(JNIEnv* env, jclass clazz) {

    for (int i = 0; i < num_controllers; i++) {
        SDL_GameControllerClose(controllers[i]);
    }

    SDL_Quit();
}<|endoftext|>