<commit_before>// Copyright (c) 2009-2018 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

#include "IntegratorHPMC.h"

namespace py = pybind11;

#include "hoomd/VectorMath.h"
#include <sstream>

using namespace std;

/*! \file IntegratorHPMC.cc
    \brief Definition of common methods for HPMC integrators
*/

namespace hpmc
{

IntegratorHPMC::IntegratorHPMC(std::shared_ptr<SystemDefinition> sysdef,
                               unsigned int seed)
    : Integrator(sysdef, 0.005), m_seed(seed),  m_move_ratio(32768), m_nselect(4),
      m_nominal_width(1.0), m_extra_ghost_width(0), m_external_base(NULL), m_patch_log(false),
      m_jit_force_log(false), m_past_first_run(false)
      #ifdef ENABLE_MPI
      ,m_communicator_ghost_width_connected(false),
      m_communicator_flags_connected(false)
      #endif
    {
    m_exec_conf->msg->notice(5) << "Constructing IntegratorHPMC" << endl;

    // broadcast the seed from rank 0 to all other ranks.
    #ifdef ENABLE_MPI
        if(this->m_pdata->getDomainDecomposition())
            bcast(m_seed, 0, this->m_exec_conf->getMPICommunicator());
    #endif

    GPUArray<hpmc_counters_t> counters(1, this->m_exec_conf);
    m_count_total.swap(counters);

    GPUVector<Scalar> d(this->m_pdata->getNTypes(), this->m_exec_conf);
    m_d.swap(d);

    GPUVector<Scalar> a(this->m_pdata->getNTypes(), this->m_exec_conf);
    m_a.swap(a);

    ArrayHandle<Scalar> h_d(m_d, access_location::host, access_mode::overwrite);
    ArrayHandle<Scalar> h_a(m_a, access_location::host, access_mode::overwrite);
    //set default values
    for(unsigned int typ=0; typ < this->m_pdata->getNTypes(); typ++)
      {
      h_d.data[typ]=0.1;
      h_a.data[typ]=0.1;
      }

    // Connect to number of types change signal
    m_pdata->getNumTypesChangeSignal().connect<IntegratorHPMC, &IntegratorHPMC::slotNumTypesChange>(this);

    resetStats();
    }

IntegratorHPMC::~IntegratorHPMC()
    {
    m_exec_conf->msg->notice(5) << "Destroying IntegratorHPMC" << endl;
    m_pdata->getNumTypesChangeSignal().disconnect<IntegratorHPMC, &IntegratorHPMC::slotNumTypesChange>(this);

    #ifdef ENABLE_MPI
    if (m_communicator_ghost_width_connected)
        m_comm->getGhostLayerWidthRequestSignal().disconnect<IntegratorHPMC, &IntegratorHPMC::getGhostLayerWidth>(this);
    if (m_communicator_flags_connected)
        m_comm->getCommFlagsRequestSignal().disconnect<IntegratorHPMC, &IntegratorHPMC::getCommFlags>(this);
    #endif
    }

void IntegratorHPMC::slotNumTypesChange()
    {
    // old size of arrays
    unsigned int old_ntypes = m_a.size();
    assert(m_a.size() == m_d.size());

    unsigned int ntypes = m_pdata->getNTypes();

    m_a.resize(ntypes);
    m_d.resize(ntypes);

    //set default values for newly added types
    ArrayHandle<Scalar> h_d(m_d, access_location::host, access_mode::readwrite);
    ArrayHandle<Scalar> h_a(m_a, access_location::host, access_mode::readwrite);
    for(unsigned int typ=old_ntypes; typ < ntypes; typ++)
        {
        h_d.data[typ]=0.1;
        h_a.data[typ]=0.1;
        }
    }

/*! IntegratorHPMC provides:
    - hpmc_sweep (Number of sweeps completed)
    - hpmc_translate_acceptance (Ratio of translation moves accepted in the last step)
    - hpmc_rotate_acceptance (Ratio of rotation moves accepted in the last step)
    - hpmc_d (maximum move displacement)
    - hpmc_a (maximum rotation move)
    - hpmc_d_<typename> (maximum move displacement by type)
    - hpmc_a_<typename> (maximum rotation move by type)
    - hpmc_move_ratio (ratio of translation moves to rotate moves)
    - hpmc_overlap_count (count of the number of particle-particle overlaps)

    \returns a list of provided quantities
*/
std::vector< std::string > IntegratorHPMC::getProvidedLogQuantities()
    {
    // start with the integrator provided quantities
    std::vector< std::string > result = Integrator::getProvidedLogQuantities();
    // then add ours
    result.push_back("hpmc_sweep");
    result.push_back("hpmc_translate_acceptance");
    result.push_back("hpmc_rotate_acceptance");
    result.push_back("hpmc_d");
    result.push_back("hpmc_a");
    result.push_back("hpmc_move_ratio");
    result.push_back("hpmc_overlap_count");
    for (unsigned int typ=0; typ<m_pdata->getNTypes();typ++)
      {
      ostringstream tmp_str0;
      tmp_str0<<"hpmc_d_"<<m_pdata->getNameByType(typ);
      result.push_back(tmp_str0.str());

      ostringstream tmp_str1;
      tmp_str1<<"hpmc_a_"<<m_pdata->getNameByType(typ);
      result.push_back(tmp_str1.str());
      }
    return result;
    }

/*! \param quantity Name of the log quantity to get
    \param timestep Current time step of the simulation
    \return the requested log quantity.
*/
Scalar IntegratorHPMC::getLogValue(const std::string& quantity, unsigned int timestep)
    {
    hpmc_counters_t counters = getCounters(2);

    if (quantity == "hpmc_sweep")
        {
        hpmc_counters_t counters_total = getCounters(0);
        return double(counters_total.getNMoves()) / double(m_pdata->getNGlobal());
        }
    else if (quantity == "hpmc_translate_acceptance")
        {
        return counters.getTranslateAcceptance();
        }
    else if (quantity == "hpmc_rotate_acceptance")
        {
        return counters.getRotateAcceptance();
        }
    else if (quantity == "hpmc_d")
        {
        ArrayHandle<Scalar> h_d(m_d, access_location::host, access_mode::read);
        return h_d.data[0];
        }
    else if (quantity == "hpmc_a")
        {
        ArrayHandle<Scalar> h_a(m_a, access_location::host, access_mode::read);
        return h_a.data[0];
        }
    else if (quantity == "hpmc_move_ratio")
        {
        return getMoveRatio();
        }
    else if (quantity == "hpmc_overlap_count")
        {
        return countOverlaps(timestep, false);
        }
    else
        {
        //loop over per particle move size quantities
        for (unsigned int typ=0; typ<m_pdata->getNTypes();typ++)
          {
          ostringstream tmp_str0;
          tmp_str0<<"hpmc_d_"<<m_pdata->getNameByType(typ);
          if (quantity==tmp_str0.str())
            {
            ArrayHandle<Scalar> h_d(m_d, access_location::host, access_mode::read);
            return h_d.data[typ];
            }

          ostringstream tmp_str1;
          tmp_str1<<"hpmc_a_"<<m_pdata->getNameByType(typ);
          if (quantity==tmp_str1.str())
            {
            ArrayHandle<Scalar> h_a(m_a, access_location::host, access_mode::read);
            return h_a.data[typ];
            }
          }

        //nothing found -> pass on to integrator
        return Integrator::getLogValue(quantity, timestep);
        }
    }

/*! \returns True if the particle orientations are normalized
*/
bool IntegratorHPMC::checkParticleOrientations()
    {
    // get the orientations data array
    ArrayHandle<Scalar4> h_orientation(m_pdata->getOrientationArray(), access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_tag(m_pdata->getTags(), access_location::host, access_mode::read);
    bool result = true;

    // loop through particles and return false if any is out of norm
    for (unsigned int i = 0; i < m_pdata->getN(); i++)
        {
        quat<Scalar> o(h_orientation.data[i]);
        if (fabs(Scalar(1.0) - norm2(o)) > 1e-3)
            {
            m_exec_conf->msg->notice(2) << "Particle " << h_tag.data[i] << " has an unnormalized orientation" << endl;
            result = false;
            }
        }

    #ifdef ENABLE_MPI
    unsigned int result_int = (unsigned int)result;
    unsigned int result_reduced;
    MPI_Reduce(&result_int, &result_reduced, 1, MPI_UNSIGNED, MPI_LOR, 0, m_exec_conf->getMPICommunicator());
    result = bool(result_reduced);
    #endif

    return result;
    }

/*! Set new box with particle positions scaled from previous box
    and check for overlaps

    \param newBox new box dimensions

    \note The particle positions and the box dimensions are updated in any case, even if the
    new box dimensions result in overlaps. To restore old particle positions,
    they have to be backed up before calling this method.

    \returns false if resize results in overlaps
*/
bool IntegratorHPMC::attemptBoxResize(unsigned int timestep, const BoxDim& new_box)
    {
    unsigned int N = m_pdata->getN();

    // Get old and new boxes;
    BoxDim curBox = m_pdata->getGlobalBox();

    // Use lexical scope block to make sure ArrayHandles get cleaned up
        {
        // Get particle positions
        ArrayHandle<Scalar4> h_pos(m_pdata->getPositions(), access_location::host, access_mode::readwrite);

        // move the particles to be inside the new box
        for (unsigned int i = 0; i < N; i++)
            {
            Scalar3 old_pos = make_scalar3(h_pos.data[i].x, h_pos.data[i].y, h_pos.data[i].z);

            // obtain scaled coordinates in the old global box
            Scalar3 f = curBox.makeFraction(old_pos);

            // scale particles
            Scalar3 scaled_pos = new_box.makeCoordinates(f);
            h_pos.data[i].x = scaled_pos.x;
            h_pos.data[i].y = scaled_pos.y;
            h_pos.data[i].z = scaled_pos.z;
            }
        } // end lexical scope

    m_pdata->setGlobalBox(new_box);

    // we have moved particles, communicate those changes
    this->communicate(false);

    // check overlaps
    return !this->countOverlaps(timestep, true);
    }

/*! \param mode 0 -> Absolute count, 1 -> relative to the start of the run, 2 -> relative to the last executed step
    \return The current state of the acceptance counters

    IntegratorHPMC maintains a count of the number of accepted and rejected moves since instantiation. getCounters()
    provides the current value. The parameter *mode* controls whether the returned counts are absolute, relative
    to the start of the run, or relative to the start of the last executed step.
*/
hpmc_counters_t IntegratorHPMC::getCounters(unsigned int mode)
    {
    ArrayHandle<hpmc_counters_t> h_counters(m_count_total, access_location::host, access_mode::read);
    hpmc_counters_t result;

    if (mode == 0)
        result = h_counters.data[0];
    else if (mode == 1)
        result = h_counters.data[0] - m_count_run_start;
    else
        result = h_counters.data[0] - m_count_step_start;

#ifdef ENABLE_MPI
    if (m_comm)
        {
        // MPI Reduction to total result values on all nodes.
        MPI_Allreduce(MPI_IN_PLACE, &result.translate_accept_count, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.translate_reject_count, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.rotate_accept_count, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.rotate_reject_count, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.overlap_checks, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.overlap_err_count, 1, MPI_UNSIGNED, MPI_SUM, m_exec_conf->getMPICommunicator());
        }
#endif
    return result;
    }

void export_IntegratorHPMC(py::module& m)
    {
   py::class_<IntegratorHPMC, std::shared_ptr< IntegratorHPMC > >(m, "IntegratorHPMC", py::base<Integrator>())
    .def(py::init< std::shared_ptr<SystemDefinition>, unsigned int >())
    .def("setD", &IntegratorHPMC::setD)
    .def("setA", &IntegratorHPMC::setA)
    .def("setMoveRatio", &IntegratorHPMC::setMoveRatio)
    .def("setNSelect", &IntegratorHPMC::setNSelect)
    .def("getD", &IntegratorHPMC::getD)
    .def("getA", &IntegratorHPMC::getA)
    .def("getMoveRatio", &IntegratorHPMC::getMoveRatio)
    .def("getNSelect", &IntegratorHPMC::getNSelect)
    .def("getMaxCoreDiameter", &IntegratorHPMC::getMaxCoreDiameter)
    .def("countOverlaps", &IntegratorHPMC::countOverlaps)
    .def("checkParticleOrientations", &IntegratorHPMC::checkParticleOrientations)
    .def("getMPS", &IntegratorHPMC::getMPS)
    .def("getCounters", &IntegratorHPMC::getCounters)
    .def("communicate", &IntegratorHPMC::communicate)
    .def("slotNumTypesChange", &IntegratorHPMC::slotNumTypesChange)
    .def("setDeterministic", &IntegratorHPMC::setDeterministic)
    .def("disablePatchEnergyLogOnly", &IntegratorHPMC::disablePatchEnergyLogOnly)
    .def("disableForceEnergyLogOnly", &IntegratorHPMC::disablePatchEnergyLogOnly)
    ;

   py::class_< hpmc_counters_t >(m, "hpmc_counters_t")
    .def_readwrite("translate_accept_count", &hpmc_counters_t::translate_accept_count)
    .def_readwrite("translate_reject_count", &hpmc_counters_t::translate_reject_count)
    .def_readwrite("rotate_accept_count", &hpmc_counters_t::rotate_accept_count)
    .def_readwrite("rotate_reject_count", &hpmc_counters_t::rotate_reject_count)
    .def_readwrite("overlap_checks", &hpmc_counters_t::overlap_checks)
    .def("getTranslateAcceptance", &hpmc_counters_t::getTranslateAcceptance)
    .def("getRotateAcceptance", &hpmc_counters_t::getRotateAcceptance)
    .def("getNMoves", &hpmc_counters_t::getNMoves)
    ;
    }

} // end namespace hpmc
<commit_msg>Fix another typo<commit_after>// Copyright (c) 2009-2018 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

#include "IntegratorHPMC.h"

namespace py = pybind11;

#include "hoomd/VectorMath.h"
#include <sstream>

using namespace std;

/*! \file IntegratorHPMC.cc
    \brief Definition of common methods for HPMC integrators
*/

namespace hpmc
{

IntegratorHPMC::IntegratorHPMC(std::shared_ptr<SystemDefinition> sysdef,
                               unsigned int seed)
    : Integrator(sysdef, 0.005), m_seed(seed),  m_move_ratio(32768), m_nselect(4),
      m_nominal_width(1.0), m_extra_ghost_width(0), m_external_base(NULL), m_patch_log(false),
      m_jit_force_log(false), m_past_first_run(false)
      #ifdef ENABLE_MPI
      ,m_communicator_ghost_width_connected(false),
      m_communicator_flags_connected(false)
      #endif
    {
    m_exec_conf->msg->notice(5) << "Constructing IntegratorHPMC" << endl;

    // broadcast the seed from rank 0 to all other ranks.
    #ifdef ENABLE_MPI
        if(this->m_pdata->getDomainDecomposition())
            bcast(m_seed, 0, this->m_exec_conf->getMPICommunicator());
    #endif

    GPUArray<hpmc_counters_t> counters(1, this->m_exec_conf);
    m_count_total.swap(counters);

    GPUVector<Scalar> d(this->m_pdata->getNTypes(), this->m_exec_conf);
    m_d.swap(d);

    GPUVector<Scalar> a(this->m_pdata->getNTypes(), this->m_exec_conf);
    m_a.swap(a);

    ArrayHandle<Scalar> h_d(m_d, access_location::host, access_mode::overwrite);
    ArrayHandle<Scalar> h_a(m_a, access_location::host, access_mode::overwrite);
    //set default values
    for(unsigned int typ=0; typ < this->m_pdata->getNTypes(); typ++)
      {
      h_d.data[typ]=0.1;
      h_a.data[typ]=0.1;
      }

    // Connect to number of types change signal
    m_pdata->getNumTypesChangeSignal().connect<IntegratorHPMC, &IntegratorHPMC::slotNumTypesChange>(this);

    resetStats();
    }

IntegratorHPMC::~IntegratorHPMC()
    {
    m_exec_conf->msg->notice(5) << "Destroying IntegratorHPMC" << endl;
    m_pdata->getNumTypesChangeSignal().disconnect<IntegratorHPMC, &IntegratorHPMC::slotNumTypesChange>(this);

    #ifdef ENABLE_MPI
    if (m_communicator_ghost_width_connected)
        m_comm->getGhostLayerWidthRequestSignal().disconnect<IntegratorHPMC, &IntegratorHPMC::getGhostLayerWidth>(this);
    if (m_communicator_flags_connected)
        m_comm->getCommFlagsRequestSignal().disconnect<IntegratorHPMC, &IntegratorHPMC::getCommFlags>(this);
    #endif
    }

void IntegratorHPMC::slotNumTypesChange()
    {
    // old size of arrays
    unsigned int old_ntypes = m_a.size();
    assert(m_a.size() == m_d.size());

    unsigned int ntypes = m_pdata->getNTypes();

    m_a.resize(ntypes);
    m_d.resize(ntypes);

    //set default values for newly added types
    ArrayHandle<Scalar> h_d(m_d, access_location::host, access_mode::readwrite);
    ArrayHandle<Scalar> h_a(m_a, access_location::host, access_mode::readwrite);
    for(unsigned int typ=old_ntypes; typ < ntypes; typ++)
        {
        h_d.data[typ]=0.1;
        h_a.data[typ]=0.1;
        }
    }

/*! IntegratorHPMC provides:
    - hpmc_sweep (Number of sweeps completed)
    - hpmc_translate_acceptance (Ratio of translation moves accepted in the last step)
    - hpmc_rotate_acceptance (Ratio of rotation moves accepted in the last step)
    - hpmc_d (maximum move displacement)
    - hpmc_a (maximum rotation move)
    - hpmc_d_<typename> (maximum move displacement by type)
    - hpmc_a_<typename> (maximum rotation move by type)
    - hpmc_move_ratio (ratio of translation moves to rotate moves)
    - hpmc_overlap_count (count of the number of particle-particle overlaps)

    \returns a list of provided quantities
*/
std::vector< std::string > IntegratorHPMC::getProvidedLogQuantities()
    {
    // start with the integrator provided quantities
    std::vector< std::string > result = Integrator::getProvidedLogQuantities();
    // then add ours
    result.push_back("hpmc_sweep");
    result.push_back("hpmc_translate_acceptance");
    result.push_back("hpmc_rotate_acceptance");
    result.push_back("hpmc_d");
    result.push_back("hpmc_a");
    result.push_back("hpmc_move_ratio");
    result.push_back("hpmc_overlap_count");
    for (unsigned int typ=0; typ<m_pdata->getNTypes();typ++)
      {
      ostringstream tmp_str0;
      tmp_str0<<"hpmc_d_"<<m_pdata->getNameByType(typ);
      result.push_back(tmp_str0.str());

      ostringstream tmp_str1;
      tmp_str1<<"hpmc_a_"<<m_pdata->getNameByType(typ);
      result.push_back(tmp_str1.str());
      }
    return result;
    }

/*! \param quantity Name of the log quantity to get
    \param timestep Current time step of the simulation
    \return the requested log quantity.
*/
Scalar IntegratorHPMC::getLogValue(const std::string& quantity, unsigned int timestep)
    {
    hpmc_counters_t counters = getCounters(2);

    if (quantity == "hpmc_sweep")
        {
        hpmc_counters_t counters_total = getCounters(0);
        return double(counters_total.getNMoves()) / double(m_pdata->getNGlobal());
        }
    else if (quantity == "hpmc_translate_acceptance")
        {
        return counters.getTranslateAcceptance();
        }
    else if (quantity == "hpmc_rotate_acceptance")
        {
        return counters.getRotateAcceptance();
        }
    else if (quantity == "hpmc_d")
        {
        ArrayHandle<Scalar> h_d(m_d, access_location::host, access_mode::read);
        return h_d.data[0];
        }
    else if (quantity == "hpmc_a")
        {
        ArrayHandle<Scalar> h_a(m_a, access_location::host, access_mode::read);
        return h_a.data[0];
        }
    else if (quantity == "hpmc_move_ratio")
        {
        return getMoveRatio();
        }
    else if (quantity == "hpmc_overlap_count")
        {
        return countOverlaps(timestep, false);
        }
    else
        {
        //loop over per particle move size quantities
        for (unsigned int typ=0; typ<m_pdata->getNTypes();typ++)
          {
          ostringstream tmp_str0;
          tmp_str0<<"hpmc_d_"<<m_pdata->getNameByType(typ);
          if (quantity==tmp_str0.str())
            {
            ArrayHandle<Scalar> h_d(m_d, access_location::host, access_mode::read);
            return h_d.data[typ];
            }

          ostringstream tmp_str1;
          tmp_str1<<"hpmc_a_"<<m_pdata->getNameByType(typ);
          if (quantity==tmp_str1.str())
            {
            ArrayHandle<Scalar> h_a(m_a, access_location::host, access_mode::read);
            return h_a.data[typ];
            }
          }

        //nothing found -> pass on to integrator
        return Integrator::getLogValue(quantity, timestep);
        }
    }

/*! \returns True if the particle orientations are normalized
*/
bool IntegratorHPMC::checkParticleOrientations()
    {
    // get the orientations data array
    ArrayHandle<Scalar4> h_orientation(m_pdata->getOrientationArray(), access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_tag(m_pdata->getTags(), access_location::host, access_mode::read);
    bool result = true;

    // loop through particles and return false if any is out of norm
    for (unsigned int i = 0; i < m_pdata->getN(); i++)
        {
        quat<Scalar> o(h_orientation.data[i]);
        if (fabs(Scalar(1.0) - norm2(o)) > 1e-3)
            {
            m_exec_conf->msg->notice(2) << "Particle " << h_tag.data[i] << " has an unnormalized orientation" << endl;
            result = false;
            }
        }

    #ifdef ENABLE_MPI
    unsigned int result_int = (unsigned int)result;
    unsigned int result_reduced;
    MPI_Reduce(&result_int, &result_reduced, 1, MPI_UNSIGNED, MPI_LOR, 0, m_exec_conf->getMPICommunicator());
    result = bool(result_reduced);
    #endif

    return result;
    }

/*! Set new box with particle positions scaled from previous box
    and check for overlaps

    \param newBox new box dimensions

    \note The particle positions and the box dimensions are updated in any case, even if the
    new box dimensions result in overlaps. To restore old particle positions,
    they have to be backed up before calling this method.

    \returns false if resize results in overlaps
*/
bool IntegratorHPMC::attemptBoxResize(unsigned int timestep, const BoxDim& new_box)
    {
    unsigned int N = m_pdata->getN();

    // Get old and new boxes;
    BoxDim curBox = m_pdata->getGlobalBox();

    // Use lexical scope block to make sure ArrayHandles get cleaned up
        {
        // Get particle positions
        ArrayHandle<Scalar4> h_pos(m_pdata->getPositions(), access_location::host, access_mode::readwrite);

        // move the particles to be inside the new box
        for (unsigned int i = 0; i < N; i++)
            {
            Scalar3 old_pos = make_scalar3(h_pos.data[i].x, h_pos.data[i].y, h_pos.data[i].z);

            // obtain scaled coordinates in the old global box
            Scalar3 f = curBox.makeFraction(old_pos);

            // scale particles
            Scalar3 scaled_pos = new_box.makeCoordinates(f);
            h_pos.data[i].x = scaled_pos.x;
            h_pos.data[i].y = scaled_pos.y;
            h_pos.data[i].z = scaled_pos.z;
            }
        } // end lexical scope

    m_pdata->setGlobalBox(new_box);

    // we have moved particles, communicate those changes
    this->communicate(false);

    // check overlaps
    return !this->countOverlaps(timestep, true);
    }

/*! \param mode 0 -> Absolute count, 1 -> relative to the start of the run, 2 -> relative to the last executed step
    \return The current state of the acceptance counters

    IntegratorHPMC maintains a count of the number of accepted and rejected moves since instantiation. getCounters()
    provides the current value. The parameter *mode* controls whether the returned counts are absolute, relative
    to the start of the run, or relative to the start of the last executed step.
*/
hpmc_counters_t IntegratorHPMC::getCounters(unsigned int mode)
    {
    ArrayHandle<hpmc_counters_t> h_counters(m_count_total, access_location::host, access_mode::read);
    hpmc_counters_t result;

    if (mode == 0)
        result = h_counters.data[0];
    else if (mode == 1)
        result = h_counters.data[0] - m_count_run_start;
    else
        result = h_counters.data[0] - m_count_step_start;

#ifdef ENABLE_MPI
    if (m_comm)
        {
        // MPI Reduction to total result values on all nodes.
        MPI_Allreduce(MPI_IN_PLACE, &result.translate_accept_count, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.translate_reject_count, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.rotate_accept_count, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.rotate_reject_count, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.overlap_checks, 1, MPI_LONG_LONG_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
        MPI_Allreduce(MPI_IN_PLACE, &result.overlap_err_count, 1, MPI_UNSIGNED, MPI_SUM, m_exec_conf->getMPICommunicator());
        }
#endif
    return result;
    }

void export_IntegratorHPMC(py::module& m)
    {
   py::class_<IntegratorHPMC, std::shared_ptr< IntegratorHPMC > >(m, "IntegratorHPMC", py::base<Integrator>())
    .def(py::init< std::shared_ptr<SystemDefinition>, unsigned int >())
    .def("setD", &IntegratorHPMC::setD)
    .def("setA", &IntegratorHPMC::setA)
    .def("setMoveRatio", &IntegratorHPMC::setMoveRatio)
    .def("setNSelect", &IntegratorHPMC::setNSelect)
    .def("getD", &IntegratorHPMC::getD)
    .def("getA", &IntegratorHPMC::getA)
    .def("getMoveRatio", &IntegratorHPMC::getMoveRatio)
    .def("getNSelect", &IntegratorHPMC::getNSelect)
    .def("getMaxCoreDiameter", &IntegratorHPMC::getMaxCoreDiameter)
    .def("countOverlaps", &IntegratorHPMC::countOverlaps)
    .def("checkParticleOrientations", &IntegratorHPMC::checkParticleOrientations)
    .def("getMPS", &IntegratorHPMC::getMPS)
    .def("getCounters", &IntegratorHPMC::getCounters)
    .def("communicate", &IntegratorHPMC::communicate)
    .def("slotNumTypesChange", &IntegratorHPMC::slotNumTypesChange)
    .def("setDeterministic", &IntegratorHPMC::setDeterministic)
    .def("disablePatchEnergyLogOnly", &IntegratorHPMC::disablePatchEnergyLogOnly)
    .def("disableForceEnergyLogOnly", &IntegratorHPMC::disableForceEnergyLogOnly)
    ;

   py::class_< hpmc_counters_t >(m, "hpmc_counters_t")
    .def_readwrite("translate_accept_count", &hpmc_counters_t::translate_accept_count)
    .def_readwrite("translate_reject_count", &hpmc_counters_t::translate_reject_count)
    .def_readwrite("rotate_accept_count", &hpmc_counters_t::rotate_accept_count)
    .def_readwrite("rotate_reject_count", &hpmc_counters_t::rotate_reject_count)
    .def_readwrite("overlap_checks", &hpmc_counters_t::overlap_checks)
    .def("getTranslateAcceptance", &hpmc_counters_t::getTranslateAcceptance)
    .def("getRotateAcceptance", &hpmc_counters_t::getRotateAcceptance)
    .def("getNMoves", &hpmc_counters_t::getNMoves)
    ;
    }

} // end namespace hpmc
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: vcldata.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: ihi $ $Date: 2007-07-10 15:19:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _SV_SETTINGS_HXX
#include <vcl/settings.hxx>
#endif

#ifndef _SVTOOLS_SVTDATA_HXX
#include <svtools/svtdata.hxx>
#endif

//============================================================================
//
//  class ImpSvtData
//
//============================================================================

ResMgr * ImpSvtData::GetResMgr()
{
    return GetResMgr(Application::GetSettings().GetUILocale());
}

ResMgr * ImpSvtData::GetPatchResMgr()
{
    return GetPatchResMgr(Application::GetSettings().GetUILocale());
}

SvpResId::SvpResId( USHORT nId ) :
    ResId( nId, *ImpSvtData::GetSvtData().GetPatchResMgr() )
{
}

<commit_msg>INTEGRATION: CWS changefileheader (1.9.228); FILE MERGED 2008/04/01 15:45:20 thb 1.9.228.3: #i85898# Stripping all external header guards 2008/04/01 12:43:49 thb 1.9.228.2: #i85898# Stripping all external header guards 2008/03/31 13:02:19 rt 1.9.228.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: vcldata.cxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
#include <svtools/svtdata.hxx>

//============================================================================
//
//  class ImpSvtData
//
//============================================================================

ResMgr * ImpSvtData::GetResMgr()
{
    return GetResMgr(Application::GetSettings().GetUILocale());
}

ResMgr * ImpSvtData::GetPatchResMgr()
{
    return GetPatchResMgr(Application::GetSettings().GetUILocale());
}

SvpResId::SvpResId( USHORT nId ) :
    ResId( nId, *ImpSvtData::GetSvtData().GetPatchResMgr() )
{
}

<|endoftext|>


<commit_before>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gst/gst.h>

#include "KmsHttpLoop.h"

#define NAME "httploop"

GST_DEBUG_CATEGORY_STATIC (kms_http_loop_debug_category);
#define GST_CAT_DEFAULT kms_http_loop_debug_category

G_DEFINE_TYPE_WITH_CODE (KmsHttpLoop, kms_http_loop,
                         G_TYPE_OBJECT,
                         GST_DEBUG_CATEGORY_INIT (kms_http_loop_debug_category,
                             NAME, 0, "debug category for kurento loop") )

#define KMS_HTTP_LOOP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), KMS_TYPE_HTTP_LOOP, KmsHttpLoopPrivate))

struct _KmsHttpLoopPrivate {
  GThread *thread;
  GRecMutex rmutex;
  GMainLoop *loop;
  GMainContext *context;
  GCond cond;
  GMutex mutex;
  gboolean initialized;
};

#define KMS_HTTP_LOOP_LOCK(elem) \
  (g_rec_mutex_lock (&KMS_HTTP_LOOP ((elem))->priv->rmutex))
#define KMS_HTTP_LOOP_UNLOCK(elem) \
  (g_rec_mutex_unlock (&KMS_HTTP_LOOP ((elem))->priv->rmutex))

/* Object properties */
enum {
  PROP_0,
  PROP_CONTEXT,
  N_PROPERTIES
};

static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };

static gboolean
quit_main_loop (GMainLoop *loop)
{
  GST_DEBUG ("Exiting main loop");

  g_main_loop_quit (loop);

  return G_SOURCE_REMOVE;
}

static gpointer
loop_thread_init (gpointer data)
{
  KmsHttpLoop *self = KMS_HTTP_LOOP (data);
  GMainLoop *loop;
  GMainContext *context;

  KMS_HTTP_LOOP_LOCK (self);
  self->priv->context = g_main_context_new ();
  context = self->priv->context;
  self->priv->loop = g_main_loop_new (context, FALSE);
  loop = self->priv->loop;
  KMS_HTTP_LOOP_UNLOCK (self);

  /* unlock main process because context is already initialized */
  g_mutex_lock (&self->priv->mutex);
  self->priv->initialized = TRUE;
  g_cond_signal (&self->priv->cond);
  g_mutex_unlock (&self->priv->mutex);

  if (!g_main_context_acquire (context) ) {
    GST_ERROR ("Can not acquire context");
    goto end;
  }

  GST_DEBUG ("Running main loop");
  g_main_loop_run (loop);
  g_main_context_release (context);

end:
  GST_DEBUG ("Thread finished");
  g_main_context_unref (context);
  g_main_loop_unref (loop);

  return NULL;
}

static void
kms_http_loop_get_property (GObject *object, guint property_id, GValue *value,
                            GParamSpec *pspec)
{
  KmsHttpLoop *self = KMS_HTTP_LOOP (object);

  KMS_HTTP_LOOP_LOCK (self);

  switch (property_id) {
  case PROP_CONTEXT:
    g_value_set_boxed (value, self->priv->context);
    break;

  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    break;
  }

  KMS_HTTP_LOOP_UNLOCK (self);
}

static void
kms_http_loop_dispose (GObject *obj)
{
  KmsHttpLoop *self = KMS_HTTP_LOOP (obj);

  GST_DEBUG_OBJECT (obj, "Dispose");

  KMS_HTTP_LOOP_LOCK (self);

  if (self->priv->thread != NULL) {
    if (g_thread_self () != self->priv->thread) {
      GThread *aux = self->priv->thread;

      kms_http_loop_idle_add (self, (GSourceFunc) quit_main_loop,
                              self->priv->loop);
      self->priv->thread = NULL;
      KMS_HTTP_LOOP_UNLOCK (self);
      g_thread_join (aux);
      KMS_HTTP_LOOP_LOCK (self);
    } else {
      /* self thread does not need to wait for itself */
      quit_main_loop (self->priv->loop);
      g_thread_unref (self->priv->thread);
      self->priv->thread = NULL;
    }
  }

  KMS_HTTP_LOOP_UNLOCK (self);

  G_OBJECT_CLASS (kms_http_loop_parent_class)->dispose (obj);
}

static void
kms_http_loop_finalize (GObject *obj)
{
  KmsHttpLoop *self = KMS_HTTP_LOOP (obj);

  GST_DEBUG_OBJECT (obj, "Finalize");

  g_rec_mutex_clear (&self->priv->rmutex);
  g_mutex_clear (&self->priv->mutex);
  g_cond_clear (&self->priv->cond);

  G_OBJECT_CLASS (kms_http_loop_parent_class)->finalize (obj);
}

static void
kms_http_loop_class_init (KmsHttpLoopClass *klass)
{
  GObjectClass *objclass = G_OBJECT_CLASS (klass);

  objclass->dispose = kms_http_loop_dispose;
  objclass->finalize = kms_http_loop_finalize;
  objclass->get_property = kms_http_loop_get_property;

  /* Install properties */
  obj_properties[PROP_CONTEXT] = g_param_spec_boxed ("context",
                                 "Main loop context",
                                 "Main loop context",
                                 G_TYPE_MAIN_CONTEXT,
                                 (GParamFlags) (G_PARAM_READABLE) );

  g_object_class_install_properties (objclass, N_PROPERTIES, obj_properties);

  /* Registers a private structure for the instantiatable type */
  g_type_class_add_private (klass, sizeof (KmsHttpLoopPrivate) );
}

static void
kms_http_loop_init (KmsHttpLoop *self)
{
  self->priv = KMS_HTTP_LOOP_GET_PRIVATE (self);
  g_rec_mutex_init (&self->priv->rmutex);
  g_cond_init (&self->priv->cond);
  g_mutex_init (&self->priv->mutex);

  self->priv->thread = g_thread_new ("KmsHttpLoop", loop_thread_init, self);

  g_mutex_lock (&self->priv->mutex);

  while (!self->priv->initialized) {
    g_cond_wait (&self->priv->cond, &self->priv->mutex);
  }

  g_mutex_unlock (&self->priv->mutex);
}

KmsHttpLoop *
kms_http_loop_new (void)
{
  return KMS_HTTP_LOOP (g_object_new (KMS_TYPE_HTTP_LOOP, NULL) );
}

static guint
kms_http_loop_attach (KmsHttpLoop *self, GSource *source, gint priority,
                      GSourceFunc function, gpointer data,
                      GDestroyNotify notify)
{
  guint id;

  KMS_HTTP_LOOP_LOCK (self);

  if (self->priv->thread == NULL) {
    KMS_HTTP_LOOP_UNLOCK (self);
    return 0;
  }

  g_source_set_priority (source, priority);
  g_source_set_callback (source, function, data, notify);
  id = g_source_attach (source, self->priv->context);

  KMS_HTTP_LOOP_UNLOCK (self);

  return id;
}

guint
kms_http_loop_idle_add_full (KmsHttpLoop *self, gint priority,
                             GSourceFunc function,
                             gpointer data, GDestroyNotify notify)
{
  GSource *source;
  guint id;

  if (!KMS_IS_HTTP_LOOP (self) ) {
    return 0;
  }

  source = g_idle_source_new ();
  id = kms_http_loop_attach (self, source, priority, function, data, notify);
  g_source_unref (source);

  return id;
}

guint
kms_http_loop_idle_add (KmsHttpLoop *self, GSourceFunc function, gpointer data)
{
  return kms_http_loop_idle_add_full (self, G_PRIORITY_DEFAULT_IDLE, function,
                                      data,
                                      NULL);
}

guint
kms_http_loop_timeout_add_full (KmsHttpLoop *self, gint priority,
                                guint interval,
                                GSourceFunc function, gpointer data,
                                GDestroyNotify notify)
{
  GSource *source;
  guint id;

  if (!KMS_IS_HTTP_LOOP (self) ) {
    return 0;
  }

  source = g_timeout_source_new (interval);
  id = kms_http_loop_attach (self, source, priority, function, data, notify);
  g_source_unref (source);

  return id;
}

guint
kms_http_loop_timeout_add (KmsHttpLoop *self, guint interval,
                           GSourceFunc function,
                           gpointer data)
{
  return kms_http_loop_timeout_add_full (self, G_PRIORITY_DEFAULT, interval,
                                         function, data, NULL);
}

gboolean
kms_http_loop_remove (KmsHttpLoop *self, guint source_id)
{
  GSource *source;

  source = g_main_context_find_source_by_id (self->priv->context, source_id);

  if (source == NULL) {
    return FALSE;
  }

  g_source_destroy (source);
  return TRUE;
}

gboolean
kms_http_loop_is_current_thread (KmsHttpLoop *self)
{
  return (g_thread_self() == self->priv->thread);
}<commit_msg>KmsHttpLoop: Fix bad read while disposing kmsloop<commit_after>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gst/gst.h>

#include "KmsHttpLoop.h"

#define NAME "httploop"

GST_DEBUG_CATEGORY_STATIC (kms_http_loop_debug_category);
#define GST_CAT_DEFAULT kms_http_loop_debug_category

G_DEFINE_TYPE_WITH_CODE (KmsHttpLoop, kms_http_loop,
                         G_TYPE_OBJECT,
                         GST_DEBUG_CATEGORY_INIT (kms_http_loop_debug_category,
                             NAME, 0, "debug category for kurento loop") )

#define KMS_HTTP_LOOP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), KMS_TYPE_HTTP_LOOP, KmsHttpLoopPrivate))

struct _KmsHttpLoopPrivate {
  GThread *thread;
  GRecMutex rmutex;
  GMainLoop *loop;
  GMainContext *context;
  GCond cond;
  GMutex mutex;
  gboolean initialized;
};

#define KMS_HTTP_LOOP_LOCK(elem) \
  (g_rec_mutex_lock (&KMS_HTTP_LOOP ((elem))->priv->rmutex))
#define KMS_HTTP_LOOP_UNLOCK(elem) \
  (g_rec_mutex_unlock (&KMS_HTTP_LOOP ((elem))->priv->rmutex))

/* Object properties */
enum {
  PROP_0,
  PROP_CONTEXT,
  N_PROPERTIES
};

static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };

static gboolean
quit_main_loop (KmsHttpLoop *self)
{
  GST_DEBUG ("Exiting main loop");

  g_main_loop_quit (self->priv->loop);
  g_main_context_release (self->priv->context);

  return G_SOURCE_REMOVE;
}

static gpointer
loop_thread_init (gpointer data)
{
  KmsHttpLoop *self = KMS_HTTP_LOOP (data);
  GMainLoop *loop;
  GMainContext *context;

  KMS_HTTP_LOOP_LOCK (self);
  self->priv->context = g_main_context_new ();
  context = self->priv->context;
  self->priv->loop = g_main_loop_new (context, FALSE);
  loop = self->priv->loop;
  KMS_HTTP_LOOP_UNLOCK (self);

  /* unlock main process because context is already initialized */
  g_mutex_lock (&self->priv->mutex);
  self->priv->initialized = TRUE;
  g_cond_signal (&self->priv->cond);
  g_mutex_unlock (&self->priv->mutex);

  if (!g_main_context_acquire (context) ) {
    GST_ERROR ("Can not acquire context");
    goto end;
  }

  GST_DEBUG ("Running main loop");
  g_main_loop_run (loop);

end:
  GST_DEBUG ("Thread finished");

  return NULL;
}

static void
kms_http_loop_get_property (GObject *object, guint property_id, GValue *value,
                            GParamSpec *pspec)
{
  KmsHttpLoop *self = KMS_HTTP_LOOP (object);

  KMS_HTTP_LOOP_LOCK (self);

  switch (property_id) {
  case PROP_CONTEXT:
    g_value_set_boxed (value, self->priv->context);
    break;

  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    break;
  }

  KMS_HTTP_LOOP_UNLOCK (self);
}

static void
kms_http_loop_dispose (GObject *obj)
{
  KmsHttpLoop *self = KMS_HTTP_LOOP (obj);

  GST_DEBUG_OBJECT (obj, "Dispose");

  KMS_HTTP_LOOP_LOCK (self);

  if (self->priv->thread != NULL) {
    if (g_thread_self () != self->priv->thread) {
      GThread *aux = self->priv->thread;

      kms_http_loop_idle_add (self, (GSourceFunc) quit_main_loop,
                              self);
      self->priv->thread = NULL;
      KMS_HTTP_LOOP_UNLOCK (self);
      g_thread_join (aux);
      KMS_HTTP_LOOP_LOCK (self);
    } else {
      /* self thread does not need to wait for itself */
      quit_main_loop (self);
      g_thread_unref (self->priv->thread);
      self->priv->thread = NULL;
    }
  }

  KMS_HTTP_LOOP_UNLOCK (self);

  G_OBJECT_CLASS (kms_http_loop_parent_class)->dispose (obj);
}

static void
kms_http_loop_finalize (GObject *obj)
{
  KmsHttpLoop *self = KMS_HTTP_LOOP (obj);

  GST_DEBUG_OBJECT (obj, "Finalize");

  if (self->priv->context != NULL) {
    g_main_context_unref (self->priv->context);
  }

  if (self->priv->loop != NULL) {
    g_main_loop_unref (self->priv->loop);
  }

  g_rec_mutex_clear (&self->priv->rmutex);
  g_mutex_clear (&self->priv->mutex);
  g_cond_clear (&self->priv->cond);

  G_OBJECT_CLASS (kms_http_loop_parent_class)->finalize (obj);
}

static void
kms_http_loop_class_init (KmsHttpLoopClass *klass)
{
  GObjectClass *objclass = G_OBJECT_CLASS (klass);

  objclass->dispose = kms_http_loop_dispose;
  objclass->finalize = kms_http_loop_finalize;
  objclass->get_property = kms_http_loop_get_property;

  /* Install properties */
  obj_properties[PROP_CONTEXT] = g_param_spec_boxed ("context",
                                 "Main loop context",
                                 "Main loop context",
                                 G_TYPE_MAIN_CONTEXT,
                                 (GParamFlags) (G_PARAM_READABLE) );

  g_object_class_install_properties (objclass, N_PROPERTIES, obj_properties);

  /* Registers a private structure for the instantiatable type */
  g_type_class_add_private (klass, sizeof (KmsHttpLoopPrivate) );
}

static void
kms_http_loop_init (KmsHttpLoop *self)
{
  self->priv = KMS_HTTP_LOOP_GET_PRIVATE (self);
  self->priv->context = NULL;
  self->priv->loop = NULL;
  g_rec_mutex_init (&self->priv->rmutex);
  g_cond_init (&self->priv->cond);
  g_mutex_init (&self->priv->mutex);

  self->priv->thread = g_thread_new ("KmsHttpLoop", loop_thread_init, self);

  g_mutex_lock (&self->priv->mutex);

  while (!self->priv->initialized) {
    g_cond_wait (&self->priv->cond, &self->priv->mutex);
  }

  g_mutex_unlock (&self->priv->mutex);
}

KmsHttpLoop *
kms_http_loop_new (void)
{
  return KMS_HTTP_LOOP (g_object_new (KMS_TYPE_HTTP_LOOP, NULL) );
}

static guint
kms_http_loop_attach (KmsHttpLoop *self, GSource *source, gint priority,
                      GSourceFunc function, gpointer data,
                      GDestroyNotify notify)
{
  guint id;

  KMS_HTTP_LOOP_LOCK (self);

  if (self->priv->thread == NULL) {
    KMS_HTTP_LOOP_UNLOCK (self);
    return 0;
  }

  g_source_set_priority (source, priority);
  g_source_set_callback (source, function, data, notify);
  id = g_source_attach (source, self->priv->context);

  KMS_HTTP_LOOP_UNLOCK (self);

  return id;
}

guint
kms_http_loop_idle_add_full (KmsHttpLoop *self, gint priority,
                             GSourceFunc function,
                             gpointer data, GDestroyNotify notify)
{
  GSource *source;
  guint id;

  if (!KMS_IS_HTTP_LOOP (self) ) {
    return 0;
  }

  source = g_idle_source_new ();
  id = kms_http_loop_attach (self, source, priority, function, data, notify);
  g_source_unref (source);

  return id;
}

guint
kms_http_loop_idle_add (KmsHttpLoop *self, GSourceFunc function, gpointer data)
{
  return kms_http_loop_idle_add_full (self, G_PRIORITY_DEFAULT_IDLE, function,
                                      data,
                                      NULL);
}

guint
kms_http_loop_timeout_add_full (KmsHttpLoop *self, gint priority,
                                guint interval,
                                GSourceFunc function, gpointer data,
                                GDestroyNotify notify)
{
  GSource *source;
  guint id;

  if (!KMS_IS_HTTP_LOOP (self) ) {
    return 0;
  }

  source = g_timeout_source_new (interval);
  id = kms_http_loop_attach (self, source, priority, function, data, notify);
  g_source_unref (source);

  return id;
}

guint
kms_http_loop_timeout_add (KmsHttpLoop *self, guint interval,
                           GSourceFunc function,
                           gpointer data)
{
  return kms_http_loop_timeout_add_full (self, G_PRIORITY_DEFAULT, interval,
                                         function, data, NULL);
}

gboolean
kms_http_loop_remove (KmsHttpLoop *self, guint source_id)
{
  GSource *source;

  source = g_main_context_find_source_by_id (self->priv->context, source_id);

  if (source == NULL) {
    return FALSE;
  }

  g_source_destroy (source);
  return TRUE;
}

gboolean
kms_http_loop_is_current_thread (KmsHttpLoop *self)
{
  return (g_thread_self() == self->priv->thread);
}
<|endoftext|>


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

#include <memory>
#include <thread>
#include <type_traits>

#include "boost_cfg.hpp"
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>

#include "Options.hpp"
#include "PerfsTimer.hpp"
#include "iterators.hpp"
#include "likely.hpp"
#include "logging.hpp"
#include "timing.hpp"
#include "GlobalContext.hpp"

#include "ltac/Statement.hpp"

#include "mtac/pass_traits.hpp"
#include "mtac/Utils.hpp"
#include "mtac/Pass.hpp"
#include "mtac/Optimizer.hpp"
#include "mtac/Program.hpp"
#include "mtac/ControlFlowGraph.hpp"
#include "mtac/Quadruple.hpp"

//The custom optimizations
#include "mtac/conditional_propagation.hpp"
#include "mtac/remove_aliases.hpp"
#include "mtac/clean_variables.hpp"
#include "mtac/remove_unused_functions.hpp"
#include "mtac/remove_empty_functions.hpp"
#include "mtac/DeadCodeElimination.hpp"
#include "mtac/merge_basic_blocks.hpp"
#include "mtac/remove_dead_basic_blocks.hpp"
#include "mtac/BranchOptimizations.hpp"
#include "mtac/inlining.hpp"
#include "mtac/loop_analysis.hpp"
#include "mtac/induction_variable_optimizations.hpp"
#include "mtac/loop_unrolling.hpp"
#include "mtac/complete_loop_peeling.hpp"
#include "mtac/remove_empty_loops.hpp"
#include "mtac/loop_invariant_code_motion.hpp"
#include "mtac/parameter_propagation.hpp"
#include "mtac/pure_analysis.hpp"

//The optimization visitors
#include "mtac/ArithmeticIdentities.hpp"
#include "mtac/ReduceInStrength.hpp"
#include "mtac/ConstantFolding.hpp"
#include "mtac/MathPropagation.hpp"
#include "mtac/PointerPropagation.hpp"

//The data-flow problems
#include "mtac/GlobalOptimizations.hpp"
#include "mtac/ConstantPropagationProblem.hpp"
#include "mtac/OffsetConstantPropagationProblem.hpp"
#include "mtac/CommonSubexpressionElimination.hpp"

#include "ltac/Register.hpp"
#include "ltac/FloatRegister.hpp"
#include "ltac/PseudoRegister.hpp"
#include "ltac/PseudoFloatRegister.hpp"
#include "ltac/Address.hpp"

using namespace eddic;

namespace eddic {
namespace mtac {

typedef boost::mpl::vector<
        mtac::ConstantFolding*
    > basic_passes;

struct all_basic_optimizations {};

template<>
struct pass_traits<all_basic_optimizations> {
    STATIC_CONSTANT(pass_type, type, pass_type::IPA_SUB);
    STATIC_STRING(name, "all_basic_optimizations");
    STATIC_CONSTANT(unsigned int, property_flags, 0);
    STATIC_CONSTANT(unsigned int, todo_after_flags, 0);

    typedef basic_passes sub_passes;
};

typedef boost::mpl::vector<
        mtac::ArithmeticIdentities*,
        mtac::ReduceInStrength*,
        mtac::ConstantFolding*,
        mtac::conditional_propagation*,
        mtac::ConstantPropagationProblem*,
        mtac::OffsetConstantPropagationProblem*,
        mtac::CommonSubexpressionElimination*,
        mtac::PointerPropagation*,
        mtac::MathPropagation*,
        mtac::optimize_branches*,
        mtac::remove_dead_basic_blocks*,
        mtac::merge_basic_blocks*,
        mtac::dead_code_elimination*,
        mtac::remove_aliases*,
        mtac::loop_analysis*,
        mtac::loop_invariant_code_motion*,
        mtac::loop_induction_variables_optimization*,
        mtac::remove_empty_loops*,
        mtac::complete_loop_peeling*,
        mtac::loop_unrolling*,
        mtac::clean_variables*
    > passes;

struct all_optimizations {};

template<>
struct pass_traits<all_optimizations> {
    STATIC_CONSTANT(pass_type, type, pass_type::IPA_SUB);
    STATIC_STRING(name, "all_optimizations");
    STATIC_CONSTANT(unsigned int, property_flags, 0);
    STATIC_CONSTANT(unsigned int, todo_after_flags, 0);

    typedef passes sub_passes;
};

}
}

namespace {

template<typename T, typename Sign>
struct has_gate {
    typedef char yes[1];
    typedef char no [2];
    template <typename U, U> struct type_check;
    template <typename _1> static yes &chk(type_check<Sign, &_1::gate> *);
    template <typename   > static no  &chk(...);
    static bool const value = sizeof(chk<T>(0)) == sizeof(yes);
};

//TODO Find a more elegant way than using pointers

typedef boost::mpl::vector<
        mtac::all_basic_optimizations*
    > ipa_basic_passes;

typedef boost::mpl::vector<
        mtac::remove_unused_functions*,
        mtac::pure_analysis*,
        mtac::all_optimizations*,
        mtac::remove_empty_functions*,
        mtac::inline_functions*,
        mtac::parameter_propagation*
    > ipa_passes;

template<typename Pass>
struct need_pool {
    static const bool value = mtac::pass_traits<Pass>::property_flags & mtac::PROPERTY_POOL;
};

template<typename Pass>
struct need_platform {
    static const bool value = mtac::pass_traits<Pass>::property_flags & mtac::PROPERTY_PLATFORM;
};

template<typename Pass>
struct need_configuration {
    static const bool value = mtac::pass_traits<Pass>::property_flags & mtac::PROPERTY_CONFIGURATION;
};

template<typename Pass>
struct need_program {
    static const bool value = mtac::pass_traits<Pass>::property_flags & mtac::PROPERTY_PROGRAM;
};

template <bool B, typename T = void>
struct disable_if {
    typedef T type;
};

template <typename T>
struct disable_if<true,T> {
    //SFINAE
};

struct pass_runner {
    bool optimized = false;

    mtac::Program& program;
    mtac::Function* function;

    std::shared_ptr<StringPool> pool;
    std::shared_ptr<Configuration> configuration;
    Platform platform;
    timing_system& system;

    pass_runner(mtac::Program& program, std::shared_ptr<StringPool> pool, std::shared_ptr<Configuration> configuration, Platform platform, timing_system& system) :
            program(program), pool(pool), configuration(configuration), platform(platform), system(system) {};

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::todo_after_flags & mtac::TODO_REMOVE_NOP, void>::type remove_nop(){
        for(auto& block : *function){
            auto it = iterate(block->statements);

            while(it.has_next()){
                if(it->op == mtac::Operator::NOP){
                    it.erase();
                    continue;
                }

                ++it;
            }
        }
    }

    template<typename Pass>
    inline typename std::enable_if<!(mtac::pass_traits<Pass>::todo_after_flags & mtac::TODO_REMOVE_NOP), void>::type remove_nop(){
        //NOP
    }

    template<typename Pass>
    inline void apply_todo(){
        remove_nop<Pass>();
    }

    template<typename Pass>
    inline typename std::enable_if<need_pool<Pass>::value, void>::type set_pool(Pass& pass){
        pass.set_pool(pool);
    }

    template<typename Pass>
    inline typename disable_if<need_pool<Pass>::value, void>::type set_pool(Pass&){
        //NOP
    }

    template<typename Pass>
    inline typename std::enable_if<need_platform<Pass>::value, void>::type set_platform(Pass& pass){
        pass.set_platform(platform);
    }

    template<typename Pass>
    inline typename disable_if<need_platform<Pass>::value, void>::type set_platform(Pass&){
        //NOP
    }

    template<typename Pass>
    inline typename std::enable_if<need_configuration<Pass>::value, void>::type set_configuration(Pass& pass){
        pass.set_configuration(configuration);
    }

    template<typename Pass>
    inline typename disable_if<need_configuration<Pass>::value, void>::type set_configuration(Pass&){
        //NOP
    }

    template<typename Pass>
    inline typename std::enable_if<need_program<Pass>::value, Pass>::type construct(){
        return Pass(program);
    }

    template<typename Pass>
    inline typename disable_if<need_program<Pass>::value, Pass>::type construct(){
        return Pass();
    }

    template<typename Pass>
    Pass make_pass(){
        auto pass = construct<Pass>();

        set_pool(pass);
        set_platform(pass);
        set_configuration(pass);

        return pass;
    }

    template<typename Pass>
    inline typename std::enable_if<has_gate<Pass, bool(Pass::*)(std::shared_ptr<Configuration>)>::value, bool>::type has_to_be_run(Pass& pass){
        return pass.gate(configuration);
    }

    template<typename Pass>
    inline typename disable_if<has_gate<Pass, bool(Pass::*)(std::shared_ptr<Configuration>)>::value, bool>::type has_to_be_run(Pass&){
        return true;
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::IPA, bool>::type apply(Pass& pass){
        return pass(program);
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::IPA_SUB, bool>::type apply(Pass&){
        for(auto& function : program.functions){
            this->function = &function;

            if(log::enabled<Debug>()){
                LOG<Debug>("Optimizer") << "Start optimizations on " << function.get_name() << log::endl;

                std::cout << function << std::endl;
            }

            boost::mpl::for_each<typename mtac::pass_traits<Pass>::sub_passes>(boost::ref(*this));
        }

        return false;
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::CUSTOM, bool>::type apply(Pass& pass){
        return pass(*function);
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::LOCAL, bool>::type apply(Pass& visitor){
        for(auto& block : *function){
            for(auto& quadruple : block->statements){
                visitor(quadruple);
            }
        }

        return visitor.optimized;
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::DATA_FLOW, bool>::type apply(Pass& problem){
        auto results = mtac::data_flow(*function, problem);

        //Once the data-flow problem is fixed, statements can be optimized
        return problem.optimize(*function, results);
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::BB, bool>::type apply(Pass& visitor){
        bool optimized = false;

        for(auto& block : *function){
            visitor.clear();

            for(auto& quadruple : block->statements){
                visitor(quadruple);
            }

            optimized |= visitor.optimized;
        }

        return optimized;
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::BB_TWO_PASS, bool>::type apply(Pass& visitor){
        bool optimized = false;

        for(auto& block : *function){
            visitor.clear();

            visitor.pass = mtac::Pass::DATA_MINING;
            for(auto& quadruple : block->statements){
                visitor(quadruple);
            }

            visitor.pass = mtac::Pass::OPTIMIZE;
            for(auto& quadruple : block->statements){
                visitor(quadruple);
            }

            optimized |= visitor.optimized;
        }

        return optimized;
    }

    template<typename Pass>
    inline typename std::enable_if<boost::type_traits::ice_or<mtac::pass_traits<Pass>::type == mtac::pass_type::IPA, mtac::pass_traits<Pass>::type == mtac::pass_type::IPA_SUB>::value, void>::type
    debug_local(bool local){
        LOG<Debug>("Optimizer") << mtac::pass_traits<Pass>::name() << " returned " << local << log::endl;
    }

    template<typename Pass>
    inline typename std::enable_if<boost::type_traits::ice_and<mtac::pass_traits<Pass>::type != mtac::pass_type::IPA, mtac::pass_traits<Pass>::type != mtac::pass_type::IPA_SUB>::value, void>::type
    debug_local(bool local){
        if(log::enabled<Debug>()){
            if(local){
                LOG<Debug>("Optimizer") << mtac::pass_traits<Pass>::name() << " returned true" << log::endl;

                //Print the function
                std::cout << *function << std::endl;
            } else {
                LOG<Debug>("Optimizer") << mtac::pass_traits<Pass>::name() << " returned false" << log::endl;
            }
        }
    }

    template<typename Pass>
    inline void operator()(Pass*){
        auto pass = make_pass<Pass>();

        if(has_to_be_run(pass)){
            bool local = false;
            {
                PerfsTimer perfs_timer(mtac::pass_traits<Pass>::name());
                timing_timer timer(system, mtac::pass_traits<Pass>::name());

                local = apply<Pass>(pass);
            }

            if(local){
                program.context->stats().inc_counter(std::string(mtac::pass_traits<Pass>::name()) + "_true");
                apply_todo<Pass>();
            }

            debug_local<Pass>(local);

            optimized |= local;
        }
    }
};

} //end of anonymous namespace

void mtac::Optimizer::optimize(mtac::Program& program, std::shared_ptr<StringPool> string_pool, Platform platform, std::shared_ptr<Configuration> configuration) const {
    timing_system timing_system(configuration);
    PerfsTimer timer("Whole optimizations");

    //Build the CFG of each functions (also needed for register allocation)
    for(auto& function : program.functions){
        mtac::build_control_flow_graph(function);
    }

    if(configuration->option_defined("fglobal-optimization")){
        //Apply Interprocedural Optimizations
        pass_runner runner(program, string_pool, configuration, platform, timing_system);
        do{
            runner.optimized = false;
            boost::mpl::for_each<ipa_passes>(boost::ref(runner));
        } while(runner.optimized);
    } else {
        //Even if global optimizations are disabled, perform basic optimization (only constant folding)
        pass_runner runner(program, string_pool, configuration, platform, timing_system);
        boost::mpl::for_each<ipa_basic_passes>(boost::ref(runner));
    }
}
<commit_msg>Build the control flow before the optimizations<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <memory>
#include <thread>
#include <type_traits>

#include "boost_cfg.hpp"
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>

#include "Options.hpp"
#include "PerfsTimer.hpp"
#include "iterators.hpp"
#include "likely.hpp"
#include "logging.hpp"
#include "timing.hpp"
#include "GlobalContext.hpp"

#include "ltac/Statement.hpp"

#include "mtac/pass_traits.hpp"
#include "mtac/Utils.hpp"
#include "mtac/Pass.hpp"
#include "mtac/Optimizer.hpp"
#include "mtac/Program.hpp"
#include "mtac/ControlFlowGraph.hpp"
#include "mtac/Quadruple.hpp"

//The custom optimizations
#include "mtac/conditional_propagation.hpp"
#include "mtac/remove_aliases.hpp"
#include "mtac/clean_variables.hpp"
#include "mtac/remove_unused_functions.hpp"
#include "mtac/remove_empty_functions.hpp"
#include "mtac/DeadCodeElimination.hpp"
#include "mtac/merge_basic_blocks.hpp"
#include "mtac/remove_dead_basic_blocks.hpp"
#include "mtac/BranchOptimizations.hpp"
#include "mtac/inlining.hpp"
#include "mtac/loop_analysis.hpp"
#include "mtac/induction_variable_optimizations.hpp"
#include "mtac/loop_unrolling.hpp"
#include "mtac/complete_loop_peeling.hpp"
#include "mtac/remove_empty_loops.hpp"
#include "mtac/loop_invariant_code_motion.hpp"
#include "mtac/parameter_propagation.hpp"
#include "mtac/pure_analysis.hpp"

//The optimization visitors
#include "mtac/ArithmeticIdentities.hpp"
#include "mtac/ReduceInStrength.hpp"
#include "mtac/ConstantFolding.hpp"
#include "mtac/MathPropagation.hpp"
#include "mtac/PointerPropagation.hpp"

//The data-flow problems
#include "mtac/GlobalOptimizations.hpp"
#include "mtac/ConstantPropagationProblem.hpp"
#include "mtac/OffsetConstantPropagationProblem.hpp"
#include "mtac/CommonSubexpressionElimination.hpp"

#include "ltac/Register.hpp"
#include "ltac/FloatRegister.hpp"
#include "ltac/PseudoRegister.hpp"
#include "ltac/PseudoFloatRegister.hpp"
#include "ltac/Address.hpp"

using namespace eddic;

namespace eddic {
namespace mtac {

typedef boost::mpl::vector<
        mtac::ConstantFolding*
    > basic_passes;

struct all_basic_optimizations {};

template<>
struct pass_traits<all_basic_optimizations> {
    STATIC_CONSTANT(pass_type, type, pass_type::IPA_SUB);
    STATIC_STRING(name, "all_basic_optimizations");
    STATIC_CONSTANT(unsigned int, property_flags, 0);
    STATIC_CONSTANT(unsigned int, todo_after_flags, 0);

    typedef basic_passes sub_passes;
};

typedef boost::mpl::vector<
        mtac::ArithmeticIdentities*,
        mtac::ReduceInStrength*,
        mtac::ConstantFolding*,
        mtac::conditional_propagation*,
        mtac::ConstantPropagationProblem*,
        mtac::OffsetConstantPropagationProblem*,
        mtac::CommonSubexpressionElimination*,
        mtac::PointerPropagation*,
        mtac::MathPropagation*,
        mtac::optimize_branches*,
        mtac::remove_dead_basic_blocks*,
        mtac::merge_basic_blocks*,
        mtac::dead_code_elimination*,
        mtac::remove_aliases*,
        mtac::loop_analysis*,
        mtac::loop_invariant_code_motion*,
        mtac::loop_induction_variables_optimization*,
        mtac::remove_empty_loops*,
        mtac::complete_loop_peeling*,
        mtac::loop_unrolling*,
        mtac::clean_variables*
    > passes;

struct all_optimizations {};

template<>
struct pass_traits<all_optimizations> {
    STATIC_CONSTANT(pass_type, type, pass_type::IPA_SUB);
    STATIC_STRING(name, "all_optimizations");
    STATIC_CONSTANT(unsigned int, property_flags, 0);
    STATIC_CONSTANT(unsigned int, todo_after_flags, 0);

    typedef passes sub_passes;
};

}
}

namespace {

template<typename T, typename Sign>
struct has_gate {
    typedef char yes[1];
    typedef char no [2];
    template <typename U, U> struct type_check;
    template <typename _1> static yes &chk(type_check<Sign, &_1::gate> *);
    template <typename   > static no  &chk(...);
    static bool const value = sizeof(chk<T>(0)) == sizeof(yes);
};

//TODO Find a more elegant way than using pointers

typedef boost::mpl::vector<
        mtac::all_basic_optimizations*
    > ipa_basic_passes;

typedef boost::mpl::vector<
        mtac::remove_unused_functions*,
        mtac::pure_analysis*,
        mtac::all_optimizations*,
        mtac::remove_empty_functions*,
        mtac::inline_functions*,
        mtac::parameter_propagation*
    > ipa_passes;

template<typename Pass>
struct need_pool {
    static const bool value = mtac::pass_traits<Pass>::property_flags & mtac::PROPERTY_POOL;
};

template<typename Pass>
struct need_platform {
    static const bool value = mtac::pass_traits<Pass>::property_flags & mtac::PROPERTY_PLATFORM;
};

template<typename Pass>
struct need_configuration {
    static const bool value = mtac::pass_traits<Pass>::property_flags & mtac::PROPERTY_CONFIGURATION;
};

template<typename Pass>
struct need_program {
    static const bool value = mtac::pass_traits<Pass>::property_flags & mtac::PROPERTY_PROGRAM;
};

template <bool B, typename T = void>
struct disable_if {
    typedef T type;
};

template <typename T>
struct disable_if<true,T> {
    //SFINAE
};

struct pass_runner {
    bool optimized = false;

    mtac::Program& program;
    mtac::Function* function;

    std::shared_ptr<StringPool> pool;
    std::shared_ptr<Configuration> configuration;
    Platform platform;
    timing_system& system;

    pass_runner(mtac::Program& program, std::shared_ptr<StringPool> pool, std::shared_ptr<Configuration> configuration, Platform platform, timing_system& system) :
            program(program), pool(pool), configuration(configuration), platform(platform), system(system) {};

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::todo_after_flags & mtac::TODO_REMOVE_NOP, void>::type remove_nop(){
        for(auto& block : *function){
            auto it = iterate(block->statements);

            while(it.has_next()){
                if(it->op == mtac::Operator::NOP){
                    it.erase();
                    continue;
                }

                ++it;
            }
        }
    }

    template<typename Pass>
    inline typename std::enable_if<!(mtac::pass_traits<Pass>::todo_after_flags & mtac::TODO_REMOVE_NOP), void>::type remove_nop(){
        //NOP
    }

    template<typename Pass>
    inline void apply_todo(){
        remove_nop<Pass>();
    }

    template<typename Pass>
    inline typename std::enable_if<need_pool<Pass>::value, void>::type set_pool(Pass& pass){
        pass.set_pool(pool);
    }

    template<typename Pass>
    inline typename disable_if<need_pool<Pass>::value, void>::type set_pool(Pass&){
        //NOP
    }

    template<typename Pass>
    inline typename std::enable_if<need_platform<Pass>::value, void>::type set_platform(Pass& pass){
        pass.set_platform(platform);
    }

    template<typename Pass>
    inline typename disable_if<need_platform<Pass>::value, void>::type set_platform(Pass&){
        //NOP
    }

    template<typename Pass>
    inline typename std::enable_if<need_configuration<Pass>::value, void>::type set_configuration(Pass& pass){
        pass.set_configuration(configuration);
    }

    template<typename Pass>
    inline typename disable_if<need_configuration<Pass>::value, void>::type set_configuration(Pass&){
        //NOP
    }

    template<typename Pass>
    inline typename std::enable_if<need_program<Pass>::value, Pass>::type construct(){
        return Pass(program);
    }

    template<typename Pass>
    inline typename disable_if<need_program<Pass>::value, Pass>::type construct(){
        return Pass();
    }

    template<typename Pass>
    Pass make_pass(){
        auto pass = construct<Pass>();

        set_pool(pass);
        set_platform(pass);
        set_configuration(pass);

        return pass;
    }

    template<typename Pass>
    inline typename std::enable_if<has_gate<Pass, bool(Pass::*)(std::shared_ptr<Configuration>)>::value, bool>::type has_to_be_run(Pass& pass){
        return pass.gate(configuration);
    }

    template<typename Pass>
    inline typename disable_if<has_gate<Pass, bool(Pass::*)(std::shared_ptr<Configuration>)>::value, bool>::type has_to_be_run(Pass&){
        return true;
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::IPA, bool>::type apply(Pass& pass){
        return pass(program);
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::IPA_SUB, bool>::type apply(Pass&){
        for(auto& function : program.functions){
            this->function = &function;

            if(log::enabled<Debug>()){
                LOG<Debug>("Optimizer") << "Start optimizations on " << function.get_name() << log::endl;

                std::cout << function << std::endl;
            }

            boost::mpl::for_each<typename mtac::pass_traits<Pass>::sub_passes>(boost::ref(*this));
        }

        return false;
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::CUSTOM, bool>::type apply(Pass& pass){
        return pass(*function);
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::LOCAL, bool>::type apply(Pass& visitor){
        for(auto& block : *function){
            for(auto& quadruple : block->statements){
                visitor(quadruple);
            }
        }

        return visitor.optimized;
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::DATA_FLOW, bool>::type apply(Pass& problem){
        auto results = mtac::data_flow(*function, problem);

        //Once the data-flow problem is fixed, statements can be optimized
        return problem.optimize(*function, results);
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::BB, bool>::type apply(Pass& visitor){
        bool optimized = false;

        for(auto& block : *function){
            visitor.clear();

            for(auto& quadruple : block->statements){
                visitor(quadruple);
            }

            optimized |= visitor.optimized;
        }

        return optimized;
    }

    template<typename Pass>
    inline typename std::enable_if<mtac::pass_traits<Pass>::type == mtac::pass_type::BB_TWO_PASS, bool>::type apply(Pass& visitor){
        bool optimized = false;

        for(auto& block : *function){
            visitor.clear();

            visitor.pass = mtac::Pass::DATA_MINING;
            for(auto& quadruple : block->statements){
                visitor(quadruple);
            }

            visitor.pass = mtac::Pass::OPTIMIZE;
            for(auto& quadruple : block->statements){
                visitor(quadruple);
            }

            optimized |= visitor.optimized;
        }

        return optimized;
    }

    template<typename Pass>
    inline typename std::enable_if<boost::type_traits::ice_or<mtac::pass_traits<Pass>::type == mtac::pass_type::IPA, mtac::pass_traits<Pass>::type == mtac::pass_type::IPA_SUB>::value, void>::type
    debug_local(bool local){
        LOG<Debug>("Optimizer") << mtac::pass_traits<Pass>::name() << " returned " << local << log::endl;
    }

    template<typename Pass>
    inline typename std::enable_if<boost::type_traits::ice_and<mtac::pass_traits<Pass>::type != mtac::pass_type::IPA, mtac::pass_traits<Pass>::type != mtac::pass_type::IPA_SUB>::value, void>::type
    debug_local(bool local){
        if(log::enabled<Debug>()){
            if(local){
                LOG<Debug>("Optimizer") << mtac::pass_traits<Pass>::name() << " returned true" << log::endl;

                //Print the function
                std::cout << *function << std::endl;
            } else {
                LOG<Debug>("Optimizer") << mtac::pass_traits<Pass>::name() << " returned false" << log::endl;
            }
        }
    }

    template<typename Pass>
    inline void operator()(Pass*){
        auto pass = make_pass<Pass>();

        if(has_to_be_run(pass)){
            bool local = false;
            {
                PerfsTimer perfs_timer(mtac::pass_traits<Pass>::name());
                timing_timer timer(system, mtac::pass_traits<Pass>::name());

                local = apply<Pass>(pass);
            }

            if(local){
                program.context->stats().inc_counter(std::string(mtac::pass_traits<Pass>::name()) + "_true");
                apply_todo<Pass>();
            }

            debug_local<Pass>(local);

            optimized |= local;
        }
    }
};

} //end of anonymous namespace

void mtac::Optimizer::optimize(mtac::Program& program, std::shared_ptr<StringPool> string_pool, Platform platform, std::shared_ptr<Configuration> configuration) const {
    timing_system timing_system(configuration);
    PerfsTimer timer("Whole optimizations");

    //Build the CFG of each functions (also needed for register allocation)
    for(auto& function : program.functions){
        mtac::build_control_flow_graph(function);
    }

    //Build the call graph (will be used for code generation as well)
    mtac::build_call_graph(program);

    if(configuration->option_defined("fglobal-optimization")){
        //Apply Interprocedural Optimizations
        pass_runner runner(program, string_pool, configuration, platform, timing_system);
        do{
            runner.optimized = false;
            boost::mpl::for_each<ipa_passes>(boost::ref(runner));
        } while(runner.optimized);
    } else {
        //Even if global optimizations are disabled, perform basic optimization (only constant folding)
        pass_runner runner(program, string_pool, configuration, platform, timing_system);
        boost::mpl::for_each<ipa_basic_passes>(boost::ref(runner));
    }
}
<|endoftext|>


<commit_before><commit_msg>#i10000#: remove extra semicolon after macro<commit_after><|endoftext|>


<commit_before>#include <string>
#include <unistd.h>
#include <signal.h>

#include <include/wrapper/cef_helpers.h>
#include <sys/stat.h>

#include "helper.h"

namespace {

    // Set the calling thread's signal mask to new_sigmask and return
    // the previous signal mask.
    sigset_t
    SetSignalMask(const sigset_t& new_sigmask) {
      sigset_t old_sigmask;
      pthread_sigmask(SIG_SETMASK, &new_sigmask, &old_sigmask);
      return old_sigmask;
    }

    bool
    LaunchProcess(const std::vector<std::string>& argv) {
      const size_t command_size = argv.size();
      char** command = new char*[command_size+1]; // extra space for terminating NULL
      sigset_t full_sigset;
      sigfillset(&full_sigset);
      const sigset_t orig_sigmask = SetSignalMask(full_sigset);

      pid_t pid;
      pid = fork();

      // Always restore the original signal mask in the parent.
      if (pid != 0) {
        SetSignalMask(orig_sigmask);
      }

      if (pid < 0) {
        LOG(ERROR)
          << "LaunchProcess: failed fork";
        return false;
      } else if (pid == 0) {
        // Child process

        // DANGER: no calls to malloc or locks are allowed from now on:
        // http://crbug.com/36678

        // DANGER: fork() rule: in the child, if you don't end up doing exec*(),
        // you call _exit() instead of exit(). This is because _exit() does not
        // call any previously-registered (in the parent) exit handlers, which
        // might do things like block waiting for threads that don't even exist
        // in the child.
        for (size_t i = 0; i < command_size; ++i)
        {
          command[i] = strdup(argv[i].c_str());
        }
        command[command_size] = NULL;

        // ToDo: Put environment like Google chrome
        //      options.allow_new_privs = true;
//      // xdg-open can fall back on mailcap which eventually might plumb through
//      // to a command that needs a terminal.  Set the environment variable telling
//      // it that we definitely don't have a terminal available and that it should
//      // bring up a new terminal if necessary.  See "man mailcap".
//      options.environ["MM_NOTTTY"] = "1";
//
//      // We do not let GNOME's bug-buddy intercept our crashes.
//      char* disable_gnome_bug_buddy = getenv("GNOME_DISABLE_CRASH_DIALOG");
//      if (disable_gnome_bug_buddy &&
//         disable_gnome_bug_buddy == std::string("SET_BY_GOOGLE_CHROME"))
//        options.environ["GNOME_DISABLE_CRASH_DIALOG"] = std::string();
        execvp(command[0], command);

        LOG(ERROR)
           << "LaunchProcess: failed to execvp:" << command[0];
        _exit(127);
      }

      return true;
    }

    void
    XDGUtil(const std::string& util, const std::string& arg) {
      std::vector<std::string> argv;
      argv.push_back(util.c_str());
      argv.push_back(arg.c_str());
      LaunchProcess(argv);
    }

    void
    XDGOpen(const std::string& path) {
      XDGUtil("xdg-open", path);
    }

    void
    XDGEmail(const std::string& email) {
      XDGUtil("xdg-email", email);
    }

}  // namespace

namespace platform_util {

    void
    OpenExternal(std::string url) {
      if (url.find("mailto:") == 0)
        XDGEmail(url);
      else
        XDGOpen(url);
    }

    bool
    IsPathExists(std::string path) {
      struct stat stat_data;
      return stat(path.c_str(), &stat_data) != -1;
    }

    bool
    MakeDirectory(std::string path) {
      if (IsPathExists(path))
        return true;

      size_t pre=0, pos;
      std::string dir;

      if (path[path.size()-1] != '/'){
        // force trailing / so we can handle everything in loop
        path += '/';
      }

      while ((pos = path.find_first_of('/', pre)) !=std::string::npos){
        dir = path.substr(0, pos++);
        pre = pos;

        if (dir.size()==0)
          continue;

        if (mkdir(dir.c_str(), 0700) && errno != EEXIST) {
          return false;
        }
      }

      return true;
    }

}  // namespace platform_util
<commit_msg>Fixed possible leak in LaunchProcess<commit_after>#include <string>
#include <unistd.h>
#include <signal.h>

#include <include/wrapper/cef_helpers.h>
#include <sys/stat.h>

#include "helper.h"

namespace {

    // Set the calling thread's signal mask to new_sigmask and return
    // the previous signal mask.
    sigset_t
    SetSignalMask(const sigset_t& new_sigmask) {
      sigset_t old_sigmask;
      pthread_sigmask(SIG_SETMASK, &new_sigmask, &old_sigmask);
      return old_sigmask;
    }

    bool
    LaunchProcess(const std::vector<std::string>& args) {
      sigset_t full_sigset;
      sigfillset(&full_sigset);
      const sigset_t orig_sigmask = SetSignalMask(full_sigset);

      pid_t pid;
      pid = fork();

      // Always restore the original signal mask in the parent.
      if (pid != 0) {
        SetSignalMask(orig_sigmask);
      }

      if (pid < 0) {
        LOG(ERROR)
          << "LaunchProcess: failed fork";
        return false;
      } else if (pid == 0) {
        // Child process

        // DANGER: fork() rule: in the child, if you don't end up doing exec*(),
        // you call _exit() instead of exit(). This is because _exit() does not
        // call any previously-registered (in the parent) exit handlers, which
        // might do things like block waiting for threads that don't even exist
        // in the child.

        // ToDo: Put environment like Google chrome
        //      options.allow_new_privs = true;
//      // xdg-open can fall back on mailcap which eventually might plumb through
//      // to a command that needs a terminal.  Set the environment variable telling
//      // it that we definitely don't have a terminal available and that it should
//      // bring up a new terminal if necessary.  See "man mailcap".
//      options.environ["MM_NOTTTY"] = "1";
//
//      // We do not let GNOME's bug-buddy intercept our crashes.
//      char* disable_gnome_bug_buddy = getenv("GNOME_DISABLE_CRASH_DIALOG");
//      if (disable_gnome_bug_buddy &&
//         disable_gnome_bug_buddy == std::string("SET_BY_GOOGLE_CHROME"))
//        options.environ["GNOME_DISABLE_CRASH_DIALOG"] = std::string();

        std::vector<char*> argv(args.size() + 1, NULL);
        for (size_t i = 0; i < args.size(); ++i) {
          argv[i] = const_cast<char*>(args[i].c_str());
        }

        execvp(argv[0], &argv[0]);

        LOG(ERROR)
           << "LaunchProcess: failed to execvp:" << argv[0];
        _exit(127);
      }

      return true;
    }

    void
    XDGUtil(const std::string& util, const std::string& arg) {
      std::vector<std::string> argv;
      argv.push_back(util.c_str());
      argv.push_back(arg.c_str());
      LaunchProcess(argv);
    }

    void
    XDGOpen(const std::string& path) {
      XDGUtil("xdg-open", path);
    }

    void
    XDGEmail(const std::string& email) {
      XDGUtil("xdg-email", email);
    }

}  // namespace

namespace platform_util {

    void
    OpenExternal(std::string url) {
      if (url.find("mailto:") == 0)
        XDGEmail(url);
      else
        XDGOpen(url);
    }

    bool
    IsPathExists(std::string path) {
      struct stat stat_data;
      return stat(path.c_str(), &stat_data) != -1;
    }

    bool
    MakeDirectory(std::string path) {
      if (IsPathExists(path))
        return true;

      size_t pre=0, pos;
      std::string dir;

      if (path[path.size()-1] != '/'){
        // force trailing / so we can handle everything in loop
        path += '/';
      }

      while ((pos = path.find_first_of('/', pre)) !=std::string::npos){
        dir = path.substr(0, pos++);
        pre = pos;

        if (dir.size()==0)
          continue;

        if (mkdir(dir.c_str(), 0700) && errno != EEXIST) {
          return false;
        }
      }

      return true;
    }

}  // namespace platform_util
<|endoftext|>


<commit_before>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
*
* Hook-setup code provided by Ruslan
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This library is distributed  in the hope that it will be useful,
* but  WITHOUT ANY WARRANTY; without even  the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygenargbhelper.h"
#include "oxygengtktypenames.h"
#include "config.h"

#include <gtk/gtk.h>
#include <sys/stat.h>

#include <cassert>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

namespace Oxygen
{

    //__________________________________________________________________
    ArgbHelper::ArgbHelper( void ):
        _hooksInitialized( false ),
        _logId( 0 )
    {}

    //_____________________________________________________
    ArgbHelper::~ArgbHelper( void )
    {

        // disconnect hooks
        _colormapHook.disconnect();
        _styleHook.disconnect();

        if( _logId > 0 )
        {

            g_log_remove_handler( "GLib-GObject", _logId );
            g_log_set_handler( "GLib-GObject", G_LOG_LEVEL_CRITICAL, g_log_default_handler, 0L );

        }

    }

    //_____________________________________________________
    void ArgbHelper::initializeHooks( void )
    {

        if( _hooksInitialized ) return;

        // lookup relevant signal
        const guint signalId( g_signal_lookup("style-set", GTK_TYPE_WINDOW ) );
        if( signalId <= 0 ) return;

        // install hooks
        _colormapHook.connect( "style-set", (GSignalEmissionHook)colormapHook, 0L );
        _styleHook.connect( "parent-set", (GSignalEmissionHook)styleHook, 0L );

        /*
        the installation of "parent-set" hook triggers some glib critical error when destructing ComboBoxEntry.
        a glib/gtk bug has been filed. In the meanwhile, and since the error is apparently harmless, we simply
        disable the corresponding log
        */
        _logId = g_log_set_handler( "GLib-GObject", G_LOG_LEVEL_CRITICAL, logHandler, 0L );

        _hooksInitialized = true;
        return;

    }

    //_____________________________________________________
    gboolean ArgbHelper::colormapHook( GSignalInvocationHint*, guint, const GValue* params, gpointer )
    {

        // get widget from params
        GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );

        // check type
        if( !GTK_IS_WIDGET( widget ) ) return FALSE;
        if( !GTK_IS_WINDOW( widget ) ) return TRUE;

        // make sure widget has not been realized already
        if( gtk_widget_get_realized( widget ) ) return TRUE;

        // cast to window
        GtkWindow* window( GTK_WINDOW( widget ) );

        // check type hint
        GdkWindowTypeHint hint = gtk_window_get_type_hint( window );

        // screen
        GdkScreen* screen = gdk_screen_get_default();
        if( !screen ) return TRUE;

        if(
            hint == GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU ||
            hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU ||
            hint == GDK_WINDOW_TYPE_HINT_TOOLTIP ||
            hint == GDK_WINDOW_TYPE_HINT_COMBO
            )
        {

            #if OXYGEN_DEBUG
            std::cerr << "Oxygen::ArgbHelper::colormapHook - "
                << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")"
                << " hint: " << Gtk::TypeNames::windowTypeHint( hint )
                << std::endl;
            #endif

            GdkColormap* cmap=gdk_screen_get_rgba_colormap( screen );
            gtk_widget_push_colormap( cmap );
            gtk_widget_set_colormap( widget, cmap );

        }

        return TRUE;

    }

    //_____________________________________________________
    gboolean ArgbHelper::styleHook( GSignalInvocationHint*, guint, const GValue* params, gpointer )
    {

        // get widget from params
        GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );

        // check type
        if( !GTK_IS_WIDGET( widget ) ) return FALSE;

        // retrieve widget style and check
        GtkStyle* style( widget->style );
        if( !( style && style->depth >= 0 ) ) return TRUE;

        // retrieve parent window and check
        GdkWindow* window( gtk_widget_get_parent_window( widget ) );
        if( !window ) return TRUE;

        // adjust depth
        if( style->depth != gdk_drawable_get_depth( window ) )
        {

            #if OXYGEN_DEBUG
            std::cerr
                << "Oxygen::ArgbHelper::styleHook -"
                << " widget: " << widget << " (" <<G_OBJECT_TYPE_NAME( widget ) << ")"
                << " style depth: " << style->depth
                << " window depth: " << gdk_drawable_get_depth( window )
                << std::endl;
            #endif

            widget->style = gtk_style_attach( style, window );

        }

        return TRUE;

    }

    //_________________________________________________________
    void ArgbHelper::logHandler( const gchar* domain, GLogLevelFlags flags, const gchar* message, gpointer data )
    {

        /*
        discard all messages containing "IA__gtk_box_reorder_child:"
        and fallback to default handler otherwise
        */
        if( std::string( message ).find( "g_object_ref" ) == std::string::npos )
        { g_log_default_handler( domain, flags, message, data ); }

    }

}
<commit_msg>Removed gtk_widget_push_colormap call. It is useless and dangerous.<commit_after>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
*
* Hook-setup code provided by Ruslan
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This library is distributed  in the hope that it will be useful,
* but  WITHOUT ANY WARRANTY; without even  the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygenargbhelper.h"
#include "oxygengtktypenames.h"
#include "config.h"

#include <gtk/gtk.h>
#include <sys/stat.h>

#include <cassert>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

namespace Oxygen
{

    //__________________________________________________________________
    ArgbHelper::ArgbHelper( void ):
        _hooksInitialized( false ),
        _logId( 0 )
    {}

    //_____________________________________________________
    ArgbHelper::~ArgbHelper( void )
    {

        // disconnect hooks
        _colormapHook.disconnect();
        _styleHook.disconnect();

        if( _logId > 0 )
        {

            g_log_remove_handler( "GLib-GObject", _logId );
            g_log_set_handler( "GLib-GObject", G_LOG_LEVEL_CRITICAL, g_log_default_handler, 0L );

        }

    }

    //_____________________________________________________
    void ArgbHelper::initializeHooks( void )
    {

        if( _hooksInitialized ) return;

        // lookup relevant signal
        const guint signalId( g_signal_lookup("style-set", GTK_TYPE_WINDOW ) );
        if( signalId <= 0 ) return;

        // install hooks
        _colormapHook.connect( "style-set", (GSignalEmissionHook)colormapHook, 0L );
        _styleHook.connect( "parent-set", (GSignalEmissionHook)styleHook, 0L );

        /*
        the installation of "parent-set" hook triggers some glib critical error when destructing ComboBoxEntry.
        a glib/gtk bug has been filed. In the meanwhile, and since the error is apparently harmless, we simply
        disable the corresponding log
        */
        _logId = g_log_set_handler( "GLib-GObject", G_LOG_LEVEL_CRITICAL, logHandler, 0L );

        _hooksInitialized = true;
        return;

    }

    //_____________________________________________________
    gboolean ArgbHelper::colormapHook( GSignalInvocationHint*, guint, const GValue* params, gpointer )
    {

        // get widget from params
        GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );

        // check type
        if( !GTK_IS_WIDGET( widget ) ) return FALSE;
        if( !GTK_IS_WINDOW( widget ) ) return TRUE;

        // make sure widget has not been realized already
        if( gtk_widget_get_realized( widget ) ) return TRUE;

        // cast to window
        GtkWindow* window( GTK_WINDOW( widget ) );

        // check type hint
        GdkWindowTypeHint hint = gtk_window_get_type_hint( window );

        // screen
        GdkScreen* screen = gdk_screen_get_default();
        if( !screen ) return TRUE;

        if(
            hint == GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU ||
            hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU ||
            hint == GDK_WINDOW_TYPE_HINT_TOOLTIP ||
            hint == GDK_WINDOW_TYPE_HINT_COMBO
            )
        {

            #if OXYGEN_DEBUG
            std::cerr << "Oxygen::ArgbHelper::colormapHook - "
                << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")"
                << " hint: " << Gtk::TypeNames::windowTypeHint( hint )
                << std::endl;
            #endif

            GdkColormap* cmap=gdk_screen_get_rgba_colormap( screen );
            gtk_widget_set_colormap( widget, cmap );

        }

        return TRUE;

    }

    //_____________________________________________________
    gboolean ArgbHelper::styleHook( GSignalInvocationHint*, guint, const GValue* params, gpointer )
    {

        // get widget from params
        GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );

        // check type
        if( !GTK_IS_WIDGET( widget ) ) return FALSE;

        // retrieve widget style and check
        GtkStyle* style( widget->style );
        if( !( style && style->depth >= 0 ) ) return TRUE;

        // retrieve parent window and check
        GdkWindow* window( gtk_widget_get_parent_window( widget ) );
        if( !window ) return TRUE;

        // adjust depth
        if( style->depth != gdk_drawable_get_depth( window ) )
        {

            #if OXYGEN_DEBUG
            std::cerr
                << "Oxygen::ArgbHelper::styleHook -"
                << " widget: " << widget << " (" <<G_OBJECT_TYPE_NAME( widget ) << ")"
                << " style depth: " << style->depth
                << " window depth: " << gdk_drawable_get_depth( window )
                << std::endl;
            #endif

            widget->style = gtk_style_attach( style, window );

        }

        return TRUE;

    }

    //_________________________________________________________
    void ArgbHelper::logHandler( const gchar* domain, GLogLevelFlags flags, const gchar* message, gpointer data )
    {

        /*
        discard all messages containing "IA__gtk_box_reorder_child:"
        and fallback to default handler otherwise
        */
        if( std::string( message ).find( "g_object_ref" ) == std::string::npos )
        { g_log_default_handler( domain, flags, message, data ); }

    }

}
<|endoftext|>