<commit_before>#pragma once

#include <algorithm>
#include <thread>

namespace tp
{

/**
 * @brief The ThreadPoolOptions class provides creation options for
 * ThreadPool.
 */
class ThreadPoolOptions
{
public:
    /**
     * @brief ThreadPoolOptions Construct default options for thread pool.
     */
    ThreadPoolOptions();

    /**
     * @brief setThreadCount Set thread count.
     * @param count Number of threads to be created.
     */
    void setThreadCount(size_t count);

    /**
     * @brief setQueueSize Set single worker queue size.
     * @param count Maximum length of queue of single worker.
     */
    void setQueueSize(size_t size);

    /**
     * @brief threadCount Return thread count.
     */
    size_t threadCount() const;

    /**
     * @brief queueSize Return single worker queue size.
     */
    size_t queueSize() const;

private:
    size_t m_thread_count;
    size_t m_queue_size;
};

/// Implementation

inline ThreadPoolOptions::ThreadPoolOptions()
    : m_thread_count(std::max<size_t>(1u, std::thread::hardware_concurrency()))
    , m_queue_size(1024u)
{
}

inline void ThreadPoolOptions::setThreadCount(size_t count)
{
    m_thread_count = std::max<size_t>(1u, count);
}

inline void ThreadPoolOptions::setQueueSize(size_t size)
{
    m_queue_size = std::max<size_t>(1u, size);
}

inline size_t ThreadPoolOptions::threadCount() const
{
    return m_thread_count;
}

inline size_t ThreadPoolOptions::queueSize() const
{
    return m_queue_size;
}

}
<commit_msg>threadpool should do hw concurrency -1 to give main thread chance to process relays<commit_after>#pragma once

#include <algorithm>
#include <thread>

namespace tp
{

/**
 * @brief The ThreadPoolOptions class provides creation options for
 * ThreadPool.
 */
class ThreadPoolOptions
{
public:
    /**
     * @brief ThreadPoolOptions Construct default options for thread pool.
     */
    ThreadPoolOptions();

    /**
     * @brief setThreadCount Set thread count.
     * @param count Number of threads to be created.
     */
    void setThreadCount(size_t count);

    /**
     * @brief setQueueSize Set single worker queue size.
     * @param count Maximum length of queue of single worker.
     */
    void setQueueSize(size_t size);

    /**
     * @brief threadCount Return thread count.
     */
    size_t threadCount() const;

    /**
     * @brief queueSize Return single worker queue size.
     */
    size_t queueSize() const;

private:
    size_t m_thread_count;
    size_t m_queue_size;
};

/// Implementation

inline ThreadPoolOptions::ThreadPoolOptions()
    : m_thread_count(std::max<size_t>(1u, std::thread::hardware_concurrency()-1))
    , m_queue_size(1024u)
{
}

inline void ThreadPoolOptions::setThreadCount(size_t count)
{
    m_thread_count = std::max<size_t>(1u, count);
}

inline void ThreadPoolOptions::setQueueSize(size_t size)
{
    m_queue_size = std::max<size_t>(1u, size);
}

inline size_t ThreadPoolOptions::threadCount() const
{
    return m_thread_count;
}

inline size_t ThreadPoolOptions::queueSize() const
{
    return m_queue_size;
}

}
<|endoftext|>


<commit_before>/*
    This file is part of solidity.

    solidity 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.

    solidity 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 solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Alex Beregszaszi
 * @date 2016
 * End to end tests for LLL.
 */

#include <string>
#include <memory>
#include <boost/test/unit_test.hpp>
#include <test/liblll/ExecutionFramework.h>

using namespace std;

namespace dev
{
namespace lll
{
namespace test
{

BOOST_FIXTURE_TEST_SUITE(LLLEndToEndTest, LLLExecutionFramework)

BOOST_AUTO_TEST_CASE(smoke_test)
{
        char const* sourceCode = "(returnlll { (return \"test\") })";
        compileAndRun(sourceCode);
        BOOST_CHECK(callFallback() == encodeArgs(string("test", 4)));
}

BOOST_AUTO_TEST_CASE(bare_panic)
{
	char const* sourceCode = "(panic)";
	compileAndRunWithoutCheck(sourceCode);
	BOOST_REQUIRE(m_output.empty());
}

BOOST_AUTO_TEST_CASE(enclosed_panic)
{
	char const* sourceCode = "(seq (panic))";
	compileAndRunWithoutCheck(sourceCode);
	BOOST_REQUIRE(m_output.empty());
}

BOOST_AUTO_TEST_SUITE_END()

}
}
} // end namespaces
<commit_msg>Added tests for exponent operator.<commit_after>/*
    This file is part of solidity.

    solidity 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.

    solidity 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 solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Alex Beregszaszi
 * @date 2016
 * End to end tests for LLL.
 */

#include <string>
#include <memory>
#include <boost/test/unit_test.hpp>
#include <test/liblll/ExecutionFramework.h>

using namespace std;

namespace dev
{
namespace lll
{
namespace test
{

BOOST_FIXTURE_TEST_SUITE(LLLEndToEndTest, LLLExecutionFramework)

BOOST_AUTO_TEST_CASE(smoke_test)
{
        char const* sourceCode = "(returnlll { (return \"test\") })";
        compileAndRun(sourceCode);
        BOOST_CHECK(callFallback() == encodeArgs(string("test", 4)));
}

BOOST_AUTO_TEST_CASE(bare_panic)
{
	char const* sourceCode = "(panic)";
	compileAndRunWithoutCheck(sourceCode);
	BOOST_REQUIRE(m_output.empty());
}

BOOST_AUTO_TEST_CASE(enclosed_panic)
{
	char const* sourceCode = "(seq (panic))";
	compileAndRunWithoutCheck(sourceCode);
	BOOST_REQUIRE(m_output.empty());
}

BOOST_AUTO_TEST_CASE(exp_operator_const)
{
	char const* sourceCode = R"(
		(returnlll
			(return (exp 2 3)))
    )";
	compileAndRun(sourceCode);
    BOOST_CHECK(callFallback() == toBigEndian(u256(8)));
}

BOOST_AUTO_TEST_CASE(exp_operator_const_signed)
{
	char const* sourceCode = R"(
		(returnlll
			(return (exp (- 0 2) 3)))
    )";
	compileAndRun(sourceCode);
    BOOST_CHECK(callFallback() == toBigEndian(u256(-8)));
}

BOOST_AUTO_TEST_CASE(exp_operator_parameter)
{
	char const* sourceCode = R"(
		(seq
			(def 'function (function-hash code-body)
				(when (= (div (calldataload 0x00) (exp 2 224)) function-hash)
					code-body))
			(returnlll
				(seq
					(function 0xb3de648b
						(return (exp 2 (calldataload 0x04))))
					(jump 0x02))))
    )";
	compileAndRun(sourceCode);
    BOOST_CHECK(callContractFunction("f(uint256)", u256(16)) == toBigEndian(u256(65536)));
}

BOOST_AUTO_TEST_SUITE_END()

}
}
} // end namespaces
<|endoftext|>


<commit_before>#include <chrono>
#include <ostream>
#include <unordered_set>

#include <sdd/values/bitset.hh>

#include "mc/units/concurrent_units.hh"

namespace pnmc { namespace mc { namespace units {

/*------------------------------------------------------------------------------------------------*/

namespace /* anonymous */{

struct nested_query_visitor
{
  using result_type = bool;

  const sdd::values::flat_set<unsigned int>& empty;
  const unsigned int j;
  mutable std::unordered_set<const sdd::flat_node<sdd_conf>*> cache;

  nested_query_visitor(const sdd::values::flat_set<unsigned int>& empty, unsigned int j)
    : empty(empty), j(j), cache()
  {}

  bool
  operator()(const sdd::zero_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|0|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::one_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|1|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::hierarchical_node<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "Hierarchy");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::flat_node<sdd_conf>& node, const order& o)
  const noexcept
  {
    const auto insertion = cache.emplace(&node);
    if (insertion.second)
    {
      if (o.identifier().user() == j)
      {
        for (const auto& arc : node)
        {
          if (arc.valuation() != empty)
          {
            return true;
          }
        }
      }
      else
      {
        for (const auto& arc : node)
        {
          if (visit(*this, arc.successor(), o.next()))
          {
            return true;
          }
        }
      }
    }
    return false;
  }
};

struct query_visitor
{
  using result_type = bool;

  const sdd::values::flat_set<unsigned int>& empty;
  const unsigned int i;
  const unsigned int j;
  mutable std::unordered_set<const sdd::flat_node<sdd_conf>*> cache;

  query_visitor(const sdd::values::flat_set<unsigned int>& empty, unsigned int i, unsigned int j)
    : empty(empty), i(i), j(j), cache()
  {}

  bool
  operator()(const sdd::zero_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|0|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::one_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|1|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::hierarchical_node<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "Hierarchy");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::flat_node<sdd_conf>& node, const order& o)
  const
  {
    const auto insertion = cache.emplace(&node);
    if (insertion.second)
    {
      if (o.identifier().user() == i)
      {
        for (const auto& arc : node)
        {
          if (arc.valuation() != empty)
          {
            if (visit(nested_query_visitor(empty, j), arc.successor(), o.next()))
            {
              return true;
            }
          }
        }
      }
      else
      {
        for (const auto& arc : node)
        {
          if (visit(*this, arc.successor(), o.next()))
          {
            return true;
          }
        }
      }
    }
    return false;
  }
};

bool
query(SDD states, const order& o, unsigned int i, unsigned int j)
{
  const sdd::values::flat_set<unsigned int> empty_unit = {0};
  if (o.node(i) < o.node(j)) // does 'i' is before 'j' in the order?
  {
    return visit(query_visitor(empty_unit, i, j), states, o);
  }
  else
  {
    return visit(query_visitor(empty_unit, j, i), states, o);
  }
}

} // namespace anonymous

/*------------------------------------------------------------------------------------------------*/

void
compute_concurrent_units( const conf::pnmc_configuration& conf, const pn::net& net
                        , const sdd::order<sdd_conf>& o, SDD states)
{
  namespace chrono = std::chrono;
  chrono::time_point<chrono::system_clock> start = chrono::system_clock::now();

  const auto nb_units = net.units().size();
  unsigned int j_end = 1;
  for (unsigned int i = 0; i < nb_units; ++i, ++j_end)
  {
    for (unsigned int j = 0; j < j_end; ++j)
    {
      if ( i == j or net.places_of_unit(i).empty() or net.places_of_unit(j).empty()
          or net.units_are_related(i, j))
      {
        std::cout << "0 ";
      }
      else
      {
        std::cout << (query(states, o, i, j) ? "1 " : "0 ");
      }
    }
    std::cout << "\n";
  }

  chrono::time_point<chrono::system_clock> end = chrono::system_clock::now();
  const std::size_t elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();
  if (conf.show_time)
  {
    std::cout << "Concurrent units computation time: " << elapsed << "s\n";
  }
}

/*------------------------------------------------------------------------------------------------*/

}}} // namespace pnmc::mc::units
<commit_msg>Compute concurrent units using their nested places.<commit_after>#include <algorithm> // sort
#include <chrono>
#include <ostream>
#include <unordered_map>
#include <utility>  //pair
#include <vector>

#include <sdd/values/bitset.hh>

#include "mc/units/concurrent_units.hh"

namespace pnmc { namespace mc { namespace units {

/*------------------------------------------------------------------------------------------------*/

namespace /* anonymous */{

struct active
{
  bool i;
  bool j;

  active(bool i, bool j)
    : i(i), j(j)
  {}

  bool
  operator==(const active& other)
  const
  {
    return i == other.i and j == other.j;
  }

  bool
  all()
  const
  {
    return i and j;
  }
};

template <typename InputIterator>
struct query_visitor
{
  using result_type = active;

  const sdd::values::flat_set<unsigned int>& inactive_unit;

  const InputIterator i_units_end;
  const InputIterator j_units_end;

  mutable std::unordered_map<const sdd::flat_node<sdd_conf>*, active> cache;

  query_visitor( const sdd::values::flat_set<unsigned int>& empty
               , InputIterator i_units_end, InputIterator j_units_end)
    : inactive_unit(empty)
    , i_units_end(i_units_end), j_units_end(j_units_end)
    , cache()
  {}

  result_type
  operator()( const sdd::zero_terminal<sdd_conf>&, const order&
            , InputIterator, InputIterator, bool, bool)
  const noexcept
  {
    assert(false && "|0|");
    __builtin_unreachable();
  }

  result_type
  operator()( const sdd::one_terminal<sdd_conf>&, const order&
            , InputIterator, InputIterator, bool, bool)
  const noexcept
  {
    return active(false, false);
  }

  result_type
  operator()( const sdd::hierarchical_node<sdd_conf>&, const order&
            , InputIterator, InputIterator, bool, bool)
  const noexcept
  {
    assert(false && "Hierarchy");
    __builtin_unreachable();
  }

  result_type
  operator()( const sdd::flat_node<sdd_conf>& node, const order& o
            , InputIterator i_units_cit, InputIterator j_units_cit, bool i_active, bool j_active)
  const
  {
    assert(i_active ? not j_active : true);
    assert(j_active ? not i_active : true);
    const auto insertion = cache.emplace(&node, active(false, false));
    auto& cache_result = insertion.first->second;
    if (insertion.second) // It's the first time that we see this node.
    {
      if (i_active) // only i or its subunits are active
      {
        assert(i_units_cit == i_units_end);
        if (on(j_units_cit, j_units_end, o)) // on j or its subunits
        {
          for (const auto& arc : node)
          {
            if (arc.valuation() != inactive_unit) // j is active
            {
              return active(true, true);
            }
            else // j is not active at this level
            {
              const auto res = visit( *this, arc.successor(), o.next()
                                    , i_units_end, ++j_units_cit, true, false);
              if (res.all())
              {
                return res;
              }
            }
          }
        }
        else // not on j or its subunits
        {
          for (const auto& arc : node)
          {
            const auto res = visit( *this, arc.successor(), o.next()
                                  , i_units_end, j_units_cit, true, false);
            if (res.all())
            {
              return res;
            }
          }
        }
        // If we come here, then i (or its subunits) is active, but not j (or its subunits).
        cache_result = active(true, false);
      }
      else if (j_active)  // only j or its subunits are active
      {
        assert(j_units_cit == j_units_end);
        if (on(i_units_cit, i_units_end, o)) // on i or its subunits
        {
          for (const auto& arc : node)
          {
            if (arc.valuation() != inactive_unit) // j is active
            {
              return active(true, true);
            }
            else // i is not active at this level
            {
              const auto res = visit( *this, arc.successor(), o.next()
                                     , ++i_units_cit, j_units_end, false, true);
              if (res.all())
              {
                return res;
              }
            }
          }
        }
        else // not on i or its subunits
        {
          for (const auto& arc : node)
          {
            const auto res = visit( *this, arc.successor(), o.next()
                                   , i_units_cit, j_units_end, false, true);
            if (res.all())
            {
              return res;
            }
          }
        }
        // If we come here, then j (or its subunits) is active, but not i (or its subunits).
        cache_result = active(false, true);
      }
      else // neither i (or its subunits) nor j (or its subunits) are active
      {
        if (on(i_units_cit, i_units_end, o)) // on i or its subunits
        {
          for (const auto& arc : node)
          {
            if (arc.valuation() != inactive_unit) // i is active
            {
              const auto res = visit( *this, arc.successor(), o.next()
                                    , i_units_end, j_units_cit, true, false);
              if (res.all())
              {
                return res;
              }
              cache_result = active(true, false);
            }
            else // i is not active at this level
            {
              const auto res = visit( *this, arc.successor(), o.next()
                                     , ++i_units_cit, j_units_cit, false, false);
              if (res.all())
              {
                return res;
              }
              cache_result = active(res.i, res.j);
            }
          }
        }
        else if (on(j_units_cit, j_units_end, o))
        {
          for (const auto& arc : node)
          {
            if (arc.valuation() != inactive_unit) // j is active
            {
              const auto res = visit( *this, arc.successor(), o.next()
                                    , i_units_cit, j_units_end, false, true);
              if (res.all())
              {
                return res;
              }
              cache_result = active(false, true);
            }
            else // j is not active at this level
            {
              const auto res = visit( *this, arc.successor(), o.next()
                                    , i_units_cit, ++j_units_cit, false, false);
              if (res.all())
              {
                return res;
              }
              cache_result = active(res.i, res.j);
            }
          }
        }
        else // neither on i (or its subunits) nor j (or its subunits)
        {
          for (const auto& arc : node)
          {
            const auto res = visit( *this, arc.successor(), o.next()
                                  , i_units_cit, j_units_cit, false, false);
            if (res.all())
            {
              return res;
            }
            cache_result = active(res.i, res.j);
          }
        }
      }
    }
    // Cache hit or not, the result is now in the cache.
    return cache_result;
  }

  static
  bool
  on(InputIterator cit, InputIterator end, const order& o)
  {
    return std::find(cit, end, o.identifier().user()) != end;
  }
};

bool
query(const pn::net& net, SDD states, const order& o, unsigned int i, unsigned int j)
{
  const sdd::values::flat_set<unsigned int> empty_unit = {0};

  const auto i_search = net.units().find(i);
  const auto j_search = net.units().find(j);
  assert(i_search != net.units().end());
  assert(j_search != net.units().end());
  const auto& i_unit = i_search->second;
  const auto& j_unit = j_search->second;

  std::vector<unsigned int> i_units(i_unit.subunits.cbegin(), i_unit.subunits.cend());
  i_units.push_back(i);
  std::vector<unsigned int> j_units(j_unit.subunits.cbegin(), j_unit.subunits.cend());
  j_units.push_back(j);

  const auto comp = [&o](unsigned int lhs, unsigned int rhs){return o.node(lhs) < o.node(rhs);};
  std::sort(i_units.begin(), i_units.end(), comp);
  std::sort(j_units.begin(), j_units.end(), comp);

  const auto res
    = visit( query_visitor<std::vector<unsigned int>::const_iterator>
               (empty_unit, i_units.cend(), j_units.cend())
           , states, o, i_units.cbegin(), j_units.cbegin(), false, false);

  return res.i and res.j;
}

} // namespace anonymous

/*------------------------------------------------------------------------------------------------*/

void
compute_concurrent_units( const conf::pnmc_configuration& conf, const pn::net& net
                        , const sdd::order<sdd_conf>& o, SDD states)
{
  namespace chrono = std::chrono;
  chrono::time_point<chrono::system_clock> start = chrono::system_clock::now();

  const auto nb_units = net.units().size();
  unsigned int j_end = 1;
  for (unsigned int i = 0; i < nb_units; ++i, ++j_end)
  {
    for (unsigned int j = 0; j < j_end; ++j)
    {
      if ( i == j or net.places_of_unit(i).empty() or net.places_of_unit(j).empty()
          or net.units_are_related(i, j))
      {
        std::cout << "0 ";
      }
      else
      {
        std::cout << (query(net, states, o, i, j) ? "1 " : "0 ");
      }
    }
    std::cout << std::endl;
  }

  chrono::time_point<chrono::system_clock> end = chrono::system_clock::now();
  const std::size_t elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();
  if (conf.show_time)
  {
    std::cout << "Concurrent units computation time: " << elapsed << "s\n";
  }
}

/*------------------------------------------------------------------------------------------------*/

}}} // namespace pnmc::mc::units
<|endoftext|>


<commit_before>#include <iostream>
#include <cassert>
#include <string>

/////////////////////////////////////////
///
/// if_
///         check condition and returns
///         different values accordingly.
///
/////////////////////////////////////////
template<bool condition, unsigned if_true, unsigned if_false>
struct if_;

template<unsigned if_true, unsigned if_false>
struct if_<true, if_true, if_false>{
    enum{ result = if_true };
};

template<unsigned if_true, unsigned if_false>
struct if_<false, if_true, if_false>{
    enum{ result = if_false };
};
/////////////////////////////////////////
///
/// bool_array_
///             creates completime array
///             with runtime accessable
///             elements.
///
/////////////////////////////////////////
template<bool... values>
struct bool_array{
    static const bool value[sizeof...(values)];
};
template<bool... values>
bool const bool_array<values...>::value[] = {values ...};

/////////////////////////////////////////////////////////////////
///
/// replace_
///             Replace elements with value after each interval.
///             First replacement starts after interval - 1.
///
///             Used for setting all values that are divideable
///             with a prime number as a non prime number
///
/////////////////////////////////////////////////////////////////
template<   bool new_value,
            size_t interval,
            size_t interval_left,
            typename...>
struct replace_rec;

template<   bool new_value,
            size_t interval,
            typename...>
struct replace_;

// End, when array is empty
template<   bool new_value,
            size_t interval,
            size_t interval_left,
            template<bool...> class array_,
            bool... new_values>
struct  replace_rec<new_value, interval, interval_left,
            array_<new_values...>,
            array_<>>{
    typedef bool_array<new_values...> type;
};

// Recursive call to replace value.
template<   bool new_value,
            size_t interval,
            size_t interval_left,
            template<bool...> class array_,
            bool old_value,
            bool... new_values,
            bool... old_values>
struct  replace_rec<new_value, interval, interval_left,
            array_<new_values...>, array_<old_value, old_values...>> :
        replace_rec<new_value, interval,
            //if current value should be replaced, replace it
            if_<interval_left == 1,
                interval,
            //else
                interval_left - 1>::result,
            //endif
            array_<new_values...,
                if_<interval_left == 1,
                    new_value,
                //else
                    old_value>::result> ,
                //endif
                array_<old_values...>
            >{};

//wrapper for more easy start call
template<   bool new_value,
            size_t interval,
            template<bool...> class array_,
            bool old_value,
            bool... old_values>
struct  replace_<new_value, interval,
            array_<old_value, old_values...>> :
        replace_rec<new_value, interval, interval - 1,
            array_<old_value> , array_<old_values...>>{};

//wrapper without elements
template<   bool new_value,
            size_t interval,
            template<bool...> class array_>
struct  replace_<new_value, interval, array_<>> {
    typedef bool_array<> type;
};

/////////////////////////////////////////////////////////////////
///
/// bool_generator
///             Create a compile-time boolean array filled with
///             values.
///
/////////////////////////////////////////////////////////////////
template<   int N,
            bool value,
            bool... values>
struct bool_generator;

// End when N reaches 0
template<   bool value,
            bool... values>
struct bool_generator<0, value, values...> {
    typedef bool_array<values...> type;
};
// Recursive inheritance to generate all values
template<   int N,
            bool value,
            bool... values>
struct  bool_generator :
        bool_generator<N - 1, value , values..., value> {};

///////////////////////////////////////////////////////////////////
///
/// calc_prime_array
///             generates a compiletime bool array with each index
///             set to whenever that number is a prime or not.
///
///////////////////////////////////////////////////////////////////
template<   size_t N,
            size_t current,
            typename...>
struct calc_prime_array;

// Recursive inheritance to generate prime array
template<   size_t N,
            size_t current,
            template<bool...> class array_,
            bool input_value,
            bool... input_values,
            bool... output_values>
struct  calc_prime_array<N, current,
            array_<input_value, input_values...>,
            array_<output_values...>> :
        calc_prime_array<N, current + 1, typename replace_<false,
        // if input value is prime, set all values divisable with prime as a non-prime
        if_<input_value,
            current,
        // else
            N>::result,
        // endif
        array_<input_values...>>::type,             // replace every dividable input with current_prime
        array_<output_values..., input_value> > {}; // place input value with the finished array

// When current == N, we have reached the end, stop
template<   size_t N,
            template<bool...> class array_,
            bool... output_values>
struct calc_prime_array<N, N, array_<>, array_<output_values...>> {
    typedef bool_array<output_values...> type;
};

///////////////////////////////////////////////////////////////////
///
/// is_prime
///             generates a compiletime bool array with the size of
///             max, and evalute witch are primes or not
///             (compile-time).
///
/// USAGE:      is_prime(i) //i should be less than 200
///             is_prime<max>(i) // i should be less than max
///
///////////////////////////////////////////////////////////////////
template<size_t max = 200>
bool is_prime(size_t number){
    assert(number < max);
    ///////////////////////////////////////////////////////////////
    ///
    /// Calculates a compile-time bool array that tells if a number
    /// accessed with some index is a prime number or not. This is
    /// done with the following steps:
    ///
    /// 1:                        [0]    [1]    [2]   [3] ... [max]
    /// Generates an array with [false, false, true, true ... true]
    ///
    /// 2:
    /// Iterate throught the array starting from 2 (first prime)
    /// to max. If that number is a prime (array[num] == true)
    /// replace all following values with the interval num (which is
    /// all numbers that are divisable with the prime number: num)
    /// with false, since they are no prime number.
    ///
    /// 3:
    /// When the end is reached, bool_array ensures that a runtime
    /// accessable boolean array is created.
    ///
    /// Then, the prime number can be accessed from a simple array
    ///
    ///////////////////////////////////////////////////////////////
    return calc_prime_array<max, 2, typename
        bool_generator<max - 2, true>::type, bool_array<false, false>>
        ::type::value[number];
}

int main(){
    const int max = 200;
    std::string input = "";
    while(input != "q") {
        std::cout << "Check if number is prime (max " << max << "): ";
        std::cin >> input;
        int value = atoi(input.c_str());
        std::cout
            << (input == "q"? "goodbye" : is_prime<max>(value) == false? "no" : "yes")
            << std::endl;
    }
}<commit_msg>update algorithm description<commit_after>#include <iostream>
#include <cassert>
#include <string>

/////////////////////////////////////////
///
/// if_
///         check condition and returns
///         different values accordingly.
///
/////////////////////////////////////////
template<bool condition, unsigned if_true, unsigned if_false>
struct if_;

template<unsigned if_true, unsigned if_false>
struct if_<true, if_true, if_false>{
    enum{ result = if_true };
};

template<unsigned if_true, unsigned if_false>
struct if_<false, if_true, if_false>{
    enum{ result = if_false };
};
/////////////////////////////////////////
///
/// bool_array_
///             creates completime array
///             with runtime accessable
///             elements.
///
/////////////////////////////////////////
template<bool... values>
struct bool_array{
    static const bool value[sizeof...(values)];
};
template<bool... values>
bool const bool_array<values...>::value[] = {values ...};

/////////////////////////////////////////////////////////////////
///
/// replace_
///             Replace elements with value after each interval.
///             First replacement starts after interval - 1.
///
///             Used for setting all values that are divideable
///             with a prime number as a non prime number
///
/////////////////////////////////////////////////////////////////
template<   bool new_value,
            size_t interval,
            size_t interval_left,
            typename...>
struct replace_rec;

template<   bool new_value,
            size_t interval,
            typename...>
struct replace_;

// End, when array is empty
template<   bool new_value,
            size_t interval,
            size_t interval_left,
            template<bool...> class array_,
            bool... new_values>
struct  replace_rec<new_value, interval, interval_left,
            array_<new_values...>,
            array_<>>{
    typedef bool_array<new_values...> type;
};

// Recursive call to replace value.
template<   bool new_value,
            size_t interval,
            size_t interval_left,
            template<bool...> class array_,
            bool old_value,
            bool... new_values,
            bool... old_values>
struct  replace_rec<new_value, interval, interval_left,
            array_<new_values...>, array_<old_value, old_values...>> :
        replace_rec<new_value, interval,
            //if current value should be replaced, replace it
            if_<interval_left == 1,
                interval,
            //else
                interval_left - 1>::result,
            //endif
            array_<new_values...,
                if_<interval_left == 1,
                    new_value,
                //else
                    old_value>::result> ,
                //endif
                array_<old_values...>
            >{};

//wrapper for more easy start call
template<   bool new_value,
            size_t interval,
            template<bool...> class array_,
            bool old_value,
            bool... old_values>
struct  replace_<new_value, interval,
            array_<old_value, old_values...>> :
        replace_rec<new_value, interval, interval - 1,
            array_<old_value> , array_<old_values...>>{};

//wrapper without elements
template<   bool new_value,
            size_t interval,
            template<bool...> class array_>
struct  replace_<new_value, interval, array_<>> {
    typedef bool_array<> type;
};

/////////////////////////////////////////////////////////////////
///
/// bool_generator
///             Create a compile-time boolean array filled with
///             values.
///
/////////////////////////////////////////////////////////////////
template<   int N,
            bool value,
            bool... values>
struct bool_generator;

// End when N reaches 0
template<   bool value,
            bool... values>
struct bool_generator<0, value, values...> {
    typedef bool_array<values...> type;
};
// Recursive inheritance to generate all values
template<   int N,
            bool value,
            bool... values>
struct  bool_generator :
        bool_generator<N - 1, value , values..., value> {};

///////////////////////////////////////////////////////////////////
///
/// calc_prime_array
///             generates a compiletime bool array with each index
///             set to whenever that number is a prime or not.
///
///////////////////////////////////////////////////////////////////
template<   size_t N,
            size_t current,
            typename...>
struct calc_prime_array;

// Recursive inheritance to generate prime array
template<   size_t N,
            size_t current,
            template<bool...> class array_,
            bool input_value,
            bool... input_values,
            bool... output_values>
struct  calc_prime_array<N, current,
            array_<input_value, input_values...>,
            array_<output_values...>> :
        calc_prime_array<N, current + 1, typename replace_<false,
        // if input value is prime, set all values divisable with prime as a non-prime
        if_<input_value,
            current,
        // else
            N>::result,
        // endif
        array_<input_values...>>::type,             // replace every dividable input with current_prime
        array_<output_values..., input_value> > {}; // place input value with the finished array

// When current == N, we have reached the end, stop
template<   size_t N,
            template<bool...> class array_,
            bool... output_values>
struct calc_prime_array<N, N, array_<>, array_<output_values...>> {
    typedef bool_array<output_values...> type;
};

///////////////////////////////////////////////////////////////////
///
/// is_prime
///             generates a compiletime bool array with the size of
///             max, and evalute witch are primes or not
///             (compile-time).
///
/// USAGE:      is_prime(i) //i should be less than 200
///             is_prime<max>(i) // i should be less than max
///
///////////////////////////////////////////////////////////////////
template<size_t max = 200>
bool is_prime(size_t number){
    assert(number < max);
    ///////////////////////////////////////////////////////////////
    ///
    /// Calculates a compile-time bool array that tells if a number
    /// accessed with some index is a prime number or not. This is
    /// done with the following steps:
    ///
    /// 1:                        [0]    [1]    [2]   [3] ... [max]
    /// Generates an array with [false, false, true, true ... true]
    ///
    /// 2:
    /// Iterate throught the array starting from 2 (first prime)
    /// to max. If that number is a prime (array[num] == true)
    /// replace all following values with the interval num (which is
    /// all numbers that are divisable with the prime number: num)
    /// with false, since they are no prime number.
    ///
    /// Algorithm:
    ///     [2] is prime -> set [4, 6, 8, 10 ... max] as non primes
    ///     [3] is prime -> set [6, 9, 12, 15... max] as non primes
    ///     [4] is not prime -> skip
    ///     [5] is prime -> set [10, 15, 20  ... max] as non primes
    ///     [6] is not prime -> skip
    ///     ...
    ///
    /// 3:
    /// When the end is reached, bool_array ensures that a runtime
    /// accessable boolean array is created.
    ///
    /// Then, each prime numbers can be accessed from a simple array
    ///
    ////////////////////////////////////////////////////////////////
    return calc_prime_array<max, 2, typename
        bool_generator<max - 2, true>::type, bool_array<false, false>>
        ::type::value[number];
}

int main(){
    const int max = 200;
    std::string input = "";
    while(input != "q") {
        std::cout << "Check if number is prime (max " << max << "): ";
        std::cin >> input;
        int value = atoi(input.c_str());
        std::cout
            << (input == "q"? "goodbye" : is_prime<max>(value)? "yes" : "no")
            << std::endl;
    }
}<|endoftext|>


<commit_before><commit_msg>Keep only the simple auxv method for detecting dotprod instructions. It's available on Linux >= 4.15 in general; on Android, at least Linux 4.14.111 thanks to a late backport. This was backported just before the Android 10 release, so this is leaving out pre-release Android 10 builds as well as earlier Android versions.<commit_after><|endoftext|>


<commit_before>/*-
 * Copyright (c) 2016 Frederic Culot <culot@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <tuple>
#include <curses.h>

#include "event.h"
#include "size.h"
#include "prompt.h"

namespace portal {
namespace gfx {

Prompt::Prompt(const Point& pos, int len)
  : Window() {
  Size size;
  size.setHeight(3);
  size.setWidth(len + 2);
  setSize(size);

  Point position;
  position.setX(pos.x() - 1);
  position.setY(pos.y() - 1);
  setPosition(position);

  showBorders(false);
  /*
  pane_->cursorLineHighlight(false);
  pane_->cursorLineUnderline(true);
  */
  draw();
}

std::string Prompt::getInput() {
  for (;;) {
    portal::Event event;
    event.poll();
    clear();
    switch (event.type()) {
      case portal::Event::Type::enter:
        return content_;
      case portal::Event::Type::keyBackspace:
        content_.pop_back();
        break;
      case portal::Event::Type::character:
        content_.push_back(event.character());
        break;
      default:
        // DO NOTHING
        break;
    }
    print(content_);
    draw();
    doupdate();
  }
}

void Prompt::setContent(const std::string& content) {
  content_ = content;
  print(content_);
  draw();
}

}
}
<commit_msg>Make use of the new Style class<commit_after>/*-
 * Copyright (c) 2016 Frederic Culot <culot@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <tuple>
#include <curses.h>

#include "event.h"
#include "size.h"
#include "prompt.h"

namespace portal {
namespace gfx {

Prompt::Prompt(const Point& pos, int len)
  : Window() {
  Size size;
  size.setHeight(3);
  size.setWidth(len + 2);
  setSize(size);

  Point position;
  position.setX(pos.x() - 1);
  position.setY(pos.y() - 1);
  setPosition(position);

  Style style;
  style.highlight = false;
  style.underline = true;
  setStyle(style);

  showBorders(false);

  draw();
}

std::string Prompt::getInput() {
  for (;;) {
    portal::Event event;
    event.poll();
    clear();
    switch (event.type()) {
      case portal::Event::Type::enter:
        return content_;
      case portal::Event::Type::keyBackspace:
        content_.pop_back();
        break;
      case portal::Event::Type::character:
        content_.push_back(event.character());
        break;
      default:
        // DO NOTHING
        break;
    }
    print(content_);
    draw();
    doupdate();
  }
}

void Prompt::setContent(const std::string& content) {
  content_ = content;
  print(content_);
  draw();
}

}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014-2018 Real Logic Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Aeron.h"

namespace aeron {

static const std::chrono::duration<long, std::milli> IDLE_SLEEP_MS(4);
static const std::chrono::duration<long, std::milli> IDLE_SLEEP_MS_1(1);
static const std::chrono::duration<long, std::milli> IDLE_SLEEP_MS_16(16);
static const std::chrono::duration<long, std::milli> IDLE_SLEEP_MS_100(100);

static const char* AGENT_NAME = "client-conductor";

static long long currentTimeMillis()
{
    using namespace std::chrono;

    system_clock::time_point now = system_clock::now();
    milliseconds ms = duration_cast<milliseconds>(now.time_since_epoch());

    return ms.count();
}

Aeron::Aeron(Context &context) :
    m_randomEngine(m_randomDevice()),
    m_sessionIdDistribution(-INT_MAX, INT_MAX),
    m_context(context.conclude()),
    m_cncBuffer(mapCncFile(context)),
    m_toDriverAtomicBuffer(CncFileDescriptor::createToDriverBuffer(m_cncBuffer)),
    m_toClientsAtomicBuffer(CncFileDescriptor::createToClientsBuffer(m_cncBuffer)),
    m_countersMetadataBuffer(CncFileDescriptor::createCounterMetadataBuffer(m_cncBuffer)),
    m_countersValueBuffer(CncFileDescriptor::createCounterValuesBuffer(m_cncBuffer)),
    m_toDriverRingBuffer(m_toDriverAtomicBuffer),
    m_driverProxy(m_toDriverRingBuffer),
    m_toClientsBroadcastReceiver(m_toClientsAtomicBuffer),
    m_toClientsCopyReceiver(m_toClientsBroadcastReceiver),
    m_conductor(
        currentTimeMillis,
        m_driverProxy,
        m_toClientsCopyReceiver,
        m_countersMetadataBuffer,
        m_countersValueBuffer,
        context.m_onNewPublicationHandler,
        context.m_onNewExclusivePublicationHandler,
        context.m_onNewSubscriptionHandler,
        context.m_exceptionHandler,
        context.m_onAvailableCounterHandler,
        context.m_onUnavailableCounterHandler,
        context.m_mediaDriverTimeout,
        context.m_resourceLingerTimeout,
        CncFileDescriptor::clientLivenessTimeout(m_cncBuffer)),
    m_idleStrategy(IDLE_SLEEP_MS),
    m_conductorRunner(m_conductor, m_idleStrategy, m_context.m_exceptionHandler, AGENT_NAME),
    m_conductorInvoker(m_conductor, m_context.m_exceptionHandler)
{
    if (m_context.m_useConductorAgentInvoker)
    {
        m_conductorInvoker.start();
    }
    else
    {
        m_conductorRunner.start();
    }
}

Aeron::~Aeron()
{
    if (m_context.m_useConductorAgentInvoker)
    {
        m_conductorInvoker.close();
    }
    else
    {
        m_conductorRunner.close();
    }

    // memory mapped files should be free'd by the destructor of the shared_ptr
}

inline MemoryMappedFile::ptr_t Aeron::mapCncFile(Context &context)
{
    const long long startMs = currentTimeMillis();
    MemoryMappedFile::ptr_t cncBuffer;

    while (true)
    {
        while (MemoryMappedFile::getFileSize(context.cncFileName().c_str()) <= 0)
        {
            if (currentTimeMillis() > (startMs + context.m_mediaDriverTimeout))
            {
                throw DriverTimeoutException("CnC file not created: " + context.cncFileName(), SOURCEINFO);
            }

            std::this_thread::sleep_for(IDLE_SLEEP_MS_16);
        }

        cncBuffer = MemoryMappedFile::mapExisting(context.cncFileName().c_str());

        std::int32_t cncVersion = 0;

        while (0 == (cncVersion = CncFileDescriptor::cncVersionVolatile(cncBuffer)))
        {
            if (currentTimeMillis() > (startMs + context.m_mediaDriverTimeout))
            {
                throw DriverTimeoutException(
                    "CnC file is created but not initialised: " + context.cncFileName(), SOURCEINFO);
            }

            std::this_thread::sleep_for(IDLE_SLEEP_MS_1);
        }

        if (CncFileDescriptor::CNC_VERSION != cncVersion)
        {
            throw util::IllegalStateException(
                "CnC file version not supported: " + std::to_string(cncVersion), SOURCEINFO);
        }

        AtomicBuffer toDriverBuffer(CncFileDescriptor::createToDriverBuffer(cncBuffer));
        ManyToOneRingBuffer ringBuffer(toDriverBuffer);

        while (0 == ringBuffer.consumerHeartbeatTime())
        {
            if (currentTimeMillis() > (startMs + context.m_mediaDriverTimeout))
            {
                throw DriverTimeoutException(std::string("No driver heartbeat detected"), SOURCEINFO);
            }

            std::this_thread::sleep_for(IDLE_SLEEP_MS_1);
        }

        const long long timeMs = currentTimeMillis();
        if (ringBuffer.consumerHeartbeatTime() < (timeMs - context.m_mediaDriverTimeout))
        {
            if (timeMs > (startMs + context.m_mediaDriverTimeout))
            {
                throw DriverTimeoutException(std::string("No driver heartbeat detected"), SOURCEINFO);
            }

            cncBuffer = nullptr;

            std::this_thread::sleep_for(IDLE_SLEEP_MS_100);
            continue;
        }

        break;
    }

    return cncBuffer;
}

}
<commit_msg>[C++] Error message formatting.<commit_after>/*
 * Copyright 2014-2018 Real Logic Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Aeron.h"

namespace aeron {

static const std::chrono::duration<long, std::milli> IDLE_SLEEP_MS(4);
static const std::chrono::duration<long, std::milli> IDLE_SLEEP_MS_1(1);
static const std::chrono::duration<long, std::milli> IDLE_SLEEP_MS_16(16);
static const std::chrono::duration<long, std::milli> IDLE_SLEEP_MS_100(100);

static const char* AGENT_NAME = "client-conductor";

static long long currentTimeMillis()
{
    using namespace std::chrono;

    system_clock::time_point now = system_clock::now();
    milliseconds ms = duration_cast<milliseconds>(now.time_since_epoch());

    return ms.count();
}

Aeron::Aeron(Context &context) :
    m_randomEngine(m_randomDevice()),
    m_sessionIdDistribution(-INT_MAX, INT_MAX),
    m_context(context.conclude()),
    m_cncBuffer(mapCncFile(context)),
    m_toDriverAtomicBuffer(CncFileDescriptor::createToDriverBuffer(m_cncBuffer)),
    m_toClientsAtomicBuffer(CncFileDescriptor::createToClientsBuffer(m_cncBuffer)),
    m_countersMetadataBuffer(CncFileDescriptor::createCounterMetadataBuffer(m_cncBuffer)),
    m_countersValueBuffer(CncFileDescriptor::createCounterValuesBuffer(m_cncBuffer)),
    m_toDriverRingBuffer(m_toDriverAtomicBuffer),
    m_driverProxy(m_toDriverRingBuffer),
    m_toClientsBroadcastReceiver(m_toClientsAtomicBuffer),
    m_toClientsCopyReceiver(m_toClientsBroadcastReceiver),
    m_conductor(
        currentTimeMillis,
        m_driverProxy,
        m_toClientsCopyReceiver,
        m_countersMetadataBuffer,
        m_countersValueBuffer,
        context.m_onNewPublicationHandler,
        context.m_onNewExclusivePublicationHandler,
        context.m_onNewSubscriptionHandler,
        context.m_exceptionHandler,
        context.m_onAvailableCounterHandler,
        context.m_onUnavailableCounterHandler,
        context.m_mediaDriverTimeout,
        context.m_resourceLingerTimeout,
        CncFileDescriptor::clientLivenessTimeout(m_cncBuffer)),
    m_idleStrategy(IDLE_SLEEP_MS),
    m_conductorRunner(m_conductor, m_idleStrategy, m_context.m_exceptionHandler, AGENT_NAME),
    m_conductorInvoker(m_conductor, m_context.m_exceptionHandler)
{
    if (m_context.m_useConductorAgentInvoker)
    {
        m_conductorInvoker.start();
    }
    else
    {
        m_conductorRunner.start();
    }
}

Aeron::~Aeron()
{
    if (m_context.m_useConductorAgentInvoker)
    {
        m_conductorInvoker.close();
    }
    else
    {
        m_conductorRunner.close();
    }

    // memory mapped files should be free'd by the destructor of the shared_ptr
}

inline MemoryMappedFile::ptr_t Aeron::mapCncFile(Context &context)
{
    const long long startMs = currentTimeMillis();
    MemoryMappedFile::ptr_t cncBuffer;

    while (true)
    {
        while (MemoryMappedFile::getFileSize(context.cncFileName().c_str()) <= 0)
        {
            if (currentTimeMillis() > (startMs + context.m_mediaDriverTimeout))
            {
                throw DriverTimeoutException("CnC file not created: " + context.cncFileName(), SOURCEINFO);
            }

            std::this_thread::sleep_for(IDLE_SLEEP_MS_16);
        }

        cncBuffer = MemoryMappedFile::mapExisting(context.cncFileName().c_str());

        std::int32_t cncVersion = 0;

        while (0 == (cncVersion = CncFileDescriptor::cncVersionVolatile(cncBuffer)))
        {
            if (currentTimeMillis() > (startMs + context.m_mediaDriverTimeout))
            {
                throw DriverTimeoutException(
                    "CnC file is created but not initialised: " + context.cncFileName(), SOURCEINFO);
            }

            std::this_thread::sleep_for(IDLE_SLEEP_MS_1);
        }

        if (CncFileDescriptor::CNC_VERSION != cncVersion)
        {
            throw util::IllegalStateException(
                "CnC file version not supported: " + std::to_string(cncVersion), SOURCEINFO);
        }

        AtomicBuffer toDriverBuffer(CncFileDescriptor::createToDriverBuffer(cncBuffer));
        ManyToOneRingBuffer ringBuffer(toDriverBuffer);

        while (0 == ringBuffer.consumerHeartbeatTime())
        {
            if (currentTimeMillis() > (startMs + context.m_mediaDriverTimeout))
            {
                throw DriverTimeoutException(std::string("no driver heartbeat detected"), SOURCEINFO);
            }

            std::this_thread::sleep_for(IDLE_SLEEP_MS_1);
        }

        const long long timeMs = currentTimeMillis();
        if (ringBuffer.consumerHeartbeatTime() < (timeMs - context.m_mediaDriverTimeout))
        {
            if (timeMs > (startMs + context.m_mediaDriverTimeout))
            {
                throw DriverTimeoutException(std::string("no driver heartbeat detected"), SOURCEINFO);
            }

            cncBuffer = nullptr;

            std::this_thread::sleep_for(IDLE_SLEEP_MS_100);
            continue;
        }

        break;
    }

    return cncBuffer;
}

}
<|endoftext|>


<commit_before>/*
 * Copyright 2014-2017 Real Logic Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdint>
#include <cstdio>
#include <signal.h>
#include <util/CommandOptionParser.h>
#include <thread>
#include <Aeron.h>
#include <array>
#include <concurrent/BusySpinIdleStrategy.h>
#include "FragmentAssembler.h"
#include "Configuration.h"

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

extern "C"
{
#include <hdr_histogram.h>
}

using namespace std::chrono;
using namespace aeron::util;
using namespace aeron;

std::atomic<bool> running (true);

void sigIntHandler (int param)
{
    running = false;
}

static const char optHelp           = 'h';
static const char optPrefix         = 'p';
static const char optPingChannel    = 'c';
static const char optPongChannel    = 'C';
static const char optPingStreamId   = 's';
static const char optPongStreamId   = 'S';
static const char optFrags          = 'f';
static const char optMessages       = 'm';
static const char optLength         = 'L';
static const char optWarmupMessages = 'w';

struct Settings
{
    std::string dirPrefix = "";
    std::string pingChannel = samples::configuration::DEFAULT_PING_CHANNEL;
    std::string pongChannel = samples::configuration::DEFAULT_PONG_CHANNEL;
    std::int32_t pingStreamId = samples::configuration::DEFAULT_PING_STREAM_ID;
    std::int32_t pongStreamId = samples::configuration::DEFAULT_PONG_STREAM_ID;
    long numberOfMessages = samples::configuration::DEFAULT_NUMBER_OF_MESSAGES;
    int messageLength = samples::configuration::DEFAULT_MESSAGE_LENGTH;
    int fragmentCountLimit = samples::configuration::DEFAULT_FRAGMENT_COUNT_LIMIT;
    long numberOfWarmupMessages = samples::configuration::DEFAULT_NUMBER_OF_MESSAGES;
};

Settings parseCmdLine(CommandOptionParser& cp, int argc, char** argv)
{
    cp.parse(argc, argv);
    if (cp.getOption(optHelp).isPresent())
    {
        cp.displayOptionsHelp(std::cout);
        exit(0);
    }

    Settings s;

    s.dirPrefix = cp.getOption(optPrefix).getParam(0, s.dirPrefix);
    s.pingChannel = cp.getOption(optPingChannel).getParam(0, s.pingChannel);
    s.pongChannel = cp.getOption(optPongChannel).getParam(0, s.pongChannel);
    s.pingStreamId = cp.getOption(optPingStreamId).getParamAsInt(0, 1, INT32_MAX, s.pingStreamId);
    s.pongStreamId = cp.getOption(optPongStreamId).getParamAsInt(0, 1, INT32_MAX, s.pongStreamId);
    s.numberOfMessages = cp.getOption(optMessages).getParamAsLong(0, 0, LONG_MAX, s.numberOfMessages);
    s.messageLength = cp.getOption(optLength).getParamAsInt(0, sizeof(std::int64_t), INT32_MAX, s.messageLength);
    s.fragmentCountLimit = cp.getOption(optFrags).getParamAsInt(0, 1, INT32_MAX, s.fragmentCountLimit);
    s.numberOfWarmupMessages = cp.getOption(optWarmupMessages).getParamAsLong(0, 0, LONG_MAX, s.numberOfWarmupMessages);
    return s;
}

void sendPingAndReceivePong(
    const fragment_handler_t& fragmentHandler,
    std::shared_ptr<Publication> publication,
    std::shared_ptr<Subscription> subscription,
    const Settings& settings)
{
    std::unique_ptr<std::uint8_t[]> buffer(new std::uint8_t[settings.messageLength]);
    concurrent::AtomicBuffer srcBuffer(buffer.get(), settings.messageLength);
    BusySpinIdleStrategy idleStrategy;

    for (int i = 0; i < settings.numberOfMessages; i++)
    {
        do
        {
            // timestamps in the message are relative to this app, so just send the timepoint directly.
            steady_clock::time_point start = steady_clock::now();

            srcBuffer.putBytes(0, (std::uint8_t*)&start, sizeof(steady_clock::time_point));
        }
        while (publication->offer(srcBuffer, 0, settings.messageLength) < 0L);

        while (subscription->poll(fragmentHandler, settings.fragmentCountLimit) <= 0)
        {
            idleStrategy.idle(0);
        }
    }
}

int main(int argc, char **argv)
{
    CommandOptionParser cp;
    cp.addOption(CommandOption (optHelp,          0, 0, "                Displays help information."));
    cp.addOption(CommandOption (optPrefix,        1, 1, "dir             Prefix directory for aeron driver."));
    cp.addOption(CommandOption (optPingChannel,   1, 1, "channel         Ping Channel."));
    cp.addOption(CommandOption (optPongChannel,   1, 1, "channel         Pong Channel."));
    cp.addOption(CommandOption (optPingStreamId,  1, 1, "streamId        Ping Stream ID."));
    cp.addOption(CommandOption (optPongStreamId,  1, 1, "streamId        Pong Stream ID."));
    cp.addOption(CommandOption (optMessages,      1, 1, "number          Number of Messages."));
    cp.addOption(CommandOption (optLength,        1, 1, "length          Length of Messages."));
    cp.addOption(CommandOption (optFrags,         1, 1, "limit           Fragment Count Limit."));
    cp.addOption(CommandOption (optWarmupMessages,1, 1, "number          Number of Messages for warmup."));

    signal (SIGINT, sigIntHandler);

    try
    {
        Settings settings = parseCmdLine(cp, argc, argv);

        std::cout << "Subscribing Pong at " << settings.pongChannel << " on Stream ID " << settings.pongStreamId << std::endl;
        std::cout << "Publishing Ping at " << settings.pingChannel << " on Stream ID " << settings.pingStreamId << std::endl;

        aeron::Context context;
        std::atomic<int> countDown(1);
        std::int64_t subscriptionId;
        std::int64_t publicationId;

        if (settings.dirPrefix != "")
        {
            context.aeronDir(settings.dirPrefix);
        }

        context.newSubscriptionHandler(
            [](const std::string& channel, std::int32_t streamId, std::int64_t correlationId)
            {
                std::cout << "Subscription: " << channel << " " << correlationId << ":" << streamId << std::endl;
            });

        context.newPublicationHandler(
            [](const std::string& channel, std::int32_t streamId, std::int32_t sessionId, std::int64_t correlationId)
            {
                std::cout << "Publication: " << channel << " " << correlationId << ":" << streamId << ":" << sessionId << std::endl;
            });

        context.availableImageHandler(
            [&](Image &image)
            {
                std::cout << "Available image correlationId=" << image.correlationId() << " sessionId=" << image.sessionId();
                std::cout << " at position=" << image.position() << " from " << image.sourceIdentity() << std::endl;

                if (image.subscriptionRegistrationId() == subscriptionId)
                {
                    countDown--;
                }
            });

        context.unavailableImageHandler([](Image &image)
            {
                std::cout << "Unavailable image on correlationId=" << image.correlationId() << " sessionId=" << image.sessionId();
                std::cout << " at position=" << image.position() << " from " << image.sourceIdentity() << std::endl;
            });

        Aeron aeron(context);

        subscriptionId = aeron.addSubscription(settings.pongChannel, settings.pongStreamId);
        publicationId = aeron.addPublication(settings.pingChannel, settings.pingStreamId);

        std::shared_ptr<Subscription> pongSubscription = aeron.findSubscription(subscriptionId);
        while (!pongSubscription)
        {
            std::this_thread::yield();
            pongSubscription = aeron.findSubscription(subscriptionId);
        }

        std::shared_ptr<Publication> pingPublication = aeron.findPublication(publicationId);
        while (!pingPublication)
        {
            std::this_thread::yield();
            pingPublication = aeron.findPublication(publicationId);
        }

        while (countDown > 0)
        {
            std::this_thread::yield();
        }

        if (settings.numberOfWarmupMessages > 0)
        {
            Settings warmupSettings = settings;
            warmupSettings.numberOfMessages = warmupSettings.numberOfWarmupMessages;

            const steady_clock::time_point start = steady_clock::now();

            std::cout << "Warming up the media driver with "
                << toStringWithCommas(warmupSettings.numberOfWarmupMessages) << " messages of length "
                << toStringWithCommas(warmupSettings.messageLength) << std::endl;

            sendPingAndReceivePong([](AtomicBuffer&, index_t, index_t, Header&){}, pingPublication, pongSubscription, warmupSettings);

            std::int64_t nanoDuration = duration<std::int64_t, std::nano>(steady_clock::now() - start).count();

            std::cout << "Warmed up the media driver in " << nanoDuration << " [ns]" << std::endl;
        }

        hdr_histogram* histogram;
        hdr_init(1, 10 * 1000 * 1000 * 1000LL, 3, &histogram);

        do
        {
            hdr_reset(histogram);

            FragmentAssembler fragmentAssembler(
                [&](const AtomicBuffer& buffer, index_t offset, index_t length, const Header& header)
                {
                    steady_clock::time_point end = steady_clock::now();
                    steady_clock::time_point start;

                    buffer.getBytes(offset, (std::uint8_t*)&start, sizeof(steady_clock::time_point));
                    std::int64_t nanoRtt = duration<std::int64_t, std::nano>(end - start).count();

                    hdr_record_value(histogram, nanoRtt);
                });

            std::cout << "Pinging "
                << toStringWithCommas(settings.numberOfMessages) << " messages of length "
                << toStringWithCommas(settings.messageLength) << " bytes" << std::endl;

            sendPingAndReceivePong(fragmentAssembler.handler(), pingPublication, pongSubscription, settings);

            hdr_percentiles_print(histogram, stdout, 5, 1000.0, CLASSIC);
            fflush(stdout);
        }
        while (running && continuationBarrier("Execute again?"));

    }
    catch (const CommandOptionException& e)
    {
        std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
        cp.displayOptionsHelp(std::cerr);
        return -1;
    }
    catch (const SourcedException& e)
    {
        std::cerr << "FAILED: " << e.what() << " : " << e.where() << std::endl;
        return -1;
    }
    catch (const std::exception& e)
    {
        std::cerr << "FAILED: " << e.what() << " : " << std::endl;
        return -1;
    }

    return 0;
}
<commit_msg>[c++] Update Ping to account for messages larger than MTU. Issue #345.<commit_after>/*
 * Copyright 2014-2017 Real Logic Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdint>
#include <cstdio>
#include <signal.h>
#include <util/CommandOptionParser.h>
#include <thread>
#include <Aeron.h>
#include <array>
#include <concurrent/BusySpinIdleStrategy.h>
#include "FragmentAssembler.h"
#include "Configuration.h"

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

extern "C"
{
#include <hdr_histogram.h>
}

using namespace std::chrono;
using namespace aeron::util;
using namespace aeron;

std::atomic<bool> running (true);

void sigIntHandler (int param)
{
    running = false;
}

static const char optHelp           = 'h';
static const char optPrefix         = 'p';
static const char optPingChannel    = 'c';
static const char optPongChannel    = 'C';
static const char optPingStreamId   = 's';
static const char optPongStreamId   = 'S';
static const char optFrags          = 'f';
static const char optMessages       = 'm';
static const char optLength         = 'L';
static const char optWarmupMessages = 'w';

struct Settings
{
    std::string dirPrefix = "";
    std::string pingChannel = samples::configuration::DEFAULT_PING_CHANNEL;
    std::string pongChannel = samples::configuration::DEFAULT_PONG_CHANNEL;
    std::int32_t pingStreamId = samples::configuration::DEFAULT_PING_STREAM_ID;
    std::int32_t pongStreamId = samples::configuration::DEFAULT_PONG_STREAM_ID;
    long numberOfMessages = samples::configuration::DEFAULT_NUMBER_OF_MESSAGES;
    int messageLength = samples::configuration::DEFAULT_MESSAGE_LENGTH;
    int fragmentCountLimit = samples::configuration::DEFAULT_FRAGMENT_COUNT_LIMIT;
    long numberOfWarmupMessages = samples::configuration::DEFAULT_NUMBER_OF_MESSAGES;
};

Settings parseCmdLine(CommandOptionParser& cp, int argc, char** argv)
{
    cp.parse(argc, argv);
    if (cp.getOption(optHelp).isPresent())
    {
        cp.displayOptionsHelp(std::cout);
        exit(0);
    }

    Settings s;

    s.dirPrefix = cp.getOption(optPrefix).getParam(0, s.dirPrefix);
    s.pingChannel = cp.getOption(optPingChannel).getParam(0, s.pingChannel);
    s.pongChannel = cp.getOption(optPongChannel).getParam(0, s.pongChannel);
    s.pingStreamId = cp.getOption(optPingStreamId).getParamAsInt(0, 1, INT32_MAX, s.pingStreamId);
    s.pongStreamId = cp.getOption(optPongStreamId).getParamAsInt(0, 1, INT32_MAX, s.pongStreamId);
    s.numberOfMessages = cp.getOption(optMessages).getParamAsLong(0, 0, LONG_MAX, s.numberOfMessages);
    s.messageLength = cp.getOption(optLength).getParamAsInt(0, sizeof(std::int64_t), INT32_MAX, s.messageLength);
    s.fragmentCountLimit = cp.getOption(optFrags).getParamAsInt(0, 1, INT32_MAX, s.fragmentCountLimit);
    s.numberOfWarmupMessages = cp.getOption(optWarmupMessages).getParamAsLong(0, 0, LONG_MAX, s.numberOfWarmupMessages);
    return s;
}

void sendPingAndReceivePong(
    const fragment_handler_t& fragmentHandler,
    std::shared_ptr<Publication> publication,
    std::shared_ptr<Subscription> subscription,
    const Settings& settings)
{
    std::unique_ptr<std::uint8_t[]> buffer(new std::uint8_t[settings.messageLength]);
    concurrent::AtomicBuffer srcBuffer(buffer.get(), settings.messageLength);
    BusySpinIdleStrategy idleStrategy;
    Image& image = subscription->images()->front();

    for (int i = 0; i < settings.numberOfMessages; i++)
    {
        std::int64_t position;

        do
        {
            // timestamps in the message are relative to this app, so just send the timepoint directly.
            steady_clock::time_point start = steady_clock::now();

            srcBuffer.putBytes(0, (std::uint8_t*)&start, sizeof(steady_clock::time_point));
        }
        while ((position = publication->offer(srcBuffer, 0, settings.messageLength)) < 0L);

        do
        {
            while (subscription->poll(fragmentHandler, settings.fragmentCountLimit) <= 0)
            {
                idleStrategy.idle(0);
            }
        }
        while (image.position() < position);
    }
}

int main(int argc, char **argv)
{
    CommandOptionParser cp;
    cp.addOption(CommandOption (optHelp,          0, 0, "                Displays help information."));
    cp.addOption(CommandOption (optPrefix,        1, 1, "dir             Prefix directory for aeron driver."));
    cp.addOption(CommandOption (optPingChannel,   1, 1, "channel         Ping Channel."));
    cp.addOption(CommandOption (optPongChannel,   1, 1, "channel         Pong Channel."));
    cp.addOption(CommandOption (optPingStreamId,  1, 1, "streamId        Ping Stream ID."));
    cp.addOption(CommandOption (optPongStreamId,  1, 1, "streamId        Pong Stream ID."));
    cp.addOption(CommandOption (optMessages,      1, 1, "number          Number of Messages."));
    cp.addOption(CommandOption (optLength,        1, 1, "length          Length of Messages."));
    cp.addOption(CommandOption (optFrags,         1, 1, "limit           Fragment Count Limit."));
    cp.addOption(CommandOption (optWarmupMessages,1, 1, "number          Number of Messages for warmup."));

    signal (SIGINT, sigIntHandler);

    try
    {
        Settings settings = parseCmdLine(cp, argc, argv);

        std::cout << "Subscribing Pong at " << settings.pongChannel << " on Stream ID " << settings.pongStreamId << std::endl;
        std::cout << "Publishing Ping at " << settings.pingChannel << " on Stream ID " << settings.pingStreamId << std::endl;

        aeron::Context context;
        std::atomic<int> countDown(1);
        std::int64_t subscriptionId;
        std::int64_t publicationId;

        if (settings.dirPrefix != "")
        {
            context.aeronDir(settings.dirPrefix);
        }

        context.newSubscriptionHandler(
            [](const std::string& channel, std::int32_t streamId, std::int64_t correlationId)
            {
                std::cout << "Subscription: " << channel << " " << correlationId << ":" << streamId << std::endl;
            });

        context.newPublicationHandler(
            [](const std::string& channel, std::int32_t streamId, std::int32_t sessionId, std::int64_t correlationId)
            {
                std::cout << "Publication: " << channel << " " << correlationId << ":" << streamId << ":" << sessionId << std::endl;
            });

        context.availableImageHandler(
            [&](Image &image)
            {
                std::cout << "Available image correlationId=" << image.correlationId() << " sessionId=" << image.sessionId();
                std::cout << " at position=" << image.position() << " from " << image.sourceIdentity() << std::endl;

                if (image.subscriptionRegistrationId() == subscriptionId)
                {
                    countDown--;
                }
            });

        context.unavailableImageHandler([](Image &image)
            {
                std::cout << "Unavailable image on correlationId=" << image.correlationId() << " sessionId=" << image.sessionId();
                std::cout << " at position=" << image.position() << " from " << image.sourceIdentity() << std::endl;
            });

        Aeron aeron(context);

        subscriptionId = aeron.addSubscription(settings.pongChannel, settings.pongStreamId);
        publicationId = aeron.addPublication(settings.pingChannel, settings.pingStreamId);

        std::shared_ptr<Subscription> pongSubscription = aeron.findSubscription(subscriptionId);
        while (!pongSubscription)
        {
            std::this_thread::yield();
            pongSubscription = aeron.findSubscription(subscriptionId);
        }

        std::shared_ptr<Publication> pingPublication = aeron.findPublication(publicationId);
        while (!pingPublication)
        {
            std::this_thread::yield();
            pingPublication = aeron.findPublication(publicationId);
        }

        while (countDown > 0)
        {
            std::this_thread::yield();
        }

        if (settings.numberOfWarmupMessages > 0)
        {
            Settings warmupSettings = settings;
            warmupSettings.numberOfMessages = warmupSettings.numberOfWarmupMessages;

            const steady_clock::time_point start = steady_clock::now();

            std::cout << "Warming up the media driver with "
                << toStringWithCommas(warmupSettings.numberOfWarmupMessages) << " messages of length "
                << toStringWithCommas(warmupSettings.messageLength) << std::endl;

            sendPingAndReceivePong([](AtomicBuffer&, index_t, index_t, Header&){}, pingPublication, pongSubscription, warmupSettings);

            std::int64_t nanoDuration = duration<std::int64_t, std::nano>(steady_clock::now() - start).count();

            std::cout << "Warmed up the media driver in " << nanoDuration << " [ns]" << std::endl;
        }

        hdr_histogram* histogram;
        hdr_init(1, 10 * 1000 * 1000 * 1000LL, 3, &histogram);

        do
        {
            hdr_reset(histogram);

            FragmentAssembler fragmentAssembler(
                [&](const AtomicBuffer& buffer, index_t offset, index_t length, const Header& header)
                {
                    steady_clock::time_point end = steady_clock::now();
                    steady_clock::time_point start;

                    buffer.getBytes(offset, (std::uint8_t*)&start, sizeof(steady_clock::time_point));
                    std::int64_t nanoRtt = duration<std::int64_t, std::nano>(end - start).count();

                    hdr_record_value(histogram, nanoRtt);
                });

            std::cout << "Pinging "
                << toStringWithCommas(settings.numberOfMessages) << " messages of length "
                << toStringWithCommas(settings.messageLength) << " bytes" << std::endl;

            sendPingAndReceivePong(fragmentAssembler.handler(), pingPublication, pongSubscription, settings);

            hdr_percentiles_print(histogram, stdout, 5, 1000.0, CLASSIC);
            fflush(stdout);
        }
        while (running && continuationBarrier("Execute again?"));

    }
    catch (const CommandOptionException& e)
    {
        std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
        cp.displayOptionsHelp(std::cerr);
        return -1;
    }
    catch (const SourcedException& e)
    {
        std::cerr << "FAILED: " << e.what() << " : " << e.where() << std::endl;
        return -1;
    }
    catch (const std::exception& e)
    {
        std::cerr << "FAILED: " << e.what() << " : " << std::endl;
        return -1;
    }

    return 0;
}
<|endoftext|>