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

#include "chrome/browser/chromeos/login/owner_key_utils.h"

#include <keyhi.h>     // SECKEY_CreateSubjectPublicKeyInfo()
#include <pk11pub.h>
#include <prerror.h>   // PR_GetError()
#include <secder.h>    // DER_Encode()
#include <secmod.h>

#include <limits>

#include "base/crypto/rsa_private_key.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/nss_util_internal.h"
#include "base/nss_util.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"

using base::RSAPrivateKey;

namespace chromeos {

///////////////////////////////////////////////////////////////////////////
// OwnerKeyUtils

// static
OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL;

OwnerKeyUtils::OwnerKeyUtils() {}

OwnerKeyUtils::~OwnerKeyUtils() {}

///////////////////////////////////////////////////////////////////////////
// OwnerKeyUtilsImpl

class OwnerKeyUtilsImpl : public OwnerKeyUtils {
 public:
  OwnerKeyUtilsImpl();
  virtual ~OwnerKeyUtilsImpl();

  RSAPrivateKey* GenerateKeyPair();

  bool ExportPublicKeyViaDbus(RSAPrivateKey* pair);

  bool ExportPublicKeyToFile(RSAPrivateKey* pair, const FilePath& key_file);

  bool ImportPublicKey(const FilePath& key_file,
                       std::vector<uint8>* output);

  RSAPrivateKey* FindPrivateKey(const std::vector<uint8>& key);

  FilePath GetOwnerKeyFilePath();

 private:
  // Fills in fields of |key_der| with DER encoded data from a file at
  // |key_file|.  The caller must pass in a pointer to an actual SECItem
  // struct for |key_der|.  |key_der->data| should be initialized to NULL
  // and |key_der->len| should be set to 0.
  //
  // Upon success, data is stored in key_der->data, and the caller takes
  // ownership.  Returns false on error.
  //
  // To free the data, call
  //    SECITEM_FreeItem(key_der, PR_FALSE);
  static bool ReadDERFromFile(const FilePath& key_file, SECItem* key_der);

  static bool EncodePublicKey(SECKEYPublicKey* key, std::string* out);

  // The file outside the owner's encrypted home directory where her
  // key will live.
  static const char kOwnerKeyFile[];

  // Key generation parameters.
  static const uint16 kKeySizeInBits;

  DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl);
};

// Defined here, instead of up above, because we need OwnerKeyUtilsImpl.
OwnerKeyUtils* OwnerKeyUtils::Create() {
  if (!factory_)
    return new OwnerKeyUtilsImpl();
  else
    return factory_->CreateOwnerKeyUtils();
}

// static
const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";

// We're generating and using 2048-bit RSA keys.
// static
const uint16 OwnerKeyUtilsImpl::kKeySizeInBits = 2048;

OwnerKeyUtilsImpl::OwnerKeyUtilsImpl() {
  // Ensure NSS is initialized.
  base::EnsureNSSInit();
}

OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {}

RSAPrivateKey* OwnerKeyUtilsImpl::GenerateKeyPair() {
  return RSAPrivateKey::CreateSensitive(kKeySizeInBits);
}

bool OwnerKeyUtilsImpl::ExportPublicKeyViaDbus(RSAPrivateKey* pair) {
  DCHECK(pair);
  bool ok = false;

  std::vector<uint8> to_export;
  if (pair->ExportPublicKey(&to_export)) {
    LOG(ERROR) << "Formatting key for export failed!";
    return false;
  }

  // TODO(cmasone): send the data over dbus.
  return ok;
}

bool OwnerKeyUtilsImpl::ExportPublicKeyToFile(RSAPrivateKey* pair,
                                              const FilePath& key_file) {
  DCHECK(pair);
  bool ok = false;
  int safe_file_size = 0;

  std::vector<uint8> to_export;
  if (!pair->ExportPublicKey(&to_export)) {
    LOG(ERROR) << "Formatting key for export failed!";
    return false;
  }

  if (to_export.size() > static_cast<uint>(INT_MAX)) {
    LOG(ERROR) << "key is too big! " << to_export.size();
  } else {
    safe_file_size = static_cast<int>(to_export.size());

    ok = (safe_file_size ==
          file_util::WriteFile(key_file,
                               reinterpret_cast<char*>(&to_export.front()),
                               safe_file_size));
  }
  return ok;
}

bool OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file,
                                        std::vector<uint8>* output) {
  SECItem key_der;
  key_der.data = NULL;
  key_der.len = 0;

  if (!ReadDERFromFile(key_file, &key_der)) {
    PLOG(ERROR) << "Could not read in key from " << key_file.value() << ":";
    return false;
  }

  // See the comment in ExportPublicKey() for why I wrote a
  // SubjectPublicKeyInfo to disk instead of a key.
  CERTSubjectPublicKeyInfo* spki =
     SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der);
  if (!spki) {
    LOG(ERROR) << "Could not decode key info: " << PR_GetError();
    SECITEM_FreeItem(&key_der, PR_FALSE);
    return false;
  }

  output->assign(reinterpret_cast<uint8*>(key_der.data),
                 reinterpret_cast<uint8*>(key_der.data + key_der.len));
  return key_der.len == output->size();
}

// static
bool OwnerKeyUtilsImpl::ReadDERFromFile(const FilePath& key_file,
                                        SECItem* key_der) {
  // I'd use NSS' SECU_ReadDERFromFile() here, but the SECU_* functions are
  // considered internal to the NSS command line utils.
  // This code is lifted, in spirit, from the implementation of that function.
  DCHECK(key_der) << "Don't pass NULL for |key_der|";
  DCHECK(key_der->data == NULL);
  DCHECK(key_der->len == 0);

  // Get the file size (must fit in a 32 bit int for NSS).
  int64 file_size;
  if (!file_util::GetFileSize(key_file, &file_size)) {
    LOG(ERROR) << "Could not get size of " << key_file.value();
    return false;
  }
  if (file_size > static_cast<int64>(std::numeric_limits<int>::max())) {
    LOG(ERROR) << key_file.value() << "is "
               << file_size << "bytes!!!  Too big!";
    return false;
  }
  int32 safe_file_size = static_cast<int32>(file_size);

  // Allocate space for the DER encoded data.
  key_der->data = NULL;
  if (!SECITEM_AllocItem(NULL, key_der, safe_file_size)) {
    LOG(ERROR) << "Could not create space for DER encoded key";
    return false;
  }

  // Get the key data off of disk
  int data_read = file_util::ReadFile(key_file,
                                      reinterpret_cast<char*>(key_der->data),
                                      safe_file_size);

  if (data_read != safe_file_size) {
    LOG(ERROR) << "Read the wrong amount of data from the DER encoded key! "
               << data_read;
    SECITEM_FreeItem(key_der, PR_FALSE);
    return false;
  }
  return true;
}

RSAPrivateKey* OwnerKeyUtilsImpl::FindPrivateKey(
    const std::vector<uint8>& key) {
  return RSAPrivateKey::FindFromPublicKeyInfo(key);
}

FilePath OwnerKeyUtilsImpl::GetOwnerKeyFilePath() {
  return FilePath(OwnerKeyUtilsImpl::kOwnerKeyFile);
}

}  // namespace chromeos
<commit_msg>Fix memory leaks in OwnerKeyUtils<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/owner_key_utils.h"

#include <keyhi.h>     // SECKEY_CreateSubjectPublicKeyInfo()
#include <pk11pub.h>
#include <prerror.h>   // PR_GetError()
#include <secder.h>    // DER_Encode()
#include <secmod.h>

#include <limits>

#include "base/crypto/rsa_private_key.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/nss_util_internal.h"
#include "base/nss_util.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"

using base::RSAPrivateKey;

namespace chromeos {

///////////////////////////////////////////////////////////////////////////
// OwnerKeyUtils

// static
OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL;

OwnerKeyUtils::OwnerKeyUtils() {}

OwnerKeyUtils::~OwnerKeyUtils() {}

///////////////////////////////////////////////////////////////////////////
// OwnerKeyUtilsImpl

class OwnerKeyUtilsImpl : public OwnerKeyUtils {
 public:
  OwnerKeyUtilsImpl();
  virtual ~OwnerKeyUtilsImpl();

  RSAPrivateKey* GenerateKeyPair();

  bool ExportPublicKeyViaDbus(RSAPrivateKey* pair);

  bool ExportPublicKeyToFile(RSAPrivateKey* pair, const FilePath& key_file);

  bool ImportPublicKey(const FilePath& key_file,
                       std::vector<uint8>* output);

  RSAPrivateKey* FindPrivateKey(const std::vector<uint8>& key);

  FilePath GetOwnerKeyFilePath();

 private:
  // The file outside the owner's encrypted home directory where her
  // key will live.
  static const char kOwnerKeyFile[];

  // Key generation parameters.
  static const uint16 kKeySizeInBits;

  DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl);
};

// Defined here, instead of up above, because we need OwnerKeyUtilsImpl.
OwnerKeyUtils* OwnerKeyUtils::Create() {
  if (!factory_)
    return new OwnerKeyUtilsImpl();
  else
    return factory_->CreateOwnerKeyUtils();
}

// static
const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";

// We're generating and using 2048-bit RSA keys.
// static
const uint16 OwnerKeyUtilsImpl::kKeySizeInBits = 2048;

OwnerKeyUtilsImpl::OwnerKeyUtilsImpl() {
  // Ensure NSS is initialized.
  base::EnsureNSSInit();
}

OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {}

RSAPrivateKey* OwnerKeyUtilsImpl::GenerateKeyPair() {
  return RSAPrivateKey::CreateSensitive(kKeySizeInBits);
}

bool OwnerKeyUtilsImpl::ExportPublicKeyViaDbus(RSAPrivateKey* pair) {
  DCHECK(pair);
  bool ok = false;

  std::vector<uint8> to_export;
  if (pair->ExportPublicKey(&to_export)) {
    LOG(ERROR) << "Formatting key for export failed!";
    return false;
  }

  // TODO(cmasone): send the data over dbus.
  return ok;
}

bool OwnerKeyUtilsImpl::ExportPublicKeyToFile(RSAPrivateKey* pair,
                                              const FilePath& key_file) {
  DCHECK(pair);
  bool ok = false;
  int safe_file_size = 0;

  std::vector<uint8> to_export;
  if (!pair->ExportPublicKey(&to_export)) {
    LOG(ERROR) << "Formatting key for export failed!";
    return false;
  }

  if (to_export.size() > static_cast<uint>(INT_MAX)) {
    LOG(ERROR) << "key is too big! " << to_export.size();
  } else {
    safe_file_size = static_cast<int>(to_export.size());

    ok = (safe_file_size ==
          file_util::WriteFile(key_file,
                               reinterpret_cast<char*>(&to_export.front()),
                               safe_file_size));
  }
  return ok;
}

bool OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file,
                                        std::vector<uint8>* output) {
  // Get the file size (must fit in a 32 bit int for NSS).
  int64 file_size;
  if (!file_util::GetFileSize(key_file, &file_size)) {
    LOG(ERROR) << "Could not get size of " << key_file.value();
    return false;
  }
  if (file_size > static_cast<int64>(std::numeric_limits<int>::max())) {
    LOG(ERROR) << key_file.value() << "is "
               << file_size << "bytes!!!  Too big!";
    return false;
  }
  int32 safe_file_size = static_cast<int32>(file_size);

  output->resize(safe_file_size);
  // Get the key data off of disk
  int data_read = file_util::ReadFile(key_file,
                                      reinterpret_cast<char*>(&(output->at(0))),
                                      safe_file_size);
  return data_read == safe_file_size;
}

RSAPrivateKey* OwnerKeyUtilsImpl::FindPrivateKey(
    const std::vector<uint8>& key) {
  return RSAPrivateKey::FindFromPublicKeyInfo(key);
}

FilePath OwnerKeyUtilsImpl::GetOwnerKeyFilePath() {
  return FilePath(OwnerKeyUtilsImpl::kOwnerKeyFile);
}

}  // namespace chromeos
<|endoftext|>


<commit_before>#include <faunus/faunus.h>

/*
 * This will simulate:
 * - an arbitrary number of rigid molecules (two different kinds)
 * - any number of atomic species
 * - equilibrium swap moves
 * - external pressure (NPT)
 * - arbitrary pair potential
 */

using namespace Faunus;
using namespace Faunus::Potential;

typedef Space<Geometry::Cuboid> Tspace;
//typedef CombinedPairPotential<CoulombWolf,LennardJonesLB> Tpairpot;
typedef CombinedPairPotential<DebyeHuckelShift,CutShift<LennardJones> > Tpairpot;

int main(int argc, char** argv) {
  Faunus::MPI::MPIController mpi;

  InputMap mcp("manybody.input");
  FormatXTC xtc(1000);                 // XTC gromacs trajectory format
  EnergyDrift sys;                     // class for tracking system energy drifts
  UnitTest test(mcp);
  bool inPlane = mcp.get<bool>("molecule_plane");

  Tspace spc(mcp);
  auto pot = Energy::NonbondedCutg2g<Tspace,Tpairpot>(mcp)
    + Energy::ExternalPressure<Tspace>(mcp)
    + Energy::HydrophobicSASA<Tspace>(mcp)
    + Energy::EquilibriumEnergy<Tspace>(mcp);// + myenergy<Tspace>(mcp);

  auto eqenergy = &pot.second;

  // Add molecules
  int N1 = mcp.get("molecule1_N",0);
  int N2 = mcp.get("molecule2_N",0);
  string file;
  vector<Group> pol(N1+N2);
  for (int i=0; i<N1+N2; i++) {
    if (i>=N1)
      file = mcp.get<string>("molecule2");
    else
      file = mcp.get<string>("molecule1");
    Tspace::ParticleVector v;
    FormatAAM::load(file,v);
    Geometry::FindSpace fs;
    fs.allowMatterOverlap=true;
    if (inPlane)
      fs.dir=Point(1,1,0);
    fs.find(spc.geo,spc.p,v);
    pol[i] = spc.insert(v);
    pol[i].name=file;
    spc.enroll( pol[i] );
  }
  Group allpol( pol.front().front(), pol.back().back() );

  // Add atomic species
  Group salt;
  salt.addParticles(spc, mcp);
  salt.name="Atomic Species";
  spc.enroll(salt);

  Analysis::RadialDistribution<> rdf(0.5);
  Analysis::ChargeMultipole mpol;
  Scatter::DebyeFormula<Scatter::FormFactorUnity<>> debye(mcp);
  Scatter::DebyeFormula<Scatter::FormFactorUnity<>> debye2(mcp);

  spc.load("state"); // load previous state, if any

  Move::Isobaric<Tspace> iso(mcp,pot,spc);
  Move::TranslateRotate<Tspace> gmv(mcp,pot,spc);
  Move::AtomicTranslation<Tspace> mv(mcp,pot,spc);
  Move::SwapMove<Tspace> tit(mcp,pot,spc,*eqenergy);

  gmv.mpi=&mpi;
  tit.mpi=&mpi;
  if (inPlane)
    for (auto &m : pol)
      gmv.directions[ m.name ]=Point(1,1,0);

  sys.init( Energy::systemEnergy(spc,pot,spc.p) );    // Store total system energy

  std::ofstream cmfile, energyfile;

  if (mpi.isMaster()) {
    cmfile.open("cm.xyz");
    energyfile.open("energy.dat");
    cout << atom.info() << spc.info() << pot.info() << tit.info()
      << textio::header("MC Simulation Begins!");
  }

  vector<Point> cm_vec; // vector of mass centers

  MCLoop loop(mcp);
  while ( loop.macroCnt() ) {  // Markov chain
    while ( loop.microCnt() ) {
      int k,i=rand() % 4;
      switch (i) {
        case 0: // move all proteins
          k=pol.size();
          while (k-->0) {
            gmv.setGroup( pol[ rand() % pol.size() ] );
            sys+=gmv.move();
          }

          // sample g(r)
          for (auto i=pol.begin(); i!=pol.end()-1; i++)
            for (auto j=i+1; j!=pol.end(); j++)
              rdf( spc.geo.dist(i->cm,j->cm) )++;

          // sample S(q)
          if (slp_global()>0.95) {
            cm_vec.clear();
            for (auto &i : pol)
              cm_vec.push_back(i.cm);
            debye.sample(cm_vec,spc.geo.getVolume());

            if (mpi.isMaster())
              if (cmfile) {
                cmfile << cm_vec.size() << "\n" << "cm" << "\n";
                for (auto &m : cm_vec)
                  cmfile << "H " << ((m+spc.geo.len_half)/10).transpose() << "\n";
              }
              if (energyfile)
                energyfile << loop.count() << " " << sys.current()
                  << " " << std::cbrt(spc.geo.getVolume()) << "\n";
          }
          break;
        case 1: // volume move (NPT)
          sys+=iso.move();
          break;
        case 2: // titration move
          sys+=tit.move();
          mpol.sample(pol,spc);
          break;
        case 3: // move atomic species
          mv.setGroup(salt);
          sys+=mv.move();
          break;
      }
      if (slp_global()>0.99 ) {
        xtc.setbox( spc.geo.len );
        xtc.save("traj.xtc", spc);
      }
    } // end of micro loop

    sys.checkDrift( Energy::systemEnergy(spc,pot,spc.p) ); // detect energy drift

    if (mpi.isMaster())
      cout << loop.timing();

  } // end of macro loop

  if (mpi.isMaster()) {
    cout << tit.info() + loop.info() + sys.info() + gmv.info() + mv.info()
      + iso.info() + mpol.info() << endl;

    rdf.save("rdf_p2p.dat");
    FormatPQR::save("confout.pqr", spc.p, spc.geo.len);
    spc.save("state");
    mcp.save("mdout.mdp");
    debye.save("debye.dat");
    debye2.save("debye.g2g.dat");

    // save first molecule with average charges (as opposed to instantaneous)
    eqenergy->eq.copyAvgCharge(spc.p);
    spc.p.erase( spc.p.begin() + spc.groupList()[0]->size(), spc.p.end() );
    Geometry::cm2origo(spc.geo, spc.p);
    FormatPQR::save("avgcharge.pqr", spc.p, spc.geo.len);
    FormatAAM::save("avgcharge.aam", spc.p);
  }
}
<commit_msg>Update of manybody to sample less<commit_after>#include <faunus/faunus.h>

/*
 * This will simulate:
 * - an arbitrary number of rigid molecules (two different kinds)
 * - any number of atomic species
 * - equilibrium swap moves
 * - external pressure (NPT)
 * - arbitrary pair potential
 */

using namespace Faunus;
using namespace Faunus::Potential;

typedef Space<Geometry::Cuboid> Tspace;
//typedef CombinedPairPotential<CoulombWolf,LennardJonesLB> Tpairpot;
typedef CombinedPairPotential<DebyeHuckelShift,CutShift<LennardJones> > Tpairpot;

int main(int argc, char** argv) {
  Faunus::MPI::MPIController mpi;

  InputMap mcp("manybody.input");
  FormatXTC xtc(1000);                 // XTC gromacs trajectory format
  EnergyDrift sys;                     // class for tracking system energy drifts
  UnitTest test(mcp);
  bool inPlane = mcp.get<bool>("molecule_plane");

  Tspace spc(mcp);
  auto pot = Energy::NonbondedCutg2g<Tspace,Tpairpot>(mcp)
    + Energy::ExternalPressure<Tspace>(mcp)
    + Energy::HydrophobicSASA<Tspace>(mcp)
    + Energy::EquilibriumEnergy<Tspace>(mcp);// + myenergy<Tspace>(mcp);

  auto eqenergy = &pot.second;

  // Add molecules
  int N1 = mcp.get("molecule1_N",0);
  int N2 = mcp.get("molecule2_N",0);
  string file;
  vector<Group> pol(N1+N2);
  for (int i=0; i<N1+N2; i++) {
    if (i>=N1)
      file = mcp.get<string>("molecule2");
    else
      file = mcp.get<string>("molecule1");
    Tspace::ParticleVector v;
    FormatAAM::load(file,v);
    Geometry::FindSpace fs;
    fs.allowMatterOverlap=true;
    if (inPlane)
      fs.dir=Point(1,1,0);
    fs.find(spc.geo,spc.p,v);
    pol[i] = spc.insert(v);
    pol[i].name=file;
    spc.enroll( pol[i] );
  }
  Group allpol( pol.front().front(), pol.back().back() );

  // Add atomic species
  Group salt;
  salt.addParticles(spc, mcp);
  salt.name="Atomic Species";
  spc.enroll(salt);

  Analysis::RadialDistribution<> rdf(0.5);
  Analysis::ChargeMultipole mpol;
  Scatter::DebyeFormula<Scatter::FormFactorUnity<>> debye(mcp);
  Scatter::DebyeFormula<Scatter::FormFactorUnity<>> debye2(mcp);

  spc.load("state"); // load previous state, if any

  Move::Isobaric<Tspace> iso(mcp,pot,spc);
  Move::TranslateRotate<Tspace> gmv(mcp,pot,spc);
  Move::AtomicTranslation<Tspace> mv(mcp,pot,spc);
  Move::SwapMove<Tspace> tit(mcp,pot,spc,*eqenergy);

  gmv.mpi=&mpi;
  tit.mpi=&mpi;
  if (inPlane)
    for (auto &m : pol)
      gmv.directions[ m.name ]=Point(1,1,0);

  sys.init( Energy::systemEnergy(spc,pot,spc.p) );    // Store total system energy

  std::ofstream cmfile, energyfile;

  if (mpi.isMaster()) {
    cmfile.open("cm.xyz");
    energyfile.open("energy.dat");
    cout << atom.info() << spc.info() << pot.info() << tit.info()
      << textio::header("MC Simulation Begins!");
  }

  vector<Point> cm_vec; // vector of mass centers

  MCLoop loop(mcp);
  while ( loop.macroCnt() ) {  // Markov chain
    while ( loop.microCnt() ) {
      int k,i=rand() % 4;
      switch (i) {
        case 0: // move all proteins
          k=pol.size();
          while (k-->0) {
            gmv.setGroup( pol[ rand() % pol.size() ] );
            sys+=gmv.move();
          }

          if (slp_global()>0.995) {
            // sample g(r)
            for (auto i=pol.begin(); i!=pol.end()-1; i++)
              for (auto j=i+1; j!=pol.end(); j++)
                rdf( spc.geo.dist(i->cm,j->cm) )++;

            cm_vec.clear();
            for (auto &i : pol)
              cm_vec.push_back(i.cm);
            debye.sample(cm_vec,spc.geo.getVolume());

            if (mpi.isMaster())
              if (cmfile) {
                cmfile << cm_vec.size() << "\n" << "cm" << "\n";
                for (auto &m : cm_vec)
                  cmfile << "H " << ((m+spc.geo.len_half)/10).transpose() << "\n";
              }
            if (energyfile)
              energyfile << loop.count() << " " << sys.current()
                << " " << std::cbrt(spc.geo.getVolume()) << "\n";
          }
          break;
        case 1: // volume move (NPT)
          sys+=iso.move();
          break;
        case 2: // titration move
          sys+=tit.move();
          mpol.sample(pol,spc);
          break;
        case 3: // move atomic species
          mv.setGroup(salt);
          sys+=mv.move();
          break;
      }
      if (slp_global()>0.99 ) {
        xtc.setbox( spc.geo.len );
        xtc.save("traj.xtc", spc);
      }
    } // end of micro loop

    sys.checkDrift( Energy::systemEnergy(spc,pot,spc.p) ); // detect energy drift

    if (mpi.isMaster()) {
      cout << loop.timing();
      rdf.save("rdf_p2p.dat");
      FormatPQR::save("confout.pqr", spc.p, spc.geo.len);
      spc.save("state");
      mcp.save("mdout.mdp");
      debye.save("debye.dat");
      debye2.save("debye.g2g.dat");
    }

  } // end of macro loop

  if (mpi.isMaster()) {
    cout << tit.info() + loop.info() + sys.info() + gmv.info() + mv.info()
      + iso.info() + mpol.info() << endl;

    // save first molecule with average charges (as opposed to instantaneous)
    eqenergy->eq.copyAvgCharge(spc.p);
    spc.p.erase( spc.p.begin() + spc.groupList()[0]->size(), spc.p.end() );
    Geometry::cm2origo(spc.geo, spc.p);
    FormatPQR::save("avgcharge.pqr", spc.p, spc.geo.len);
    FormatAAM::save("avgcharge.aam", spc.p);
  }
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef CPM_BOOTSTRAP_THEME_HPP
#define CPM_BOOTSTRAP_THEME_HPP

#include "cpm/io.hpp"
#include "cpm/data.hpp"

namespace cpm {

struct bootstrap_theme {
    const reports_data& data;
    cxxopts::Options& options;
    std::ostream& stream;
    std::string current_compiler;
    std::string current_configuration;

    std::size_t current_column = 0;

    bootstrap_theme(const reports_data& data, cxxopts::Options& options, std::ostream& stream, std::string compiler, std::string configuration)
        : data(data), options(options), stream(stream), current_compiler(std::move(compiler)), current_configuration(std::move(configuration)) {}

    void include(){
        stream << "\n";
        stream << "<link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css\" rel=\"stylesheet\">\n";
        stream << "<link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css\" rel=\"stylesheet\">\n";
    }

    void header(){
        stream << R"=====(

            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbarCollapse">
            Toggle navigation

            </button>
            Results

Home

Generated with CPM

        )=====";
    }

    void footer(){
        stream << R"=====(

Generated with CPM

        )=====";

        if(options.count("pages")){
            stream << "
\n";
            stream << "
\n";
        }
    }

    void before_information(){
        stream << "
\n";
        stream << "
\n";
    }

    void after_information(){
        stream << "
\n";
        stream << "
\n";

        if(options.count("pages")){
            stream << R"=====(

            )=====";

            for(auto& link : data.files){
                stream << "
<a href=\"" << link.second << "\">" << link.first << "
" << std::endl;
            }

            stream << R"=====(

            )=====";
        } else {
            stream << "
\n";
        }
    }

    void compiler_buttons(){
        stream << R"=====(
)=====";
        stream << R"=====(
)=====";

        stream << R"=====(Select compiler: )=====";

        stream << R"=====(
)=====";
        for(auto& compiler : data.compilers){
            if(compiler == current_compiler){
                stream << "<a class=\"btn btn-primary\" href=\"" << cpm::filify(compiler, current_configuration)  << "\">" << compiler << "\n";
            } else {
                stream << "<a class=\"btn btn-default\" href=\"" << cpm::filify(compiler, current_configuration)  << "\">" << compiler << "\n";
            }
        }
        stream << "
\n";

        stream << "
\n";
        stream << "
\n";
    }

    void configuration_buttons(){
        if(data.compilers.size() > 1){
            stream << R"=====(
)=====";
        } else {
            stream << R"=====(
)=====";
        }

        stream << R"=====(
)=====";

        stream << R"=====(Select configuration: )=====";

        stream << R"=====(
)=====";
        for(auto& configuration : data.configurations){
            if(configuration == current_configuration){
                stream << "<a class=\"btn btn-primary\" href=\"" << cpm::filify(current_compiler, configuration)  << "\">" << configuration << "\n";
            } else {
                stream << "<a class=\"btn btn-default\" href=\"" << cpm::filify(current_compiler, configuration)  << "\">" << configuration << "\n";
            }
        }
        stream << "
\n";

        stream << "
\n";
        stream << "
\n";
    }

    virtual void start_column(const std::string& style = ""){
        std::size_t columns = 1; //Always the first grapah

        if(data.documents.size() > 1 && !options.count("disable-time")){
            ++columns;
        }

        if(data.compilers.size() > 1 && !options.count("disable-compiler")){
            ++columns;
        }

        if(data.configurations.size() > 1 && !options.count("disable-configuration")){
            ++columns;
        }

        if(!options.count("disable-summary")){
            ++columns;
        }

        if(columns < 4){
            stream << "<div class=\"col-xs-" << 12 / columns << "\"" << style << ">\n";
        } else if(columns == 4){
            if(current_column == 2){
                stream << "
\n";
                stream << "
\n";
            }

            stream << "<div class=\"col-xs-6\"" << style << ">\n";
        } else if(columns == 5){
            if(current_column == 3){
                stream << "
\n";
                stream << "
\n";
            }

            if(current_column < 3){
                stream << "<div class=\"col-xs-4\"" << style << ">\n";
            } else if(current_column == 3){
                stream << "<div class=\"col-xs-4\"" << style << ">\n";
            } else if(current_column == 4){
                stream << "<div class=\"col-xs-8\"" << style << ">\n";
            }
        }

        ++current_column;
    }

    virtual void close_column(){
        stream << "
\n";
    }

    void before_graph(std::size_t id){
        start_column();

        stream << "<div id=\"chart_" << id << "\" style=\"height: 400px;\">
\n";
    }

    void after_graph(){
        close_column();
    }

    void before_result(const std::string& title, bool sub = false){
        stream << "
\n";
        stream << "
" << title << "
\n";
        stream << "
\n";

        if(sub){
            stream << "
\n";
        } else {
            stream << "
\n";
        }

        current_column = 0;
    }

    void after_result(){
        stream << "
\n";
    }

    void before_sub_graphs(std::size_t id, std::vector<std::string> graphs){
        start_column("style=\"align-self: flex-start; \"");

        stream << "
\n";
        stream << "
\n";

        std::string active = "class=\"active\"";
        std::size_t sub = 0;
        for(auto& g : graphs){
            auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub++);
            stream << "<li " << active << " role=\"presentation\"><a href=\"#" << sub_id << "\" aria-controls=\""
                << sub_id << "\" role=\"tab\" data-toggle=\"tab\">" << g << "
\n";
            active = "";
        }

        stream << "
\n";
        stream << "
\n";
    }

    void after_sub_graphs(){
        stream << "
\n";
        stream << "
\n";

        close_column();
    }

    void before_sub_graph(std::size_t id, std::size_t sub){
        auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub);
        std::string active;
        if(sub == 0){
            active = " active";
        }
        stream << "<div role=\"tabpanel\" class=\"tab-pane" << active << "\" id=\"" << sub_id << "\">\n";

        stream << "<div id=\"chart_" << id << "-" << sub << "\" style=\"height: 400px;\">
\n";
    }

    void after_sub_graph(){
        stream << "
\n";
    }

    void before_summary(){
        start_column();

        stream << "
\n";
    }

    void after_summary(){
        stream << "
\n";

        close_column();
    }

    void before_sub_summary(std::size_t id, std::size_t sub){
        auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub);
        std::string active;
        if(sub == 0){
            active = " active";
        }

        stream << "<div role=\"tabpanel\" class=\"tab-pane" << active << "\" id=\"" << sub_id << "\">\n";
        stream << "
\n";
    }

    void after_sub_summary(){
        stream << "
\n";
        stream << "
\n";
    }

    void cell(const std::string& v){
        stream << "" << v << "	\n";
    }

    void red_cell(const std::string& v){
        stream << ""<< v << "	\n";
    }

    void green_cell(const std::string& v){
        stream << "" << v << "	\n";
    }

    template<typename T>
    bootstrap_theme& operator<<(const T& v){
        stream << v;
        return *this;
    }
};

} //end of namespace cpm

#endif //CPM_BOOTSTRAP_THEME_HPP
<commit_msg>Reduce the size of the jumbotron<commit_after>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef CPM_BOOTSTRAP_THEME_HPP
#define CPM_BOOTSTRAP_THEME_HPP

#include "cpm/io.hpp"
#include "cpm/data.hpp"

namespace cpm {

struct bootstrap_theme {
    const reports_data& data;
    cxxopts::Options& options;
    std::ostream& stream;
    std::string current_compiler;
    std::string current_configuration;

    std::size_t current_column = 0;

    bootstrap_theme(const reports_data& data, cxxopts::Options& options, std::ostream& stream, std::string compiler, std::string configuration)
        : data(data), options(options), stream(stream), current_compiler(std::move(compiler)), current_configuration(std::move(configuration)) {}

    void include(){
        stream << "\n";
        stream << "<link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css\" rel=\"stylesheet\">\n";
        stream << "<link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css\" rel=\"stylesheet\">\n";

        stream << R"=====(

        )=====";
    }

    void header(){
        stream << R"=====(

            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbarCollapse">
            Toggle navigation

            </button>
            Results

Home

Generated with CPM

        )=====";
    }

    void footer(){
        stream << R"=====(

Generated with CPM

        )=====";

        if(options.count("pages")){
            stream << "
\n";
            stream << "
\n";
        }
    }

    void before_information(){
        stream << "
\n";
        stream << "
\n";
    }

    void after_information(){
        stream << "
\n";
        stream << "
\n";

        if(options.count("pages")){
            stream << R"=====(

            )=====";

            for(auto& link : data.files){
                stream << "
<a href=\"" << link.second << "\">" << link.first << "
" << std::endl;
            }

            stream << R"=====(

            )=====";
        } else {
            stream << "
\n";
        }
    }

    void compiler_buttons(){
        stream << R"=====(
)=====";
        stream << R"=====(
)=====";

        stream << R"=====(Select compiler: )=====";

        stream << R"=====(
)=====";
        for(auto& compiler : data.compilers){
            if(compiler == current_compiler){
                stream << "<a class=\"btn btn-primary\" href=\"" << cpm::filify(compiler, current_configuration)  << "\">" << compiler << "\n";
            } else {
                stream << "<a class=\"btn btn-default\" href=\"" << cpm::filify(compiler, current_configuration)  << "\">" << compiler << "\n";
            }
        }
        stream << "
\n";

        stream << "
\n";
        stream << "
\n";
    }

    void configuration_buttons(){
        if(data.compilers.size() > 1){
            stream << R"=====(
)=====";
        } else {
            stream << R"=====(
)=====";
        }

        stream << R"=====(
)=====";

        stream << R"=====(Select configuration: )=====";

        stream << R"=====(
)=====";
        for(auto& configuration : data.configurations){
            if(configuration == current_configuration){
                stream << "<a class=\"btn btn-primary\" href=\"" << cpm::filify(current_compiler, configuration)  << "\">" << configuration << "\n";
            } else {
                stream << "<a class=\"btn btn-default\" href=\"" << cpm::filify(current_compiler, configuration)  << "\">" << configuration << "\n";
            }
        }
        stream << "
\n";

        stream << "
\n";
        stream << "
\n";
    }

    virtual void start_column(const std::string& style = ""){
        std::size_t columns = 1; //Always the first grapah

        if(data.documents.size() > 1 && !options.count("disable-time")){
            ++columns;
        }

        if(data.compilers.size() > 1 && !options.count("disable-compiler")){
            ++columns;
        }

        if(data.configurations.size() > 1 && !options.count("disable-configuration")){
            ++columns;
        }

        if(!options.count("disable-summary")){
            ++columns;
        }

        if(columns < 4){
            stream << "<div class=\"col-xs-" << 12 / columns << "\"" << style << ">\n";
        } else if(columns == 4){
            if(current_column == 2){
                stream << "
\n";
                stream << "
\n";
            }

            stream << "<div class=\"col-xs-6\"" << style << ">\n";
        } else if(columns == 5){
            if(current_column == 3){
                stream << "
\n";
                stream << "
\n";
            }

            if(current_column < 3){
                stream << "<div class=\"col-xs-4\"" << style << ">\n";
            } else if(current_column == 3){
                stream << "<div class=\"col-xs-4\"" << style << ">\n";
            } else if(current_column == 4){
                stream << "<div class=\"col-xs-8\"" << style << ">\n";
            }
        }

        ++current_column;
    }

    virtual void close_column(){
        stream << "
\n";
    }

    void before_graph(std::size_t id){
        start_column();

        stream << "<div id=\"chart_" << id << "\" style=\"height: 400px;\">
\n";
    }

    void after_graph(){
        close_column();
    }

    void before_result(const std::string& title, bool sub = false){
        stream << "
\n";
        stream << "
" << title << "
\n";
        stream << "
\n";

        if(sub){
            stream << "
\n";
        } else {
            stream << "
\n";
        }

        current_column = 0;
    }

    void after_result(){
        stream << "
\n";
    }

    void before_sub_graphs(std::size_t id, std::vector<std::string> graphs){
        start_column("style=\"align-self: flex-start; \"");

        stream << "
\n";
        stream << "
\n";

        std::string active = "class=\"active\"";
        std::size_t sub = 0;
        for(auto& g : graphs){
            auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub++);
            stream << "<li " << active << " role=\"presentation\"><a href=\"#" << sub_id << "\" aria-controls=\""
                << sub_id << "\" role=\"tab\" data-toggle=\"tab\">" << g << "
\n";
            active = "";
        }

        stream << "
\n";
        stream << "
\n";
    }

    void after_sub_graphs(){
        stream << "
\n";
        stream << "
\n";

        close_column();
    }

    void before_sub_graph(std::size_t id, std::size_t sub){
        auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub);
        std::string active;
        if(sub == 0){
            active = " active";
        }
        stream << "<div role=\"tabpanel\" class=\"tab-pane" << active << "\" id=\"" << sub_id << "\">\n";

        stream << "<div id=\"chart_" << id << "-" << sub << "\" style=\"height: 400px;\">
\n";
    }

    void after_sub_graph(){
        stream << "
\n";
    }

    void before_summary(){
        start_column();

        stream << "
\n";
    }

    void after_summary(){
        stream << "
\n";

        close_column();
    }

    void before_sub_summary(std::size_t id, std::size_t sub){
        auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub);
        std::string active;
        if(sub == 0){
            active = " active";
        }

        stream << "<div role=\"tabpanel\" class=\"tab-pane" << active << "\" id=\"" << sub_id << "\">\n";
        stream << "
\n";
    }

    void after_sub_summary(){
        stream << "
\n";
        stream << "
\n";
    }

    void cell(const std::string& v){
        stream << "" << v << "	\n";
    }

    void red_cell(const std::string& v){
        stream << ""<< v << "	\n";
    }

    void green_cell(const std::string& v){
        stream << "" << v << "	\n";
    }

    template<typename T>
    bootstrap_theme& operator<<(const T& v){
        stream << v;
        return *this;
    }
};

} //end of namespace cpm

#endif //CPM_BOOTSTRAP_THEME_HPP
<|endoftext|>


<commit_before>/**
 * \file
 * \brief Semaphore class header
 *
 * \author Copyright (C) 2014-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_SEMAPHORE_HPP_
#define INCLUDE_DISTORTOS_SEMAPHORE_HPP_

#include "distortos/internal/scheduler/ThreadList.hpp"

#include "distortos/TickClock.hpp"

namespace distortos
{

/**
 * \brief Semaphore is the basic synchronization primitive
 *
 * Similar to POSIX semaphores - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
 *
 * \ingroup synchronization
 */

class Semaphore
{
public:

	/// type used for semaphore's "value"
	using Value = unsigned int;

	/**
	 * \brief Semaphore's constructor
	 *
	 * Similar to sem_init() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html#
	 *
	 * \param [in] value is the initial value of the semaphore, if this value is greater than maxValue, it will be
	 * truncated
	 * \param [in] maxValue is the max value of the semaphore before post() returns EOVERFLOW, default - max for Value
	 * type
	 */

	constexpr explicit Semaphore(const Value value, const Value maxValue = std::numeric_limits<Value>::max()) :
			blockedList_{},
			value_{value < maxValue ? value : maxValue},
			maxValue_{maxValue}
	{

	}

	/**
	 * \brief Semaphore's destructor
	 *
	 * Similar to sem_destroy() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html#
	 *
	 * It is safe to destroy a semaphore upon which no threads are currently blocked. The effect of destroying a
	 * semaphore upon which other threads are currently blocked is system error.
	 */

	~Semaphore() = default;

	/**
	 * \brief Gets current value of semaphore.
	 *
	 * Similar to sem_getvalue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html#
	 *
	 * \return current value of semaphore, positive value if semaphore is not locked, 0 otherwise
	 */

	Value getValue() const
	{
		return value_;
	}

	/**
	 * \brief Unlocks the semaphore.
	 *
	 * Similar to sem_post() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html#
	 *
	 * This function shall unlock the semaphore by performing a semaphore unlock operation. If the semaphore value
	 * resulting from this operation is positive, then no threads were blocked waiting for the semaphore to become
	 * unlocked; the semaphore value is simply incremented. Otherwise one of the threads blocked waiting for the
	 * semaphore shall be allowed to return successfully from its call to lock() - the highest priority waiting thread
	 * shall be unblocked, and if there is more than one highest priority thread blocked waiting for the semaphore, then
	 * the highest priority thread that has been waiting the longest shall be unblocked.
	 *
	 * \return 0 if the calling process successfully "posted" the semaphore, error code otherwise:
	 * - EOVERFLOW - the maximum allowable value for a semaphore would be exceeded;
	 */

	int post();

	/**
	 * \brief Tries to lock the semaphore.
	 *
	 * Similar to sem_trywait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
	 *
	 * This function shall lock the semaphore only if the semaphore is currently not locked; that is, if the semaphore
	 * value is currently positive. Otherwise, it shall not lock the semaphore. Upon successful return, the state of the
	 * semaphore shall be locked and shall remain locked until unlock() function is executed.
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EAGAIN - semaphore was already locked, so it cannot be immediately locked by the tryWait() operation;
	 */

	int tryWait();

	/**
	 * \brief Tries to lock the semaphore for given duration of time.
	 *
	 * Similar to sem_timedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html#
	 *
	 * If the semaphore is already locked, the calling thread shall block until the semaphore becomes available as in
	 * wait() function. If the semaphore cannot be locked without waiting for another thread to unlock the semaphore,
	 * this wait shall be terminated when the specified timeout expires.
	 *
	 * Under no circumstance shall the function fail with a timeout if the semaphore can be locked immediately. The
	 * validity of the duration parameter need not be checked if the semaphore can be locked immediately.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] duration is the duration after which the wait will be terminated without locking the semaphore
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
	 */

	int tryWaitFor(TickClock::duration duration);

	/**
	 * \brief Tries to lock the semaphore for given duration of time.
	 *
	 * Template variant of tryWaitFor(TickClock::duration duration).
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \tparam Rep is type of tick counter
	 * \tparam Period is std::ratio type representing the tick period of the clock, seconds
	 *
	 * \param [in] duration is the duration after which the wait will be terminated without locking the semaphore
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
	 */

	template<typename Rep, typename Period>
	int tryWaitFor(const std::chrono::duration<Rep, Period> duration)
	{
		return tryWaitFor(std::chrono::duration_cast<TickClock::duration>(duration));
	}

	/**
	 * \brief Tries to lock the semaphore until given time point.
	 *
	 * Similar to sem_timedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html#
	 *
	 * If the semaphore is already locked, the calling thread shall block until the semaphore becomes available as in
	 * wait() function. If the semaphore cannot be locked without waiting for another thread to unlock the semaphore,
	 * this wait shall be terminated when the specified timeout expires.
	 *
	 * Under no circumstance shall the function fail with a timeout if the semaphore can be locked immediately. The
	 * validity of the timePoint parameter need not be checked if the semaphore can be locked immediately.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] timePoint is the time point at which the wait will be terminated without locking the semaphore
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
	 */

	int tryWaitUntil(TickClock::time_point timePoint);

	/**
	 * \brief Tries to lock the semaphore until given time point.
	 *
	 * Template variant of tryWaitUntil(TickClock::time_point timePoint).
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \tparam Duration is a std::chrono::duration type used to measure duration
	 *
	 * \param [in] timePoint is the time point at which the wait will be terminated without locking the semaphore
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
	 */

	template<typename Duration>
	int tryWaitUntil(const std::chrono::time_point<TickClock, Duration> timePoint)
	{
		return tryWaitUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint));
	}

	/**
	 * \brief Locks the semaphore.
	 *
	 * Similar to sem_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
	 *
	 * This function shall lock the semaphore by performing a semaphore lock operation on that semaphore. If the
	 * semaphore value is currently zero, then the calling thread shall not return from the call to lock() until it
	 * either locks the semaphore or the call is interrupted by a signal. Upon successful return, the state of the
	 * semaphore shall be locked and shall remain locked until unlock() function is executed.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 */

	int wait();

	Semaphore(const Semaphore&) = delete;
	Semaphore(Semaphore&&) = default;
	const Semaphore& operator=(const Semaphore&) = delete;
	Semaphore& operator=(Semaphore&&) = delete;

private:

	/**
	 * \brief Internal version of tryWait().
	 *
	 * Internal version with no interrupt masking.
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EAGAIN - semaphore was already locked, so it cannot be immediately locked by the tryWait() operation;
	 */

	int tryWaitInternal();

	/// ThreadControlBlock objects blocked on this semaphore
	internal::ThreadList blockedList_;

	/// internal value of the semaphore
	Value value_;

	/// max value of the semaphore
	Value maxValue_;
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SEMAPHORE_HPP_
<commit_msg>Add Semaphore::getMaxValue()<commit_after>/**
 * \file
 * \brief Semaphore class header
 *
 * \author Copyright (C) 2014-2019 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_SEMAPHORE_HPP_
#define INCLUDE_DISTORTOS_SEMAPHORE_HPP_

#include "distortos/internal/scheduler/ThreadList.hpp"

#include "distortos/TickClock.hpp"

namespace distortos
{

/**
 * \brief Semaphore is the basic synchronization primitive
 *
 * Similar to POSIX semaphores - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
 *
 * \ingroup synchronization
 */

class Semaphore
{
public:

	/// type used for semaphore's "value"
	using Value = unsigned int;

	/**
	 * \brief Semaphore's constructor
	 *
	 * Similar to sem_init() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html#
	 *
	 * \param [in] value is the initial value of the semaphore, if this value is greater than maxValue, it will be
	 * truncated
	 * \param [in] maxValue is the max value of the semaphore before post() returns EOVERFLOW, default - max for Value
	 * type
	 */

	constexpr explicit Semaphore(const Value value, const Value maxValue = std::numeric_limits<Value>::max()) :
			blockedList_{},
			value_{value < maxValue ? value : maxValue},
			maxValue_{maxValue}
	{

	}

	/**
	 * \brief Semaphore's destructor
	 *
	 * Similar to sem_destroy() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html#
	 *
	 * It is safe to destroy a semaphore upon which no threads are currently blocked. The effect of destroying a
	 * semaphore upon which other threads are currently blocked is system error.
	 */

	~Semaphore() = default;

	/**
	 * \return max value of the semaphore
	 */

	Value getMaxValue() const
	{
		return maxValue_;
	}

	/**
	 * \brief Gets current value of semaphore.
	 *
	 * Similar to sem_getvalue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html#
	 *
	 * \return current value of semaphore, positive value if semaphore is not locked, 0 otherwise
	 */

	Value getValue() const
	{
		return value_;
	}

	/**
	 * \brief Unlocks the semaphore.
	 *
	 * Similar to sem_post() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html#
	 *
	 * This function shall unlock the semaphore by performing a semaphore unlock operation. If the semaphore value
	 * resulting from this operation is positive, then no threads were blocked waiting for the semaphore to become
	 * unlocked; the semaphore value is simply incremented. Otherwise one of the threads blocked waiting for the
	 * semaphore shall be allowed to return successfully from its call to lock() - the highest priority waiting thread
	 * shall be unblocked, and if there is more than one highest priority thread blocked waiting for the semaphore, then
	 * the highest priority thread that has been waiting the longest shall be unblocked.
	 *
	 * \return 0 if the calling process successfully "posted" the semaphore, error code otherwise:
	 * - EOVERFLOW - the maximum allowable value for a semaphore would be exceeded;
	 */

	int post();

	/**
	 * \brief Tries to lock the semaphore.
	 *
	 * Similar to sem_trywait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
	 *
	 * This function shall lock the semaphore only if the semaphore is currently not locked; that is, if the semaphore
	 * value is currently positive. Otherwise, it shall not lock the semaphore. Upon successful return, the state of the
	 * semaphore shall be locked and shall remain locked until unlock() function is executed.
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EAGAIN - semaphore was already locked, so it cannot be immediately locked by the tryWait() operation;
	 */

	int tryWait();

	/**
	 * \brief Tries to lock the semaphore for given duration of time.
	 *
	 * Similar to sem_timedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html#
	 *
	 * If the semaphore is already locked, the calling thread shall block until the semaphore becomes available as in
	 * wait() function. If the semaphore cannot be locked without waiting for another thread to unlock the semaphore,
	 * this wait shall be terminated when the specified timeout expires.
	 *
	 * Under no circumstance shall the function fail with a timeout if the semaphore can be locked immediately. The
	 * validity of the duration parameter need not be checked if the semaphore can be locked immediately.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] duration is the duration after which the wait will be terminated without locking the semaphore
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
	 */

	int tryWaitFor(TickClock::duration duration);

	/**
	 * \brief Tries to lock the semaphore for given duration of time.
	 *
	 * Template variant of tryWaitFor(TickClock::duration duration).
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \tparam Rep is type of tick counter
	 * \tparam Period is std::ratio type representing the tick period of the clock, seconds
	 *
	 * \param [in] duration is the duration after which the wait will be terminated without locking the semaphore
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
	 */

	template<typename Rep, typename Period>
	int tryWaitFor(const std::chrono::duration<Rep, Period> duration)
	{
		return tryWaitFor(std::chrono::duration_cast<TickClock::duration>(duration));
	}

	/**
	 * \brief Tries to lock the semaphore until given time point.
	 *
	 * Similar to sem_timedwait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html#
	 *
	 * If the semaphore is already locked, the calling thread shall block until the semaphore becomes available as in
	 * wait() function. If the semaphore cannot be locked without waiting for another thread to unlock the semaphore,
	 * this wait shall be terminated when the specified timeout expires.
	 *
	 * Under no circumstance shall the function fail with a timeout if the semaphore can be locked immediately. The
	 * validity of the timePoint parameter need not be checked if the semaphore can be locked immediately.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] timePoint is the time point at which the wait will be terminated without locking the semaphore
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
	 */

	int tryWaitUntil(TickClock::time_point timePoint);

	/**
	 * \brief Tries to lock the semaphore until given time point.
	 *
	 * Template variant of tryWaitUntil(TickClock::time_point timePoint).
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \tparam Duration is a std::chrono::duration type used to measure duration
	 *
	 * \param [in] timePoint is the time point at which the wait will be terminated without locking the semaphore
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - ETIMEDOUT - the semaphore could not be locked before the specified timeout expired;
	 */

	template<typename Duration>
	int tryWaitUntil(const std::chrono::time_point<TickClock, Duration> timePoint)
	{
		return tryWaitUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint));
	}

	/**
	 * \brief Locks the semaphore.
	 *
	 * Similar to sem_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html#
	 *
	 * This function shall lock the semaphore by performing a semaphore lock operation on that semaphore. If the
	 * semaphore value is currently zero, then the calling thread shall not return from the call to lock() until it
	 * either locks the semaphore or the call is interrupted by a signal. Upon successful return, the state of the
	 * semaphore shall be locked and shall remain locked until unlock() function is executed.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 */

	int wait();

	Semaphore(const Semaphore&) = delete;
	Semaphore(Semaphore&&) = default;
	const Semaphore& operator=(const Semaphore&) = delete;
	Semaphore& operator=(Semaphore&&) = delete;

private:

	/**
	 * \brief Internal version of tryWait().
	 *
	 * Internal version with no interrupt masking.
	 *
	 * \return 0 if the calling process successfully performed the semaphore lock operation, error code otherwise:
	 * - EAGAIN - semaphore was already locked, so it cannot be immediately locked by the tryWait() operation;
	 */

	int tryWaitInternal();

	/// ThreadControlBlock objects blocked on this semaphore
	internal::ThreadList blockedList_;

	/// internal value of the semaphore
	Value value_;

	/// max value of the semaphore
	Value maxValue_;
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SEMAPHORE_HPP_
<|endoftext|>


<commit_before>#include "Config.hpp"
#include "Exception.hpp"
#include "Utility.hpp"
#include <fstream>

// Includes needed to get path of dynamic library
#ifdef _WIN32
#include <windows.h>
#else
#define __USE_GNU 1
#include <dlfcn.h>
#endif

namespace fast {

std::string Config::getPath() {
    if(mBasePath != "")
        return mBasePath;
    std::string path;
	std::string slash = "/";
    // Find path of the FAST dynamic library
    // The fast_configuration.txt file should lie in the folder below
#ifdef _WIN32
    // http://stackoverflow.com/questions/6924195/get-dll-path-at-runtime
    HMODULE hm = NULL;

    if(!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
            (LPCSTR) &localFunc,
            &hm)) {
        int ret = GetLastError();
        throw Exception("Error reading dyanmic library address in getPath()");
    }
    char dlpath[MAX_PATH];
    GetModuleFileNameA(hm, path, sizeof(path));
#else
    // http://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded
    Dl_info dl_info;
    int ret = dladdr((void *)&Config::getPath, &dl_info);
    if(ret == 0)
        throw Exception("Error reading dynamic library address in getPath()");
    const char* dlpath = dl_info.dli_fname;
#endif
    // Find last / and remove binary name
    path = std::string(dlpath);
    int lastSlashPos = path.rfind(slash);
    path = path.substr(0, lastSlashPos);
    lastSlashPos = path.rfind(slash);
    path = path.substr(0, lastSlashPos);
    path = path + slash;

    return path;
}

// Initialize statics
bool Config::mConfigurationLoaded = false;
std::string Config::mConfigFilename = "";
std::string Config::mBasePath = "";

// Default paths
std::string Config::mTestDataPath = getPath() + "../data/";
std::string Config::mKernelSourcePath = getPath() + "../source/FAST/";
std::string Config::mKernelBinaryPath = getPath() + "kernel_binaries/";
std::string Config::mDocumentationPath = getPath() + "../doc/";
std::string Config::mPipelinePath = getPath() + "../pipelines/";

std::string Config::getTestDataPath() {
    loadConfiguration();
    return mTestDataPath;
}

std::string Config::getKernelSourcePath() {
    loadConfiguration();
    return mKernelSourcePath;
}

std::string Config::getKernelBinaryPath() {
    loadConfiguration();
    return mKernelBinaryPath;
}

std::string Config::getDocumentationPath() {
    loadConfiguration();
    return mDocumentationPath;
}

std::string Config::getPipelinePath() {
    loadConfiguration();
    return mPipelinePath;
}

void Config::setConfigFilename(std::string filename) {
    mConfigFilename = filename;
    loadConfiguration();
}

void Config::setBasePath(std::string path) {
    mBasePath = path;
    if(mBasePath[mBasePath.size()-1] != '/')
        mBasePath += "/";
    mTestDataPath = getPath() + "../data/";
    mKernelSourcePath = getPath() + "../source/FAST/";
    mKernelBinaryPath = getPath() + "kernel_binaries/";
    mDocumentationPath = getPath() + "../doc/";
    mPipelinePath = getPath() + "../pipelines/";
    loadConfiguration();
}

void Config::loadConfiguration() {
    if(mConfigurationLoaded)
        return;

    // Read and parse configuration file
    // It should reside in the build folder when compiling, and in the root folder when using release
    std::string filename;
    if(mConfigFilename == "") {
        filename = getPath() + "fast_configuration.txt";
    } else {
        filename = mConfigFilename;
    }
    //std::string filename = "/home/smistad/workspace/FAST/build_Debug/lib/fast_configuration.txt";
    std::ifstream file(filename);
    if(!file.is_open()) {
        Reporter::warning() << "Unable to open the configuration file " << filename << ". Using defaults instead." << Reporter::end;
        mConfigurationLoaded = true;
        return;
    }
    Reporter::info() << "Loaded configuration file: " << filename << Reporter::end;

    std::string line;
    std::getline(file, line);
    while(!file.eof()) {
        trim(line);
        if(line[0] == '#' || line.size() == 0) {
            // Comment or empty line, skip
            std::getline(file, line);
            continue;
        }
        std::vector<std::string> list = split(line, "=");
        if(list.size() != 2) {
            throw Exception("Error parsing configuration file. Expected key = value pair, got: " + line);
        }

        std::string key = list[0];
        std::string value = list[1];
        trim(key);
        trim(value);
        value = replace(value, "@ROOT@", getPath());

        if(key == "TestDataPath") {
            mTestDataPath = value;
        } else if(key == "KernelSourcePath") {
            mKernelSourcePath = value;
        } else if(key == "KernelBinaryPath") {
            mKernelBinaryPath = value;
        } else if(key == "DocumentationPath") {
            mDocumentationPath = value;
        } else if(key == "PipelinePath") {
            mPipelinePath = value;
        } else {
            throw Exception("Error parsing configuration file. Unrecognized key: " + key);
        }

        std::getline(file, line);
    }
    file.close();

    Reporter::info() << "Test data path: " << mTestDataPath << Reporter::end;
    Reporter::info() << "Kernel source path: " << mKernelSourcePath << Reporter::end;
    Reporter::info() << "Kernel binary path: " << mKernelBinaryPath << Reporter::end;
    Reporter::info() << "Documentation path: " << mDocumentationPath << Reporter::end;
    Reporter::info() << "Pipeline path: " << mPipelinePath << Reporter::end;

    mConfigurationLoaded = true;
}

}; // end namespace fast
<commit_msg>output path in config<commit_after>#include "Config.hpp"
#include "Exception.hpp"
#include "Utility.hpp"
#include <fstream>

// Includes needed to get path of dynamic library
#ifdef _WIN32
#include <windows.h>
#else
#define __USE_GNU 1
#include <dlfcn.h>
#endif

namespace fast {

std::string Config::getPath() {
    if(mBasePath != "")
        return mBasePath;
    std::string path;
	std::string slash = "/";
    // Find path of the FAST dynamic library
    // The fast_configuration.txt file should lie in the folder below
#ifdef _WIN32
    // http://stackoverflow.com/questions/6924195/get-dll-path-at-runtime
    HMODULE hm = NULL;

    if(!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
            (LPCSTR) &localFunc,
            &hm)) {
        int ret = GetLastError();
        throw Exception("Error reading dyanmic library address in getPath()");
    }
    char dlpath[MAX_PATH];
    GetModuleFileNameA(hm, path, sizeof(path));
#else
    // http://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded
    Dl_info dl_info;
    int ret = dladdr((void *)&Config::getPath, &dl_info);
    if(ret == 0)
        throw Exception("Error reading dynamic library address in getPath()");
    const char* dlpath = dl_info.dli_fname;
#endif
    path = std::string(dlpath);
    std::cout << path << std::endl;

    // Remove lib name
    int lastSlashPos = path.rfind(slash);
    path = path.substr(0, lastSlashPos);
    std::cout << path << std::endl;

    // Remove lib folder from path
    lastSlashPos = path.rfind(slash);
    path = path.substr(0, lastSlashPos);
    std::cout << path << std::endl;
#if defined(__APPLE__) || defined(__MACOSX)
    // Remove one more on mac
    lastSlashPos = path.rfind(slash);
    path = path.substr(0, lastSlashPos);
#endif
    path = path + slash;

    return path;
}

// Initialize statics
bool Config::mConfigurationLoaded = false;
std::string Config::mConfigFilename = "";
std::string Config::mBasePath = "";

// Default paths
std::string Config::mTestDataPath = getPath() + "../data/";
std::string Config::mKernelSourcePath = getPath() + "../source/FAST/";
std::string Config::mKernelBinaryPath = getPath() + "kernel_binaries/";
std::string Config::mDocumentationPath = getPath() + "../doc/";
std::string Config::mPipelinePath = getPath() + "../pipelines/";

std::string Config::getTestDataPath() {
    loadConfiguration();
    return mTestDataPath;
}

std::string Config::getKernelSourcePath() {
    loadConfiguration();
    return mKernelSourcePath;
}

std::string Config::getKernelBinaryPath() {
    loadConfiguration();
    return mKernelBinaryPath;
}

std::string Config::getDocumentationPath() {
    loadConfiguration();
    return mDocumentationPath;
}

std::string Config::getPipelinePath() {
    loadConfiguration();
    return mPipelinePath;
}

void Config::setConfigFilename(std::string filename) {
    mConfigFilename = filename;
    loadConfiguration();
}

void Config::setBasePath(std::string path) {
    mBasePath = path;
    if(mBasePath[mBasePath.size()-1] != '/')
        mBasePath += "/";
    mTestDataPath = getPath() + "../data/";
    mKernelSourcePath = getPath() + "../source/FAST/";
    mKernelBinaryPath = getPath() + "kernel_binaries/";
    mDocumentationPath = getPath() + "../doc/";
    mPipelinePath = getPath() + "../pipelines/";
    loadConfiguration();
}

void Config::loadConfiguration() {
    if(mConfigurationLoaded)
        return;

    // Read and parse configuration file
    // It should reside in the build folder when compiling, and in the root folder when using release
    std::string filename;
    if(mConfigFilename == "") {
        filename = getPath() + "fast_configuration.txt";
    } else {
        filename = mConfigFilename;
    }
    //std::string filename = "/home/smistad/workspace/FAST/build_Debug/lib/fast_configuration.txt";
    std::ifstream file(filename);
    if(!file.is_open()) {
        Reporter::warning() << "Unable to open the configuration file " << filename << ". Using defaults instead." << Reporter::end;
        mConfigurationLoaded = true;
        return;
    }
    Reporter::info() << "Loaded configuration file: " << filename << Reporter::end;

    std::string line;
    std::getline(file, line);
    while(!file.eof()) {
        trim(line);
        if(line[0] == '#' || line.size() == 0) {
            // Comment or empty line, skip
            std::getline(file, line);
            continue;
        }
        std::vector<std::string> list = split(line, "=");
        if(list.size() != 2) {
            throw Exception("Error parsing configuration file. Expected key = value pair, got: " + line);
        }

        std::string key = list[0];
        std::string value = list[1];
        trim(key);
        trim(value);
        value = replace(value, "@ROOT@", getPath());

        if(key == "TestDataPath") {
            mTestDataPath = value;
        } else if(key == "KernelSourcePath") {
            mKernelSourcePath = value;
        } else if(key == "KernelBinaryPath") {
            mKernelBinaryPath = value;
        } else if(key == "DocumentationPath") {
            mDocumentationPath = value;
        } else if(key == "PipelinePath") {
            mPipelinePath = value;
        } else {
            throw Exception("Error parsing configuration file. Unrecognized key: " + key);
        }

        std::getline(file, line);
    }
    file.close();

    Reporter::info() << "Test data path: " << mTestDataPath << Reporter::end;
    Reporter::info() << "Kernel source path: " << mKernelSourcePath << Reporter::end;
    Reporter::info() << "Kernel binary path: " << mKernelBinaryPath << Reporter::end;
    Reporter::info() << "Documentation path: " << mDocumentationPath << Reporter::end;
    Reporter::info() << "Pipeline path: " << mPipelinePath << Reporter::end;

    mConfigurationLoaded = true;
}

}; // end namespace fast
<|endoftext|>


<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <fclaw2d_forestclaw.h>
#include <fclaw2d_clawpatch.h>
#include <fclaw2d_domain.h>
#include <fclaw2d_regrid.h>
#include <fclaw2d_vtable.h>
#include <fclaw2d_partition.h>

#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif

static
void  cb_partition_transfer(fclaw2d_domain_t * old_domain,
                            fclaw2d_patch_t * old_patch,
                            fclaw2d_domain_t * new_domain,
                            fclaw2d_patch_t * new_patch,
                            int blockno,
                            int old_patchno, int new_patchno,
                            void *user)
{
    fclaw2d_domain_data_t *ddata_old = fclaw2d_domain_get_data (old_domain);
    fclaw2d_domain_data_t *ddata_new = fclaw2d_domain_get_data (new_domain);

    if (old_patch != NULL)
    {
        FCLAW_ASSERT(old_patch->xlower == new_patch->xlower);
        FCLAW_ASSERT(old_patch->ylower == new_patch->ylower);
        FCLAW_ASSERT(old_patch->xupper == new_patch->xupper);
        FCLAW_ASSERT(old_patch->yupper == new_patch->yupper);

        new_patch->user = old_patch->user;
        old_patch->user = NULL;
        ++ddata_old->count_delete_clawpatch;
        ++ddata_new->count_set_clawpatch;
    }
    else
    {
        /* We need to rebuild the patch from scratch. 'user' contains
           the packed data received from remote processor. */
        cb_fclaw2d_clawpatch_partition_unpack(new_domain,new_patch,
                                              blockno,new_patchno,user);
    }
}

/* --------------------------------------------------------------------------
   Public interface
   -------------------------------------------------------------------------- */
/* Question : Do all patches on this processor get packed? */
void fclaw2d_partition_domain(fclaw2d_domain_t** domain, int mode)
{
    char basename[BUFSIZ];

    /* will need to access the subcyle switch */
    const amr_options_t *gparms = get_domain_parms(*domain);

    /* allocate memory for parallel transfor of patches
       use data size (in bytes per patch) below. */
    size_t data_size = fclaw2d_clawpatch_partition_packsize(*domain);
    void ** patch_data = NULL;

    fclaw2d_domain_allocate_before_partition (*domain, data_size,
                                              &patch_data);

    /* For all (patch i) { pack its numerical data into patch_data[i] }
       Does all the data in every patch need to be copied?  */
    fclaw2d_domain_iterate_patches(*domain,
                                   cb_fclaw2d_clawpatch_partition_pack,
                                   (void *) patch_data);

    /* this call creates a new domain that is valid after partitioning
       and transfers the data packed above to the new owner processors */
    int exponent = gparms->subcycle && !gparms->noweightedp ? 1 : 0;
    fclaw2d_domain_t *domain_partitioned =
        fclaw2d_domain_partition (*domain, exponent);

    fclaw_bool have_new_partition = domain_partitioned != NULL;

    if (have_new_partition)
    {
        fclaw2d_domain_setup(*domain, domain_partitioned);

        /* update patch array to point to the numerical data that was received */
        fclaw2d_domain_retrieve_after_partition (domain_partitioned,&patch_data);

        /* TODO: for all (patch i) { unpack numerical data from patch_data[i] } */
        fclaw2d_domain_data_t* ddata = fclaw2d_domain_get_data(domain_partitioned);
        fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_BUILDPARTITION]);

        /* Old version */
        fclaw2d_domain_iterate_patches(domain_partitioned,
                                       cb_fclaw2d_clawpatch_partition_unpack,
                                       (void *) patch_data);

#if 0
        /* New version? */
        fclaw2d_domain_iterate_partitioned(*domain,domain_partitioned,
                                           cb_partition_transfer,
                                           NULL);
#endif

        fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_BUILDPARTITION]);

        /* then the old domain is no longer necessary */
        fclaw2d_domain_reset(domain);
        *domain = domain_partitioned;
        domain_partitioned = NULL;

        /* VTK output during amrinit */
        if (mode >= 0 && gparms->vtkout & 1) {
            // into timer
            fclaw2d_domain_data_t *ddata = fclaw2d_domain_get_data (*domain);
            fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_INIT]);
            fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);

            // output
            snprintf (basename, BUFSIZ, "%s_init_level_%02d_partition",
                      gparms->prefix, mode);
            fclaw2d_output_write_vtk (*domain, basename);

            // out of timer
            fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);
            fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_INIT]);
        }

        /* internal clean up */
        fclaw2d_domain_complete(*domain);
    }

    /* free the data that was used in the parallel transfer of patches */
    fclaw2d_domain_free_after_partition (*domain, &patch_data);
}

#ifdef __cplusplus
#if 0
{
#endif
}
#endif
<commit_msg>add new partition iterator<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <fclaw2d_forestclaw.h>
#include <fclaw2d_clawpatch.h>
#include <fclaw2d_domain.h>
#include <fclaw2d_regrid.h>
#include <fclaw2d_vtable.h>
#include <fclaw2d_partition.h>

#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif

static
void  cb_partition_transfer(fclaw2d_domain_t * old_domain,
                            fclaw2d_patch_t * old_patch,
                            fclaw2d_domain_t * new_domain,
                            fclaw2d_patch_t * new_patch,
                            int blockno,
                            int old_patchno, int new_patchno,
                            void *user)
{
    fclaw2d_domain_data_t *ddata_old = fclaw2d_domain_get_data (old_domain);
    fclaw2d_domain_data_t *ddata_new = fclaw2d_domain_get_data (new_domain);

    if (old_patch != NULL)
    {
        FCLAW_ASSERT(old_patch->xlower == new_patch->xlower);
        FCLAW_ASSERT(old_patch->ylower == new_patch->ylower);
        FCLAW_ASSERT(old_patch->xupper == new_patch->xupper);
        FCLAW_ASSERT(old_patch->yupper == new_patch->yupper);

        new_patch->user = old_patch->user;
        old_patch->user = NULL;
        ++ddata_old->count_delete_clawpatch;
        ++ddata_new->count_set_clawpatch;
    }
    else
    {
        /* We need to rebuild the patch from scratch. 'user' contains
           the packed data received from remote processor. */
        cb_fclaw2d_clawpatch_partition_unpack(new_domain,new_patch,
                                              blockno,new_patchno,user);
    }
}

/* --------------------------------------------------------------------------
   Public interface
   -------------------------------------------------------------------------- */
/* Question : Do all patches on this processor get packed? */
void fclaw2d_partition_domain(fclaw2d_domain_t** domain, int mode)
{
    char basename[BUFSIZ];

    /* will need to access the subcyle switch */
    const amr_options_t *gparms = get_domain_parms(*domain);

    /* allocate memory for parallel transfor of patches
       use data size (in bytes per patch) below. */
    size_t data_size = fclaw2d_clawpatch_partition_packsize(*domain);
    void ** patch_data = NULL;

    fclaw2d_domain_allocate_before_partition (*domain, data_size,
                                              &patch_data);

    /* For all (patch i) { pack its numerical data into patch_data[i] }
       Does all the data in every patch need to be copied?  */
    fclaw2d_domain_iterate_patches(*domain,
                                   cb_fclaw2d_clawpatch_partition_pack,
                                   (void *) patch_data);

    /* this call creates a new domain that is valid after partitioning
       and transfers the data packed above to the new owner processors */
    int exponent = gparms->subcycle && !gparms->noweightedp ? 1 : 0;
    fclaw2d_domain_t *domain_partitioned =
        fclaw2d_domain_partition (*domain, exponent);

    fclaw_bool have_new_partition = domain_partitioned != NULL;

    if (have_new_partition)
    {
        fclaw2d_domain_setup(*domain, domain_partitioned);

        /* update patch array to point to the numerical data that was received */
        fclaw2d_domain_retrieve_after_partition (domain_partitioned,&patch_data);

        /* TODO: for all (patch i) { unpack numerical data from patch_data[i] } */
        fclaw2d_domain_data_t* ddata = fclaw2d_domain_get_data(domain_partitioned);
        fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_BUILDPARTITION]);

#if 0
        /* Old version */
        fclaw2d_domain_iterate_patches(domain_partitioned,
                                       cb_fclaw2d_clawpatch_partition_unpack,
                                       (void *) patch_data);
#endif

        /* New version? */
        fclaw2d_domain_iterate_partitioned(*domain,domain_partitioned,
                                           cb_partition_transfer,
                                           (void*) patch_data);

        fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_BUILDPARTITION]);

        /* then the old domain is no longer necessary */
        fclaw2d_domain_reset(domain);
        *domain = domain_partitioned;
        domain_partitioned = NULL;

        /* VTK output during amrinit */
        if (mode >= 0 && gparms->vtkout & 1) {
            // into timer
            fclaw2d_domain_data_t *ddata = fclaw2d_domain_get_data (*domain);
            fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_INIT]);
            fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);

            // output
            snprintf (basename, BUFSIZ, "%s_init_level_%02d_partition",
                      gparms->prefix, mode);
            fclaw2d_output_write_vtk (*domain, basename);

            // out of timer
            fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);
            fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_INIT]);
        }

        /* internal clean up */
        fclaw2d_domain_complete(*domain);
    }

    /* free the data that was used in the parallel transfer of patches */
    fclaw2d_domain_free_after_partition (*domain, &patch_data);
}

#ifdef __cplusplus
#if 0
{
#endif
}
#endif
<|endoftext|>


<commit_before>//
// PROJECT:         Aspia Remote Desktop
// FILE:            base/desktop.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "base/desktop.h"
#include "base/logging.h"

namespace aspia {

Desktop::Desktop(HDESK desktop, bool own)
    : desktop_(desktop), own_(own)
{
    // Nothing
}

Desktop::~Desktop()
{
    if (own_ && desktop_)
    {
        if (!CloseDesktop(desktop_))
        {
            LOG(ERROR) << "Failed to close the owned desktop handle: "
                       << GetLastSystemErrorString();
        }
    }
}

bool Desktop::GetName(WCHAR* name, DWORD length) const
{
    if (!desktop_)
        return false;

    if (!GetUserObjectInformationW(desktop_, UOI_NAME, name, length, nullptr))
    {
        LOG(ERROR) << "Failed to query the desktop name: "
                   << GetLastSystemErrorString();
        return false;
    }

    return true;
}

bool Desktop::IsSame(const Desktop& other) const
{
    WCHAR name[128];

    if (!GetName(name, sizeof(name)))
        return false;

    WCHAR other_name[128];

    if (!other.GetName(other_name, sizeof(other_name)))
        return false;

    return wcscmp(name, other_name) == 0;
}

bool Desktop::SetThreadDesktop() const
{
    if (!::SetThreadDesktop(desktop_))
    {
        LOG(ERROR) << "Failed to assign the desktop to the current thread: "
                   << GetLastSystemErrorString();
        return false;
    }

    return true;
}

Desktop* Desktop::GetDesktop(const WCHAR* desktop_name)
{
    ACCESS_MASK desired_access =
        DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
        DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
        DESKTOP_SWITCHDESKTOP | GENERIC_WRITE;
    HDESK desktop = OpenDesktop(desktop_name, 0, FALSE, desired_access);
    if (!desktop)
    {
        LOG(ERROR) << "Failed to open the desktop '" << desktop_name << "': "
                   << GetLastSystemErrorString();
        return nullptr;
    }

    return new Desktop(desktop, true);
}

Desktop* Desktop::GetInputDesktop()
{
    HDESK desktop = OpenInputDesktop(
        0, FALSE, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
    if (!desktop)
        return nullptr;

    return new Desktop(desktop, true);
}

Desktop* Desktop::GetThreadDesktop()
{
    HDESK desktop = ::GetThreadDesktop(GetCurrentThreadId());
    if (!desktop)
    {
        LOG(ERROR) << "Failed to retrieve the handle of the desktop assigned to "
                      "the current thread: "
                   << GetLastSystemErrorString();
        return nullptr;
    }

    return new Desktop(desktop, false);
}

} // namespace aspia
<commit_msg>- Using OpenDesktopW instead OpenDesktop<commit_after>//
// PROJECT:         Aspia Remote Desktop
// FILE:            base/desktop.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "base/desktop.h"
#include "base/logging.h"

namespace aspia {

Desktop::Desktop(HDESK desktop, bool own)
    : desktop_(desktop), own_(own)
{
    // Nothing
}

Desktop::~Desktop()
{
    if (own_ && desktop_)
    {
        if (!CloseDesktop(desktop_))
        {
            LOG(ERROR) << "Failed to close the owned desktop handle: "
                       << GetLastSystemErrorString();
        }
    }
}

bool Desktop::GetName(WCHAR* name, DWORD length) const
{
    if (!desktop_)
        return false;

    if (!GetUserObjectInformationW(desktop_, UOI_NAME, name, length, nullptr))
    {
        LOG(ERROR) << "Failed to query the desktop name: "
                   << GetLastSystemErrorString();
        return false;
    }

    return true;
}

bool Desktop::IsSame(const Desktop& other) const
{
    WCHAR name[128];

    if (!GetName(name, sizeof(name)))
        return false;

    WCHAR other_name[128];

    if (!other.GetName(other_name, sizeof(other_name)))
        return false;

    return wcscmp(name, other_name) == 0;
}

bool Desktop::SetThreadDesktop() const
{
    if (!::SetThreadDesktop(desktop_))
    {
        LOG(ERROR) << "Failed to assign the desktop to the current thread: "
                   << GetLastSystemErrorString();
        return false;
    }

    return true;
}

Desktop* Desktop::GetDesktop(const WCHAR* desktop_name)
{
    ACCESS_MASK desired_access =
        DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
        DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
        DESKTOP_SWITCHDESKTOP | GENERIC_WRITE;
    HDESK desktop = OpenDesktopW(desktop_name, 0, FALSE, desired_access);
    if (!desktop)
    {
        LOG(ERROR) << "Failed to open the desktop '" << desktop_name << "': "
                   << GetLastSystemErrorString();
        return nullptr;
    }

    return new Desktop(desktop, true);
}

Desktop* Desktop::GetInputDesktop()
{
    HDESK desktop = OpenInputDesktop(
        0, FALSE, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
    if (!desktop)
        return nullptr;

    return new Desktop(desktop, true);
}

Desktop* Desktop::GetThreadDesktop()
{
    HDESK desktop = ::GetThreadDesktop(GetCurrentThreadId());
    if (!desktop)
    {
        LOG(ERROR) << "Failed to retrieve the handle of the desktop assigned to "
                      "the current thread: "
                   << GetLastSystemErrorString();
        return nullptr;
    }

    return new Desktop(desktop, false);
}

} // namespace aspia
<|endoftext|>