<commit_before>#ifndef MJOLNIR_CORE_NEIGHBOR_LIST_HPP
#define MJOLNIR_CORE_NEIGHBOR_LIST_HPP
#include <mjolnir/util/range.hpp>
#include <mjolnir/util/empty.hpp>
#include <type_traits>
#include <algorithm>
#include <iterator>
#include <utility>
#include <vector>

//! a container for verlet-list, cell-list, and other spatial indexing methods.
//! the objectives are
//! - store indices of possible partners that has interaction.
//! - store pre-calculated parameters. e.g. epsilon_ij = sqrt(eps_i * eps_j)
//!   for Lennard-Jones takes relatively large computational cost to obtain.
//!   calculate it for all the possible pairs to make force calculation fast.

namespace mjolnir
{

// google with "empty base optimization(EBO)".
// By using EBO, we can compress the object size when `potT` is a empty class.
// without this, empty parameter type consumes 8 byte (on x86_64) because
// std::size_t requires 8-byte alignment.

namespace detail
{
// In order to handle `double` or other non-class object, neighbor_element need
// another layer that checks `std::is_empty`. If empty, it inherits it and EBO
// removes the overhead. If not empty(like `double`), it keeps storage for the
// value. `neighbor_elmenet_impl` stores value if `std::true_type` is passed.
template<typename potT, bool IsEmpty>
struct neighbor_element_impl;

template<typename potT>
struct neighbor_element_impl<potT, true> : private potT // for EBO
{
    using potential_type = potT;

    explicit neighbor_element_impl(const potential_type&) {}
    explicit neighbor_element_impl(potential_type&&)      {}

    neighbor_element_impl()  = default;
    ~neighbor_element_impl() = default;
    neighbor_element_impl(const neighbor_element_impl&) = default;
    neighbor_element_impl(neighbor_element_impl&&)      = default;
    neighbor_element_impl& operator=(const neighbor_element_impl&) = default;
    neighbor_element_impl& operator=(neighbor_element_impl&&)      = default;

    potential_type&       potential()       noexcept {return *this;}
    potential_type const& potential() const noexcept {return *this;}
};

template<typename potT>
struct neighbor_element_impl<potT, false>
{
    using potential_type = potT;

    explicit neighbor_element_impl(const potential_type& p): pot(p) {}
    explicit neighbor_element_impl(potential_type&& p): pot(std::move(p)) {}

    neighbor_element_impl()  = default;
    ~neighbor_element_impl() = default;
    neighbor_element_impl(const neighbor_element_impl&) = default;
    neighbor_element_impl(neighbor_element_impl&&)      = default;
    neighbor_element_impl& operator=(const neighbor_element_impl&) = default;
    neighbor_element_impl& operator=(neighbor_element_impl&&)      = default;

    potential_type&       potential()       noexcept {return this->pot;}
    potential_type const& potential() const noexcept {return this->pot;}

    potential_type pot;
};

} // detail

template<typename potT>
struct neighbor_element
    : private detail::neighbor_element_impl<potT, std::is_empty<potT>::value>
{
    static constexpr bool potential_is_empty = std::is_empty<potT>::value;

    using base_type = detail::neighbor_element_impl<potT, potential_is_empty>;
    using potential_type = typename base_type::potential_type;

    neighbor_element(std::size_t idx, const potT& p)
        : base_type(p), index(idx)
    {}
    neighbor_element(std::size_t idx, potT&& p)
        : base_type(std::move(p)), index(idx)
    {}

    neighbor_element()  = default;
    ~neighbor_element() = default;
    neighbor_element(const neighbor_element&) = default;
    neighbor_element(neighbor_element&&)      = default;
    neighbor_element& operator=(const neighbor_element&) = default;
    neighbor_element& operator=(neighbor_element&&)      = default;

    potential_type&       potential()       noexcept {return base_type::potential();}
    potential_type const& potential() const noexcept {return base_type::potential();}

    // potential_type pot; // derived from neighbor_element_impl
    std::size_t index;
};
template<typename potT>
constexpr bool neighbor_element<potT>::potential_is_empty;

// Check the EBO works and the size of neighbor_element with empty class
// is equal to the size of `std::size_t index;`.
static_assert(sizeof(std::size_t) == sizeof(neighbor_element<empty_t>),
              "checking neighbor_element reduces size of empty object");

template<typename potT>
inline bool operator==(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index == rhs.index;
}
template<typename potT>
inline bool operator!=(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index != rhs.index;
}
template<typename potT>
inline bool operator<(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index < rhs.index;
}
template<typename potT>
inline bool operator>(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index > rhs.index;
}
template<typename potT>
inline bool operator<=(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index <= rhs.index;
}
template<typename potT>
inline bool operator>=(
    const neighbor_element<paramT>& lhs, const neighbor_element<paramT>& rhs)
{
    return lhs.index >= rhs.index;
}

// ----------------------------------------------------------------------------
// neighbor list

template<typename potentialT>
class NeighborList
{
  public:
    using potential_type = potentialT;
    using neighbor_type  = neighbor_element<potential_type>;
    using container_type = std::vector<neighbor_type>;
    using range_type     = range<typename container_type::const_iterator>;

    // XXX this contains the list in the following way.
    //
    // 1. The neighboring list that has interaction partners of each particle
    //    and the parameter for each pairs (e.g. `q_i*q_j` for electrostatics).
    //
    //  __partner of p1__ __partner of p2___________ ____ ... pN__
    // '                 '                          '             '
    // |{p2,q12}|{p3,q13}|{p4,q24}|{p6,q26}|{p7,q27}|{    ...    }|
    //   0th      1st      2nd      3rd      4th      5th ... M-1 th element
    //
    // 2. The range list that contains from where to where the partners are
    //    contained.
    //  +---- partner of p1 starts from 0th element of the above array
    //  | +-- partner of p2 starts from 2nd element of the above array
    //  v v
    // |0|2|5|...|M|
    //    ^ ^     ^
    //    +-+-----+-- the last partner of p1 is 2-1 = 1.
    //      +-----+-- the last pertner of p2 is 5-1 = 4.
    //            +-- the last element of pN is M-1.
    //
    // This list should have N+1 elements because i-th and (i+1)-th elements of
    // the list is needed to obtain the partner.
    //
    // By doing this, we can reduce the memory resource to have the list.

  public:

    NeighborList()  = default;
    ~NeighborList() = default;
    NeighborList(const NeighborList&) = default;
    NeighborList(NeighborList&&)      = default;
    NeighborList& operator=(const NeighborList&) = default;
    NeighborList& operator=(NeighborList&&)      = default;

    void clear()
    {
        this->neighbors_.clear();
        this->ranges_   .clear();
        return;
    }

    // assign the partners in range [first, last) as the partner of particle i.
    template<typename Iterator>
    void add_list_for(const std::size_t i, Iterator first, Iterator last)
    {
        static_assert(std::is_same<
            typename std::iterator_traits<Iterator>::value_type, neighbor_type
            >::value, "The iterator must points neighbor type.");

        if(this->ranges_.size() <= i+1)
        {
            this->ranges_.resize(i+2, 0);
        }

        assert(ranges_[i] == 0 || ranges_[i] == this->neighbors_.size());

        this->ranges_[i]   = this->neighbors_.size();
        this->ranges_[i+1] = this->neighbors_.size() + std::distance(first, last);

        // allcoate if the current size is not enough.
        // XXX
        // This invalidates iterators because of the re-allocation.
        // So the `ranges_` cannot have iterators.
        // The elements of `ranges_` must be indices.
        this->neighbors_.reserve(neighbors_.size() + std::distance(first, last));

        std::copy(first, last, std::back_inserter(this->neighbors_));
        return ;
    }

    void reserve(const std::size_t approx_neighbors,
                 const std::size_t num_participants,
                 const std::size_t num_particles)
    {
        neighbors_.reserve(approx_neighbors * num_participants);
        ranges_.reserve(num_particles);
    }

    std::size_t num_neighbors() const noexcept {return neighbors_.size();}

    range_type operator[](const std::size_t i) const noexcept
    {
        return range_type{
            this->neighbors_.begin() + this->ranges_[i],
            this->neighbors_.begin() + this->ranges_[i+1]
        };
    }
    range_type at(const std::size_t i) const
    {
        return range_type{
            this->neighbors_.begin() + this->ranges_.at(i),
            this->neighbors_.begin() + this->ranges_.at(i+1)
        };
    }

    // ------------------------------------------------------------------------
    // Caution: take great care when you use the following functions.
    //          If possible, use `add_list_for` instead.

    container_type&        neighbors() noexcept {return neighbors_;}
    std::vector<std::size_t>& ranges() noexcept {return ranges_;}

  private:
    container_type           neighbors_;
    std::vector<std::size_t> ranges_;
};

} // mjolnir
#endif// MJOLNIR_NEIGHBOR_LIST_HPP
<commit_msg>fix: fix typo in type<commit_after>#ifndef MJOLNIR_CORE_NEIGHBOR_LIST_HPP
#define MJOLNIR_CORE_NEIGHBOR_LIST_HPP
#include <mjolnir/util/range.hpp>
#include <mjolnir/util/empty.hpp>
#include <type_traits>
#include <algorithm>
#include <iterator>
#include <utility>
#include <vector>

//! a container for verlet-list, cell-list, and other spatial indexing methods.
//! the objectives are
//! - store indices of possible partners that has interaction.
//! - store pre-calculated parameters. e.g. epsilon_ij = sqrt(eps_i * eps_j)
//!   for Lennard-Jones takes relatively large computational cost to obtain.
//!   calculate it for all the possible pairs to make force calculation fast.

namespace mjolnir
{

// google with "empty base optimization(EBO)".
// By using EBO, we can compress the object size when `potT` is a empty class.
// without this, empty parameter type consumes 8 byte (on x86_64) because
// std::size_t requires 8-byte alignment.

namespace detail
{
// In order to handle `double` or other non-class object, neighbor_element need
// another layer that checks `std::is_empty`. If empty, it inherits it and EBO
// removes the overhead. If not empty(like `double`), it keeps storage for the
// value. `neighbor_elmenet_impl` stores value if `std::true_type` is passed.
template<typename potT, bool IsEmpty>
struct neighbor_element_impl;

template<typename potT>
struct neighbor_element_impl<potT, true> : private potT // for EBO
{
    using potential_type = potT;

    explicit neighbor_element_impl(const potential_type&) {}
    explicit neighbor_element_impl(potential_type&&)      {}

    neighbor_element_impl()  = default;
    ~neighbor_element_impl() = default;
    neighbor_element_impl(const neighbor_element_impl&) = default;
    neighbor_element_impl(neighbor_element_impl&&)      = default;
    neighbor_element_impl& operator=(const neighbor_element_impl&) = default;
    neighbor_element_impl& operator=(neighbor_element_impl&&)      = default;

    potential_type&       potential()       noexcept {return *this;}
    potential_type const& potential() const noexcept {return *this;}
};

template<typename potT>
struct neighbor_element_impl<potT, false>
{
    using potential_type = potT;

    explicit neighbor_element_impl(const potential_type& p): pot(p) {}
    explicit neighbor_element_impl(potential_type&& p): pot(std::move(p)) {}

    neighbor_element_impl()  = default;
    ~neighbor_element_impl() = default;
    neighbor_element_impl(const neighbor_element_impl&) = default;
    neighbor_element_impl(neighbor_element_impl&&)      = default;
    neighbor_element_impl& operator=(const neighbor_element_impl&) = default;
    neighbor_element_impl& operator=(neighbor_element_impl&&)      = default;

    potential_type&       potential()       noexcept {return this->pot;}
    potential_type const& potential() const noexcept {return this->pot;}

    potential_type pot;
};

} // detail

template<typename potT>
struct neighbor_element
    : private detail::neighbor_element_impl<potT, std::is_empty<potT>::value>
{
    static constexpr bool potential_is_empty = std::is_empty<potT>::value;

    using base_type = detail::neighbor_element_impl<potT, potential_is_empty>;
    using potential_type = typename base_type::potential_type;

    neighbor_element(std::size_t idx, const potT& p)
        : base_type(p), index(idx)
    {}
    neighbor_element(std::size_t idx, potT&& p)
        : base_type(std::move(p)), index(idx)
    {}

    neighbor_element()  = default;
    ~neighbor_element() = default;
    neighbor_element(const neighbor_element&) = default;
    neighbor_element(neighbor_element&&)      = default;
    neighbor_element& operator=(const neighbor_element&) = default;
    neighbor_element& operator=(neighbor_element&&)      = default;

    potential_type&       potential()       noexcept {return base_type::potential();}
    potential_type const& potential() const noexcept {return base_type::potential();}

    // potential_type pot; // derived from neighbor_element_impl
    std::size_t index;
};
template<typename potT>
constexpr bool neighbor_element<potT>::potential_is_empty;

// Check the EBO works and the size of neighbor_element with empty class
// is equal to the size of `std::size_t index;`.
static_assert(sizeof(std::size_t) == sizeof(neighbor_element<empty_t>),
              "checking neighbor_element reduces size of empty object");

template<typename potT>
inline bool operator==(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index == rhs.index;
}
template<typename potT>
inline bool operator!=(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index != rhs.index;
}
template<typename potT>
inline bool operator<(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index < rhs.index;
}
template<typename potT>
inline bool operator>(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index > rhs.index;
}
template<typename potT>
inline bool operator<=(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index <= rhs.index;
}
template<typename potT>
inline bool operator>=(
    const neighbor_element<potT>& lhs, const neighbor_element<potT>& rhs)
{
    return lhs.index >= rhs.index;
}

// ----------------------------------------------------------------------------
// neighbor list

template<typename potentialT>
class NeighborList
{
  public:
    using potential_type = potentialT;
    using neighbor_type  = neighbor_element<potential_type>;
    using container_type = std::vector<neighbor_type>;
    using range_type     = range<typename container_type::const_iterator>;

    // XXX this contains the list in the following way.
    //
    // 1. The neighboring list that has interaction partners of each particle
    //    and the parameter for each pairs (e.g. `q_i*q_j` for electrostatics).
    //
    //  __partner of p1__ __partner of p2___________ ____ ... pN__
    // '                 '                          '             '
    // |{p2,q12}|{p3,q13}|{p4,q24}|{p6,q26}|{p7,q27}|{    ...    }|
    //   0th      1st      2nd      3rd      4th      5th ... M-1 th element
    //
    // 2. The range list that contains from where to where the partners are
    //    contained.
    //  +---- partner of p1 starts from 0th element of the above array
    //  | +-- partner of p2 starts from 2nd element of the above array
    //  v v
    // |0|2|5|...|M|
    //    ^ ^     ^
    //    +-+-----+-- the last partner of p1 is 2-1 = 1.
    //      +-----+-- the last pertner of p2 is 5-1 = 4.
    //            +-- the last element of pN is M-1.
    //
    // This list should have N+1 elements because i-th and (i+1)-th elements of
    // the list is needed to obtain the partner.
    //
    // By doing this, we can reduce the memory resource to have the list.

  public:

    NeighborList()  = default;
    ~NeighborList() = default;
    NeighborList(const NeighborList&) = default;
    NeighborList(NeighborList&&)      = default;
    NeighborList& operator=(const NeighborList&) = default;
    NeighborList& operator=(NeighborList&&)      = default;

    void clear()
    {
        this->neighbors_.clear();
        this->ranges_   .clear();
        return;
    }

    // assign the partners in range [first, last) as the partner of particle i.
    template<typename Iterator>
    void add_list_for(const std::size_t i, Iterator first, Iterator last)
    {
        static_assert(std::is_same<
            typename std::iterator_traits<Iterator>::value_type, neighbor_type
            >::value, "The iterator must points neighbor type.");

        if(this->ranges_.size() <= i+1)
        {
            this->ranges_.resize(i+2, 0);
        }

        assert(ranges_[i] == 0 || ranges_[i] == this->neighbors_.size());

        this->ranges_[i]   = this->neighbors_.size();
        this->ranges_[i+1] = this->neighbors_.size() + std::distance(first, last);

        // allcoate if the current size is not enough.
        // XXX
        // This invalidates iterators because of the re-allocation.
        // So the `ranges_` cannot have iterators.
        // The elements of `ranges_` must be indices.
        this->neighbors_.reserve(neighbors_.size() + std::distance(first, last));

        std::copy(first, last, std::back_inserter(this->neighbors_));
        return ;
    }

    void reserve(const std::size_t approx_neighbors,
                 const std::size_t num_participants,
                 const std::size_t num_particles)
    {
        neighbors_.reserve(approx_neighbors * num_participants);
        ranges_.reserve(num_particles);
    }

    std::size_t num_neighbors() const noexcept {return neighbors_.size();}

    range_type operator[](const std::size_t i) const noexcept
    {
        return range_type{
            this->neighbors_.begin() + this->ranges_[i],
            this->neighbors_.begin() + this->ranges_[i+1]
        };
    }
    range_type at(const std::size_t i) const
    {
        return range_type{
            this->neighbors_.begin() + this->ranges_.at(i),
            this->neighbors_.begin() + this->ranges_.at(i+1)
        };
    }

    // ------------------------------------------------------------------------
    // Caution: take great care when you use the following functions.
    //          If possible, use `add_list_for` instead.

    container_type&        neighbors() noexcept {return neighbors_;}
    std::vector<std::size_t>& ranges() noexcept {return ranges_;}

  private:
    container_type           neighbors_;
    std::vector<std::size_t> ranges_;
};

} // mjolnir
#endif// MJOLNIR_NEIGHBOR_LIST_HPP
<|endoftext|>


<commit_before>#ifndef MJOLNIR_UTIL_PROGRESS_BAR_HPP
#define MJOLNIR_UTIL_PROGRESS_BAR_HPP
#include <array>
#include <cstring>
#include <cmath>
#include <cassert>

namespace mjolnir
{

template<std::size_t Width>
class progress_bar
{
  public:

    progress_bar() noexcept
        : total_(1), r_total_(1.0)
    {}
    explicit progress_bar(std::size_t tot) noexcept
        : total_(tot), r_total_(1.0 / tot)
    {}
    ~progress_bar() = default;
    progress_bar(progress_bar const&) = default;
    progress_bar(progress_bar &&)     = default;
    progress_bar& operator=(progress_bar const&) = default;
    progress_bar& operator=(progress_bar &&)     = default;

    void reset(const std::size_t total_step)
    {
        this->total_   = total_step;
        this->r_total_ = 1.0 / static_cast<double>(total_step);
        return;
    }

    void format(std::size_t count, std::ostream& os)
    {
        //XXX: requires UTF-8. TODO: consider setting locale
        constexpr auto full  = u8"█"; // U+2588 Full block
        constexpr auto l7    = u8"▉"; // U+2589 Left seven eighths block
        constexpr auto l6    = u8"▊"; // U+258A Left three quarters block
        constexpr auto l5    = u8"▋"; // U+258B Left five eighths block
        constexpr auto l4    = u8"▌"; // U+258C Left half block
        constexpr auto l3    = u8"▍"; // U+258D Left three eighths block
        constexpr auto l2    = u8"▎"; // U+258E Left one quarter block
        constexpr auto l1    = u8"▏"; // U+258F Left one eighth block

        const double ratio = (count == total_) ? 1.0 :
            std::max(0.0, std::min(1.0, count * this->r_total_));

        std::array<char, 8> buf1;
        std::snprintf(buf1.data(), 8, "%5.1f%%|", ratio * 100.0);
        os << '\r' << buf1.data();

        const std::size_t filled = std::floor(ratio*Width);
        for(std::size_t i=0; i<filled; ++i)
        {
            os << full;
        }
        if(Width > filled)
        {
            switch(static_cast<std::size_t>(ratio * Width * 8) % 8)
            {
                case 0:{os << ' '; break;}
                case 1:{os << l1;  break;}
                case 2:{os << l2;  break;}
                case 3:{os << l3;  break;}
                case 4:{os << l4;  break;}
                case 5:{os << l5;  break;}
                case 6:{os << l6;  break;}
                case 7:{os << l7;  break;}
            }
            for(std::size_t i=1; i<Width - filled; ++i)
            {
                os << ' ';
            }
        }
        os << '|' << std::flush;
        return ;
    }

    std::size_t total() const noexcept {return total_;}

  private:

    std::size_t total_;
    double      r_total_;
};

} // mjolnir
#endif// MJOLNIR_PROGRESS_BAR_HPP
<commit_msg>feat: output remaining time in progress bar<commit_after>#ifndef MJOLNIR_UTIL_PROGRESS_BAR_HPP
#define MJOLNIR_UTIL_PROGRESS_BAR_HPP
#include <array>
#include <chrono>
#include <cstring>
#include <cmath>
#include <cassert>

namespace mjolnir
{

template<std::size_t Width>
class progress_bar
{
  public:

    progress_bar() noexcept
        : total_(1), r_total_(1.0), start_(std::chrono::system_clock::now())
    {}
    explicit progress_bar(std::size_t tot) noexcept
        : total_(tot), r_total_(1.0 / tot),
          start_(std::chrono::system_clock::now())
    {}
    ~progress_bar() = default;
    progress_bar(progress_bar const&) = default;
    progress_bar(progress_bar &&)     = default;
    progress_bar& operator=(progress_bar const&) = default;
    progress_bar& operator=(progress_bar &&)     = default;

    void reset(const std::size_t total_step)
    {
        this->total_   = total_step;
        this->r_total_ = 1.0 / static_cast<double>(total_step);
        this->start_   = std::chrono::system_clock::now();
        return;
    }

    void format(std::size_t count, std::ostream& os)
    {
        if(count == 0){start_ = std::chrono::system_clock::now();}

        //XXX: requires UTF-8.
        constexpr auto full  = u8"█"; // U+2588 Full block
        constexpr auto l7    = u8"▉"; // U+2589 Left seven eighths block
        constexpr auto l6    = u8"▊"; // U+258A Left three quarters block
        constexpr auto l5    = u8"▋"; // U+258B Left five eighths block
        constexpr auto l4    = u8"▌"; // U+258C Left half block
        constexpr auto l3    = u8"▍"; // U+258D Left three eighths block
        constexpr auto l2    = u8"▎"; // U+258E Left one quarter block
        constexpr auto l1    = u8"▏"; // U+258F Left one eighth block

        const double ratio = (count == total_) ? 1.0 :
            std::max(0.0, std::min(1.0, count * this->r_total_));

        std::array<char, 8> buf;
        std::snprintf(buf.data(), 8, "%5.1f%%|", ratio * 100.0);
        os << '\r' << buf.data();

        const std::size_t filled = std::floor(ratio*Width);
        for(std::size_t i=0; i<filled; ++i)
        {
            os << full;
        }
        if(Width > filled)
        {
            switch(static_cast<std::size_t>(ratio * Width * 8) % 8)
            {
                case 0: {os << ' '; break;}
                case 1: {os << l1;  break;}
                case 2: {os << l2;  break;}
                case 3: {os << l3;  break;}
                case 4: {os << l4;  break;}
                case 5: {os << l5;  break;}
                case 6: {os << l6;  break;}
                case 7: {os << l7;  break;}
            }
            for(std::size_t i=1; i<Width - filled; ++i)
            {
                os << ' ';
            }
        }
        os << '|';

        const auto current  = std::chrono::system_clock::now();
        const auto residual = std::chrono::duration_cast<std::chrono::milliseconds>(
            (current - start_) * (1.0 - ratio) / ratio).count() * 0.001;

        if(residual < 60.0)
        {
            std::snprintf(buf.data(), 6, "%5.1f", residual);
            os << buf.data() << " seconds remaining ";
        }
        else if(residual < 60.0 * 60.0)
        {
            std::snprintf(buf.data(), 6, "%5.1f", residual * 0.0167);
            os << buf.data() << " minutes remaining ";
        }
        else if(residual < 60.0 * 60.0 * 24.0)
        {
            std::snprintf(buf.data(), 6, "%5.1f", residual * 0.0167 * 0.0167);
            os << buf.data() << " hours remaining   ";
        }
        else if(residual < 60.0 * 60.0 * 24.0 * 99.0)
        {
            std::snprintf(buf.data(), 6, "%5.1f", residual * 0.0167 * 0.0167 * 0.0417);
            os << buf.data() << " days remaining    ";
        }
        else
        {
            os << " over 100 days remaining";
        }
        os << std::flush;
        return ;
    }

    std::size_t total() const noexcept {return total_;}

  private:

    std::size_t total_;
    double      r_total_;
    std::chrono::system_clock::time_point start_;
};

} // mjolnir
#endif// MJOLNIR_PROGRESS_BAR_HPP
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <iostream>
#include <Context.h>
#include <Filter.h>
#include <text.h>
#include <util.h>
#include <i18n.h>
#include <main.h>
#include <CmdDenotate.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdDenotate::CmdDenotate ()
{
  _keyword     = "denotate";
  _usage       = "task <filter> denotate <pattern>";
  _description = STRING_CMD_DENO_USAGE;
  _read_only   = false;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdDenotate::execute (std::string& output)
{
  int rc = 0;
  int count = 0;
  bool sensitive = context.config.getBoolean ("search.case.sensitive");

  // Apply filter.
  Filter filter;
  std::vector <Task> filtered;
  filter.subset (filtered);
  if (filtered.size () == 0)
  {
    context.footnote (STRING_FEEDBACK_NO_TASKS_SP);
    return 1;
  }

  // Apply the command line modifications to the completed task.
  A3 words = context.a3.extract_modifications ();
  if (!words.size ())
    throw std::string (STRING_CMD_DENO_WORDS);

  // Accumulated project change notifications.
  std::map <std::string, std::string> projectChanges;

  std::string pattern = words.combine ();

  std::vector <Task>::iterator task;
  for (task = filtered.begin (); task != filtered.end (); ++task)
  {
    Task before (*task);

    std::map <std::string, std::string> annotations;
    task->getAnnotations (annotations);

    if (annotations.size () == 0)
      throw std::string (STRING_CMD_DENO_NONE);

    std::map <std::string, std::string>::iterator i;
    std::string anno;
    bool match = false;
    for (i = annotations.begin (); i != annotations.end (); ++i)
    {
      if (i->second == pattern)
      {
        match = true;
        anno = i->second;
        annotations.erase (i);
        task->setAnnotations (annotations);
        break;
      }
    }
    if (!match)
    {
      for (i = annotations.begin (); i != annotations.end (); ++i)
      {
        std::string::size_type loc = find (i->second, pattern, sensitive);
        if (loc != std::string::npos)
        {
          anno = i->second;
          annotations.erase (i);
          task->setAnnotations (annotations);
          break;
        }
      }
    }

    if (taskDiff (before, *task))
    {
      std::string question = format (STRING_CMD_DENO_CONFIRM,
                                     task->id,
                                     task->get ("description"));

      if (permission (*task, taskDifferences (before, *task) + question, filtered.size ()))
      {
        ++count;
        context.tdb2.modify (*task);
        feedback_affected (format (STRING_CMD_DENO_FOUND, anno));
        if (context.verbose ("project"))
          projectChanges[task->get ("project")] = onProjectChange (*task, false);
      }
      else
      {
        std::cout << STRING_CMD_DENO_NO << "\n";
        rc = 1;
        if (_permission_quit)
          break;
      }
    }
    else
    {
      std::cout << format (STRING_CMD_DENO_NOMATCH, pattern) << "\n";
      rc = 1;
    }
  }

  // Now list the project changes.
  std::map <std::string, std::string>::iterator i;
  for (i = projectChanges.begin (); i != projectChanges.end (); ++i)
    if (i->first != "")
      context.footnote (i->second);

  context.tdb2.commit ();
  feedback_affected (count == 1 ? STRING_CMD_DENO_1 : STRING_CMD_DENO_N, count);
  return rc;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>CmdDenotate<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <iostream>
#include <Context.h>
#include <Filter.h>
#include <text.h>
#include <util.h>
#include <i18n.h>
#include <main.h>
#include <CmdDenotate.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdDenotate::CmdDenotate ()
{
  _keyword     = "denotate";
  _usage       = "task <filter> denotate <pattern>";
  _description = STRING_CMD_DENO_USAGE;
  _read_only   = false;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdDenotate::execute (std::string& output)
{
  int rc = 0;
  int count = 0;
  bool sensitive = context.config.getBoolean ("search.case.sensitive");

  // Apply filter.
  Filter filter;
  std::vector <Task> filtered;
  filter.subset (filtered);
  if (filtered.size () == 0)
  {
    context.footnote (STRING_FEEDBACK_NO_TASKS_SP);
    return 1;
  }

  // Apply the command line modifications to the completed task.
  std::vector <std::string> words = context.parser.getWords ();
  if (!words.size ())
    throw std::string (STRING_CMD_DENO_WORDS);

  // Accumulated project change notifications.
  std::map <std::string, std::string> projectChanges;

  //std::string pattern = words.combine ();
  std::string pattern;
  join (pattern, " ", words);

  std::vector <Task>::iterator task;
  for (task = filtered.begin (); task != filtered.end (); ++task)
  {
    Task before (*task);

    std::map <std::string, std::string> annotations;
    task->getAnnotations (annotations);

    if (annotations.size () == 0)
      throw std::string (STRING_CMD_DENO_NONE);

    std::map <std::string, std::string>::iterator i;
    std::string anno;
    bool match = false;
    for (i = annotations.begin (); i != annotations.end (); ++i)
    {
      if (i->second == pattern)
      {
        match = true;
        anno = i->second;
        annotations.erase (i);
        task->setAnnotations (annotations);
        break;
      }
    }
    if (!match)
    {
      for (i = annotations.begin (); i != annotations.end (); ++i)
      {
        std::string::size_type loc = find (i->second, pattern, sensitive);
        if (loc != std::string::npos)
        {
          anno = i->second;
          annotations.erase (i);
          task->setAnnotations (annotations);
          break;
        }
      }
    }

    if (taskDiff (before, *task))
    {
      std::string question = format (STRING_CMD_DENO_CONFIRM,
                                     task->id,
                                     task->get ("description"));

      if (permission (*task, taskDifferences (before, *task) + question, filtered.size ()))
      {
        ++count;
        context.tdb2.modify (*task);
        feedback_affected (format (STRING_CMD_DENO_FOUND, anno));
        if (context.verbose ("project"))
          projectChanges[task->get ("project")] = onProjectChange (*task, false);
      }
      else
      {
        std::cout << STRING_CMD_DENO_NO << "\n";
        rc = 1;
        if (_permission_quit)
          break;
      }
    }
    else
    {
      std::cout << format (STRING_CMD_DENO_NOMATCH, pattern) << "\n";
      rc = 1;
    }
  }

  // Now list the project changes.
  std::map <std::string, std::string>::iterator i;
  for (i = projectChanges.begin (); i != projectChanges.end (); ++i)
    if (i->first != "")
      context.footnote (i->second);

  context.tdb2.commit ();
  feedback_affected (count == 1 ? STRING_CMD_DENO_1 : STRING_CMD_DENO_N, count);
  return rc;
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


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

#ifndef BOOST_PP_IS_ITERATING

    #ifndef CUDA_FUNCTION_HPP
    #define CUDA_FUNCTION_HPP

    #include <boost/preprocessor/iteration/iterate.hpp>
    #include <boost/preprocessor/repetition/enum_params.hpp>
    #include <boost/preprocessor/repetition/enum_binary_params.hpp>
    #include <boost/preprocessor/repetition/repeat.hpp>
    #include <cuda/cuda_runtime.h>
    #ifndef __CUDACC__
    #include <cuda_wrapper/error.hpp>
    #include <cuda_wrapper/stream.hpp>
    #endif

    /* maximum number of arguments passed to device functions */
    #ifndef CUDA_FUNCTION_MAX_ARGS
    #define CUDA_FUNCTION_MAX_ARGS 10
    #endif

    namespace cuda
    {

    /*
     * CUDA execution configuration
     */
    class config
    {
    public:
	/* grid dimensions */
	dim3 grid;
	/* block dimensions */
	dim3 block;
	/* FIXME store useful numbers (no. of threads per grid/block) */

	config()
	{
	}

	config(dim3 grid, dim3 block) : grid(grid), block(block)
	{
	    /* FIXME store useful numbers (no. of threads per grid/block) */
	}

	size_t threads() const
	{
	    return grid.y * grid.x * block.z * block.y * block.x;
	}

	size_t blocks_per_grid() const
	{
	    return grid.y * grid.x;
	}

	size_t threads_per_block() const
	{
	    return block.z * block.y * block.x;
	}
    };

    } // namespace cuda

    #define BOOST_PP_FILENAME_1 <cuda_wrapper/function.hpp>
    #define BOOST_PP_ITERATION_LIMITS (1, CUDA_FUNCTION_MAX_ARGS)
    #include BOOST_PP_ITERATE()

    #endif /* ! CUDA_FUNCTION_HPP */

#else /* ! BOOST_PP_IS_ITERATING */

    namespace cuda
    {

    template <typename T>
    class function;

    /**
     * CUDA kernel execution wrapper for n-ary device function
     */
    template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename T)>
    class function<void (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))>
    {
    public:
	typedef void T (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T));

    public:
	function(T *entry) : entry(entry) {}

    #ifndef __CUDACC__

	/**
	 * configure execution parameters
	 */
	static void configure(config const& dim, size_t shared_mem = 0)
	{
	    CUDA_CALL(cudaConfigureCall(dim.grid, dim.block, shared_mem, 0));
	}

    #ifdef CUDA_WRAPPER_ASYNC_API
	/**
	 * configure execution parameters
	 */
	static void configure(config const& dim, stream& stream)
	{
	    CUDA_CALL(cudaConfigureCall(dim.grid, dim.block, 0, stream.data()));
	}

	/**
	 * configure execution parameters
	 */
	static void configure(config const& dim, size_t shared_mem, stream& stream)
	{
	    CUDA_CALL(cudaConfigureCall(dim.grid, dim.block, shared_mem, stream.data()));
	}
    #endif /* CUDA_WRAPPER_ASYNC_API */

	/**
	 * execute kernel
	 */
	void operator()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), T, const& x))
	{
	    size_t offset = 0;
    #define SETUP_ARGUMENT(z, n, x) setup_argument(x##n, offset);
	    BOOST_PP_REPEAT(BOOST_PP_ITERATION(), SETUP_ARGUMENT, x)
    #undef SETUP_ARGUMENT
	    CUDA_CALL(cudaLaunch(reinterpret_cast<const char *>(entry)));
	}

    private:
	/**
	 * push arbitrary argument into argument passing area
	 */
	template <typename U>
	static void setup_argument(U const& arg, size_t& offset)
	{
	    /* respect alignment requirements of passed argument */
	    if (0 != offset % __alignof(U)) {
		offset += __alignof(U) - offset % __alignof(U);
	    }

	    CUDA_CALL(cudaSetupArgument(&arg, sizeof(U), offset));

	    /* advance argument offset for next call */
	    offset += sizeof(U);
	}

    #endif /* ! __CUDACC__ */

    private:
	T *entry;
    };

    } // namespace cuda

#endif /* ! BOOST_PP_IS_ITERATING */
<commit_msg>Remove CUDA execution preparation from CUDA device function template<commit_after>/* CUDA device function execution
 *
 * Copyright (C) 2007  Peter Colberg
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef BOOST_PP_IS_ITERATING

    #ifndef CUDA_FUNCTION_HPP
    #define CUDA_FUNCTION_HPP

    #include <boost/preprocessor/iteration/iterate.hpp>
    #include <boost/preprocessor/repetition/enum_params.hpp>
    #include <boost/preprocessor/repetition/enum_binary_params.hpp>
    #include <boost/preprocessor/repetition/repeat.hpp>
    #include <cuda/cuda_runtime.h>
    #ifndef __CUDACC__
    #include <cuda_wrapper/error.hpp>
    #include <cuda_wrapper/stream.hpp>
    #endif

    /* maximum number of arguments passed to device functions */
    #ifndef CUDA_FUNCTION_MAX_ARGS
    #define CUDA_FUNCTION_MAX_ARGS 10
    #endif

    namespace cuda
    {

    /*
     * CUDA execution configuration
     */
    class config
    {
    public:
	/* grid dimensions */
	dim3 grid;
	/* block dimensions */
	dim3 block;
	/* FIXME store useful numbers (no. of threads per grid/block) */

	config()
	{
	}

	config(dim3 grid, dim3 block) : grid(grid), block(block)
	{
	    /* FIXME store useful numbers (no. of threads per grid/block) */
	}

	size_t threads() const
	{
	    return grid.y * grid.x * block.z * block.y * block.x;
	}

	size_t blocks_per_grid() const
	{
	    return grid.y * grid.x;
	}

	size_t threads_per_block() const
	{
	    return block.z * block.y * block.x;
	}
    };

    #ifndef __CUDACC__

    /**
     * configure execution parameters
     */
    __inline__ void configure(dim3 const& grid, dim3 const& block, size_t shared_mem = 0)
    {
	CUDA_CALL(cudaConfigureCall(grid, block, shared_mem, 0));
    }

    #ifdef CUDA_WRAPPER_ASYNC_API
    /**
     * configure execution parameters
     */
    __inline__ void configure(dim3 const& grid, dim3 const& block, stream& stream)
    {
	CUDA_CALL(cudaConfigureCall(grid, block, 0, stream.data()));
    }

    /**
     * configure execution parameters
     */
    __inline__ void configure(dim3 const& grid, dim3 const& block, size_t shared_mem, stream& stream)
    {
	CUDA_CALL(cudaConfigureCall(grid, block, shared_mem, stream.data()));
    }
    #endif /* CUDA_WRAPPER_ASYNC_API */

    #endif /* ! __CUDACC__ */

    } // namespace cuda

    #define BOOST_PP_FILENAME_1 <cuda_wrapper/function.hpp>
    #define BOOST_PP_ITERATION_LIMITS (1, CUDA_FUNCTION_MAX_ARGS)
    #include BOOST_PP_ITERATE()

    #endif /* ! CUDA_FUNCTION_HPP */

#else /* ! BOOST_PP_IS_ITERATING */

    namespace cuda
    {

    template <typename T>
    class function;

    /**
     * CUDA kernel execution wrapper for n-ary device function
     */
    template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename T)>
    class function<void (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))>
    {
    public:
	typedef void T (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T));

    public:
	function(T *entry) : entry(entry) {}

    #ifndef __CUDACC__

	/**
	 * execute kernel
	 */
	void operator()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), T, const& x))
	{
	    size_t offset = 0;
    #define SETUP_ARGUMENT(z, n, x) setup_argument(x##n, offset);
	    BOOST_PP_REPEAT(BOOST_PP_ITERATION(), SETUP_ARGUMENT, x)
    #undef SETUP_ARGUMENT
	    CUDA_CALL(cudaLaunch(reinterpret_cast<const char *>(entry)));
	}

    private:
	/**
	 * push arbitrary argument into argument passing area
	 */
	template <typename U>
	static void setup_argument(U const& arg, size_t& offset)
	{
	    /* respect alignment requirements of passed argument */
	    if (0 != offset % __alignof(U)) {
		offset += __alignof(U) - offset % __alignof(U);
	    }

	    CUDA_CALL(cudaSetupArgument(&arg, sizeof(U), offset));

	    /* advance argument offset for next call */
	    offset += sizeof(U);
	}

    #endif /* ! __CUDACC__ */

    private:
	T *entry;
    };

    } // namespace cuda

#endif /* ! BOOST_PP_IS_ITERATING */
<|endoftext|>


<commit_before>//+ Example of a simple script creating 2 threads each with one canvas.
// This script can only be executed via ACliC .x threadsh2.C++.
// The canvases are saved in a animated gif file.

#include "TROOT.h"
#include "TCanvas.h"
#include "TRootCanvas.h"
#include "TFrame.h"
#include "TH1F.h"
#include "TRandom.h"
#include "TThread.h"
#include "TMethodCall.h"

TCanvas *c1, *c2;
TH1F    *hpx, *total, *hmain, *s1, *s2;
TThread *thread1, *thread2, *threadj;
Bool_t   finished;

void *handle1(void *)
{
   int nfills = 10000;
   int upd = 500;

   TThread::Lock();
   hpx = new TH1F("hpx", "This is the px distribution", 100, -4, 4);
   hpx->SetFillColor(48);
   TThread::UnLock();
   Float_t px, py, pz;
   gRandom->SetSeed();
   for (Int_t i = 0; i < nfills; i++) {
      gRandom->Rannor(px, py);
      pz = px*px + py*py;
      hpx->Fill(px);
      if (i && (i%upd) == 0) {
         if (i == upd) {
            c1->cd();
            hpx->Draw();
         }
         c1->Modified();
         c1->Update();
         gSystem->Sleep(10);
         TMethodCall c(c1->IsA(), "Print", "");
         void *arr[4];
         arr[1] = &c;
         arr[2] = (void *)c1;
         arr[3] = (void*)"\"hpxanim.gif+50\"";
         (*gThreadXAR)("METH", 4, arr, NULL);
      }
   }
   c1->Modified();
   c1->Update();
   TMethodCall c(c1->IsA(), "Print", "");
   void *arr[4];
   arr[1] = &c;
   arr[2] = (void *)c1;
   arr[3] = (void*)"\"hpxanim.gif++\"";
   (*gThreadXAR)("METH", 4, arr, NULL);
   return 0;
}

void *handle2(void *)
{
   int nfills = 10000;
   int upd = 500;

   TThread::Lock();
   total  = new TH1F("total","This is the total distribution",100,-4,4);
   hmain  = new TH1F("hmain","Main contributor",100,-4,4);
   s1     = new TH1F("s1","This is the first signal",100,-4,4);
   s2     = new TH1F("s2","This is the second signal",100,-4,4);
   total->Sumw2();   // this makes sure that the sum of squares of weights will be stored
   total->SetMarkerStyle(21);
   total->SetMarkerSize(0.7);
   hmain->SetFillColor(16);
   s1->SetFillColor(42);
   s2->SetFillColor(46);
   TThread::UnLock();
   Float_t xs1, xs2, xmain;
   gRandom->SetSeed();
   for (Int_t i = 0; i < nfills; i++) {
      xmain = gRandom->Gaus(-1,1.5);
      xs1   = gRandom->Gaus(-0.5,0.5);
      xs2   = gRandom->Landau(1,0.15);
      hmain->Fill(xmain);
      s1->Fill(xs1,0.3);
      s2->Fill(xs2,0.2);
      total->Fill(xmain);
      total->Fill(xs1,0.3);
      total->Fill(xs2,0.2);
      if (i && (i%upd) == 0) {
         if (i == upd) {
            c2->cd();
            total->Draw("e1p");
            hmain->Draw("same");
            s1->Draw("same");
            s2->Draw("same");
         }
         c2->Modified();
         c2->Update();
         gSystem->Sleep(10);
         TMethodCall c(c2->IsA(), "Print", "");
         void *arr[4];
         arr[1] = &c;
         arr[2] = (void *)c2;
         arr[3] = (void*)"\"hsumanim.gif+50\"";
         (*gThreadXAR)("METH", 4, arr, NULL);
      }
   }
   total->Draw("sameaxis"); // to redraw axis hidden by the fill area
   c2->Modified();
   c2->Update();
   // make infinite animation by adding "++" to the file name
   TMethodCall c(c2->IsA(), "Print", "");
   void *arr[4];
   arr[1] = &c;
   arr[2] = (void *)c2;
   arr[3] = (void*)"\"hsumanim.gif++\"";
   (*gThreadXAR)("METH", 4, arr, NULL);
   return 0;
}

void *joiner(void *)
{
   thread1->Join();
   thread2->Join();

   finished = kTRUE;

   return 0;
}

void tryclosing(Int_t id)
{
   // allow to close the canvas only after the threads are done
   if (!finished) return;
   if (id == 1) ((TRootCanvas *)c1->GetCanvasImp())->CloseWindow();
   else if (id == 2) ((TRootCanvas *)c2->GetCanvasImp())->CloseWindow();
}

void threadsh2()
{
#ifdef __CINT__
   printf("This script can only be executed via ACliC: .x threadsh2.C++\n");
   return;
#endif

   c1 = new TCanvas("c1","Dynamic Filling Example", 100, 30, 400, 300);
   c1->SetFillColor(42);
   c1->GetFrame()->SetFillColor(21);
   c1->GetFrame()->SetBorderSize(6);
   c1->GetFrame()->SetBorderMode(-1);
   // connect to the CloseWindow() signal and prevent to close the canvas
   // while the thread is running
   ((TRootCanvas *)c1->GetCanvasImp())->Connect("CloseWindow()", 0, 0,
                                                "tryclosing(Int_t=1)");
   ((TRootCanvas *)c1->GetCanvasImp())->DontCallClose();

   c2 = new TCanvas("c2","Dynamic Filling Example", 515, 30, 400, 300);
   c2->SetGrid();
   // connect to the CloseWindow() signal and prevent to close the canvas
   // while the thread is running
   ((TRootCanvas *)c2->GetCanvasImp())->Connect("CloseWindow()", 0, 0,
                                                "tryclosing(Int_t=2)");
   ((TRootCanvas *)c2->GetCanvasImp())->DontCallClose();

   finished = kFALSE;
   //gDebug = 1;
   gSystem->Unlink("hpxanim.gif");
   gSystem->Unlink("hsumanim.gif");

   printf("Starting Thread 0\n");
   thread1 = new TThread("t0", handle1, (void*) 0);
   thread1->Run();
   printf("Starting Thread 1\n");
   thread2 = new TThread("t1", handle2, (void*) 1);
   thread2->Run();
   printf("Starting Joiner Thread \n");
   threadj = new TThread("t4", joiner, (void*) 3);
   threadj->Run();

   TThread::Ps();

   while (!finished) {
      gSystem->Sleep(100);
      gSystem->ProcessEvents();
   }

   threadj->Join();
   TThread::Ps();

   delete thread1;
   delete thread2;
   delete threadj;
}
<commit_msg>threadsh2 must be run in interactive ... nonetheless succeed (do nothing) in batch mode<commit_after>//+ Example of a simple script creating 2 threads each with one canvas.
// This script can only be executed via ACliC .x threadsh2.C++.
// The canvases are saved in a animated gif file.

#include "TROOT.h"
#include "TCanvas.h"
#include "TRootCanvas.h"
#include "TFrame.h"
#include "TH1F.h"
#include "TRandom.h"
#include "TThread.h"
#include "TMethodCall.h"

TCanvas *c1, *c2;
TH1F    *hpx, *total, *hmain, *s1, *s2;
TThread *thread1, *thread2, *threadj;
Bool_t   finished;

void *handle1(void *)
{
   int nfills = 10000;
   int upd = 500;

   TThread::Lock();
   hpx = new TH1F("hpx", "This is the px distribution", 100, -4, 4);
   hpx->SetFillColor(48);
   TThread::UnLock();
   Float_t px, py, pz;
   gRandom->SetSeed();
   for (Int_t i = 0; i < nfills; i++) {
      gRandom->Rannor(px, py);
      pz = px*px + py*py;
      hpx->Fill(px);
      if (i && (i%upd) == 0) {
         if (i == upd) {
            c1->cd();
            hpx->Draw();
         }
         c1->Modified();
         c1->Update();
         gSystem->Sleep(10);
         TMethodCall c(c1->IsA(), "Print", "");
         void *arr[4];
         arr[1] = &c;
         arr[2] = (void *)c1;
         arr[3] = (void*)"\"hpxanim.gif+50\"";
         (*gThreadXAR)("METH", 4, arr, NULL);
      }
   }
   c1->Modified();
   c1->Update();
   TMethodCall c(c1->IsA(), "Print", "");
   void *arr[4];
   arr[1] = &c;
   arr[2] = (void *)c1;
   arr[3] = (void*)"\"hpxanim.gif++\"";
   (*gThreadXAR)("METH", 4, arr, NULL);
   return 0;
}

void *handle2(void *)
{
   int nfills = 10000;
   int upd = 500;

   TThread::Lock();
   total  = new TH1F("total","This is the total distribution",100,-4,4);
   hmain  = new TH1F("hmain","Main contributor",100,-4,4);
   s1     = new TH1F("s1","This is the first signal",100,-4,4);
   s2     = new TH1F("s2","This is the second signal",100,-4,4);
   total->Sumw2();   // this makes sure that the sum of squares of weights will be stored
   total->SetMarkerStyle(21);
   total->SetMarkerSize(0.7);
   hmain->SetFillColor(16);
   s1->SetFillColor(42);
   s2->SetFillColor(46);
   TThread::UnLock();
   Float_t xs1, xs2, xmain;
   gRandom->SetSeed();
   for (Int_t i = 0; i < nfills; i++) {
      xmain = gRandom->Gaus(-1,1.5);
      xs1   = gRandom->Gaus(-0.5,0.5);
      xs2   = gRandom->Landau(1,0.15);
      hmain->Fill(xmain);
      s1->Fill(xs1,0.3);
      s2->Fill(xs2,0.2);
      total->Fill(xmain);
      total->Fill(xs1,0.3);
      total->Fill(xs2,0.2);
      if (i && (i%upd) == 0) {
         if (i == upd) {
            c2->cd();
            total->Draw("e1p");
            hmain->Draw("same");
            s1->Draw("same");
            s2->Draw("same");
         }
         c2->Modified();
         c2->Update();
         gSystem->Sleep(10);
         TMethodCall c(c2->IsA(), "Print", "");
         void *arr[4];
         arr[1] = &c;
         arr[2] = (void *)c2;
         arr[3] = (void*)"\"hsumanim.gif+50\"";
         (*gThreadXAR)("METH", 4, arr, NULL);
      }
   }
   total->Draw("sameaxis"); // to redraw axis hidden by the fill area
   c2->Modified();
   c2->Update();
   // make infinite animation by adding "++" to the file name
   TMethodCall c(c2->IsA(), "Print", "");
   void *arr[4];
   arr[1] = &c;
   arr[2] = (void *)c2;
   arr[3] = (void*)"\"hsumanim.gif++\"";
   (*gThreadXAR)("METH", 4, arr, NULL);
   return 0;
}

void *joiner(void *)
{
   thread1->Join();
   thread2->Join();

   finished = kTRUE;

   return 0;
}

void tryclosing(Int_t id)
{
   // allow to close the canvas only after the threads are done
   if (!finished) return;
   if (id == 1) ((TRootCanvas *)c1->GetCanvasImp())->CloseWindow();
   else if (id == 2) ((TRootCanvas *)c2->GetCanvasImp())->CloseWindow();
}

#include "TClass.h"

void threadsh2()
{
#ifdef __CINT__
   printf("This script can only be executed via ACliC: .x threadsh2.C++\n");
   return;
#endif

   if (gROOT->IsBatch()) {
      return;
   }
   c1 = new TCanvas("c1","Dynamic Filling Example", 100, 30, 400, 300);
   c1->SetFillColor(42);
   c1->GetFrame()->SetFillColor(21);
   c1->GetFrame()->SetBorderSize(6);
   c1->GetFrame()->SetBorderMode(-1);
   // connect to the CloseWindow() signal and prevent to close the canvas
   // while the thread is running
   TRootCanvas *rc = dynamic_cast<TRootCanvas*>(c1->GetCanvasImp());
   if (!rc) return;

   rc->Connect("CloseWindow()", 0, 0,
               "tryclosing(Int_t=1)");
   rc->DontCallClose();

   c2 = new TCanvas("c2","Dynamic Filling Example", 515, 30, 400, 300);
   c2->SetGrid();
   // connect to the CloseWindow() signal and prevent to close the canvas
   // while the thread is running
   rc = dynamic_cast<TRootCanvas*>(c2->GetCanvasImp());
   if (!rc) return;
   rc->Connect("CloseWindow()", 0, 0,
               "tryclosing(Int_t=2)");
   rc->DontCallClose();

   finished = kFALSE;
   //gDebug = 1;
   gSystem->Unlink("hpxanim.gif");
   gSystem->Unlink("hsumanim.gif");

   printf("Starting Thread 0\n");
   thread1 = new TThread("t0", handle1, (void*) 0);
   thread1->Run();
   printf("Starting Thread 1\n");
   thread2 = new TThread("t1", handle2, (void*) 1);
   thread2->Run();
   printf("Starting Joiner Thread \n");
   threadj = new TThread("t4", joiner, (void*) 3);
   threadj->Run();

   TThread::Ps();

   while (!finished) {
      gSystem->Sleep(100);
      gSystem->ProcessEvents();
   }

   threadj->Join();
   TThread::Ps();

   delete thread1;
   delete thread2;
   delete threadj;
}
<|endoftext|>


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

#include "chrome/test/in_process_browser_test.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/string_number_conversions.h"
#include "base/test/test_file_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/intranet_redirect_detector.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/net/url_request_mock_util.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#if defined(OS_WIN)
#include "chrome/browser/views/frame/browser_view.h"
#endif
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/testing_browser_process.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/mock_host_resolver.h"
#include "net/test/test_server.h"
#include "sandbox/src/dep.h"

#if defined(OS_LINUX)
#include "base/singleton.h"
#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
#include "chrome/browser/zygote_host_linux.h"

namespace {

// A helper class to do Linux-only initialization only once per process.
class LinuxHostInit {
 public:
  LinuxHostInit() {
    RenderSandboxHostLinux* shost = Singleton<RenderSandboxHostLinux>::get();
    shost->Init("");
    ZygoteHost* zhost = Singleton<ZygoteHost>::get();
    zhost->Init("");
  }
  ~LinuxHostInit() {}
};

}  // namespace
#endif

extern int BrowserMain(const MainFunctionParams&);

const wchar_t kUnitTestShowWindows[] = L"show-windows";

// Passed as value of kTestType.
static const char kBrowserTestType[] = "browser";

// Default delay for the time-out at which we stop the
// inner-message loop the first time.
const int kInitialTimeoutInMS = 30000;

// Delay for sub-sequent time-outs once the initial time-out happened.
const int kSubsequentTimeoutInMS = 5000;

InProcessBrowserTest::InProcessBrowserTest()
    : browser_(NULL),
      test_server_(net::TestServer::TYPE_HTTP,
                   FilePath(FILE_PATH_LITERAL("chrome/test/data"))),
      show_window_(false),
      dom_automation_enabled_(false),
      tab_closeable_state_watcher_enabled_(false),
      original_single_process_(false),
      initial_timeout_(kInitialTimeoutInMS) {
}

InProcessBrowserTest::~InProcessBrowserTest() {
}

void InProcessBrowserTest::SetUp() {
  // Cleanup the user data dir.
  FilePath user_data_dir;
  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  ASSERT_LT(10, static_cast<int>(user_data_dir.value().size())) <<
      "The user data directory name passed into this test was too "
      "short to delete safely.  Please check the user-data-dir "
      "argument and try again.";
  ASSERT_TRUE(file_util::DieFileDie(user_data_dir, true));

  // Recreate the user data dir. (PathService::Get guarantees that the directory
  // exists if it returns true, but it only actually checks on the first call,
  // the rest are cached.  Thus we need to recreate it ourselves to not break
  // the PathService guarantee.)
  ASSERT_TRUE(file_util::CreateDirectory(user_data_dir));

  // The unit test suite creates a testingbrowser, but we want the real thing.
  // Delete the current one. We'll install the testing one in TearDown.
  delete g_browser_process;
  g_browser_process = NULL;

  SetUpUserDataDirectory();

  // Don't delete the resources when BrowserMain returns. Many ui classes
  // cache SkBitmaps in a static field so that if we delete the resource
  // bundle we'll crash.
  browser_shutdown::delete_resources_on_shutdown = false;

  // Remember the command line.  Normally this doesn't matter, because the test
  // harness creates a new process for each test, but when the test harness is
  // running in single process mode, we can't let one test's command-line
  // changes (e.g. enabling DOM automation) affect other tests.
  CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
  original_command_line_.reset(new CommandLine(*command_line));

  SetUpCommandLine(command_line);

#if defined(OS_WIN)
  // Hide windows on show.
  if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
    BrowserView::SetShowState(SW_HIDE);
#endif

  if (dom_automation_enabled_)
    command_line->AppendSwitch(switches::kDomAutomationController);

  // Turn off tip loading for tests; see http://crbug.com/17725
  command_line->AppendSwitch(switches::kDisableWebResources);

  command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);

  // Don't show the first run ui.
  command_line->AppendSwitch(switches::kNoFirstRun);

  // This is a Browser test.
  command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);

  // Single-process mode is not set in BrowserMain so it needs to be processed
  // explicitly.
  original_single_process_ = RenderProcessHost::run_renderer_in_process();
  if (command_line->HasSwitch(switches::kSingleProcess))
    RenderProcessHost::set_run_renderer_in_process(true);

#if defined(OS_WIN)
  // The Windows sandbox requires that the browser and child processes are the
  // same binary.  So we launch browser_process.exe which loads chrome.dll
  command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
                                 command_line->GetProgram());
#else
  // Explicitly set the path of the binary used for child processes, otherwise
  // they'll try to use browser_tests which doesn't contain ChromeMain.
  FilePath subprocess_path;
  PathService::Get(base::FILE_EXE, &subprocess_path);
  subprocess_path = subprocess_path.DirName();
  subprocess_path = subprocess_path.AppendASCII(WideToASCII(
      chrome::kBrowserProcessExecutablePath));
#if defined(OS_MACOSX)
  // Recreate the real environment, run the helper within the app bundle.
  subprocess_path = subprocess_path.DirName().DirName();
  DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
  subprocess_path =
      subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
  subprocess_path =
      subprocess_path.Append(chrome::kHelperProcessExecutablePath);
#endif
  command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
                                 subprocess_path);
#endif

  // Enable warning level logging so that we can see when bad stuff happens.
  command_line->AppendSwitch(switches::kEnableLogging);
  command_line->AppendSwitchASCII(switches::kLoggingLevel, "1");  // warning

  // If ncecessary, disable TabCloseableStateWatcher.
  if (!tab_closeable_state_watcher_enabled_)
    command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);

  SandboxInitWrapper sandbox_wrapper;
  MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
  params.ui_task =
      NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);

  host_resolver_ = new net::RuleBasedHostResolverProc(
      new IntranetRedirectHostResolverProc(NULL));

  // Something inside the browser does this lookup implicitly. Make it fail
  // to avoid external dependency. It won't break the tests.
  host_resolver_->AddSimulatedFailure("*.google.com");

  // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
  // We don't want the test code to use it.
  host_resolver_->AddSimulatedFailure("wpad");

  net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
      host_resolver_.get());

  SetUpInProcessBrowserTestFixture();

  // Before we run the browser, we have to hack the path to the exe to match
  // what it would be if Chrome was running, because it is used to fork renderer
  // processes, on Linux at least (failure to do so will cause a browser_test to
  // be run instead of a renderer).
  FilePath chrome_path;
  CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
  chrome_path = chrome_path.DirName();
#if defined(OS_WIN)
  chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
#elif defined(OS_POSIX)
  chrome_path = chrome_path.Append(
      WideToASCII(chrome::kBrowserProcessExecutablePath));
#endif
  CHECK(PathService::Override(base::FILE_EXE, chrome_path));

#if defined(OS_LINUX)
  // Initialize the RenderSandbox and Zygote hosts. Apparently they get used
  // for InProcessBrowserTest, and this is not the normal browser startup path.
  Singleton<LinuxHostInit>::get();
#endif

  BrowserMain(params);
  TearDownInProcessBrowserTestFixture();
}

void InProcessBrowserTest::TearDown() {
  // Reinstall testing browser process.
  delete g_browser_process;
  g_browser_process = new TestingBrowserProcess();

  browser_shutdown::delete_resources_on_shutdown = true;

#if defined(OS_WIN)
  BrowserView::SetShowState(-1);
#endif

  *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
  RenderProcessHost::set_run_renderer_in_process(original_single_process_);
}

// Creates a browser with a single tab (about:blank), waits for the tab to
// finish loading and shows the browser.
Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
  Browser* browser = Browser::Create(profile);

  browser->AddTabWithURL(GURL(chrome::kAboutBlankURL), GURL(),
                         PageTransition::START_PAGE, -1,
                         TabStripModel::ADD_SELECTED, NULL, std::string(),
                         &browser);

  // Wait for the page to finish loading.
  ui_test_utils::WaitForNavigation(
      &browser->GetSelectedTabContents()->controller());

  browser->window()->Show();

  return browser;
}

void InProcessBrowserTest::RunTestOnMainThreadLoop() {
  // On Mac, without the following autorelease pool, code which is directly
  // executed (as opposed to executed inside a message loop) would autorelease
  // objects into a higher-level pool. This pool is not recycled in-sync with
  // the message loops' pools and causes problems with code relying on
  // deallocation via an autorelease pool (such as browser window closure and
  // browser shutdown). To avoid this, the following pool is recycled after each
  // time code is directly executed.
  base::ScopedNSAutoreleasePool pool;

  // Pump startup related events.
  MessageLoopForUI::current()->RunAllPending();

  // In the long term it would be great if we could use a TestingProfile
  // here and only enable services you want tested, but that requires all
  // consumers of Profile to handle NULL services.
  Profile* profile = ProfileManager::GetDefaultProfile();
  if (!profile) {
    // We should only be able to get here if the profile already exists and
    // has been created.
    NOTREACHED();
    return;
  }
  pool.Recycle();

  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));

  browser_ = CreateBrowser(profile);
  pool.Recycle();

  // Start the timeout timer to prevent hangs.
  MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
      NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
      initial_timeout_);

  // Pump any pending events that were created as a result of creating a
  // browser.
  MessageLoopForUI::current()->RunAllPending();

  RunTestOnMainThread();
  pool.Recycle();

  CleanUpOnMainThread();
  pool.Recycle();

  QuitBrowsers();
  pool.Recycle();
}

void InProcessBrowserTest::QuitBrowsers() {
  if (BrowserList::size() == 0)
    return;

  // Invoke CloseAllBrowsersAndExit on a running message loop.
  // CloseAllBrowsersAndExit exits the message loop after everything has been
  // shut down properly.
  MessageLoopForUI::current()->PostTask(
      FROM_HERE,
      NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
  ui_test_utils::RunMessageLoop();
}

void InProcessBrowserTest::TimedOut() {
  std::string error_message = "Test timed out. Each test runs for a max of ";
  error_message += base::IntToString(initial_timeout_);
  error_message += " ms (kInitialTimeoutInMS).";

  MessageLoopForUI::current()->Quit();

  // WARNING: This must be after Quit as it returns.
  FAIL() << error_message;
}

void InProcessBrowserTest::SetInitialTimeoutInMS(int timeout_value) {
  DCHECK_GT(timeout_value, 0);
  initial_timeout_ = timeout_value;
}
<commit_msg>The browser tests seem to fail with preconnects; the python server crashes.  Preconnect seems to be working properly.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/in_process_browser_test.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/string_number_conversions.h"
#include "base/test/test_file_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/intranet_redirect_detector.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/net/url_request_mock_util.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#if defined(OS_WIN)
#include "chrome/browser/views/frame/browser_view.h"
#endif
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/testing_browser_process.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/mock_host_resolver.h"
#include "net/test/test_server.h"
#include "sandbox/src/dep.h"

#if defined(OS_LINUX)
#include "base/singleton.h"
#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
#include "chrome/browser/zygote_host_linux.h"

namespace {

// A helper class to do Linux-only initialization only once per process.
class LinuxHostInit {
 public:
  LinuxHostInit() {
    RenderSandboxHostLinux* shost = Singleton<RenderSandboxHostLinux>::get();
    shost->Init("");
    ZygoteHost* zhost = Singleton<ZygoteHost>::get();
    zhost->Init("");
  }
  ~LinuxHostInit() {}
};

}  // namespace
#endif

extern int BrowserMain(const MainFunctionParams&);

const wchar_t kUnitTestShowWindows[] = L"show-windows";

// Passed as value of kTestType.
static const char kBrowserTestType[] = "browser";

// Default delay for the time-out at which we stop the
// inner-message loop the first time.
const int kInitialTimeoutInMS = 30000;

// Delay for sub-sequent time-outs once the initial time-out happened.
const int kSubsequentTimeoutInMS = 5000;

InProcessBrowserTest::InProcessBrowserTest()
    : browser_(NULL),
      test_server_(net::TestServer::TYPE_HTTP,
                   FilePath(FILE_PATH_LITERAL("chrome/test/data"))),
      show_window_(false),
      dom_automation_enabled_(false),
      tab_closeable_state_watcher_enabled_(false),
      original_single_process_(false),
      initial_timeout_(kInitialTimeoutInMS) {
}

InProcessBrowserTest::~InProcessBrowserTest() {
}

void InProcessBrowserTest::SetUp() {
  // Cleanup the user data dir.
  FilePath user_data_dir;
  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  ASSERT_LT(10, static_cast<int>(user_data_dir.value().size())) <<
      "The user data directory name passed into this test was too "
      "short to delete safely.  Please check the user-data-dir "
      "argument and try again.";
  ASSERT_TRUE(file_util::DieFileDie(user_data_dir, true));

  // Recreate the user data dir. (PathService::Get guarantees that the directory
  // exists if it returns true, but it only actually checks on the first call,
  // the rest are cached.  Thus we need to recreate it ourselves to not break
  // the PathService guarantee.)
  ASSERT_TRUE(file_util::CreateDirectory(user_data_dir));

  // The unit test suite creates a testingbrowser, but we want the real thing.
  // Delete the current one. We'll install the testing one in TearDown.
  delete g_browser_process;
  g_browser_process = NULL;

  SetUpUserDataDirectory();

  // Don't delete the resources when BrowserMain returns. Many ui classes
  // cache SkBitmaps in a static field so that if we delete the resource
  // bundle we'll crash.
  browser_shutdown::delete_resources_on_shutdown = false;

  // Remember the command line.  Normally this doesn't matter, because the test
  // harness creates a new process for each test, but when the test harness is
  // running in single process mode, we can't let one test's command-line
  // changes (e.g. enabling DOM automation) affect other tests.
  CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
  original_command_line_.reset(new CommandLine(*command_line));

  SetUpCommandLine(command_line);

#if defined(OS_WIN)
  // Hide windows on show.
  if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
    BrowserView::SetShowState(SW_HIDE);
#endif

  if (dom_automation_enabled_)
    command_line->AppendSwitch(switches::kDomAutomationController);

  // Turn off tip loading for tests; see http://crbug.com/17725
  command_line->AppendSwitch(switches::kDisableWebResources);

  // Turn off preconnects because they break the brittle python webserver.
  command_line->AppendSwitch(switches::kDisablePreconnect);

  command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);

  // Don't show the first run ui.
  command_line->AppendSwitch(switches::kNoFirstRun);

  // This is a Browser test.
  command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);

  // Single-process mode is not set in BrowserMain so it needs to be processed
  // explicitly.
  original_single_process_ = RenderProcessHost::run_renderer_in_process();
  if (command_line->HasSwitch(switches::kSingleProcess))
    RenderProcessHost::set_run_renderer_in_process(true);

#if defined(OS_WIN)
  // The Windows sandbox requires that the browser and child processes are the
  // same binary.  So we launch browser_process.exe which loads chrome.dll
  command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
                                 command_line->GetProgram());
#else
  // Explicitly set the path of the binary used for child processes, otherwise
  // they'll try to use browser_tests which doesn't contain ChromeMain.
  FilePath subprocess_path;
  PathService::Get(base::FILE_EXE, &subprocess_path);
  subprocess_path = subprocess_path.DirName();
  subprocess_path = subprocess_path.AppendASCII(WideToASCII(
      chrome::kBrowserProcessExecutablePath));
#if defined(OS_MACOSX)
  // Recreate the real environment, run the helper within the app bundle.
  subprocess_path = subprocess_path.DirName().DirName();
  DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
  subprocess_path =
      subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
  subprocess_path =
      subprocess_path.Append(chrome::kHelperProcessExecutablePath);
#endif
  command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
                                 subprocess_path);
#endif

  // Enable warning level logging so that we can see when bad stuff happens.
  command_line->AppendSwitch(switches::kEnableLogging);
  command_line->AppendSwitchASCII(switches::kLoggingLevel, "1");  // warning

  // If ncecessary, disable TabCloseableStateWatcher.
  if (!tab_closeable_state_watcher_enabled_)
    command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);

  SandboxInitWrapper sandbox_wrapper;
  MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
  params.ui_task =
      NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);

  host_resolver_ = new net::RuleBasedHostResolverProc(
      new IntranetRedirectHostResolverProc(NULL));

  // Something inside the browser does this lookup implicitly. Make it fail
  // to avoid external dependency. It won't break the tests.
  host_resolver_->AddSimulatedFailure("*.google.com");

  // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
  // We don't want the test code to use it.
  host_resolver_->AddSimulatedFailure("wpad");

  net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
      host_resolver_.get());

  SetUpInProcessBrowserTestFixture();

  // Before we run the browser, we have to hack the path to the exe to match
  // what it would be if Chrome was running, because it is used to fork renderer
  // processes, on Linux at least (failure to do so will cause a browser_test to
  // be run instead of a renderer).
  FilePath chrome_path;
  CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
  chrome_path = chrome_path.DirName();
#if defined(OS_WIN)
  chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
#elif defined(OS_POSIX)
  chrome_path = chrome_path.Append(
      WideToASCII(chrome::kBrowserProcessExecutablePath));
#endif
  CHECK(PathService::Override(base::FILE_EXE, chrome_path));

#if defined(OS_LINUX)
  // Initialize the RenderSandbox and Zygote hosts. Apparently they get used
  // for InProcessBrowserTest, and this is not the normal browser startup path.
  Singleton<LinuxHostInit>::get();
#endif

  BrowserMain(params);
  TearDownInProcessBrowserTestFixture();
}

void InProcessBrowserTest::TearDown() {
  // Reinstall testing browser process.
  delete g_browser_process;
  g_browser_process = new TestingBrowserProcess();

  browser_shutdown::delete_resources_on_shutdown = true;

#if defined(OS_WIN)
  BrowserView::SetShowState(-1);
#endif

  *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
  RenderProcessHost::set_run_renderer_in_process(original_single_process_);
}

// Creates a browser with a single tab (about:blank), waits for the tab to
// finish loading and shows the browser.
Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
  Browser* browser = Browser::Create(profile);

  browser->AddTabWithURL(GURL(chrome::kAboutBlankURL), GURL(),
                         PageTransition::START_PAGE, -1,
                         TabStripModel::ADD_SELECTED, NULL, std::string(),
                         &browser);

  // Wait for the page to finish loading.
  ui_test_utils::WaitForNavigation(
      &browser->GetSelectedTabContents()->controller());

  browser->window()->Show();

  return browser;
}

void InProcessBrowserTest::RunTestOnMainThreadLoop() {
  // On Mac, without the following autorelease pool, code which is directly
  // executed (as opposed to executed inside a message loop) would autorelease
  // objects into a higher-level pool. This pool is not recycled in-sync with
  // the message loops' pools and causes problems with code relying on
  // deallocation via an autorelease pool (such as browser window closure and
  // browser shutdown). To avoid this, the following pool is recycled after each
  // time code is directly executed.
  base::ScopedNSAutoreleasePool pool;

  // Pump startup related events.
  MessageLoopForUI::current()->RunAllPending();

  // In the long term it would be great if we could use a TestingProfile
  // here and only enable services you want tested, but that requires all
  // consumers of Profile to handle NULL services.
  Profile* profile = ProfileManager::GetDefaultProfile();
  if (!profile) {
    // We should only be able to get here if the profile already exists and
    // has been created.
    NOTREACHED();
    return;
  }
  pool.Recycle();

  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));

  browser_ = CreateBrowser(profile);
  pool.Recycle();

  // Start the timeout timer to prevent hangs.
  MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
      NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
      initial_timeout_);

  // Pump any pending events that were created as a result of creating a
  // browser.
  MessageLoopForUI::current()->RunAllPending();

  RunTestOnMainThread();
  pool.Recycle();

  CleanUpOnMainThread();
  pool.Recycle();

  QuitBrowsers();
  pool.Recycle();
}

void InProcessBrowserTest::QuitBrowsers() {
  if (BrowserList::size() == 0)
    return;

  // Invoke CloseAllBrowsersAndExit on a running message loop.
  // CloseAllBrowsersAndExit exits the message loop after everything has been
  // shut down properly.
  MessageLoopForUI::current()->PostTask(
      FROM_HERE,
      NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
  ui_test_utils::RunMessageLoop();
}

void InProcessBrowserTest::TimedOut() {
  std::string error_message = "Test timed out. Each test runs for a max of ";
  error_message += base::IntToString(initial_timeout_);
  error_message += " ms (kInitialTimeoutInMS).";

  MessageLoopForUI::current()->Quit();

  // WARNING: This must be after Quit as it returns.
  FAIL() << error_message;
}

void InProcessBrowserTest::SetInitialTimeoutInMS(int timeout_value) {
  DCHECK_GT(timeout_value, 0);
  initial_timeout_ = timeout_value;
}
<|endoftext|>