<commit_before>/***************************************************************************
   Copyright (C) 2007
   by Marco Gulino <marco@kmobiletools.org>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
 ***************************************************************************/
#include "enginedata.h"

#include "engine.h"
#include "smslist.h"
#include "contactslist.h"
#include <kabc/addressee.h>

using namespace KMobileTools;

class EngineDataPrivate {
    public:
        EngineDataPrivate() : engine(NULL), i_manufacturer(KMobileTools::Engine::Unknown) {}
        KMobileTools::Engine *engine;
        bool b_connected;                           // phone connected?
        int i_signalStrength;                       // signal strength in percent
        int i_charge;                               // charge in percent
        EngineData::ChargeType m_chargeType;        // charge type
        bool b_ringing;                             // phone is ringing?
        QString s_networkName;                      // network name
        QString s_manufacturer;                     // manufacturer raw string
        int i_manufacturer;                         // enum value?
        QString s_model;                            // phone model
        QString s_imei;                             // phone imei code
        QString s_smscenter;                        // SMS Center number
        QString s_revision;                         // Firmware revision
        KCal::Event::List *p_calendar;              // Internal Calendar Events List
        ContactsList* p_addresseeList;              // Phonebook Contacts List
        SMSList *p_smsList;                         // List of SMS fetched from the phone
};

EngineData::EngineData(KMobileTools::Engine *parentEngine)
    : QObject(parentEngine), d(new EngineDataPrivate)
{
    d->engine=parentEngine;
    if(d->engine)
        d->p_smsList=new SMSList(d->engine->objectName() );
    d->p_addresseeList = new ContactsList();
    d->p_calendar=new KCal::Event::List();

    connect( d->p_smsList, SIGNAL( added( const QByteArray& ) ), SIGNAL( smsAdded( const QByteArray& ) ) );
    connect( d->p_smsList, SIGNAL( removed( const QByteArray& ) ), SIGNAL( smsDeleted( const QByteArray& ) ) );
    connect( d->p_smsList, SIGNAL( modified( const QByteArray& ) ), SIGNAL( smsModified( const QByteArray& ) ) );

}

EngineData::~EngineData()
{
    delete d->p_smsList;
    delete d->p_calendar;
    delete d->p_addresseeList;
    delete d;
}

//KMobileTools::Engine *EngineData::engine() { return d->engine; }

#include "enginedata.moc"

QString EngineData::manufacturer() const { return d->s_manufacturer;}
void EngineData::setManufacturer(const QString &s) { d->s_manufacturer=s;}

void EngineData::setManufacturerID(int i) { d->i_manufacturer=i; }
int EngineData::manufacturerID() const { return d->i_manufacturer; }

void EngineData::setModel(const QString &s) { d->s_model=s;}
QString EngineData::model() const { return d->s_model; }

void EngineData::setIMEI(const QString &s) { d->s_imei=s;}
QString EngineData::imei() const { return d->s_imei; }

void EngineData::setSMSCenter(const QString &s) { d->s_smscenter=s;}
QString EngineData::smsCenter() const { return d->s_smscenter;}

void EngineData::setRevision(const QString &s) { d->s_revision=s;}
QString EngineData::revision() const { return d->s_revision; }

KCal::Event::List *EngineData::calendar() { return d->p_calendar; }

const SMSList* EngineData::constSMSList() const {
    return d->p_smsList;
}

SMSList* EngineData::smsList() const {
    return d->p_smsList;
}

ContactsList *EngineData::contactsList() const { return d->p_addresseeList; }

void EngineData::setContactsList( ContactsList* cl ) {
    if( cl != d->p_addresseeList )
        emit phoneBookChanged();

    d->p_addresseeList=cl;
}

void EngineData::setPhoneConnected( bool b ) {
    // did the connection state change?
    if( d->b_connected != b ) {
        if( b )
            emit connected();
        else
            emit disconnected();
    }

    d->b_connected=b;
}
bool EngineData::phoneConnected() const {
    return d->b_connected;
}

int EngineData::signalStrength() const {
    return d->i_signalStrength;
}

void EngineData::setSignalStrength( int signalStrength ) {
    if( signalStrength != d->i_signalStrength )
        emit signalStrengthChanged( signalStrength );

    d->i_signalStrength = signalStrength;
}

int EngineData::charge() const {
    return d->i_charge;
}

void EngineData::setCharge( int charge ) {
    if( charge != d->i_charge )
        emit chargeChanged( charge );

    d->i_charge = charge;
}

int EngineData::chargeType() const {
    return d->m_chargeType;
}

void EngineData::setChargeType( ChargeType chargeType ) {
    if( chargeType != d->m_chargeType )
        emit chargeTypeChanged( chargeType );

    d->m_chargeType = chargeType;
}

bool EngineData::phoneRinging() const {
    return d->b_ringing;
}

void EngineData::setPhoneRinging( bool ringing ) {
    if( ringing != d->b_ringing )
        emit EngineData::ringing( ringing );

    d->b_ringing = ringing;
}

QString EngineData::networkName() const {
    return d->s_networkName;
}

void EngineData::setNetworkName( const QString& networkName ) {
    if( networkName != d->s_networkName )
        emit networkNameChanged( networkName );

    d->s_networkName = networkName;
}
<commit_msg>comparing pointers doesn't make sense here ;)<commit_after>/***************************************************************************
   Copyright (C) 2007
   by Marco Gulino <marco@kmobiletools.org>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
 ***************************************************************************/
#include "enginedata.h"

#include "engine.h"
#include "smslist.h"
#include "contactslist.h"
#include <kabc/addressee.h>

using namespace KMobileTools;

class EngineDataPrivate {
    public:
        EngineDataPrivate() : engine(NULL), i_manufacturer(KMobileTools::Engine::Unknown) {}
        KMobileTools::Engine *engine;
        bool b_connected;                           // phone connected?
        int i_signalStrength;                       // signal strength in percent
        int i_charge;                               // charge in percent
        EngineData::ChargeType m_chargeType;        // charge type
        bool b_ringing;                             // phone is ringing?
        QString s_networkName;                      // network name
        QString s_manufacturer;                     // manufacturer raw string
        int i_manufacturer;                         // enum value?
        QString s_model;                            // phone model
        QString s_imei;                             // phone imei code
        QString s_smscenter;                        // SMS Center number
        QString s_revision;                         // Firmware revision
        KCal::Event::List *p_calendar;              // Internal Calendar Events List
        ContactsList* p_addresseeList;              // Phonebook Contacts List
        SMSList *p_smsList;                         // List of SMS fetched from the phone
};

EngineData::EngineData(KMobileTools::Engine *parentEngine)
    : QObject(parentEngine), d(new EngineDataPrivate)
{
    d->engine=parentEngine;
    if(d->engine)
        d->p_smsList=new SMSList(d->engine->objectName() );
    d->p_addresseeList = new ContactsList();
    d->p_calendar=new KCal::Event::List();

    connect( d->p_smsList, SIGNAL( added( const QByteArray& ) ), SIGNAL( smsAdded( const QByteArray& ) ) );
    connect( d->p_smsList, SIGNAL( removed( const QByteArray& ) ), SIGNAL( smsDeleted( const QByteArray& ) ) );
    connect( d->p_smsList, SIGNAL( modified( const QByteArray& ) ), SIGNAL( smsModified( const QByteArray& ) ) );

}

EngineData::~EngineData()
{
    delete d->p_smsList;
    delete d->p_calendar;
    delete d->p_addresseeList;
    delete d;
}

//KMobileTools::Engine *EngineData::engine() { return d->engine; }

#include "enginedata.moc"

QString EngineData::manufacturer() const { return d->s_manufacturer;}
void EngineData::setManufacturer(const QString &s) { d->s_manufacturer=s;}

void EngineData::setManufacturerID(int i) { d->i_manufacturer=i; }
int EngineData::manufacturerID() const { return d->i_manufacturer; }

void EngineData::setModel(const QString &s) { d->s_model=s;}
QString EngineData::model() const { return d->s_model; }

void EngineData::setIMEI(const QString &s) { d->s_imei=s;}
QString EngineData::imei() const { return d->s_imei; }

void EngineData::setSMSCenter(const QString &s) { d->s_smscenter=s;}
QString EngineData::smsCenter() const { return d->s_smscenter;}

void EngineData::setRevision(const QString &s) { d->s_revision=s;}
QString EngineData::revision() const { return d->s_revision; }

KCal::Event::List *EngineData::calendar() { return d->p_calendar; }

const SMSList* EngineData::constSMSList() const {
    return d->p_smsList;
}

SMSList* EngineData::smsList() const {
    return d->p_smsList;
}

ContactsList *EngineData::contactsList() const { return d->p_addresseeList; }

void EngineData::setContactsList( ContactsList* cl ) {
    emit phoneBookChanged();
    d->p_addresseeList=cl;
}

void EngineData::setPhoneConnected( bool b ) {
    // did the connection state change?
    if( d->b_connected != b ) {
        if( b )
            emit connected();
        else
            emit disconnected();
    }

    d->b_connected=b;
}
bool EngineData::phoneConnected() const {
    return d->b_connected;
}

int EngineData::signalStrength() const {
    return d->i_signalStrength;
}

void EngineData::setSignalStrength( int signalStrength ) {
    if( signalStrength != d->i_signalStrength )
        emit signalStrengthChanged( signalStrength );

    d->i_signalStrength = signalStrength;
}

int EngineData::charge() const {
    return d->i_charge;
}

void EngineData::setCharge( int charge ) {
    if( charge != d->i_charge )
        emit chargeChanged( charge );

    d->i_charge = charge;
}

int EngineData::chargeType() const {
    return d->m_chargeType;
}

void EngineData::setChargeType( ChargeType chargeType ) {
    if( chargeType != d->m_chargeType )
        emit chargeTypeChanged( chargeType );

    d->m_chargeType = chargeType;
}

bool EngineData::phoneRinging() const {
    return d->b_ringing;
}

void EngineData::setPhoneRinging( bool ringing ) {
    if( ringing != d->b_ringing )
        emit EngineData::ringing( ringing );

    d->b_ringing = ringing;
}

QString EngineData::networkName() const {
    return d->s_networkName;
}

void EngineData::setNetworkName( const QString& networkName ) {
    if( networkName != d->s_networkName )
        emit networkNameChanged( networkName );

    d->s_networkName = networkName;
}
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

#include "eval_state.h"
#include "game_state.h"

static const string type_names[] = {"Prep", "Catch", "Pierce", "Aura"};

void printState(const struct game_state &state) {
  cout << "Player 1" << endl;
  cout << "HP: " << static_cast<int>(state.p1.hp) << endl;
  cout << "Ammo: " << static_cast<int>(state.p1.bullets) << endl;
  cout << "Fatigue: " << static_cast<int>(state.p1.fatigue) << endl;
  cout << "Power: " << type_names[state.p1.type] << endl << endl;

  cout << "Player 2" << endl;
  cout << "HP: " << static_cast<int>(state.p2.hp) << endl;
  cout << "Ammo: " << static_cast<int>(state.p2.bullets) << endl;
  cout << "Fatigue: " << static_cast<int>(state.p2.fatigue) << endl;
  cout << "Power: " << type_names[state.p2.type] << endl << endl;

  cout << "Round " << static_cast<int>(state.round) << endl;
}

// MoonBurst is a lazy pony
static void moonburst_loop() {
  for (;;) {
    string s, p1power, p2power;
    int p1hp, p1ammo, p1fat, p2hp, p2ammo, p2fat, round;
    do {
      cin >> s;
    } while (s != "HP:" && cin);
    cin >> p1hp >> s >> p1ammo >> s >> p1fat >> p1power;
    if (p1power == "Power:") {
      cin >> p1power;
    }
    do {
      cin >> s;
    } while (s != "HP:" && cin);
    cin >> p2hp >> s >> p2ammo >> s >> p2fat >> p2power;
    if (p2power == "Power:") {
      cin >> p2power;
    }
    cin >> s >> round;
    if (!cin) {
      if (cin.eof())
        return;
      std::cerr << "NO U" << endl;
      cin.clear();
      continue;
    }
    struct game_state state1;
    state1.p1.hp = p1hp; state1.p1.bullets = p1ammo; state1.p1.fatigue = p1fat;
    state1.p2.hp = p2hp; state1.p2.bullets = p2ammo; state1.p2.fatigue = p2fat;
    if (p1power.find("Prep") != string::npos) {
      state1.p1.type = PREPARATION;
    } else if (p1power.find("Pierce") != string::npos) {
      state1.p1.type = PIERCE;
    } else if (p1power.find("Catch") != string::npos) {
      state1.p1.type = CATCH;
    } else if (p1power.find("Aura") != string::npos) {
      state1.p1.type = AURA;
    } else {
      std::cerr << "Invalid power for player 1" << endl;
    }
    if (p2power.find("Prep") != string::npos) {
      state1.p2.type = PREPARATION;
    } else if (p2power.find("Pierce") != string::npos) {
      state1.p2.type = PIERCE;
    } else if (p2power.find("Catch") != string::npos) {
      state1.p2.type = CATCH;
    } else if (p2power.find("Aura") != string::npos) {
      state1.p2.type = AURA;
    } else {
      std::cerr << "Invalid power for player 2" << endl;
    }
    state1.round = round;
    get_doubletime_strat(state1);
  }
}

// legacy code - takes states in the old format
static void solve_loop() {
  // Takes input from cin
  string argv[10];  // this array is named argv because I'm lazy
  while (true) {
    cout << "Input position:" << endl;
    cin >> argv[1] >> argv[2] >> argv[3] >> argv[4];
    cin >> argv[5] >> argv[6] >> argv[7] >> argv[8];
    cin >> argv[9];
    if (!cin) {
      if (cin.eof())
        return;  // who cares what happened
      std::cerr << "Invalid position" << endl;
      cin.clear();
      continue;
    }
    struct game_state state1;
    state1.p1.hp = stoi(argv[1]);
    state1.p1.bullets = stoi(argv[2]);
    state1.p1.fatigue = stoi(argv[3]);
    if (argv[4] == "prep") {
      state1.p1.type = PREPARATION;
    } else if (argv[4] == "catch") {
      state1.p1.type = CATCH;
    } else if (argv[4] == "pierce") {
      state1.p1.type = PIERCE;
    } else if (argv[4] == "aura") {
      state1.p1.type = AURA;
    } else {
      std::cerr << "Invalid power for player 1" << endl;
      continue;
    }

    state1.p2.hp = stoi(argv[5]);
    state1.p2.bullets = stoi(argv[6]);
    state1.p2.fatigue = stoi(argv[7]);
    if (argv[8] == "prep") {
      state1.p2.type = PREPARATION;
    } else if (argv[8] == "catch") {
      state1.p2.type = CATCH;
    } else if (argv[8] == "pierce") {
      state1.p2.type = PIERCE;
    } else if (argv[8] == "aura") {
      state1.p2.type = AURA;
    } else {
      std::cerr << "Invalid power for player 2" << endl;
      continue;
    }
    state1.round = stoi(argv[9]);
    cout << endl << "Solving position (with doubletimes):" << endl;
    printState(state1);
    get_doubletime_strat(state1);
  }
}

int main() {
  cout << "N1 bot: ver 0.2.1" << endl;
  cout << "Copy the match information from the N1 page (N1 Enhancer script"
          " compatible)" << endl;

  std::ifstream data_file("n1bot_data.bin", std::ios::in | std::ios::binary);
  if (!data_file) {
    cout << "Data file not found, generating..." << endl;
    dout.reset(new std::ofstream("n1bot_data.bin",
                                 std::ios::out | std::ios::binary));
    int type1, type2;
    for (type1 = 0; type1 < 4; ++type1) {
      for (type2 = 0; type2 < 4; ++type2) {
        struct game_state state1 = new_game(type1, type2);
        double winChance = eval_state(state1);
        cout << type_names[type1] << " v " << type_names[type2] << '\t'
             << winChance << endl;
      }
    }
    dout.reset();
  } else {
    // Read from data file
    int nstates;
    union {
      int state;
      char state_[sizeof(state)];
    };
    union {
      double winchance;
      char winchance_[sizeof(winchance)];
    };
    for (nstates = 0; ; nstates++) {
      data_file.read(state_, sizeof(state));
      data_file.read(winchance_, sizeof(winchance));
      if (!data_file)
        break;
      if (state >= 1 << 25 ||
          winchance < -0.01 ||
          winchance > 1.01) {
        std::cerr << "Data file is corrupt" << endl;
        exit(-1);
      }
      memoization[state] = winchance;
    }
    cout << "Read " << nstates << " states from data file" << endl;
  }
  cout << "Finished initializing." << endl;
  moonburst_loop();
}
<commit_msg>look for the data file next to the executable<commit_after>#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>

using std::cin;
using std::cout;
using std::endl;
using std::string;

#include "eval_state.h"
#include "game_state.h"

static const string type_names[] = {"Prep", "Catch", "Pierce", "Aura"};

void printState(const struct game_state &state) {
  cout << "Player 1" << endl;
  cout << "HP: " << static_cast<int>(state.p1.hp) << endl;
  cout << "Ammo: " << static_cast<int>(state.p1.bullets) << endl;
  cout << "Fatigue: " << static_cast<int>(state.p1.fatigue) << endl;
  cout << "Power: " << type_names[state.p1.type] << endl << endl;

  cout << "Player 2" << endl;
  cout << "HP: " << static_cast<int>(state.p2.hp) << endl;
  cout << "Ammo: " << static_cast<int>(state.p2.bullets) << endl;
  cout << "Fatigue: " << static_cast<int>(state.p2.fatigue) << endl;
  cout << "Power: " << type_names[state.p2.type] << endl << endl;

  cout << "Round " << static_cast<int>(state.round) << endl;
}

// MoonBurst is a lazy pony
static void moonburst_loop() {
  for (;;) {
    string s, p1power, p2power;
    int p1hp, p1ammo, p1fat, p2hp, p2ammo, p2fat, round;
    do {
      cin >> s;
    } while (s != "HP:" && cin);
    cin >> p1hp >> s >> p1ammo >> s >> p1fat >> p1power;
    if (p1power == "Power:") {
      cin >> p1power;
    }
    do {
      cin >> s;
    } while (s != "HP:" && cin);
    cin >> p2hp >> s >> p2ammo >> s >> p2fat >> p2power;
    if (p2power == "Power:") {
      cin >> p2power;
    }
    cin >> s >> round;
    if (!cin) {
      if (cin.eof())
        return;
      std::cerr << "NO U" << endl;
      cin.clear();
      continue;
    }
    struct game_state state1;
    state1.p1.hp = p1hp; state1.p1.bullets = p1ammo; state1.p1.fatigue = p1fat;
    state1.p2.hp = p2hp; state1.p2.bullets = p2ammo; state1.p2.fatigue = p2fat;
    if (p1power.find("Prep") != string::npos) {
      state1.p1.type = PREPARATION;
    } else if (p1power.find("Pierce") != string::npos) {
      state1.p1.type = PIERCE;
    } else if (p1power.find("Catch") != string::npos) {
      state1.p1.type = CATCH;
    } else if (p1power.find("Aura") != string::npos) {
      state1.p1.type = AURA;
    } else {
      std::cerr << "Invalid power for player 1" << endl;
    }
    if (p2power.find("Prep") != string::npos) {
      state1.p2.type = PREPARATION;
    } else if (p2power.find("Pierce") != string::npos) {
      state1.p2.type = PIERCE;
    } else if (p2power.find("Catch") != string::npos) {
      state1.p2.type = CATCH;
    } else if (p2power.find("Aura") != string::npos) {
      state1.p2.type = AURA;
    } else {
      std::cerr << "Invalid power for player 2" << endl;
    }
    state1.round = round;
    get_doubletime_strat(state1);
  }
}

// legacy code - takes states in the old format
static void solve_loop() {
  // Takes input from cin
  string argv[10];  // this array is named argv because I'm lazy
  while (true) {
    cout << "Input position:" << endl;
    cin >> argv[1] >> argv[2] >> argv[3] >> argv[4];
    cin >> argv[5] >> argv[6] >> argv[7] >> argv[8];
    cin >> argv[9];
    if (!cin) {
      if (cin.eof())
        return;  // who cares what happened
      std::cerr << "Invalid position" << endl;
      cin.clear();
      continue;
    }
    struct game_state state1;
    state1.p1.hp = stoi(argv[1]);
    state1.p1.bullets = stoi(argv[2]);
    state1.p1.fatigue = stoi(argv[3]);
    if (argv[4] == "prep") {
      state1.p1.type = PREPARATION;
    } else if (argv[4] == "catch") {
      state1.p1.type = CATCH;
    } else if (argv[4] == "pierce") {
      state1.p1.type = PIERCE;
    } else if (argv[4] == "aura") {
      state1.p1.type = AURA;
    } else {
      std::cerr << "Invalid power for player 1" << endl;
      continue;
    }

    state1.p2.hp = stoi(argv[5]);
    state1.p2.bullets = stoi(argv[6]);
    state1.p2.fatigue = stoi(argv[7]);
    if (argv[8] == "prep") {
      state1.p2.type = PREPARATION;
    } else if (argv[8] == "catch") {
      state1.p2.type = CATCH;
    } else if (argv[8] == "pierce") {
      state1.p2.type = PIERCE;
    } else if (argv[8] == "aura") {
      state1.p2.type = AURA;
    } else {
      std::cerr << "Invalid power for player 2" << endl;
      continue;
    }
    state1.round = stoi(argv[9]);
    cout << endl << "Solving position (with doubletimes):" << endl;
    printState(state1);
    get_doubletime_strat(state1);
  }
}

string dirname(string source)
{
  source.erase(std::find(source.rbegin(), source.rend(), '/').base(), source.end());
  return source;
}

int main(int argc, char** argv) {
  cout << "N1 bot: ver 0.2.1" << endl;
  cout << "Copy the match information from the N1 page (N1 Enhancer script"
          " compatible)" << endl;

  string data_path = dirname(argv[0]) + "n1bot_data.bin";

  std::ifstream data_file(data_path, std::ios::in | std::ios::binary);
  if (!data_file) {
    cout << "Data file not found, generating..." << endl;
    dout.reset(new std::ofstream("n1bot_data.bin",
                                 std::ios::out | std::ios::binary));
    int type1, type2;
    for (type1 = 0; type1 < 4; ++type1) {
      for (type2 = 0; type2 < 4; ++type2) {
        struct game_state state1 = new_game(type1, type2);
        double winChance = eval_state(state1);
        cout << type_names[type1] << " v " << type_names[type2] << '\t'
             << winChance << endl;
      }
    }
    dout.reset();
  } else {
    // Read from data file
    int nstates;
    union {
      int state;
      char state_[sizeof(state)];
    };
    union {
      double winchance;
      char winchance_[sizeof(winchance)];
    };
    for (nstates = 0; ; nstates++) {
      data_file.read(state_, sizeof(state));
      data_file.read(winchance_, sizeof(winchance));
      if (!data_file)
        break;
      if (state >= 1 << 25 ||
          winchance < -0.01 ||
          winchance > 1.01) {
        std::cerr << "Data file is corrupt" << endl;
        exit(-1);
      }
      memoization[state] = winchance;
    }
    cout << "Read " << nstates << " states from data file" << endl;
  }
  cout << "Finished initializing." << endl;
  moonburst_loop();
}
<|endoftext|>


<commit_before><commit_msg>refactor away common arguments struct and local function<commit_after><|endoftext|>


<commit_before>// Copyright 2010-2014 RethinkDB, all rights reserved.
#ifndef CLUSTERING_REACTOR_REACTOR_HPP_
#define CLUSTERING_REACTOR_REACTOR_HPP_

#include <map>
#include <vector>

#include "clustering/immediate_consistency/branch/history.hpp"
#include "clustering/immediate_consistency/query/master.hpp"
#include "clustering/reactor/blueprint.hpp"
#include "clustering/reactor/directory_echo.hpp"
#include "clustering/reactor/metadata.hpp"
#include "concurrency/watchable.hpp"
#include "containers/cow_ptr.hpp"
#include "rpc/connectivity/peer_id.hpp"
#include "rpc/semilattice/view.hpp"

class io_backender_t;
class multistore_ptr_t;
class backfill_throttler_t;

/* `reactor_t::get_progress()` will return a map with one `reactor_progress_report_t` for
each primary or secondary shard that is currently backfilling or has completed a
backfill. */
class reactor_progress_report_t {
public:
    /* `is_ready` is true if the shard is completely ready. */
    bool is_ready;

    /* `start_time` is the moment the `reactor_progress_report_t` was constructed. */
    microtime_t start_time;

    /* `backfills` contains the peer ID and progress fraction (from 0 to 1) for each
    backfill that this server is receiving for that shard. The backfills will stay even
    after `is_ready` becomes `true`, but all the progress fractions will be 1.  */
    std::vector<std::pair<peer_id_t, double> > backfills;
};

class reactor_t : public home_thread_mixin_t {
public:
    reactor_t(
            const base_path_t& base_path,
            io_backender_t *io_backender,
            mailbox_manager_t *mailbox_manager,
            const server_id_t &server_id,
            backfill_throttler_t *backfill_throttler,
            ack_checker_t *ack_checker,
            watchable_map_t<
                peer_id_t,
                directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t> >
                > *reactor_directory,
            branch_history_manager_t *branch_history_manager,
            clone_ptr_t<watchable_t<blueprint_t> > blueprint_watchable,
            multistore_ptr_t *_underlying_svs,
            perfmon_collection_t *_parent_perfmon_collection,
            rdb_context_t *) THROWS_NOTHING;

    clone_ptr_t<watchable_t<directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t> > > > get_reactor_directory();

    /* This might block */
    std::map<region_t, reactor_progress_report_t> get_progress();

private:
    /* a directory_entry_t is a sentry that in its contructor inserts an entry
     * into the directory for a role that we are performing (a role that we
     * have spawned a coroutine to perform). In its destructor it removes that
     * entry.
     */
    class directory_entry_t {
    public:
        directory_entry_t(reactor_t *, region_t);

        //Changes just the activity, leaves everything else in tact
        directory_echo_version_t set(reactor_business_card_t::activity_t);

        //XXX this is a bit of a hack that we should revisit when we know more
        directory_echo_version_t update_without_changing_id(reactor_business_card_t::activity_t);
        ~directory_entry_t();

        reactor_activity_id_t get_reactor_activity_id() const;
    private:
        reactor_t *const parent;
        const region_t region;
        reactor_activity_id_t reactor_activity_id;

        DISABLE_COPYING(directory_entry_t);
    };

    class current_role_t {
    public:
        current_role_t(blueprint_role_t r, const blueprint_t &b);
        blueprint_role_t role;
        watchable_variable_t<blueprint_t> blueprint;
        cond_t abort_roles;
    };

    /* To save typing */
    peer_id_t get_me() THROWS_NOTHING;

    void on_blueprint_changed() THROWS_NOTHING;
    void try_spawn_roles() THROWS_NOTHING;
    void run_cpu_sharded_role(
            int cpu_shard_number,
            current_role_t *role,
            const region_t& region,
            multistore_ptr_t *svs_subview,
            signal_t *interruptor,
            cond_t *abort_roles) THROWS_NOTHING;
    void run_role(
            region_t region,
            current_role_t *role,
            auto_drainer_t::lock_t keepalive) THROWS_NOTHING;

    /* Implemented in clustering/reactor/reactor_be_primary.tcc */
    void be_primary(region_t region, store_view_t *store, const clone_ptr_t<watchable_t<blueprint_t> > &,
            signal_t *interruptor) THROWS_NOTHING;

    /* A backfill candidate is a structure we use to keep track of the different
     * peers we could backfill from and what we could backfill from them to make it
     * easier to grab data from them. */
    class backfill_candidate_t {
    public:
        version_range_t version_range;
        typedef clone_ptr_t<watchable_t<boost::optional<boost::optional<backfiller_business_card_t> > > > backfiller_bcard_view_t;
        class backfill_location_t {
        public:
            backfill_location_t(const backfiller_bcard_view_t &b, peer_id_t p, reactor_activity_id_t i);
            backfiller_bcard_view_t backfiller;
            peer_id_t peer_id;
            reactor_activity_id_t activity_id;
        };

        std::vector<backfill_location_t> places_to_get_this_version;
        bool present_in_our_store;

        backfill_candidate_t(version_range_t _version_range, std::vector<backfill_location_t> _places_to_get_this_version, bool _present_in_our_store);
    };

    typedef region_map_t<backfill_candidate_t> best_backfiller_map_t;

    void update_best_backfiller(const region_map_t<version_range_t> &offered_backfill_versions,
                                const backfill_candidate_t::backfill_location_t &backfiller,
                                best_backfiller_map_t *best_backfiller_out);

    bool is_safe_for_us_to_be_primary(
        watchable_map_t<peer_id_t, cow_ptr_t<reactor_business_card_t> > *directory,
        const blueprint_t &blueprint,
        const region_t &region,
        best_backfiller_map_t *best_backfiller_out,
        branch_history_t *branch_history_to_merge_out,
        bool *should_merge_metadata);

    void is_safe_for_us_to_be_primary_helper(
        const peer_id_t &peer,
        const reactor_business_card_t &bcard,
        const region_t &region,
        best_backfiller_map_t *best_backfiller_out,
        branch_history_t *branch_history_to_merge_out,
        bool *merge_branch_history_out,
        bool *its_not_safe_out);

    static backfill_candidate_t make_backfill_candidate_from_version_range(const version_range_t &b);

    /* Implemented in clustering/reactor/reactor_be_secondary.tcc */
    bool find_broadcaster_in_directory(
        const region_t &region,
        const blueprint_t &bp,
        watchable_map_t<peer_id_t, cow_ptr_t<reactor_business_card_t> > *directory,
        clone_ptr_t<watchable_t<boost::optional<boost::optional<
            broadcaster_business_card_t> > > > *broadcaster_out);

    bool find_replier_in_directory(
        const region_t &region,
        const branch_id_t &b_id,
        const blueprint_t &bp,
        watchable_map_t<peer_id_t, cow_ptr_t<reactor_business_card_t> > *directory,
        clone_ptr_t<watchable_t<boost::optional<boost::optional<
            replier_business_card_t> > > > *replier_out,
        peer_id_t *peer_id_out,
        reactor_activity_id_t *activity_out);

    void be_secondary(region_t region, store_view_t *store, const clone_ptr_t<watchable_t<blueprint_t> > &,
            signal_t *interruptor) THROWS_NOTHING;

    /* Implemented in clustering/reactor/reactor_be_nothing.tcc */
    bool is_safe_for_us_to_be_nothing(
        watchable_map_t<peer_id_t, cow_ptr_t<reactor_business_card_t> > *directory,
        const blueprint_t &blueprint,
        const region_t &region);

    void be_nothing(region_t region, store_view_t *store, const clone_ptr_t<watchable_t<blueprint_t> > &,
            signal_t *interruptor) THROWS_NOTHING;

    static boost::optional<boost::optional<broadcaster_business_card_t> > extract_broadcaster_from_reactor_business_card_primary(
        const boost::optional<boost::optional<reactor_business_card_t::primary_t> > &bcard);

    /* Shared between all three roles (primary, secondary, nothing) */

    void wait_for_directory_acks(directory_echo_version_t, signal_t *interruptor) THROWS_ONLY(interrupted_exc_t);

    bool attempt_backfill_from_peers(
        directory_entry_t *directory_entry,
        reactor_progress_report_t *progress_tracker_on_svs_thread,
        order_source_t *order_source,
        const region_t &region,
        store_view_t *svs,
        const clone_ptr_t<watchable_t<blueprint_t> > &blueprint,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t);

    template <class activity_t>
    clone_ptr_t<watchable_t<boost::optional<boost::optional<activity_t> > > > get_directory_entry_view(peer_id_t id, const reactor_activity_id_t&);

    const base_path_t base_path;
    perfmon_collection_t *parent_perfmon_collection;
    perfmon_collection_t regions_perfmon_collection;
    perfmon_membership_t regions_perfmon_membership;

    io_backender_t *io_backender;

    mailbox_manager_t *mailbox_manager;

    server_id_t server_id;

    backfill_throttler_t *backfill_throttler;

    ack_checker_t *ack_checker;

    directory_echo_writer_t<cow_ptr_t<reactor_business_card_t> > directory_echo_writer;
    watchable_buffer_t<directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t> > >
        directory_buffer;
    directory_echo_mirror_t<cow_ptr_t<reactor_business_card_t> > directory_echo_mirror;
    branch_history_manager_t *branch_history_manager;

    clone_ptr_t<watchable_t<blueprint_t> > blueprint_watchable;

    multistore_ptr_t *underlying_svs;

    std::map<region_t, current_role_t *> current_roles;

    /* `reactor_be_primary()` and `reactor_be_secondary()` automatically maintain their
    own entries in this map. Using `one_per_thread_t` is kind of overkill here because
    it automatically switches threads to do the construction and destruction, but the
    additional overhead from the thread switches isn't a big enough cost to justify
    changing it. */
    one_per_thread_t<std::map<region_t, reactor_progress_report_t> > progress_map;

    auto_drainer_t drainer;

    watchable_t<blueprint_t>::subscription_t blueprint_subscription;
    rdb_context_t *ctx;

    DISABLE_COPYING(reactor_t);
};

template <class activity_t>
clone_ptr_t<watchable_t<boost::optional<boost::optional<activity_t> > > > reactor_t::get_directory_entry_view(peer_id_t p_id, const reactor_activity_id_t &ra_id) {
    return get_watchable_for_key(directory_echo_mirror.get_internal(), p_id)->subview(
        [this, p_id, ra_id]
        (const boost::optional<cow_ptr_t<reactor_business_card_t> > &bcard)
        -> boost::optional<boost::optional<activity_t> > {
            if (!static_cast<bool>(bcard)) {
                return boost::optional<boost::optional<activity_t> >();
            }
            reactor_business_card_t::activity_map_t::const_iterator jt =
                (*bcard)->activities.find(ra_id);
            if (jt == (*bcard)->activities.end()) {
                return boost::optional<boost::optional<activity_t> >(
                    boost::optional<activity_t>());
            }
            try {
                return boost::optional<boost::optional<activity_t> >(
                    boost::optional<activity_t>(
                        boost::get<activity_t>(jt->second.activity)));
            } catch (const boost::bad_get &) {
                crash("Tried to get an activity of an unexpected type! It is assumed "
                    "the person calling this function knows the type of the activity "
                    "they will be getting back.\n");
            }
        });
}

/* `run_until_satisfied_2` repeatedly calls the given function on the contents of the
given `watchable_map_t` and `watchable_t` until the function returns `true` or the
interruptor is pulsed. It's efficient because it only calls the function when the values
of the watchables change. */
template<class key_t, class value_t, class value2_t, class callable_t>
void run_until_satisfied_2(
        watchable_map_t<key_t, value_t> *input1,
        clone_ptr_t<watchable_t<value2_t> > input2,
        const callable_t &fun,
        signal_t *interruptor,
        int64_t nap_before_retry_ms = 0) {
    cond_t *notify = nullptr;
    typename watchable_map_t<key_t, value_t>::all_subs_t all_subs(
        input1,
        [&notify](const key_t &, const value_t *) {
            if (notify != nullptr) {
                notify->pulse_if_not_already_pulsed();
            }
        },
        false);
    typename watchable_t<value2_t>::subscription_t subs(
        [&notify]() {
            if (notify != nullptr) {
                notify->pulse_if_not_already_pulsed();
            }
        });
    {
        typename watchable_t<value2_t>::freeze_t freeze(input2);
        subs.reset(input2, &freeze);
    }
    while (true) {
        cond_t cond;
        assignment_sentry_t<cond_t *> sentry(&notify, &cond);
        bool ok;
        input2->apply_read(
            [&](const value2_t *value2) {
                ok = fun(input1, *value2);
            });
        if (ok) {
            return;
        }
        signal_timer_t timeout;
        timeout.start(nap_before_retry_ms);
        wait_interruptible(&timeout, interruptor);
        wait_interruptible(&cond, interruptor);
    }
}

#endif /* CLUSTERING_REACTOR_REACTOR_HPP_ */

<commit_msg>fixing memory corruption due to invalidated vector pointer<commit_after>// Copyright 2010-2014 RethinkDB, all rights reserved.
#ifndef CLUSTERING_REACTOR_REACTOR_HPP_
#define CLUSTERING_REACTOR_REACTOR_HPP_

#include <map>
#include <list>
#include <vector>

#include "clustering/immediate_consistency/branch/history.hpp"
#include "clustering/immediate_consistency/query/master.hpp"
#include "clustering/reactor/blueprint.hpp"
#include "clustering/reactor/directory_echo.hpp"
#include "clustering/reactor/metadata.hpp"
#include "concurrency/watchable.hpp"
#include "containers/cow_ptr.hpp"
#include "rpc/connectivity/peer_id.hpp"
#include "rpc/semilattice/view.hpp"

class io_backender_t;
class multistore_ptr_t;
class backfill_throttler_t;

/* `reactor_t::get_progress()` will return a map with one `reactor_progress_report_t` for
each primary or secondary shard that is currently backfilling or has completed a
backfill. */
class reactor_progress_report_t {
public:
    /* `is_ready` is true if the shard is completely ready. */
    bool is_ready;

    /* `start_time` is the moment the `reactor_progress_report_t` was constructed. */
    microtime_t start_time;

    /* `backfills` contains the peer ID and progress fraction (from 0 to 1) for each
    backfill that this server is receiving for that shard. The backfills will stay even
    after `is_ready` becomes `true`, but all the progress fractions will be 1.
    Warning: pointers to the members of this list are passed around, do not
    change this from a `std::list` unless you are sure you won't be invalidating
    these pointers. */
    std::list<std::pair<peer_id_t, double> > backfills;
};

class reactor_t : public home_thread_mixin_t {
public:
    reactor_t(
            const base_path_t& base_path,
            io_backender_t *io_backender,
            mailbox_manager_t *mailbox_manager,
            const server_id_t &server_id,
            backfill_throttler_t *backfill_throttler,
            ack_checker_t *ack_checker,
            watchable_map_t<
                peer_id_t,
                directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t> >
                > *reactor_directory,
            branch_history_manager_t *branch_history_manager,
            clone_ptr_t<watchable_t<blueprint_t> > blueprint_watchable,
            multistore_ptr_t *_underlying_svs,
            perfmon_collection_t *_parent_perfmon_collection,
            rdb_context_t *) THROWS_NOTHING;

    clone_ptr_t<watchable_t<directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t> > > > get_reactor_directory();

    /* This might block */
    std::map<region_t, reactor_progress_report_t> get_progress();

private:
    /* a directory_entry_t is a sentry that in its contructor inserts an entry
     * into the directory for a role that we are performing (a role that we
     * have spawned a coroutine to perform). In its destructor it removes that
     * entry.
     */
    class directory_entry_t {
    public:
        directory_entry_t(reactor_t *, region_t);

        //Changes just the activity, leaves everything else in tact
        directory_echo_version_t set(reactor_business_card_t::activity_t);

        //XXX this is a bit of a hack that we should revisit when we know more
        directory_echo_version_t update_without_changing_id(reactor_business_card_t::activity_t);
        ~directory_entry_t();

        reactor_activity_id_t get_reactor_activity_id() const;
    private:
        reactor_t *const parent;
        const region_t region;
        reactor_activity_id_t reactor_activity_id;

        DISABLE_COPYING(directory_entry_t);
    };

    class current_role_t {
    public:
        current_role_t(blueprint_role_t r, const blueprint_t &b);
        blueprint_role_t role;
        watchable_variable_t<blueprint_t> blueprint;
        cond_t abort_roles;
    };

    /* To save typing */
    peer_id_t get_me() THROWS_NOTHING;

    void on_blueprint_changed() THROWS_NOTHING;
    void try_spawn_roles() THROWS_NOTHING;
    void run_cpu_sharded_role(
            int cpu_shard_number,
            current_role_t *role,
            const region_t& region,
            multistore_ptr_t *svs_subview,
            signal_t *interruptor,
            cond_t *abort_roles) THROWS_NOTHING;
    void run_role(
            region_t region,
            current_role_t *role,
            auto_drainer_t::lock_t keepalive) THROWS_NOTHING;

    /* Implemented in clustering/reactor/reactor_be_primary.tcc */
    void be_primary(region_t region, store_view_t *store, const clone_ptr_t<watchable_t<blueprint_t> > &,
            signal_t *interruptor) THROWS_NOTHING;

    /* A backfill candidate is a structure we use to keep track of the different
     * peers we could backfill from and what we could backfill from them to make it
     * easier to grab data from them. */
    class backfill_candidate_t {
    public:
        version_range_t version_range;
        typedef clone_ptr_t<watchable_t<boost::optional<boost::optional<backfiller_business_card_t> > > > backfiller_bcard_view_t;
        class backfill_location_t {
        public:
            backfill_location_t(const backfiller_bcard_view_t &b, peer_id_t p, reactor_activity_id_t i);
            backfiller_bcard_view_t backfiller;
            peer_id_t peer_id;
            reactor_activity_id_t activity_id;
        };

        std::vector<backfill_location_t> places_to_get_this_version;
        bool present_in_our_store;

        backfill_candidate_t(version_range_t _version_range, std::vector<backfill_location_t> _places_to_get_this_version, bool _present_in_our_store);
    };

    typedef region_map_t<backfill_candidate_t> best_backfiller_map_t;

    void update_best_backfiller(const region_map_t<version_range_t> &offered_backfill_versions,
                                const backfill_candidate_t::backfill_location_t &backfiller,
                                best_backfiller_map_t *best_backfiller_out);

    bool is_safe_for_us_to_be_primary(
        watchable_map_t<peer_id_t, cow_ptr_t<reactor_business_card_t> > *directory,
        const blueprint_t &blueprint,
        const region_t &region,
        best_backfiller_map_t *best_backfiller_out,
        branch_history_t *branch_history_to_merge_out,
        bool *should_merge_metadata);

    void is_safe_for_us_to_be_primary_helper(
        const peer_id_t &peer,
        const reactor_business_card_t &bcard,
        const region_t &region,
        best_backfiller_map_t *best_backfiller_out,
        branch_history_t *branch_history_to_merge_out,
        bool *merge_branch_history_out,
        bool *its_not_safe_out);

    static backfill_candidate_t make_backfill_candidate_from_version_range(const version_range_t &b);

    /* Implemented in clustering/reactor/reactor_be_secondary.tcc */
    bool find_broadcaster_in_directory(
        const region_t &region,
        const blueprint_t &bp,
        watchable_map_t<peer_id_t, cow_ptr_t<reactor_business_card_t> > *directory,
        clone_ptr_t<watchable_t<boost::optional<boost::optional<
            broadcaster_business_card_t> > > > *broadcaster_out);

    bool find_replier_in_directory(
        const region_t &region,
        const branch_id_t &b_id,
        const blueprint_t &bp,
        watchable_map_t<peer_id_t, cow_ptr_t<reactor_business_card_t> > *directory,
        clone_ptr_t<watchable_t<boost::optional<boost::optional<
            replier_business_card_t> > > > *replier_out,
        peer_id_t *peer_id_out,
        reactor_activity_id_t *activity_out);

    void be_secondary(region_t region, store_view_t *store, const clone_ptr_t<watchable_t<blueprint_t> > &,
            signal_t *interruptor) THROWS_NOTHING;

    /* Implemented in clustering/reactor/reactor_be_nothing.tcc */
    bool is_safe_for_us_to_be_nothing(
        watchable_map_t<peer_id_t, cow_ptr_t<reactor_business_card_t> > *directory,
        const blueprint_t &blueprint,
        const region_t &region);

    void be_nothing(region_t region, store_view_t *store, const clone_ptr_t<watchable_t<blueprint_t> > &,
            signal_t *interruptor) THROWS_NOTHING;

    static boost::optional<boost::optional<broadcaster_business_card_t> > extract_broadcaster_from_reactor_business_card_primary(
        const boost::optional<boost::optional<reactor_business_card_t::primary_t> > &bcard);

    /* Shared between all three roles (primary, secondary, nothing) */

    void wait_for_directory_acks(directory_echo_version_t, signal_t *interruptor) THROWS_ONLY(interrupted_exc_t);

    bool attempt_backfill_from_peers(
        directory_entry_t *directory_entry,
        reactor_progress_report_t *progress_tracker_on_svs_thread,
        order_source_t *order_source,
        const region_t &region,
        store_view_t *svs,
        const clone_ptr_t<watchable_t<blueprint_t> > &blueprint,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t);

    template <class activity_t>
    clone_ptr_t<watchable_t<boost::optional<boost::optional<activity_t> > > > get_directory_entry_view(peer_id_t id, const reactor_activity_id_t&);

    const base_path_t base_path;
    perfmon_collection_t *parent_perfmon_collection;
    perfmon_collection_t regions_perfmon_collection;
    perfmon_membership_t regions_perfmon_membership;

    io_backender_t *io_backender;

    mailbox_manager_t *mailbox_manager;

    server_id_t server_id;

    backfill_throttler_t *backfill_throttler;

    ack_checker_t *ack_checker;

    directory_echo_writer_t<cow_ptr_t<reactor_business_card_t> > directory_echo_writer;
    watchable_buffer_t<directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t> > >
        directory_buffer;
    directory_echo_mirror_t<cow_ptr_t<reactor_business_card_t> > directory_echo_mirror;
    branch_history_manager_t *branch_history_manager;

    clone_ptr_t<watchable_t<blueprint_t> > blueprint_watchable;

    multistore_ptr_t *underlying_svs;

    std::map<region_t, current_role_t *> current_roles;

    /* `reactor_be_primary()` and `reactor_be_secondary()` automatically maintain their
    own entries in this map. Using `one_per_thread_t` is kind of overkill here because
    it automatically switches threads to do the construction and destruction, but the
    additional overhead from the thread switches isn't a big enough cost to justify
    changing it. */
    one_per_thread_t<std::map<region_t, reactor_progress_report_t> > progress_map;

    auto_drainer_t drainer;

    watchable_t<blueprint_t>::subscription_t blueprint_subscription;
    rdb_context_t *ctx;

    DISABLE_COPYING(reactor_t);
};

template <class activity_t>
clone_ptr_t<watchable_t<boost::optional<boost::optional<activity_t> > > > reactor_t::get_directory_entry_view(peer_id_t p_id, const reactor_activity_id_t &ra_id) {
    return get_watchable_for_key(directory_echo_mirror.get_internal(), p_id)->subview(
        [this, p_id, ra_id]
        (const boost::optional<cow_ptr_t<reactor_business_card_t> > &bcard)
        -> boost::optional<boost::optional<activity_t> > {
            if (!static_cast<bool>(bcard)) {
                return boost::optional<boost::optional<activity_t> >();
            }
            reactor_business_card_t::activity_map_t::const_iterator jt =
                (*bcard)->activities.find(ra_id);
            if (jt == (*bcard)->activities.end()) {
                return boost::optional<boost::optional<activity_t> >(
                    boost::optional<activity_t>());
            }
            try {
                return boost::optional<boost::optional<activity_t> >(
                    boost::optional<activity_t>(
                        boost::get<activity_t>(jt->second.activity)));
            } catch (const boost::bad_get &) {
                crash("Tried to get an activity of an unexpected type! It is assumed "
                    "the person calling this function knows the type of the activity "
                    "they will be getting back.\n");
            }
        });
}

/* `run_until_satisfied_2` repeatedly calls the given function on the contents of the
given `watchable_map_t` and `watchable_t` until the function returns `true` or the
interruptor is pulsed. It's efficient because it only calls the function when the values
of the watchables change. */
template<class key_t, class value_t, class value2_t, class callable_t>
void run_until_satisfied_2(
        watchable_map_t<key_t, value_t> *input1,
        clone_ptr_t<watchable_t<value2_t> > input2,
        const callable_t &fun,
        signal_t *interruptor,
        int64_t nap_before_retry_ms = 0) {
    cond_t *notify = nullptr;
    typename watchable_map_t<key_t, value_t>::all_subs_t all_subs(
        input1,
        [&notify](const key_t &, const value_t *) {
            if (notify != nullptr) {
                notify->pulse_if_not_already_pulsed();
            }
        },
        false);
    typename watchable_t<value2_t>::subscription_t subs(
        [&notify]() {
            if (notify != nullptr) {
                notify->pulse_if_not_already_pulsed();
            }
        });
    {
        typename watchable_t<value2_t>::freeze_t freeze(input2);
        subs.reset(input2, &freeze);
    }
    while (true) {
        cond_t cond;
        assignment_sentry_t<cond_t *> sentry(&notify, &cond);
        bool ok;
        input2->apply_read(
            [&](const value2_t *value2) {
                ok = fun(input1, *value2);
            });
        if (ok) {
            return;
        }
        signal_timer_t timeout;
        timeout.start(nap_before_retry_ms);
        wait_interruptible(&timeout, interruptor);
        wait_interruptible(&cond, interruptor);
    }
}

#endif /* CLUSTERING_REACTOR_REACTOR_HPP_ */

<|endoftext|>


<commit_before>/**
 * @author: Jeff Thompson
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_INTEREST_HPP
#define	NDN_INTEREST_HPP

#include <vector>
#include "Name.hpp"
#include "c/Interest.h"

namespace ndn {

class ExcludeEntry {
public:
  /**
   * Create an ExcludeEntry of type ndn_Exclude_ANY
   */
  ExcludeEntry()
  : type_(ndn_Exclude_ANY)
  {
  }

  /**
   * Create an ExcludeEntry of type ndn_Exclude_COMPONENT
   */
  ExcludeEntry(unsigned char *component, unsigned int componentLen)
  : type_(ndn_Exclude_COMPONENT), component_(component, component + componentLen)
  {
  }

  /**
   * Set the type in the excludeEntryStruct and to point to this component, without copying any memory.
   * WARNING: The resulting pointer in excludeEntryStruct is invalid after a further use of this object which could reallocate memory.
   * @param excludeEntryStruct the C ndn_NameComponent struct to receive the pointer.
   */
  void get(struct ndn_ExcludeEntry &excludeEntryStruct) const
  {
    excludeEntryStruct.type = type_;
    if (type_ == ndn_Exclude_COMPONENT) {
      excludeEntryStruct.componentLength = component_.size();
      excludeEntryStruct.component = (unsigned char *)&component_[0];
    }
  }

  ndn_ExcludeType getType() const { return type_; }

  const std::vector<unsigned char> &getComponent() const { return component_; }

private:
  ndn_ExcludeType type_;
  std::vector<unsigned char> component_; /**< only used if type_ is ndn_Exclude_COMPONENT */
};

class Exclude {
public:
  /**
   * Create a new Exclude with no entries.
   */
  Exclude() {
  }

  unsigned int getEntryCount() const {
    return entries_.size();
  }

  const ExcludeEntry &getEntry(unsigned int i) const { return entries_[i]; }

  /**
   * Set the excludeStruct to point to the entries in this exclude, without copying any memory.
   * WARNING: The resulting pointers in excludeStruct are invalid after a further use of this object which could reallocate memory.
   * @param excludeStruct a C ndn_Exclude struct where the entries array is already allocated.
   */
  void get(struct ndn_Exclude &excludeStruct) const;

  /**
   * Clear this exclude, and set the entries by copying from the ndn_Exclude struct.
   * @param excludeStruct a C ndn_Exclude struct
   */
  void set(struct ndn_Exclude &excludeStruct);

  /**
   * Add a new entry of type ndn_Exclude_ANY
   */
  void addAny()
  {
    entries_.push_back(ExcludeEntry());
  }

  /**
   * Add a new entry of type ndn_Exclude_COMPONENT, copying from component of length compnentLength
   */
  void addComponent(unsigned char *component, unsigned int componentLen)
  {
    entries_.push_back(ExcludeEntry(component, componentLen));
  }

  /**
   * Clear all the entries.
   */
  void clear() {
    entries_.clear();
  }

private:
	std::vector<ExcludeEntry> entries_;
};

class Interest {
public:
  void encode(std::vector<unsigned char> &output, WireFormat &wireFormat) const
  {
    wireFormat.encodeInterest(*this, output);
  }
  void encode(std::vector<unsigned char> &output) const
  {
    encode(output, BinaryXMLWireFormat::instance());
  }
  void decode(const unsigned char *input, unsigned int inputLength, WireFormat &wireFormat)
  {
    wireFormat.decodeInterest(*this, input, inputLength);
  }
  void decode(const unsigned char *input, unsigned int inputLength)
  {
    decode(input, inputLength, BinaryXMLWireFormat::instance());
  }
  void decode(const std::vector<unsigned char> &input, WireFormat &wireFormat)
  {
    decode(&input[0], input.size(), wireFormat);
  }
  void decode(const std::vector<unsigned char> &input)
  {
    decode(&input[0], input.size());
  }

  /**
   * Set the interestStruct to point to the components in this interest, without copying any memory.
   * WARNING: The resulting pointers in interestStruct are invalid after a further use of this object which could reallocate memory.
   * @param interestStruct a C ndn_Interest struct where the name components array is already allocated.
   */
  void get(struct ndn_Interest &interestStruct) const;

  Name &getName() { return name_; }
  const Name &getName() const { return name_; }

  int getMinSuffixComponents() const { return minSuffixComponents_; }

  int getMaxSuffixComponents() const { return maxSuffixComponents_; }

  const std::vector<unsigned char> getPublisherPublicKeyDigest() const { return publisherPublicKeyDigest_; }

  Exclude &getExclude() { return exclude_; }
  const Exclude &getExclude() const { return exclude_; }

  int getChildSelector() const { return childSelector_; }

  int getAnswerOriginKind() const { return answerOriginKind_; }

  int getScope() const { return scope_; }

  int getInterestLifetime() const { return interestLifetime_; }

  const std::vector<unsigned char> getNonce() const { return nonce_; }

  /**
   * Clear this interest, and set the values by copying from the interest struct.
   * @param interestStruct a C ndn_Interest struct
   */
  void set(struct ndn_Interest &interestStruct);

private:

  Name name_;
	int minSuffixComponents_;
	int maxSuffixComponents_;
	std::vector<unsigned char> publisherPublicKeyDigest_;
  Exclude exclude_;
	int childSelector_;
	int answerOriginKind_;
	int scope_;
	int interestLifetime_;
	std::vector<unsigned char> nonce_;
};

}

#endif
<commit_msg>Added setter methods.<commit_after>/**
 * @author: Jeff Thompson
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_INTEREST_HPP
#define	NDN_INTEREST_HPP

#include <vector>
#include "Name.hpp"
#include "c/Interest.h"

namespace ndn {

class ExcludeEntry {
public:
  /**
   * Create an ExcludeEntry of type ndn_Exclude_ANY
   */
  ExcludeEntry()
  : type_(ndn_Exclude_ANY)
  {
  }

  /**
   * Create an ExcludeEntry of type ndn_Exclude_COMPONENT
   */
  ExcludeEntry(unsigned char *component, unsigned int componentLen)
  : type_(ndn_Exclude_COMPONENT), component_(component, component + componentLen)
  {
  }

  /**
   * Set the type in the excludeEntryStruct and to point to this component, without copying any memory.
   * WARNING: The resulting pointer in excludeEntryStruct is invalid after a further use of this object which could reallocate memory.
   * @param excludeEntryStruct the C ndn_NameComponent struct to receive the pointer.
   */
  void get(struct ndn_ExcludeEntry &excludeEntryStruct) const
  {
    excludeEntryStruct.type = type_;
    if (type_ == ndn_Exclude_COMPONENT) {
      excludeEntryStruct.componentLength = component_.size();
      excludeEntryStruct.component = (unsigned char *)&component_[0];
    }
  }

  ndn_ExcludeType getType() const { return type_; }

  const std::vector<unsigned char> &getComponent() const { return component_; }

private:
  ndn_ExcludeType type_;
  std::vector<unsigned char> component_; /**< only used if type_ is ndn_Exclude_COMPONENT */
};

class Exclude {
public:
  /**
   * Create a new Exclude with no entries.
   */
  Exclude() {
  }

  unsigned int getEntryCount() const {
    return entries_.size();
  }

  const ExcludeEntry &getEntry(unsigned int i) const { return entries_[i]; }

  /**
   * Set the excludeStruct to point to the entries in this exclude, without copying any memory.
   * WARNING: The resulting pointers in excludeStruct are invalid after a further use of this object which could reallocate memory.
   * @param excludeStruct a C ndn_Exclude struct where the entries array is already allocated.
   */
  void get(struct ndn_Exclude &excludeStruct) const;

  /**
   * Clear this exclude, and set the entries by copying from the ndn_Exclude struct.
   * @param excludeStruct a C ndn_Exclude struct
   */
  void set(struct ndn_Exclude &excludeStruct);

  /**
   * Add a new entry of type ndn_Exclude_ANY
   */
  void addAny()
  {
    entries_.push_back(ExcludeEntry());
  }

  /**
   * Add a new entry of type ndn_Exclude_COMPONENT, copying from component of length compnentLength
   */
  void addComponent(unsigned char *component, unsigned int componentLen)
  {
    entries_.push_back(ExcludeEntry(component, componentLen));
  }

  /**
   * Clear all the entries.
   */
  void clear() {
    entries_.clear();
  }

private:
	std::vector<ExcludeEntry> entries_;
};

class Interest {
public:
  void encode(std::vector<unsigned char> &output, WireFormat &wireFormat) const
  {
    wireFormat.encodeInterest(*this, output);
  }
  void encode(std::vector<unsigned char> &output) const
  {
    encode(output, BinaryXMLWireFormat::instance());
  }
  void decode(const unsigned char *input, unsigned int inputLength, WireFormat &wireFormat)
  {
    wireFormat.decodeInterest(*this, input, inputLength);
  }
  void decode(const unsigned char *input, unsigned int inputLength)
  {
    decode(input, inputLength, BinaryXMLWireFormat::instance());
  }
  void decode(const std::vector<unsigned char> &input, WireFormat &wireFormat)
  {
    decode(&input[0], input.size(), wireFormat);
  }
  void decode(const std::vector<unsigned char> &input)
  {
    decode(&input[0], input.size());
  }

  /**
   * Set the interestStruct to point to the components in this interest, without copying any memory.
   * WARNING: The resulting pointers in interestStruct are invalid after a further use of this object which could reallocate memory.
   * @param interestStruct a C ndn_Interest struct where the name components array is already allocated.
   */
  void get(struct ndn_Interest &interestStruct) const;

  Name &getName() { return name_; }
  const Name &getName() const { return name_; }

  int getMinSuffixComponents() const { return minSuffixComponents_; }

  int getMaxSuffixComponents() const { return maxSuffixComponents_; }

  const std::vector<unsigned char> getPublisherPublicKeyDigest() const { return publisherPublicKeyDigest_; }

  Exclude &getExclude() { return exclude_; }
  const Exclude &getExclude() const { return exclude_; }

  int getChildSelector() const { return childSelector_; }

  int getAnswerOriginKind() const { return answerOriginKind_; }

  int getScope() const { return scope_; }

  int getInterestLifetime() const { return interestLifetime_; }

  const std::vector<unsigned char> getNonce() const { return nonce_; }

  /**
   * Clear this interest, and set the values by copying from the interest struct.
   * @param interestStruct a C ndn_Interest struct
   */
  void set(struct ndn_Interest &interestStruct);

  void setMinSuffixComponents(int value) { minSuffixComponents_ = value; }

  void setMaxSuffixComponents(int value) { maxSuffixComponents_ = value; }

  void setPublisherPublicKeyDigest(const std::vector<unsigned char> &value) { publisherPublicKeyDigest_ = value; }

  void setChildSelector(int value) { childSelector_ = value; }

  void setAnswerOriginKind(int value) { answerOriginKind_ = value; }

  void setScope(int value) { scope_ = value; }

  void setInterestLifetime(int value) { interestLifetime_ = value; }

  void setNonce(const std::vector<unsigned char> &value) { nonce_ = value; }

private:

  Name name_;
	int minSuffixComponents_;
	int maxSuffixComponents_;
	std::vector<unsigned char> publisherPublicKeyDigest_;
  Exclude exclude_;
	int childSelector_;
	int answerOriginKind_;
	int scope_;
	int interestLifetime_;
	std::vector<unsigned char> nonce_;
};

}

#endif
<|endoftext|>


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

#include <string>
#include <vector>
#include <cmath>
#include <x86intrin.h>
#include <omp.h>
using std::string;
using std::vector;
using std::make_pair;
using std::pow;
using std::ceil;

#include <Observation.hpp>
using AstroData::Observation;

#ifndef FOLDING_CPU_HPP
#define FOLDING_CPU_HPP

namespace PulsarSearch {

// OpenMP folding algorithm
template< typename T > void folding(const unsigned int second, const Observation< T > & observation, const T * const __restrict__ samples, T * const __restrict__ bins, unsigned int * const __restrict__ counters);

// Implementation
template< typename T > void folding(const unsigned int second, const Observation< T > & observation, const T * const __restrict__ samples, T * const __restrict__ bins, unsigned int * const __restrict__ counters) {
	for ( unsigned int globalSample = 0; globalSample < observation.getNrSamplesPerSecond(); globalSample++ ) {
		const unsigned int sample = ( second * observation.getNrSamplesPerSecond() ) + globalSample;

		#pragma omp parallel for schedule(static)
		for ( unsigned int periodIndex = 0; periodIndex < observation.getNrPeriods(); periodIndex++ ) {
			const unsigned int periodValue = observation.getNrBins() * (periodIndex + 1);
			const float phase = ( sample / static_cast< float >(periodValue) ) - ( sample / periodValue );
			const unsigned int bin = static_cast< unsigned int >(phase * static_cast< float >(observation.getNrBins()));

			#pragma omp parallel for schedule(static)
			for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
				const unsigned int globalItem = (bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (periodIndex * observation.getNrPaddedDMs()) + dm;
				T cValue = samples[(globalSample * observation.getNrPaddedDMs()) + dm];
				const unsigned int pCounter = counters[globalItem];
				const T pValue = bins[globalItem];
				unsigned int cCounter = pCounter + 1;

				if ( pCounter != 0 ) {
					cValue = pValue + ( ( cValue - pValue ) / cCounter );
				}
				bins[globalItem] = cValue;
				counters[globalItem] = cCounter;
			}
		}
	}
}

} // PulsarSearch

#endif // FOLDING_CPU_HPP<commit_msg>Implemented a second algorithm for the CPU. This algorithm matches the OpenCL implementation.<commit_after>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <string>
#include <vector>
#include <cmath>
#include <x86intrin.h>
#include <omp.h>
using std::string;
using std::vector;
using std::make_pair;
using std::pow;
using std::ceil;

#include <Observation.hpp>
using AstroData::Observation;

#ifndef FOLDING_CPU_HPP
#define FOLDING_CPU_HPP

namespace PulsarSearch {

// OpenMP folding algorithm
template< typename T > void folding(const unsigned int second, const Observation< T > & observation, const T * const __restrict__ samples, T * const __restrict__ bins, unsigned int * const __restrict__ counters);
template< typename T > void folding(const Observation< T > & observation, const T * const __restrict__ samples, T * const __restrict__ bins, unsigned int * const __restrict__ counters);

// Implementation
template< typename T > void folding(const unsigned int second, const Observation< T > & observation, const T * const __restrict__ samples, T * const __restrict__ bins, unsigned int * const __restrict__ counters) {
	for ( unsigned int globalSample = 0; globalSample < observation.getNrSamplesPerSecond(); globalSample++ ) {
		const unsigned int sample = ( second * observation.getNrSamplesPerSecond() ) + globalSample;

		#pragma omp parallel for schedule(static)
		for ( unsigned int periodIndex = 0; periodIndex < observation.getNrPeriods(); periodIndex++ ) {
			const unsigned int periodValue = observation.getNrBins() * (periodIndex + 1);
			const float phase = ( sample / static_cast< float >(periodValue) ) - ( sample / periodValue );
			const unsigned int bin = static_cast< unsigned int >(phase * static_cast< float >(observation.getNrBins()));

			#pragma omp parallel for schedule(static)
			for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
				const unsigned int globalItem = (bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (periodIndex * observation.getNrPaddedDMs()) + dm;
				T cValue = samples[(globalSample * observation.getNrPaddedDMs()) + dm];
				const unsigned int pCounter = counters[globalItem];
				const T pValue = bins[globalItem];
				unsigned int cCounter = pCounter + 1;

				if ( pCounter != 0 ) {
					cValue = pValue + ( ( cValue - pValue ) / cCounter );
				}
				bins[globalItem] = cValue;
				counters[globalItem] = cCounter;
			}
		}
	}
}

template< typename T > void folding(const Observation< T > & observation, const T * const __restrict__ samples, T * const __restrict__ bins, unsigned int * const __restrict__ counters) {
	#pragma omp parallel for schedule(static)
	for ( unsigned int periodIndex = 0; periodIndex < observation.getNrPeriods(); periodIndex++ ) {
		unsigned int periodValue = (periodIndex + 1) * observation.getNrBins();

		for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
			for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
				const unsigned int pCounter = counters[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (periodIndex * observation.getNrPaddedDMs()) + dm];
				unsigned int sample = (bin * periodIndex) + bin + ((pCounter / (periodIndex + 1)) * periodValue) + (pCounter % (periodIndex + 1));
				T foldedSample = 0;
				unsigned int foldedCounter = 0;

				if ( (sample % observation.getNrSamplesPerSecond()) == 0 ) {
					sample = 0;
				} else {
					sample = (sample % observation.getNrSamplesPerSecond()) - (sample / observation.getNrSamplesPerSecond());
				}
				while ( sample < observation.getNrSamplesPerSecond() ) {
					foldedSample += samples[(sample * observation.getNrPaddedDMs()) + dm];
					foldedCounter++;

					if ( (foldedCounter + pCounter) % (periodIndex + 1) == 0 ) {
						sample += periodValue;
					} else {
						sample++;
					}
				}

				if ( foldedCounter > 0 ) {
					const T pValue = bins[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (periodIndex * observation.getNrPaddedDMs()) + dm];
					float addedFraction = static_cast< float >(foldedCounter) / (foldedCounter + pCounter);

					foldedSample /= foldedCounter;
					counters[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (periodIndex * observation.getNrPaddedDMs()) + dm] = pCounter + foldedCounter;
					bins[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (periodIndex * observation.getNrPaddedDMs()) + dm] = (addedFraction * foldedSample) + ((1.0f - addedFraction) * pValue);
				}
			}
		}
	}
}

} // PulsarSearch

#endif // FOLDING_CPU_HPP<|endoftext|>


<commit_before>//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FixedVector_unittest:
//   Tests of the FastVector class
//

#include <gtest/gtest.h>

#include "common/FastVector.h"

namespace angle
{
// Make sure the various constructors compile and do basic checks
TEST(FastVector, Constructors)
{
    FastVector<int, 5> defaultContructor;
    EXPECT_EQ(0u, defaultContructor.size());

    FastVector<int, 5> count(3);
    EXPECT_EQ(3u, count.size());

    FastVector<int, 5> countAndValue(3, 2);
    EXPECT_EQ(3u, countAndValue.size());
    EXPECT_EQ(2, countAndValue[1]);

    FastVector<int, 5> copy(countAndValue);
    EXPECT_EQ(copy, countAndValue);

    FastVector<int, 5> copyRValue(std::move(count));
    EXPECT_EQ(3u, copyRValue.size());

    FastVector<int, 5> initializerList{1, 2, 3, 4, 5};
    EXPECT_EQ(5u, initializerList.size());
    EXPECT_EQ(3, initializerList[2]);

    FastVector<int, 5> assignCopy(copyRValue);
    EXPECT_EQ(3u, assignCopy.size());

    FastVector<int, 5> assignRValue(std::move(assignCopy));
    EXPECT_EQ(3u, assignRValue.size());

    FastVector<int, 5> assignmentInitializerList = {1, 2, 3, 4, 5};
    EXPECT_EQ(5u, assignmentInitializerList.size());
    EXPECT_EQ(3, assignmentInitializerList[2]);
}

// Test indexing operations (at, operator[])
TEST(FastVector, Indexing)
{
    FastVector<int, 5> vec = {0, 1, 2, 3, 4};
    for (int i = 0; i < 5; ++i)
    {
        EXPECT_EQ(i, vec.at(i));
        EXPECT_EQ(vec[i], vec.at(i));
    }
}

// Test the push_back functions
TEST(FastVector, PushBack)
{
    FastVector<int, 5> vec;
    vec.push_back(1);
    EXPECT_EQ(1, vec[0]);
    vec.push_back(1);
    vec.push_back(1);
    vec.push_back(1);
    vec.push_back(1);
    EXPECT_EQ(5u, vec.size());
}

// Tests growing the fast vector beyond the fixed storage.
TEST(FastVector, Growth)
{
    constexpr size_t kSize = 4;
    FastVector<size_t, kSize> vec;

    for (size_t i = 0; i < kSize * 2; ++i)
    {
        vec.push_back(i);
    }

    EXPECT_EQ(kSize * 2, vec.size());

    for (size_t i = kSize * 2; i > 0; --i)
    {
        ASSERT_EQ(vec.back(), i - 1);
        vec.pop_back();
    }

    EXPECT_EQ(0u, vec.size());
}

// Test the pop_back function
TEST(FastVector, PopBack)
{
    FastVector<int, 5> vec;
    vec.push_back(1);
    EXPECT_EQ(1, (int)vec.size());
    vec.pop_back();
    EXPECT_EQ(0, (int)vec.size());
}

// Test the back function
TEST(FastVector, Back)
{
    FastVector<int, 5> vec;
    vec.push_back(1);
    vec.push_back(2);
    EXPECT_EQ(2, vec.back());
}

// Test the back function
TEST(FastVector, Front)
{
    FastVector<int, 5> vec;
    vec.push_back(1);
    vec.push_back(2);
    EXPECT_EQ(1, vec.front());
}

// Test the sizing operations
TEST(FastVector, Size)
{
    FastVector<int, 5> vec;
    EXPECT_TRUE(vec.empty());
    EXPECT_EQ(0u, vec.size());

    vec.push_back(1);
    EXPECT_FALSE(vec.empty());
    EXPECT_EQ(1u, vec.size());
}

// Test clearing the vector
TEST(FastVector, Clear)
{
    FastVector<int, 5> vec = {0, 1, 2, 3, 4};
    vec.clear();
    EXPECT_TRUE(vec.empty());
}

// Test clearing the vector larger than the fixed size.
TEST(FastVector, ClearWithLargerThanFixedSize)
{
    FastVector<int, 3> vec = {0, 1, 2, 3, 4};
    vec.clear();
    EXPECT_TRUE(vec.empty());
}

// Test resizing the vector
TEST(FastVector, Resize)
{
    FastVector<int, 5> vec;
    vec.resize(5u, 1);
    EXPECT_EQ(5u, vec.size());
    for (int i : vec)
    {
        EXPECT_EQ(1, i);
    }

    vec.resize(2u);
    EXPECT_EQ(2u, vec.size());
    for (int i : vec)
    {
        EXPECT_EQ(1, i);
    }

    // Resize to larger than minimum
    vec.resize(10u, 2);
    EXPECT_EQ(10u, vec.size());

    for (size_t index = 0; index < 2u; ++index)
    {
        EXPECT_EQ(1, vec[index]);
    }
    for (size_t index = 2u; index < 10u; ++index)
    {
        EXPECT_EQ(2, vec[index]);
    }

    // Resize back to smaller
    vec.resize(2u, 2);
    EXPECT_EQ(2u, vec.size());
}

// Test iterating over the vector
TEST(FastVector, Iteration)
{
    FastVector<int, 5> vec = {0, 1, 2, 3};

    int vistedCount = 0;
    for (int value : vec)
    {
        EXPECT_EQ(vistedCount, value);
        vistedCount++;
    }
    EXPECT_EQ(4, vistedCount);
}

// Tests that equality comparisons work even if reserved size differs.
TEST(FastVector, EqualityWithDifferentReservedSizes)
{
    FastVector<int, 3> vec1 = {1, 2, 3, 4, 5};
    FastVector<int, 5> vec2 = {1, 2, 3, 4, 5};
    EXPECT_EQ(vec1, vec2);
    vec2.push_back(6);
    EXPECT_NE(vec1, vec2);
}

// Tests vector operations with a non copyable type.
TEST(FastVector, NonCopyable)
{
    struct s : angle::NonCopyable
    {
        s() : x(0) {}
        s(int xin) : x(xin) {}
        s(s &&other) : x(other.x) {}
        s &operator=(s &&other)
        {
            x = other.x;
            return *this;
        }
        int x;
    };

    FastVector<s, 3> vec;
    vec.push_back(3);
    EXPECT_EQ(3, vec[0].x);

    FastVector<s, 3> copy = std::move(vec);
    EXPECT_EQ(1u, copy.size());
    EXPECT_EQ(3, copy[0].x);
}

// Basic functionality for FastUnorderedMap
TEST(FastUnorderedMap, BasicUsage)
{
    FastUnorderedMap<int, bool, 3> testMap;
    EXPECT_TRUE(testMap.empty());
    EXPECT_EQ(testMap.size(), 0u);

    testMap.insert(5, true);
    EXPECT_TRUE(testMap.contains(5));
    EXPECT_EQ(testMap.size(), 1u);

    bool value = false;
    EXPECT_TRUE(testMap.get(5, &value));
    EXPECT_TRUE(value);
    EXPECT_FALSE(testMap.get(6, &value));

    EXPECT_FALSE(testMap.empty());
    testMap.clear();
    EXPECT_TRUE(testMap.empty());
    EXPECT_EQ(testMap.size(), 0u);

    for (int i = 0; i < 10; ++i)
    {
        testMap.insert(i, false);
    }

    EXPECT_FALSE(testMap.empty());
    EXPECT_EQ(testMap.size(), 10u);

    for (int i = 0; i < 10; ++i)
    {
        EXPECT_TRUE(testMap.contains(i));
        EXPECT_TRUE(testMap.get(i, &value));
        EXPECT_FALSE(value);
    }
}

// Basic functionality for FastUnorderedSet
TEST(FastUnorderedSet, BasicUsage)
{
    FastUnorderedSet<int, 3> testMap;
    EXPECT_TRUE(testMap.empty());

    testMap.insert(5);
    EXPECT_TRUE(testMap.contains(5));
    EXPECT_FALSE(testMap.contains(6));
    EXPECT_FALSE(testMap.empty());

    testMap.clear();
    EXPECT_TRUE(testMap.empty());

    for (int i = 0; i < 10; ++i)
    {
        testMap.insert(i);
    }

    for (int i = 0; i < 10; ++i)
    {
        EXPECT_TRUE(testMap.contains(i));
    }
}

// Basic functionality for FastIntegerSet
TEST(FastIntegerSet, BasicUsage)
{
    FastIntegerSet testMap;
    EXPECT_TRUE(testMap.empty());

    testMap.insert(5);
    EXPECT_TRUE(testMap.contains(5));
    EXPECT_FALSE(testMap.contains(6));
    EXPECT_FALSE(testMap.empty());

    testMap.clear();
    EXPECT_TRUE(testMap.empty());

    for (int i = 0; i < 10; ++i)
    {
        testMap.insert(i);
    }

    for (int i = 0; i < 10; ++i)
    {
        EXPECT_TRUE(testMap.contains(i));
    }
}

// Basic functionality for FastIntegerMap
TEST(FastIntegerMap, BasicUsage)
{
    using KeyValuePair             = std::pair<int, std::string>;
    std::set<KeyValuePair> entries = {KeyValuePair(17, "testing"), KeyValuePair(63, "fast"),
                                      KeyValuePair(97, "integer"), KeyValuePair(256, "map")};

    FastIntegerMap<std::string> testMap;
    EXPECT_TRUE(testMap.empty());

    std::string str;
    testMap.insert(entries.begin()->first, entries.begin()->second);
    EXPECT_TRUE(testMap.contains(entries.begin()->first));
    EXPECT_FALSE(testMap.contains(entries.end()->first));
    EXPECT_FALSE(testMap.empty());
    EXPECT_EQ(testMap.size(), 1u);
    EXPECT_TRUE(testMap.get(entries.begin()->first, &str));
    EXPECT_EQ(entries.begin()->second, str);
    EXPECT_FALSE(testMap.get(1, &str));

    testMap.clear();
    EXPECT_TRUE(testMap.empty());
    EXPECT_EQ(testMap.size(), 0u);

    for (KeyValuePair entry : entries)
    {
        testMap.insert(entry.first, entry.second);
    }
    EXPECT_EQ(testMap.size(), 4u);

    for (KeyValuePair entry : entries)
    {
        std::string str;
        EXPECT_TRUE(testMap.get(entry.first, &str));
        EXPECT_EQ(entry.second, str);
    }

    testMap.clear();
    EXPECT_TRUE(testMap.empty());
    EXPECT_EQ(testMap.size(), 0u);
}
}  // namespace angle
<commit_msg>Fix ASAN issue with FastIntegerMap.BasicUsage<commit_after>//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FixedVector_unittest:
//   Tests of the FastVector class
//

#include <gtest/gtest.h>

#include "common/FastVector.h"

namespace angle
{
// Make sure the various constructors compile and do basic checks
TEST(FastVector, Constructors)
{
    FastVector<int, 5> defaultContructor;
    EXPECT_EQ(0u, defaultContructor.size());

    FastVector<int, 5> count(3);
    EXPECT_EQ(3u, count.size());

    FastVector<int, 5> countAndValue(3, 2);
    EXPECT_EQ(3u, countAndValue.size());
    EXPECT_EQ(2, countAndValue[1]);

    FastVector<int, 5> copy(countAndValue);
    EXPECT_EQ(copy, countAndValue);

    FastVector<int, 5> copyRValue(std::move(count));
    EXPECT_EQ(3u, copyRValue.size());

    FastVector<int, 5> initializerList{1, 2, 3, 4, 5};
    EXPECT_EQ(5u, initializerList.size());
    EXPECT_EQ(3, initializerList[2]);

    FastVector<int, 5> assignCopy(copyRValue);
    EXPECT_EQ(3u, assignCopy.size());

    FastVector<int, 5> assignRValue(std::move(assignCopy));
    EXPECT_EQ(3u, assignRValue.size());

    FastVector<int, 5> assignmentInitializerList = {1, 2, 3, 4, 5};
    EXPECT_EQ(5u, assignmentInitializerList.size());
    EXPECT_EQ(3, assignmentInitializerList[2]);
}

// Test indexing operations (at, operator[])
TEST(FastVector, Indexing)
{
    FastVector<int, 5> vec = {0, 1, 2, 3, 4};
    for (int i = 0; i < 5; ++i)
    {
        EXPECT_EQ(i, vec.at(i));
        EXPECT_EQ(vec[i], vec.at(i));
    }
}

// Test the push_back functions
TEST(FastVector, PushBack)
{
    FastVector<int, 5> vec;
    vec.push_back(1);
    EXPECT_EQ(1, vec[0]);
    vec.push_back(1);
    vec.push_back(1);
    vec.push_back(1);
    vec.push_back(1);
    EXPECT_EQ(5u, vec.size());
}

// Tests growing the fast vector beyond the fixed storage.
TEST(FastVector, Growth)
{
    constexpr size_t kSize = 4;
    FastVector<size_t, kSize> vec;

    for (size_t i = 0; i < kSize * 2; ++i)
    {
        vec.push_back(i);
    }

    EXPECT_EQ(kSize * 2, vec.size());

    for (size_t i = kSize * 2; i > 0; --i)
    {
        ASSERT_EQ(vec.back(), i - 1);
        vec.pop_back();
    }

    EXPECT_EQ(0u, vec.size());
}

// Test the pop_back function
TEST(FastVector, PopBack)
{
    FastVector<int, 5> vec;
    vec.push_back(1);
    EXPECT_EQ(1, (int)vec.size());
    vec.pop_back();
    EXPECT_EQ(0, (int)vec.size());
}

// Test the back function
TEST(FastVector, Back)
{
    FastVector<int, 5> vec;
    vec.push_back(1);
    vec.push_back(2);
    EXPECT_EQ(2, vec.back());
}

// Test the back function
TEST(FastVector, Front)
{
    FastVector<int, 5> vec;
    vec.push_back(1);
    vec.push_back(2);
    EXPECT_EQ(1, vec.front());
}

// Test the sizing operations
TEST(FastVector, Size)
{
    FastVector<int, 5> vec;
    EXPECT_TRUE(vec.empty());
    EXPECT_EQ(0u, vec.size());

    vec.push_back(1);
    EXPECT_FALSE(vec.empty());
    EXPECT_EQ(1u, vec.size());
}

// Test clearing the vector
TEST(FastVector, Clear)
{
    FastVector<int, 5> vec = {0, 1, 2, 3, 4};
    vec.clear();
    EXPECT_TRUE(vec.empty());
}

// Test clearing the vector larger than the fixed size.
TEST(FastVector, ClearWithLargerThanFixedSize)
{
    FastVector<int, 3> vec = {0, 1, 2, 3, 4};
    vec.clear();
    EXPECT_TRUE(vec.empty());
}

// Test resizing the vector
TEST(FastVector, Resize)
{
    FastVector<int, 5> vec;
    vec.resize(5u, 1);
    EXPECT_EQ(5u, vec.size());
    for (int i : vec)
    {
        EXPECT_EQ(1, i);
    }

    vec.resize(2u);
    EXPECT_EQ(2u, vec.size());
    for (int i : vec)
    {
        EXPECT_EQ(1, i);
    }

    // Resize to larger than minimum
    vec.resize(10u, 2);
    EXPECT_EQ(10u, vec.size());

    for (size_t index = 0; index < 2u; ++index)
    {
        EXPECT_EQ(1, vec[index]);
    }
    for (size_t index = 2u; index < 10u; ++index)
    {
        EXPECT_EQ(2, vec[index]);
    }

    // Resize back to smaller
    vec.resize(2u, 2);
    EXPECT_EQ(2u, vec.size());
}

// Test iterating over the vector
TEST(FastVector, Iteration)
{
    FastVector<int, 5> vec = {0, 1, 2, 3};

    int vistedCount = 0;
    for (int value : vec)
    {
        EXPECT_EQ(vistedCount, value);
        vistedCount++;
    }
    EXPECT_EQ(4, vistedCount);
}

// Tests that equality comparisons work even if reserved size differs.
TEST(FastVector, EqualityWithDifferentReservedSizes)
{
    FastVector<int, 3> vec1 = {1, 2, 3, 4, 5};
    FastVector<int, 5> vec2 = {1, 2, 3, 4, 5};
    EXPECT_EQ(vec1, vec2);
    vec2.push_back(6);
    EXPECT_NE(vec1, vec2);
}

// Tests vector operations with a non copyable type.
TEST(FastVector, NonCopyable)
{
    struct s : angle::NonCopyable
    {
        s() : x(0) {}
        s(int xin) : x(xin) {}
        s(s &&other) : x(other.x) {}
        s &operator=(s &&other)
        {
            x = other.x;
            return *this;
        }
        int x;
    };

    FastVector<s, 3> vec;
    vec.push_back(3);
    EXPECT_EQ(3, vec[0].x);

    FastVector<s, 3> copy = std::move(vec);
    EXPECT_EQ(1u, copy.size());
    EXPECT_EQ(3, copy[0].x);
}

// Basic functionality for FastUnorderedMap
TEST(FastUnorderedMap, BasicUsage)
{
    FastUnorderedMap<int, bool, 3> testMap;
    EXPECT_TRUE(testMap.empty());
    EXPECT_EQ(testMap.size(), 0u);

    testMap.insert(5, true);
    EXPECT_TRUE(testMap.contains(5));
    EXPECT_EQ(testMap.size(), 1u);

    bool value = false;
    EXPECT_TRUE(testMap.get(5, &value));
    EXPECT_TRUE(value);
    EXPECT_FALSE(testMap.get(6, &value));

    EXPECT_FALSE(testMap.empty());
    testMap.clear();
    EXPECT_TRUE(testMap.empty());
    EXPECT_EQ(testMap.size(), 0u);

    for (int i = 0; i < 10; ++i)
    {
        testMap.insert(i, false);
    }

    EXPECT_FALSE(testMap.empty());
    EXPECT_EQ(testMap.size(), 10u);

    for (int i = 0; i < 10; ++i)
    {
        EXPECT_TRUE(testMap.contains(i));
        EXPECT_TRUE(testMap.get(i, &value));
        EXPECT_FALSE(value);
    }
}

// Basic functionality for FastUnorderedSet
TEST(FastUnorderedSet, BasicUsage)
{
    FastUnorderedSet<int, 3> testMap;
    EXPECT_TRUE(testMap.empty());

    testMap.insert(5);
    EXPECT_TRUE(testMap.contains(5));
    EXPECT_FALSE(testMap.contains(6));
    EXPECT_FALSE(testMap.empty());

    testMap.clear();
    EXPECT_TRUE(testMap.empty());

    for (int i = 0; i < 10; ++i)
    {
        testMap.insert(i);
    }

    for (int i = 0; i < 10; ++i)
    {
        EXPECT_TRUE(testMap.contains(i));
    }
}

// Basic functionality for FastIntegerSet
TEST(FastIntegerSet, BasicUsage)
{
    FastIntegerSet testMap;
    EXPECT_TRUE(testMap.empty());

    testMap.insert(5);
    EXPECT_TRUE(testMap.contains(5));
    EXPECT_FALSE(testMap.contains(6));
    EXPECT_FALSE(testMap.empty());

    testMap.clear();
    EXPECT_TRUE(testMap.empty());

    for (int i = 0; i < 10; ++i)
    {
        testMap.insert(i);
    }

    for (int i = 0; i < 10; ++i)
    {
        EXPECT_TRUE(testMap.contains(i));
    }
}

// Basic functionality for FastIntegerMap
TEST(FastIntegerMap, BasicUsage)
{
    using KeyValuePair             = std::pair<int, std::string>;
    std::set<KeyValuePair> entries = {KeyValuePair(17, "testing"), KeyValuePair(63, "fast"),
                                      KeyValuePair(97, "integer"), KeyValuePair(256, "map")};

    FastIntegerMap<std::string> testMap;
    EXPECT_TRUE(testMap.empty());

    std::string str;
    testMap.insert(entries.begin()->first, entries.begin()->second);
    EXPECT_TRUE(testMap.contains(entries.begin()->first));
    EXPECT_FALSE(testMap.contains(entries.rbegin()->first));
    EXPECT_FALSE(testMap.empty());
    EXPECT_EQ(testMap.size(), 1u);
    EXPECT_TRUE(testMap.get(entries.begin()->first, &str));
    EXPECT_EQ(entries.begin()->second, str);
    EXPECT_FALSE(testMap.get(1, &str));

    testMap.clear();
    EXPECT_TRUE(testMap.empty());
    EXPECT_EQ(testMap.size(), 0u);

    for (KeyValuePair entry : entries)
    {
        testMap.insert(entry.first, entry.second);
    }
    EXPECT_EQ(testMap.size(), 4u);

    for (KeyValuePair entry : entries)
    {
        std::string str;
        EXPECT_TRUE(testMap.get(entry.first, &str));
        EXPECT_EQ(entry.second, str);
    }

    testMap.clear();
    EXPECT_TRUE(testMap.empty());
    EXPECT_EQ(testMap.size(), 0u);
}
}  // namespace angle
<|endoftext|>