<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <string>
#include <type_traits>
#include <vector>

#include "caf/dictionary.hpp"
#include "caf/fwd.hpp"
#include "caf/timestamp.hpp"

namespace caf {
namespace detail {

template <size_t Bytes>
struct type_name_builder_int_size;

template <>
struct type_name_builder_int_size<1> {
  inline void operator()(std::string& result) const {
    result += "8";
  }
};

template <>
struct type_name_builder_int_size<2> {
  inline void operator()(std::string& result) const {
    result += "16";
  }
};

template <>
struct type_name_builder_int_size<4> {
  inline void operator()(std::string& result) const {
    result += "32";
  }
};

template <>
struct type_name_builder_int_size<8> {
  inline void operator()(std::string& result) const {
    result += "64";
  }
};

template <class T, bool IsInteger = std::is_integral<T>::value>
struct type_name_builder;

template <>
struct type_name_builder<bool, true> {
  inline void operator()(std::string& result) const {
    result += "boolean";
  }
};

template <>
struct type_name_builder<float, false> {
  inline void operator()(std::string& result) const {
    result += "32-bit real";
  }
};

template <>
struct type_name_builder<double, false> {
  inline void operator()(std::string& result) const {
    result += "64-bit real";
  }
};

template <>
struct type_name_builder<timespan, false> {
  inline void operator()(std::string& result) const {
    result += "timespan";
  }
};

template <>
struct type_name_builder<std::string, false> {
  inline void operator()(std::string& result) const {
    result += "string";
  }
};

template <>
struct type_name_builder<atom_value, false> {
  inline void operator()(std::string& result) const {
    result += "atom";
  }
};

template <class T>
struct type_name_builder<T, true> {
  void operator()(std::string& result) const {
    // TODO: replace with if constexpr when switching to C++17
    if (!std::is_signed<T>::value)
      result += 'u';
    result += "int";
    type_name_builder_int_size<sizeof(T)> g;
    g(result);
  }
};

template <class T>
struct type_name_builder<std::vector<T>, false> {
  void operator()(std::string& result) const {
    result += "list of ";
    type_name_builder<T> g;
    g(result);
  }
};

template <class T>
struct type_name_builder<dictionary<T>, false> {
  void operator()(std::string& result) const {
    result += "dictionary of ";
    type_name_builder<T> g;
    g(result);
  }
};

template <class T>
std::string type_name() {
  std::string result;
  type_name_builder<T> f;
  f(result);
  return result;
}

} // namespace detail
} // namespace caf

<commit_msg>Add missing type to type name builder<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <string>
#include <type_traits>
#include <vector>

#include "caf/dictionary.hpp"
#include "caf/fwd.hpp"
#include "caf/timestamp.hpp"

namespace caf {
namespace detail {

template <size_t Bytes>
struct type_name_builder_int_size;

template <>
struct type_name_builder_int_size<1> {
  void operator()(std::string& result) const {
    result += "8";
  }
};

template <>
struct type_name_builder_int_size<2> {
  void operator()(std::string& result) const {
    result += "16";
  }
};

template <>
struct type_name_builder_int_size<4> {
  void operator()(std::string& result) const {
    result += "32";
  }
};

template <>
struct type_name_builder_int_size<8> {
  void operator()(std::string& result) const {
    result += "64";
  }
};

template <class T, bool IsInteger = std::is_integral<T>::value>
struct type_name_builder;

template <>
struct type_name_builder<bool, true> {
  void operator()(std::string& result) const {
    result += "boolean";
  }
};

#define CAF_TYPE_NAME_BUILDER_NOINT(class_name, pretty_name)                   \
  template <>                                                                  \
  struct type_name_builder<class_name, false> {                                \
    void operator()(std::string& result) const {                               \
      result += pretty_name;                                                   \
    }                                                                          \
  }

CAF_TYPE_NAME_BUILDER_NOINT(float, "32-bit real");

CAF_TYPE_NAME_BUILDER_NOINT(double, "64-bit real");

CAF_TYPE_NAME_BUILDER_NOINT(timespan, "timespan");

CAF_TYPE_NAME_BUILDER_NOINT(std::string, "string");

CAF_TYPE_NAME_BUILDER_NOINT(atom_value, "atom");

CAF_TYPE_NAME_BUILDER_NOINT(uri, "uri");

#undef CAF_TYPE_NAME_BUILDER

template <class T>
struct type_name_builder<T, true> {
  void operator()(std::string& result) const {
    // TODO: replace with if constexpr when switching to C++17
    if (!std::is_signed<T>::value)
      result += 'u';
    result += "int";
    type_name_builder_int_size<sizeof(T)> g;
    g(result);
  }
};

template <class T>
struct type_name_builder<std::vector<T>, false> {
  void operator()(std::string& result) const {
    result += "list of ";
    type_name_builder<T> g;
    g(result);
  }
};

template <class T>
struct type_name_builder<dictionary<T>, false> {
  void operator()(std::string& result) const {
    result += "dictionary of ";
    type_name_builder<T> g;
    g(result);
  }
};

template <class T>
std::string type_name() {
  std::string result;
  type_name_builder<T> f;
  f(result);
  return result;
}

} // namespace detail
} // namespace caf
<|endoftext|>


<commit_before>#ifndef MANIFOLDS_FUNCTIONS_INTEGRAL_POLYNOMIAL_SIMPLIFICATIONS_HH
#define MANIFOLDS_FUNCTIONS_INTEGRAL_POLYNOMIAL_SIMPLIFICATIONS_HH

#include "integral_polynomial.hh"
#include "polynomial.hh"
#include "addition.hh"
#include "simplify.hh"
#include "unary_minus.hh"
#include "zero.hh"

namespace manifolds {
template <IPInt_t... t1s, IPInt_t... t2s>
struct Simplification<
    Addition<IntegralPolynomial<t1s...>, IntegralPolynomial<t2s...> >,
    /*add_ip_ip*/ 0> {
  template <class, class> struct Extended;

  template <IPInt_t... indices, IPInt_t... padding>
  struct Extended<std::integer_sequence<IPInt_t, indices...>,
                  std::integer_sequence<IPInt_t, padding...> > {
    typedef std::integer_sequence<IPInt_t, indices..., (padding - padding)...>
    type;
  };

  static const int padding1 =
      sizeof...(t1s) < sizeof...(t2s) ? sizeof...(t2s) - sizeof...(t1s) : 0;
  typedef typename Extended<
      std::integer_sequence<IPInt_t, t1s...>,
      std::make_integer_sequence<IPInt_t, padding1> >::type padded1;

  static const int padding2 =
      sizeof...(t2s) < sizeof...(t1s) ? sizeof...(t1s) - sizeof...(t2s) : 0;
  typedef typename Extended<
      std::integer_sequence<IPInt_t, t2s...>,
      std::make_integer_sequence<IPInt_t, padding2> >::type padded2;

  template <class, class> struct Add;

  template <IPInt_t... indices1, IPInt_t... indices2>
  struct Add<std::integer_sequence<IPInt_t, indices1...>,
             std::integer_sequence<IPInt_t, indices2...> > {
    typedef IntegralPolynomial<(indices1 + indices2)...> type;
  };

  typedef typename Add<padded1, padded2>::type type;

  static type
  Combine(Addition<IntegralPolynomial<t1s...>, IntegralPolynomial<t2s...> >) {
    SIMPLIFY_INFO("Simplifying addition of "
                  "integral_polynomials\n");
    return type{};
  }
};

template <IPInt_t... t1s, IPInt_t... t2s>
struct Simplification<
    Multiplication<IntegralPolynomial<t1s...>, IntegralPolynomial<t2s...> >,
    /*mult_ip_ip*/ 0> {
  typedef IPInt_t Tr;

  typedef std::integer_sequence<IPInt_t, t1s...> inputs1;
  typedef std::integer_sequence<IPInt_t, t2s...> inputs2;

  template <int, class> struct get_value;

  template <int i, IPInt_t... ts>
  struct get_value<
      i, std::integer_sequence<
             IPInt_t, ts...> > : nth<i, std::integral_constant<IPInt_t,
                                                               ts>...>::type {};

  template <int, Tr, class> struct set_value;

  template <int i, Tr t, class T, T... ts>
  struct set_value<i, t, std::integer_sequence<T, ts...> > {
    typedef std::integer_sequence<T, ts...> values;
    template <class, class> struct apply;

    template <int... lefts, int... rights>
    struct apply<std::integer_sequence<int, lefts...>,
                 std::integer_sequence<int, rights...> > {
      typedef std::integer_sequence<Tr, get_value<lefts, values>::value..., t,
                                    get_value<rights + i + 1, values>::value...>
      type;
    };

    typedef typename apply<
        std::make_integer_sequence<int, i>,
        std::make_integer_sequence<int, sizeof...(ts) - i - 1> >::type type;
  };

  template <int i, int j, class OutSeq,
            bool = (i + j < seq_size<OutSeq>::value)>
  struct Add {
    typedef typename set_value<i + j, get_value<i + j, OutSeq>::value +
                                          (Tr)get_value<i, inputs1>::value *(
                                              Tr)get_value<j, inputs2>::value,
                               OutSeq>::type type;
  };

  template <int i, int j, class T, T... ts>
  struct Add<i, j, std::integer_sequence<T, ts...>, false> {
    static_assert(i + j == sizeof...(ts), "Internal error");
    typedef std::integer_sequence<T, ts..., (Tr)get_value<i, inputs1>::value *(
                                                Tr)get_value<j, inputs2>::value>
    type;
  };

  template <int i, int j, class OutSeq> struct P2Loop {
    typedef typename P2Loop<i, j - 1, typename Add<i, j, OutSeq>::type>::type
    type;
  };

  template <int i, class OutSeq> struct P2Loop<i, -1, OutSeq> {
    typedef OutSeq type;
  };

  template <int i, class OutSeq> struct P1Loop {
    typedef typename P1Loop<
        i - 1, typename P2Loop<i, sizeof...(t2s) - 1, OutSeq>::type>::type type;
  };

  template <IPInt_t... ts>
  struct P1Loop<-1, std::integer_sequence<IPInt_t, ts...> > {
    typedef IntegralPolynomial<ts...> type;
  };

  template <class> struct InitOutput;

  template <IPInt_t... indices> struct InitOutput<iseq<indices...> > {
    typedef std::integer_sequence<Tr, ((void)indices, 0)...> type;
  };

  typedef typename P1Loop<
      sizeof...(t1s) - 1,
      typename InitOutput<
          miseq<sizeof...(t1s) + sizeof...(t2s) - 1> >::type>::type type;

  static type Combine(
      Multiplication<IntegralPolynomial<t1s...>, IntegralPolynomial<t2s...> >) {
    SIMPLIFY_INFO("Simplifying multiplication of "
                  "integral_polynomials\n");
    return type{};
  }
};

template <IPInt_t... ts>
struct Simplification<IntegralPolynomial<ts...>,
                      /*ip*/ 0> {
  template <IPInt_t t> using ic = std::integral_constant<IPInt_t, t>;

  template <IPInt_t... t2s> struct pop {
    template <class> struct apply;

    template <std::size_t... is>
    struct apply<std::integer_sequence<std::size_t, is...> > {
      typedef std::integer_sequence<IPInt_t,
                                    nth<is, ic<t2s>...>::type::value...> type;
    };

    typedef typename apply<std::make_index_sequence<sizeof...(t2s) - 1> >::type
    type;
  };

  template <class, bool> struct pop_if;

  template <class> struct stopping_condition;

  template <IPInt_t... touts>
  struct stopping_condition<std::integer_sequence<IPInt_t, touts...> > {
    static const bool value =
        sizeof...(ts) == 1 || last<ic<touts>...>::type::value != 0;
  };

  template <IPInt_t... touts>
  struct pop_if<std::integer_sequence<IPInt_t, touts...>, true> {
    typedef IntegralPolynomial<touts...> type;
  };

  template <IPInt_t... touts>
  struct pop_if<std::integer_sequence<IPInt_t, touts...>, false> {
    typedef typename pop<touts...>::type next;
    typedef typename pop_if<next, stopping_condition<next>::value>::type type;
  };

  typedef typename pop_if<
      std::integer_sequence<IPInt_t, ts...>,
      stopping_condition<std::integer_sequence<IPInt_t, ts...> >::value>::type
  type;

  static type Combine(IntegralPolynomial<ts...>) {
    SIMPLIFY_INFO("Simplifying of integral_polynomial\n");
    return type{};
  }
};

template <template <class...> class Variadic, class T1, class O1,
          IPInt_t... t2s>
struct Simplification<Variadic<Polynomial<T1, O1>, IntegralPolynomial<t2s...> >,
                      /*var_p_ip*/ 2> {
  typedef Variadic<Polynomial<T1, O1>,
                   Polynomial<IPInt_t, int_<sizeof...(t2s)> > > type;

  static type
  Combine(Variadic<Polynomial<T1, O1>, IntegralPolynomial<t2s...> > v) {
    SIMPLIFY_INFO("Simplifying variadic of "
                  "polynomial and integral_polynomial\n");
    return { std::get<0>(v.GetFunctions()),
             std::get<1>(v.GetFunctions()).ToPoly() };
  }
};

template <template <class...> class Variadic, class T1, class O1,
          IPInt_t... t2s>
struct Simplification<Variadic<IntegralPolynomial<t2s...>, Polynomial<T1, O1> >,
                      /*var_ip_p*/ 0> {
  typedef Variadic<Polynomial<IPInt_t, int_<sizeof...(t2s)> >,
                   Polynomial<T1, O1> > type;

  static type
  Combine(Variadic<IntegralPolynomial<t2s...>, Polynomial<T1, O1> > v) {
    SIMPLIFY_INFO("Simplifying variadic of "
                  "integral_polynomial and polynomial\n");
    return { std::get<0>(v.GetFunctions()).ToPoly(),
             std::get<1>(v.GetFunctions()) };
  }
};

template <IPInt_t... coeffs>
struct Simplification<UnaryMinus<IntegralPolynomial<coeffs...> >, 0> {
  typedef IntegralPolynomial<-coeffs...> type;

  static type Combine(UnaryMinus<IntegralPolynomial<coeffs...> >) {
    SIMPLIFY_INFO("Simplifying negative of integral polynomial");
    return type{};
  }
};

template <class A>
struct Simplification<Addition<A, A>, /*add_f_f*/ 3,
                      typename std::enable_if<is_stateless<A>::value>::type> {
  typedef Composition<IntegralPolynomial<0, 2>, A> type;
  static type Combine(Addition<A, A> a) {
    SIMPLIFY_INFO("Simplifying addition of function by itself\n");
    type b = { IntegralPolynomial<0, 2>(), A() };
    return b;
  }
};

template <class A>
struct Simplification<Multiplication<A, A>, /*mult_f_f*/ 3,
                      typename std::enable_if<is_stateless<A>::value>::type> {
  typedef Composition<IntegralPolynomial<0, 0, 1>, A> type;

  static type Combine(Multiplication<A, A>) {
    SIMPLIFY_INFO("Simplifying multiplication of function "
                  "by itself\n");
    return { IntegralPolynomial<0, 0, 1>(), A() };
  }
};

template <class T, IPInt_t us>
struct Simplification<Addition<T, IntegralPolynomial<us> >,
                      /*add_f_ip_1*/ 3> {
  typedef Composition<IntegralPolynomial<us, 1>, T> type;

  static type Combine(Addition<T, IntegralPolynomial<us> > a) {
    SIMPLIFY_INFO("Simplifying addition of constant "
                  "and another function");
    auto t = a.GetFunctions();
    return { IntegralPolynomial<us, 1>(), std::get<0>(t) };
  }
};

template <class T>
struct Simplification<Multiplication<T, IntegralPolynomial<1> >,
                      /*mult_f_ip_1*/ 1> {
  static T Combine(Multiplication<T, IntegralPolynomial<1> > m) {
    SIMPLIFY_INFO("Simplifying multiplication of function by 1");
    return std::get<0>(m.GetFunctions());
  }
};

template <>
struct Simplification<IntegralPolynomial<0>,
                      /*ip_0*/ 0> {
  static auto Combine(IntegralPolynomial<0>) { return zero; }
};

template <class C>
struct Simplification<Composition<IntegralPolynomial<0, 1>, C>,
                      /*com_ip01_f*/ 0> {
  static auto Combine(Composition<IntegralPolynomial<0, 1>, C> a) {
    return std::get<1>(a.GetFunctions());
  }
};

template <class C, IPInt_t i>
struct Simplification<Composition<C, IntegralPolynomial<i> >, 0> {
  static auto Combine(Composition<C, IntegralPolynomial<i> > c) {
    return GetPolynomial((std::get<0>(c.GetFunctions()))(i));
  }
};

template <class C, IPInt_t... coeffs>
struct Simplification<
    Multiplication<C, Composition<IntegralPolynomial<coeffs...>, C> >, 0,
    typename std::enable_if<C::stateless>::type> {
  static auto Combine(
      Multiplication<C, Composition<IntegralPolynomial<coeffs...>, C> >) {
    return GetIPolynomial<0, coeffs...>()(C{});
  }
};

template <class... Fs, IPInt_t... coeffs>
struct Simplification<
    Multiplication<Composition<Fs...>,
                   Composition<IntegralPolynomial<coeffs...>, Fs...> >,
    0, typename std::enable_if<Composition<Fs...>::stateless>::type> {
  static auto Combine(Multiplication<
      Composition<Fs...>, Composition<IntegralPolynomial<coeffs...>, Fs...> >) {
    return GetIPolynomial<0, coeffs...>()(Composition<Fs...>());
  }
};

template <IPInt_t... c1s, IPInt_t... c2s>
struct Simplification<
    Composition<IntegralPolynomial<c1s...>, IntegralPolynomial<c2s...> >, 0> {
  typedef IntegralPolynomial<c2s...> inner;

  template <int i>
  using ith = typename nth<i, std::integral_constant<IPInt_t, c1s>...>::type;

  template <IPInt_t, class> struct Term2 {};

  template <int i, class F> struct Class {
    typedef F type;
  };

  template <IPInt_t c, std::size_t... is>
  struct Term2<c, std::integer_sequence<std::size_t, is...> > {
    typedef Multiplication<IntegralPolynomial<c>,
                           typename Class<is, inner>::type...> type;
  };

  template <int i> struct Term {
    typedef typename Term2<ith<i>::value, std::make_index_sequence<i> >::type
    type;
  };

  template <class> struct Add {};
  template <std::size_t... is>
  struct Add<std::integer_sequence<std::size_t, is...> > {
    typedef Addition<typename Term<is>::type...> type;
  };

  static auto Combine(
      Composition<IntegralPolynomial<c1s...>, IntegralPolynomial<c2s...> >) {
    return typename Add<std::make_index_sequence<sizeof...(c1s)> >::type();
  }
};
}

#endif
<commit_msg>Simplifying composition of polynomial and unary minus<commit_after>#ifndef MANIFOLDS_FUNCTIONS_INTEGRAL_POLYNOMIAL_SIMPLIFICATIONS_HH
#define MANIFOLDS_FUNCTIONS_INTEGRAL_POLYNOMIAL_SIMPLIFICATIONS_HH

#include "integral_polynomial.hh"
#include "polynomial.hh"
#include "addition.hh"
#include "simplify.hh"
#include "unary_minus.hh"
#include "zero.hh"

namespace manifolds {
template <IPInt_t... t1s, IPInt_t... t2s>
struct Simplification<
    Addition<IntegralPolynomial<t1s...>, IntegralPolynomial<t2s...> >,
    /*add_ip_ip*/ 0> {
  template <class, class> struct Extended;

  template <IPInt_t... indices, IPInt_t... padding>
  struct Extended<std::integer_sequence<IPInt_t, indices...>,
                  std::integer_sequence<IPInt_t, padding...> > {
    typedef std::integer_sequence<IPInt_t, indices..., (padding - padding)...>
    type;
  };

  static const int padding1 =
      sizeof...(t1s) < sizeof...(t2s) ? sizeof...(t2s) - sizeof...(t1s) : 0;
  typedef typename Extended<
      std::integer_sequence<IPInt_t, t1s...>,
      std::make_integer_sequence<IPInt_t, padding1> >::type padded1;

  static const int padding2 =
      sizeof...(t2s) < sizeof...(t1s) ? sizeof...(t1s) - sizeof...(t2s) : 0;
  typedef typename Extended<
      std::integer_sequence<IPInt_t, t2s...>,
      std::make_integer_sequence<IPInt_t, padding2> >::type padded2;

  template <class, class> struct Add;

  template <IPInt_t... indices1, IPInt_t... indices2>
  struct Add<std::integer_sequence<IPInt_t, indices1...>,
             std::integer_sequence<IPInt_t, indices2...> > {
    typedef IntegralPolynomial<(indices1 + indices2)...> type;
  };

  typedef typename Add<padded1, padded2>::type type;

  static type
  Combine(Addition<IntegralPolynomial<t1s...>, IntegralPolynomial<t2s...> >) {
    SIMPLIFY_INFO("Simplifying addition of "
                  "integral_polynomials\n");
    return type{};
  }
};

template <IPInt_t... t1s, IPInt_t... t2s>
struct Simplification<
    Multiplication<IntegralPolynomial<t1s...>, IntegralPolynomial<t2s...> >,
    /*mult_ip_ip*/ 0> {
  typedef IPInt_t Tr;

  typedef std::integer_sequence<IPInt_t, t1s...> inputs1;
  typedef std::integer_sequence<IPInt_t, t2s...> inputs2;

  template <int, class> struct get_value;

  template <int i, IPInt_t... ts>
  struct get_value<
      i, std::integer_sequence<
             IPInt_t, ts...> > : nth<i, std::integral_constant<IPInt_t,
                                                               ts>...>::type {};

  template <int, Tr, class> struct set_value;

  template <int i, Tr t, class T, T... ts>
  struct set_value<i, t, std::integer_sequence<T, ts...> > {
    typedef std::integer_sequence<T, ts...> values;
    template <class, class> struct apply;

    template <int... lefts, int... rights>
    struct apply<std::integer_sequence<int, lefts...>,
                 std::integer_sequence<int, rights...> > {
      typedef std::integer_sequence<Tr, get_value<lefts, values>::value..., t,
                                    get_value<rights + i + 1, values>::value...>
      type;
    };

    typedef typename apply<
        std::make_integer_sequence<int, i>,
        std::make_integer_sequence<int, sizeof...(ts) - i - 1> >::type type;
  };

  template <int i, int j, class OutSeq,
            bool = (i + j < seq_size<OutSeq>::value)>
  struct Add {
    typedef typename set_value<i + j, get_value<i + j, OutSeq>::value +
                                          (Tr)get_value<i, inputs1>::value *(
                                              Tr)get_value<j, inputs2>::value,
                               OutSeq>::type type;
  };

  template <int i, int j, class T, T... ts>
  struct Add<i, j, std::integer_sequence<T, ts...>, false> {
    static_assert(i + j == sizeof...(ts), "Internal error");
    typedef std::integer_sequence<T, ts..., (Tr)get_value<i, inputs1>::value *(
                                                Tr)get_value<j, inputs2>::value>
    type;
  };

  template <int i, int j, class OutSeq> struct P2Loop {
    typedef typename P2Loop<i, j - 1, typename Add<i, j, OutSeq>::type>::type
    type;
  };

  template <int i, class OutSeq> struct P2Loop<i, -1, OutSeq> {
    typedef OutSeq type;
  };

  template <int i, class OutSeq> struct P1Loop {
    typedef typename P1Loop<
        i - 1, typename P2Loop<i, sizeof...(t2s) - 1, OutSeq>::type>::type type;
  };

  template <IPInt_t... ts>
  struct P1Loop<-1, std::integer_sequence<IPInt_t, ts...> > {
    typedef IntegralPolynomial<ts...> type;
  };

  template <class> struct InitOutput;

  template <IPInt_t... indices> struct InitOutput<iseq<indices...> > {
    typedef std::integer_sequence<Tr, ((void)indices, 0)...> type;
  };

  typedef typename P1Loop<
      sizeof...(t1s) - 1,
      typename InitOutput<
          miseq<sizeof...(t1s) + sizeof...(t2s) - 1> >::type>::type type;

  static type Combine(
      Multiplication<IntegralPolynomial<t1s...>, IntegralPolynomial<t2s...> >) {
    SIMPLIFY_INFO("Simplifying multiplication of "
                  "integral_polynomials\n");
    return type{};
  }
};

template <IPInt_t... ts>
struct Simplification<IntegralPolynomial<ts...>,
                      /*ip*/ 0> {
  template <IPInt_t t> using ic = std::integral_constant<IPInt_t, t>;

  template <IPInt_t... t2s> struct pop {
    template <class> struct apply;

    template <std::size_t... is>
    struct apply<std::integer_sequence<std::size_t, is...> > {
      typedef std::integer_sequence<IPInt_t,
                                    nth<is, ic<t2s>...>::type::value...> type;
    };

    typedef typename apply<std::make_index_sequence<sizeof...(t2s) - 1> >::type
    type;
  };

  template <class, bool> struct pop_if;

  template <class> struct stopping_condition;

  template <IPInt_t... touts>
  struct stopping_condition<std::integer_sequence<IPInt_t, touts...> > {
    static const bool value =
        sizeof...(ts) == 1 || last<ic<touts>...>::type::value != 0;
  };

  template <IPInt_t... touts>
  struct pop_if<std::integer_sequence<IPInt_t, touts...>, true> {
    typedef IntegralPolynomial<touts...> type;
  };

  template <IPInt_t... touts>
  struct pop_if<std::integer_sequence<IPInt_t, touts...>, false> {
    typedef typename pop<touts...>::type next;
    typedef typename pop_if<next, stopping_condition<next>::value>::type type;
  };

  typedef typename pop_if<
      std::integer_sequence<IPInt_t, ts...>,
      stopping_condition<std::integer_sequence<IPInt_t, ts...> >::value>::type
  type;

  static type Combine(IntegralPolynomial<ts...>) {
    SIMPLIFY_INFO("Simplifying of integral_polynomial\n");
    return type{};
  }
};

template <template <class...> class Variadic, class T1, class O1,
          IPInt_t... t2s>
struct Simplification<Variadic<Polynomial<T1, O1>, IntegralPolynomial<t2s...> >,
                      /*var_p_ip*/ 2> {
  typedef Variadic<Polynomial<T1, O1>,
                   Polynomial<IPInt_t, int_<sizeof...(t2s)> > > type;

  static type
  Combine(Variadic<Polynomial<T1, O1>, IntegralPolynomial<t2s...> > v) {
    SIMPLIFY_INFO("Simplifying variadic of "
                  "polynomial and integral_polynomial\n");
    return { std::get<0>(v.GetFunctions()),
             std::get<1>(v.GetFunctions()).ToPoly() };
  }
};

template <template <class...> class Variadic, class T1, class O1,
          IPInt_t... t2s>
struct Simplification<Variadic<IntegralPolynomial<t2s...>, Polynomial<T1, O1> >,
                      /*var_ip_p*/ 0> {
  typedef Variadic<Polynomial<IPInt_t, int_<sizeof...(t2s)> >,
                   Polynomial<T1, O1> > type;

  static type
  Combine(Variadic<IntegralPolynomial<t2s...>, Polynomial<T1, O1> > v) {
    SIMPLIFY_INFO("Simplifying variadic of "
                  "integral_polynomial and polynomial\n");
    return { std::get<0>(v.GetFunctions()).ToPoly(),
             std::get<1>(v.GetFunctions()) };
  }
};

template <IPInt_t... coeffs>
struct Simplification<UnaryMinus<IntegralPolynomial<coeffs...> >, 0> {
  typedef IntegralPolynomial<-coeffs...> type;

  static type Combine(UnaryMinus<IntegralPolynomial<coeffs...> >) {
    SIMPLIFY_INFO("Simplifying negative of integral polynomial");
    return type{};
  }
};

template <class A>
struct Simplification<Addition<A, A>, /*add_f_f*/ 3,
                      typename std::enable_if<is_stateless<A>::value>::type> {
  typedef Composition<IntegralPolynomial<0, 2>, A> type;
  static type Combine(Addition<A, A> a) {
    SIMPLIFY_INFO("Simplifying addition of function by itself\n");
    type b = { IntegralPolynomial<0, 2>(), A() };
    return b;
  }
};

template <class A>
struct Simplification<Multiplication<A, A>, /*mult_f_f*/ 3,
                      typename std::enable_if<is_stateless<A>::value>::type> {
  typedef Composition<IntegralPolynomial<0, 0, 1>, A> type;

  static type Combine(Multiplication<A, A>) {
    SIMPLIFY_INFO("Simplifying multiplication of function "
                  "by itself\n");
    return { IntegralPolynomial<0, 0, 1>(), A() };
  }
};

template <class T, IPInt_t us>
struct Simplification<Addition<T, IntegralPolynomial<us> >,
                      /*add_f_ip_1*/ 3> {
  typedef Composition<IntegralPolynomial<us, 1>, T> type;

  static type Combine(Addition<T, IntegralPolynomial<us> > a) {
    SIMPLIFY_INFO("Simplifying addition of constant "
                  "and another function");
    auto t = a.GetFunctions();
    return { IntegralPolynomial<us, 1>(), std::get<0>(t) };
  }
};

template <class T>
struct Simplification<Multiplication<T, IntegralPolynomial<1> >,
                      /*mult_f_ip_1*/ 1> {
  static T Combine(Multiplication<T, IntegralPolynomial<1> > m) {
    SIMPLIFY_INFO("Simplifying multiplication of function by 1");
    return std::get<0>(m.GetFunctions());
  }
};

template <>
struct Simplification<IntegralPolynomial<0>,
                      /*ip_0*/ 0> {
  static auto Combine(IntegralPolynomial<0>) { return zero; }
};

template <class C>
struct Simplification<Composition<IntegralPolynomial<0, 1>, C>,
                      /*com_ip01_f*/ 0> {
  static auto Combine(Composition<IntegralPolynomial<0, 1>, C> a) {
    return std::get<1>(a.GetFunctions());
  }
};

template <class C, IPInt_t i>
struct Simplification<Composition<C, IntegralPolynomial<i> >, 0> {
  static auto Combine(Composition<C, IntegralPolynomial<i> > c) {
    return GetPolynomial((std::get<0>(c.GetFunctions()))(i));
  }
};

template <class C, IPInt_t... coeffs>
struct Simplification<
    Multiplication<C, Composition<IntegralPolynomial<coeffs...>, C> >, 0,
    typename std::enable_if<C::stateless>::type> {
  static auto Combine(
      Multiplication<C, Composition<IntegralPolynomial<coeffs...>, C> >) {
    return GetIPolynomial<0, coeffs...>()(C{});
  }
};

template <class... Fs, IPInt_t... coeffs>
struct Simplification<
    Multiplication<Composition<Fs...>,
                   Composition<IntegralPolynomial<coeffs...>, Fs...> >,
    0, typename std::enable_if<Composition<Fs...>::stateless>::type> {
  static auto Combine(Multiplication<
      Composition<Fs...>, Composition<IntegralPolynomial<coeffs...>, Fs...> >) {
    return GetIPolynomial<0, coeffs...>()(Composition<Fs...>());
  }
};

template <IPInt_t... c1s, IPInt_t... c2s>
struct Simplification<
    Composition<IntegralPolynomial<c1s...>, IntegralPolynomial<c2s...> >, 0> {
  typedef IntegralPolynomial<c2s...> inner;

  template <int i>
  using ith = typename nth<i, std::integral_constant<IPInt_t, c1s>...>::type;

  template <IPInt_t, class> struct Term2 {};

  template <int i, class F> struct Class {
    typedef F type;
  };

  template <IPInt_t c, std::size_t... is>
  struct Term2<c, std::integer_sequence<std::size_t, is...> > {
    typedef Multiplication<IntegralPolynomial<c>,
                           typename Class<is, inner>::type...> type;
  };

  template <int i> struct Term {
    typedef typename Term2<ith<i>::value, std::make_index_sequence<i> >::type
    type;
  };

  template <class> struct Add {};
  template <std::size_t... is>
  struct Add<std::integer_sequence<std::size_t, is...> > {
    typedef Addition<typename Term<is>::type...> type;
  };

  static auto Combine(
      Composition<IntegralPolynomial<c1s...>, IntegralPolynomial<c2s...> >) {
    return typename Add<std::make_index_sequence<sizeof...(c1s)> >::type();
  }
};

    template <IPInt_t ... coeffs, class F>
    struct Simplification<Composition<IntegralPolynomial<coeffs...>, UnaryMinus<F> >, 0>
    {
        template <int i, class T, IPInt_t ... ncoeffs>
        struct NewCoeffs
        {
            static const IPInt_t c =
                std::tuple_element<i, T>::type::value;
            static const IPInt_t nc =
                i % 2 == 0 ? c : -c;
            typedef typename NewCoeffs<i-1, T, nc, ncoeffs...>::type type;
        };

        template <class T, IPInt_t ... ncoeffs>
        struct NewCoeffs<0, T, ncoeffs...>
        {
            typedef IntegralPolynomial<ncoeffs...> type;
        };

        static auto Combine(Composition<IntegralPolynomial<coeffs...>, UnaryMinus<F> > c)
        {
            typename NewCoeffs<
                sizeof...(coeffs)-1,
                std::tuple<std::integral_constant<IPInt_t, coeffs>...> >::type np;
            return np(std::get<1>(c.GetFunctions()).GetFunction());
        }
    };
}

#endif
<|endoftext|>


<commit_before>#include "mainwindow.h"

#include "shaderrenderwidget.h"
#include "codeeditor.h"
#include "shadersyntaxhighlighter.h"

#include "widgets/layouts/coverlaylayout.h"
#include "assert/advanced_assert.h"
#include "settings/csettings.h"

DISABLE_COMPILER_WARNINGS
#include "ui_mainwindow.h"

#include <QActionGroup>
#include <QStringBuilder>
RESTORE_COMPILER_WARNINGS

// Keys for storing option in the settings
#define SETTINGS_KEY_UI_SHADER_FRAMEWORK QStringLiteral("Ui/ShaderFamework")
#define SETTINGS_KEY_UI_WINDOWGEOMETRY QStringLiteral("Ui/WindowGeometry")
#define SETTINGS_KEY_UI_WINDOWSTATE QStringLiteral("Ui/WindowState")

inline QString textFromResource(const char* resourcePath)
{
	QFile resourceFile(resourcePath);
	assert(resourceFile.exists());
	assert_r(resourceFile.open(QFile::ReadOnly));

	return resourceFile.readAll();
}

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::MainWindow)
{
	ui->setupUi(this);

	auto overlayLayout = new COverlayLayout(ui->shaderWidgetsHost);
	_renderWidget = new ShaderRenderWidget();
	overlayLayout->addWidget(_renderWidget);

	_shaderEditorWidget = new CodeEditor();
	overlayLayout->addWidget(_shaderEditorWidget);
	new ShaderSyntaxHighlighter(_shaderEditorWidget->document());

	ui->shaderWidgetsHost->setLayout(overlayLayout);

	QFont editorFont;
	editorFont.setFamily("Consolas");
	editorFont.setFixedPitch(true);
	editorFont.setPointSize(10);

	_shaderEditorWidget->setFont(editorFont);
	_shaderEditorWidget->setStyleSheet("color: white; selection-background-color: rgba(200, 200, 200, 150); selection-color: rgb(30, 30, 30);");
	_shaderEditorWidget->setFrameStyle(QFrame::NoFrame);
	auto editorPalette = _shaderEditorWidget->palette();
	editorPalette.setColor(QPalette::Active, QPalette::Base, Qt::transparent);
	editorPalette.setColor(QPalette::Inactive, QPalette::Base, Qt::transparent);
	_shaderEditorWidget->setPalette(editorPalette);

	_shaderEditorWidget->setTextBackgroundColor(QColor(20, 20, 20, 130));

	_shaderEditorWidget->setPlainText(textFromResource(":/resources/default_fragment_shader_shadertoy.fsh"));
	_shaderEditorWidget->setLineWrapMode(QPlainTextEdit::NoWrap);
	_shaderEditorWidget->setTabStopWidth(4 * _shaderEditorWidget->fontMetrics().width(' '));
	connect(_shaderEditorWidget, &QPlainTextEdit::textChanged, this, &MainWindow::updateFragmentShader);

	ui->mainSplitter->setStretchFactor(0, 1);
	ui->mainSplitter->setStretchFactor(1, 0);
	ui->mainSplitter->setSizes({0, 100});

	connect(ui->actionToggle_fullscreen_mode, &QAction::triggered, this, [this](bool checked) {
		if (checked)
			showFullScreen();
		else
			showNormal();
	});

	auto shaderFrameworkModeMenuGroup = new QActionGroup(this);
	shaderFrameworkModeMenuGroup->addAction(ui->actionBarebone_GLSL);
	shaderFrameworkModeMenuGroup->addAction(ui->actionShadertoy_compatibility);

	const auto currentFramework = (ShaderFramework::Framework)CSettings().value(SETTINGS_KEY_UI_SHADER_FRAMEWORK, ShaderFramework::ShaderToy).toInt();
	_shaderFramework.setFrameworkMode(currentFramework);
	if (currentFramework == ShaderFramework::GLSL)
		ui->actionBarebone_GLSL->setChecked(true);
	else
		ui->actionShadertoy_compatibility->setChecked(true);

	connect(ui->actionBarebone_GLSL, &QAction::triggered, this, [this]() {
		setShaderFramework(ShaderFramework::GLSL);
	});

	connect(ui->actionShadertoy_compatibility, &QAction::triggered, this, [this]() {
		setShaderFramework(ShaderFramework::ShaderToy);
	});

	connect(ui->actionExit, &QAction::triggered, qApp, &QApplication::quit);

	connect(&_fpsUpdaterTimer, &QTimer::timeout, this, &MainWindow::updateWindowTitle);
	_fpsUpdaterTimer.start(100);
}

MainWindow::~MainWindow()
{
	delete ui;
}

void MainWindow::showEvent(QShowEvent* e)
{
	QMainWindow::showEvent(e);
	updateFragmentShader();
}

void MainWindow::setShaderFramework(ShaderFramework::Framework framework)
{
	CSettings().setValue(SETTINGS_KEY_UI_SHADER_FRAMEWORK, framework);
	_shaderFramework.setFrameworkMode(framework);
	updateFragmentShader();
}

void MainWindow::updateFragmentShader()
{
	const QString log = _renderWidget->setFragmentShader(_shaderFramework.processedShaderSource(_shaderEditorWidget->toPlainText()));
	ui->output->setPlainText(log);
}

void MainWindow::updateWindowTitle()
{
	setWindowTitle("Shader Playground - " % QString::number((int)(1000.0f / _renderWidget->frameRenderingPeriod())) % " fps");
}
<commit_msg>Default shader for GLSL mode fixed<commit_after>#include "mainwindow.h"

#include "shaderrenderwidget.h"
#include "codeeditor.h"
#include "shadersyntaxhighlighter.h"

#include "widgets/layouts/coverlaylayout.h"
#include "assert/advanced_assert.h"
#include "settings/csettings.h"

DISABLE_COMPILER_WARNINGS
#include "ui_mainwindow.h"

#include <QActionGroup>
#include <QStringBuilder>
RESTORE_COMPILER_WARNINGS

// Keys for storing option in the settings
#define SETTINGS_KEY_UI_SHADER_FRAMEWORK QStringLiteral("Ui/ShaderFamework")
#define SETTINGS_KEY_UI_WINDOWGEOMETRY QStringLiteral("Ui/WindowGeometry")
#define SETTINGS_KEY_UI_WINDOWSTATE QStringLiteral("Ui/WindowState")

inline QString textFromResource(const char* resourcePath)
{
	QFile resourceFile(resourcePath);
	assert(resourceFile.exists());
	assert_r(resourceFile.open(QFile::ReadOnly));

	return resourceFile.readAll();
}

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::MainWindow)
{
	ui->setupUi(this);

	auto overlayLayout = new COverlayLayout(ui->shaderWidgetsHost);
	_renderWidget = new ShaderRenderWidget();
	overlayLayout->addWidget(_renderWidget);

	_shaderEditorWidget = new CodeEditor();
	overlayLayout->addWidget(_shaderEditorWidget);
	new ShaderSyntaxHighlighter(_shaderEditorWidget->document());

	ui->shaderWidgetsHost->setLayout(overlayLayout);

	const auto currentFramework = (ShaderFramework::Framework)CSettings().value(SETTINGS_KEY_UI_SHADER_FRAMEWORK, ShaderFramework::ShaderToy).toInt();
	_shaderFramework.setFrameworkMode(currentFramework);
	if (currentFramework == ShaderFramework::GLSL)
		ui->actionBarebone_GLSL->setChecked(true);
	else
		ui->actionShadertoy_compatibility->setChecked(true);

	QFont editorFont;
	editorFont.setFamily("Consolas");
	editorFont.setFixedPitch(true);
	editorFont.setPointSize(10);

	_shaderEditorWidget->setFont(editorFont);
	_shaderEditorWidget->setStyleSheet("color: white; selection-background-color: rgba(200, 200, 200, 150); selection-color: rgb(30, 30, 30);");
	_shaderEditorWidget->setFrameStyle(QFrame::NoFrame);
	auto editorPalette = _shaderEditorWidget->palette();
	editorPalette.setColor(QPalette::Active, QPalette::Base, Qt::transparent);
	editorPalette.setColor(QPalette::Inactive, QPalette::Base, Qt::transparent);
	_shaderEditorWidget->setPalette(editorPalette);

	_shaderEditorWidget->setTextBackgroundColor(QColor(20, 20, 20, 130));

	_shaderEditorWidget->setPlainText(textFromResource(currentFramework == ShaderFramework::ShaderToy ? ":/resources/default_fragment_shader_shadertoy.fsh" : ":/resources/default_fragment_shader_barebone.fsh"));
	_shaderEditorWidget->setLineWrapMode(QPlainTextEdit::NoWrap);
	_shaderEditorWidget->setTabStopWidth(4 * _shaderEditorWidget->fontMetrics().width(' '));
	connect(_shaderEditorWidget, &QPlainTextEdit::textChanged, this, &MainWindow::updateFragmentShader);

	ui->mainSplitter->setStretchFactor(0, 1);
	ui->mainSplitter->setStretchFactor(1, 0);
	ui->mainSplitter->setSizes({0, 100});

	connect(ui->actionToggle_fullscreen_mode, &QAction::triggered, this, [this](bool checked) {
		if (checked)
			showFullScreen();
		else
			showNormal();
	});

	auto shaderFrameworkModeMenuGroup = new QActionGroup(this);
	shaderFrameworkModeMenuGroup->addAction(ui->actionBarebone_GLSL);
	shaderFrameworkModeMenuGroup->addAction(ui->actionShadertoy_compatibility);

	connect(ui->actionBarebone_GLSL, &QAction::triggered, this, [this]() {
		setShaderFramework(ShaderFramework::GLSL);
	});

	connect(ui->actionShadertoy_compatibility, &QAction::triggered, this, [this]() {
		setShaderFramework(ShaderFramework::ShaderToy);
	});

	connect(ui->actionExit, &QAction::triggered, qApp, &QApplication::quit);

	connect(&_fpsUpdaterTimer, &QTimer::timeout, this, &MainWindow::updateWindowTitle);
	_fpsUpdaterTimer.start(100);
}

MainWindow::~MainWindow()
{
	delete ui;
}

void MainWindow::showEvent(QShowEvent* e)
{
	QMainWindow::showEvent(e);
	updateFragmentShader();
}

void MainWindow::setShaderFramework(ShaderFramework::Framework framework)
{
	CSettings().setValue(SETTINGS_KEY_UI_SHADER_FRAMEWORK, framework);
	_shaderFramework.setFrameworkMode(framework);
	updateFragmentShader();
}

void MainWindow::updateFragmentShader()
{
	const QString log = _renderWidget->setFragmentShader(_shaderFramework.processedShaderSource(_shaderEditorWidget->toPlainText()));
	ui->output->setPlainText(log);
}

void MainWindow::updateWindowTitle()
{
	setWindowTitle("Shader Playground - " % QString::number((int)(1000.0f / _renderWidget->frameRenderingPeriod())) % " fps");
}
<|endoftext|>


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

#ifndef _DBAUI_UNOADMIN_
#define _DBAUI_UNOADMIN_

#ifndef _SVT_GENERICUNODIALOG_HXX_
#include <svtools/genericunodialog.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
#include <com/sun/star/sdbc/XConnection.hpp>
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _DBAUI_DSNTYPES_HXX_
#include "dsntypes.hxx"
#endif

class SfxItemSet;
class SfxItemPool;
class SfxPoolItem;

//.........................................................................
namespace dbaui
{
//.........................................................................

class IAdminHelper;

//=========================================================================
//= ODatabaseAdministrationDialog
//=========================================================================
typedef ::svt::OGenericUnoDialog ODatabaseAdministrationDialogBase;
class ODatabaseAdministrationDialog
        :public ODatabaseAdministrationDialogBase
        ,public OModuleClient
{
protected:
    SfxItemSet*             m_pDatasourceItems;     // item set for the dialog
    SfxItemPool*            m_pItemPool;            // item pool for the item set for the dialog
    SfxPoolItem**           m_pItemPoolDefaults;    // pool defaults
    ODsnTypeCollection*     m_pCollection;          // datasource type collection

    ::com::sun::star::uno::Any          m_aInitialSelection;
    ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xActiveConnection;

protected:
    ODatabaseAdministrationDialog(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB);
    virtual ~ODatabaseAdministrationDialog();
protected:
// OGenericUnoDialog overridables
    virtual void destroyDialog();
    virtual void implInitialize(const com::sun::star::uno::Any& _rValue);
};

//.........................................................................
}   // namespace dbaui
//.........................................................................

#endif // _DBAUI_UNOADMIN_

<commit_msg>INTEGRATION: CWS dba23a (1.10.254); FILE MERGED 2007/03/13 08:42:17 fs 1.10.254.1: some slight re-factoring (class/method renaming), plus some rudimentary fix for #b6532894#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unoadmin.hxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: kz $ $Date: 2007-05-10 10:33:51 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _DBAUI_UNOADMIN_
#define _DBAUI_UNOADMIN_

#ifndef _SVT_GENERICUNODIALOG_HXX_
#include <svtools/genericunodialog.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
#include <com/sun/star/sdbc/XConnection.hpp>
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _DBAUI_DSNTYPES_HXX_
#include "dsntypes.hxx"
#endif

class SfxItemSet;
class SfxItemPool;
class SfxPoolItem;

//.........................................................................
namespace dbaui
{
//.........................................................................

class IDatabaseSettingsDialog;

//=========================================================================
//= ODatabaseAdministrationDialog
//=========================================================================
typedef ::svt::OGenericUnoDialog ODatabaseAdministrationDialogBase;
class ODatabaseAdministrationDialog
        :public ODatabaseAdministrationDialogBase
        ,public OModuleClient
{
protected:
    SfxItemSet*             m_pDatasourceItems;     // item set for the dialog
    SfxItemPool*            m_pItemPool;            // item pool for the item set for the dialog
    SfxPoolItem**           m_pItemPoolDefaults;    // pool defaults
    ODsnTypeCollection*     m_pCollection;          // datasource type collection

    ::com::sun::star::uno::Any          m_aInitialSelection;
    ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xActiveConnection;

protected:
    ODatabaseAdministrationDialog(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB);
    virtual ~ODatabaseAdministrationDialog();
protected:
// OGenericUnoDialog overridables
    virtual void destroyDialog();
    virtual void implInitialize(const com::sun::star::uno::Any& _rValue);
};

//.........................................................................
}   // namespace dbaui
//.........................................................................

#endif // _DBAUI_UNOADMIN_

<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2015 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   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.
*/

#include <Modules/Render/ViewScene.h>
#include <Core/Datatypes/Geometry.h>
#include <Core/Logging/Log.h>
#include <Core/Datatypes/Color.h>
#include <Core/Datatypes/DenseMatrix.h>

// Needed to fix conflict between define in X11 header
// and eigen enum member.
#ifdef Success
#  undef Success
#endif

using namespace SCIRun::Modules::Render;
using namespace SCIRun::Core::Algorithms;
using namespace Render;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Thread;

ModuleLookupInfo ViewScene::staticInfo_("ViewScene", "Render", "SCIRun");
Mutex ViewScene::mutex_("ViewScene");

ALGORITHM_PARAMETER_DEF(Render, GeomData);
ALGORITHM_PARAMETER_DEF(Render, GeometryFeedbackInfo);
ALGORITHM_PARAMETER_DEF(Render, ScreenshotData);

ViewScene::ViewScene() : ModuleWithAsyncDynamicPorts(staticInfo_, true)
{
  INITIALIZE_PORT(GeneralGeom);
#ifdef BUILD_TESTING
  INITIALIZE_PORT(ScreenshotData);
#endif
}

void ViewScene::setStateDefaults()
{
  auto state = get_state();
  state->setValue(BackgroundColor, ColorRGB(0.0, 0.0, 0.0).toString());
  postStateChangeInternalSignalHookup();
}

void ViewScene::postStateChangeInternalSignalHookup()
{
  get_state()->connect_state_changed([this]() { processViewSceneObjectFeedback(); });
}

void ViewScene::portRemovedSlotImpl(const PortId& pid)
{
  //lock for state modification
  {
    Guard lock(mutex_.get());
    auto loc = activeGeoms_.find(pid);
    if (loc != activeGeoms_.end())
      activeGeoms_.erase(loc);
    updateTransientList();
  }
  get_state()->fireTransientStateChangeSignal();
}

void ViewScene::updateTransientList()
{
  auto transient = get_state()->getTransientValue(Parameters::GeomData);

  auto geoms = optional_any_cast_or_default<GeomListPtr>(transient);
  if (!geoms)
  {
    geoms.reset(new GeomList());
  }
  auto activeHandles = activeGeoms_ | boost::adaptors::map_values;
  geoms->clear();
  geoms->insert(activeHandles.begin(), activeHandles.end());

  // Grab geometry inputs and pass them along in a transient value to the GUI
  // thread where they will be transported to Spire.
  // NOTE: I'm not implementing mutex locks for this now. But for production
  // purposes, they NEED to be in there!

  // Pass geometry object up through transient... really need to be concerned
  // about the lifetimes of the buffers we have in GeometryObject. Need to
  // switch to std::shared_ptr on an std::array when in production.

  /// \todo Need to make this data transfer mechanism thread safe!
  // I thought about dynamic casting geometry object to a weak_ptr, but I don't
  // know where it will be destroyed. For now, it will have have stale pointer
  // data lying around in it... yuck.
  get_state()->setTransientValue(Parameters::GeomData, geoms, false);
}

void ViewScene::asyncExecute(const PortId& pid, DatatypeHandle data)
{
  //lock for state modification
  {
    LOG_DEBUG("ViewScene::asyncExecute before locking");
    Guard lock(mutex_.get());
    get_state()->setTransientValue(Parameters::ScreenshotData, nullptr, false);

    LOG_DEBUG("ViewScene::asyncExecute after locking");

    auto geom = boost::dynamic_pointer_cast<GeometryObject>(data);
    if (!geom)
    {
      error("Logical error: not a geometry object on ViewScene");
      return;
    }

    activeGeoms_[pid] = geom;
    updateTransientList();
  }
  get_state()->fireTransientStateChangeSignal();
}

#ifdef BUILD_TESTING
void ViewScene::execute()
{
  DenseMatrixHandle screenshotData;
  auto state = get_state();
  do
  {
    auto transient = state->getTransientValue(Parameters::ScreenshotData);
    screenshotData = optional_any_cast_or_default<DenseMatrixHandle>(transient);
    if (screenshotData)
    {
      sendOutput(ScreenshotData, screenshotData);
    }
  }
  while (!screenshotData);
}
#endif

void ViewScene::processViewSceneObjectFeedback()
{
  //TODO: match ID of touched geom object with port id, and send that info back too.
  //std::cout << "slot for state change in VS module" << std::endl;
  auto state = get_state();
  auto newInfo = state->getValue(Parameters::GeometryFeedbackInfo).toVector();
  //std::cout << "feedback info: " << newInfo << std::endl;
  if (feedbackInfo_ != newInfo)
  {
    //std::cout << "new feedback info: " << newInfo << std::endl;
    feedbackInfo_ = newInfo;

    sendFeedbackUpstreamAlongIncomingConnections(feedbackInfo_);
  }
}

AlgorithmParameterName ViewScene::BackgroundColor("BackgroundColor");
<commit_msg>Fix disconnected VS hang<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2015 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   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.
*/

#include <Modules/Render/ViewScene.h>
#include <Core/Datatypes/Geometry.h>
#include <Core/Logging/Log.h>
#include <Core/Datatypes/Color.h>
#include <Core/Datatypes/DenseMatrix.h>

// Needed to fix conflict between define in X11 header
// and eigen enum member.
#ifdef Success
#  undef Success
#endif

using namespace SCIRun::Modules::Render;
using namespace SCIRun::Core::Algorithms;
using namespace Render;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Thread;

ModuleLookupInfo ViewScene::staticInfo_("ViewScene", "Render", "SCIRun");
Mutex ViewScene::mutex_("ViewScene");

ALGORITHM_PARAMETER_DEF(Render, GeomData);
ALGORITHM_PARAMETER_DEF(Render, GeometryFeedbackInfo);
ALGORITHM_PARAMETER_DEF(Render, ScreenshotData);

ViewScene::ViewScene() : ModuleWithAsyncDynamicPorts(staticInfo_, true)
{
  INITIALIZE_PORT(GeneralGeom);
#ifdef BUILD_TESTING
  INITIALIZE_PORT(ScreenshotData);
#endif
}

void ViewScene::setStateDefaults()
{
  auto state = get_state();
  state->setValue(BackgroundColor, ColorRGB(0.0, 0.0, 0.0).toString());
  postStateChangeInternalSignalHookup();
}

void ViewScene::postStateChangeInternalSignalHookup()
{
  get_state()->connect_state_changed([this]() { processViewSceneObjectFeedback(); });
}

void ViewScene::portRemovedSlotImpl(const PortId& pid)
{
  //lock for state modification
  {
    Guard lock(mutex_.get());
    auto loc = activeGeoms_.find(pid);
    if (loc != activeGeoms_.end())
      activeGeoms_.erase(loc);
    updateTransientList();
  }
  get_state()->fireTransientStateChangeSignal();
}

void ViewScene::updateTransientList()
{
  auto transient = get_state()->getTransientValue(Parameters::GeomData);

  auto geoms = optional_any_cast_or_default<GeomListPtr>(transient);
  if (!geoms)
  {
    geoms.reset(new GeomList());
  }
  auto activeHandles = activeGeoms_ | boost::adaptors::map_values;
  geoms->clear();
  geoms->insert(activeHandles.begin(), activeHandles.end());

  // Grab geometry inputs and pass them along in a transient value to the GUI
  // thread where they will be transported to Spire.
  // NOTE: I'm not implementing mutex locks for this now. But for production
  // purposes, they NEED to be in there!

  // Pass geometry object up through transient... really need to be concerned
  // about the lifetimes of the buffers we have in GeometryObject. Need to
  // switch to std::shared_ptr on an std::array when in production.

  /// \todo Need to make this data transfer mechanism thread safe!
  // I thought about dynamic casting geometry object to a weak_ptr, but I don't
  // know where it will be destroyed. For now, it will have have stale pointer
  // data lying around in it... yuck.
  get_state()->setTransientValue(Parameters::GeomData, geoms, false);
}

void ViewScene::asyncExecute(const PortId& pid, DatatypeHandle data)
{
  //lock for state modification
  {
    LOG_DEBUG("ViewScene::asyncExecute before locking");
    Guard lock(mutex_.get());
    get_state()->setTransientValue(Parameters::ScreenshotData, nullptr, false);

    LOG_DEBUG("ViewScene::asyncExecute after locking");

    auto geom = boost::dynamic_pointer_cast<GeometryObject>(data);
    if (!geom)
    {
      error("Logical error: not a geometry object on ViewScene");
      return;
    }

    activeGeoms_[pid] = geom;
    updateTransientList();
  }
  get_state()->fireTransientStateChangeSignal();
}

#ifdef BUILD_TESTING
void ViewScene::execute()
{
  if (inputPorts().size() > 1) // only send screenshot if input is present
  {
    DenseMatrixHandle screenshotData;
    auto state = get_state();
    do
    {
      auto transient = state->getTransientValue(Parameters::ScreenshotData);
      screenshotData = optional_any_cast_or_default<DenseMatrixHandle>(transient);
      if (screenshotData)
      {
        sendOutput(ScreenshotData, screenshotData);
      }
    }
    while (!screenshotData);
  }
}
#endif

void ViewScene::processViewSceneObjectFeedback()
{
  //TODO: match ID of touched geom object with port id, and send that info back too.
  //std::cout << "slot for state change in VS module" << std::endl;
  auto state = get_state();
  auto newInfo = state->getValue(Parameters::GeometryFeedbackInfo).toVector();
  //std::cout << "feedback info: " << newInfo << std::endl;
  if (feedbackInfo_ != newInfo)
  {
    //std::cout << "new feedback info: " << newInfo << std::endl;
    feedbackInfo_ = newInfo;

    sendFeedbackUpstreamAlongIncomingConnections(feedbackInfo_);
  }
}

AlgorithmParameterName ViewScene::BackgroundColor("BackgroundColor");
<|endoftext|>


<commit_before><commit_msg>disable frame selection (Format_ARGB32 is blank)<commit_after><|endoftext|>


<commit_before>#include "arch/runtime/message_hub.hpp"

#include <math.h>
#include <unistd.h>

#include "config/args.hpp"
#include "arch/runtime/event_queue.hpp"
#include "arch/runtime/thread_pool.hpp"
#include "logger.hpp"

linux_message_hub_t::linux_message_hub_t(linux_event_queue_t *queue, linux_thread_pool_t *thread_pool, int current_thread)
    : queue_(queue), thread_pool_(thread_pool), current_thread_(current_thread) {

    // We have to do this through dynamically, otherwise we might
    // allocate far too many file descriptors since this is what the
    // constructor of the system_event_t object (which is a member of
    // notify_t) does.
    notify_ = new notify_t[thread_pool_->n_threads];

    for (int i = 0; i < thread_pool_->n_threads; i++) {
        int res = pthread_spin_init(&incoming_messages_lock_, PTHREAD_PROCESS_PRIVATE);
        guarantee(res == 0, "Could not initialize spin lock");

        // Create notify fd for other cores that send work to us
        notify_[i].notifier_thread = i;
        notify_[i].parent = this;

        queue_->watch_resource(notify_[i].event.get_notify_fd(), poll_event_in, &notify_[i]);
    }
}

linux_message_hub_t::~linux_message_hub_t() {
    int res;

    for (int i = 0; i < thread_pool_->n_threads; i++) {
        rassert(queues_[i].msg_local_list.empty());

        res = pthread_spin_destroy(&incoming_messages_lock_);
        guarantee(res == 0, "Could not destroy spin lock");
    }

    rassert(incoming_messages_.empty());

    delete[] notify_;
}

void linux_message_hub_t::do_store_message(unsigned int nthread, linux_thread_message_t *msg) {
    rassert(nthread < (unsigned)thread_pool_->n_threads);
    queues_[nthread].msg_local_list.push_back(msg);
}

// Collects a message for a given thread onto a local list.
void linux_message_hub_t::store_message(unsigned int nthread, linux_thread_message_t *msg) {
#ifndef NDEBUG
    // We default to 1, not zero, to allow store_message_sometime messages to sometimes jump ahead of
    // store_message messages.
    msg->reloop_count_ = 1;
#endif
    do_store_message(nthread, msg);
}

int rand_reloop_count() {
    int x;
    frexp(randint(10000) / 10000.0, &x);
    int ret = -x;
    rassert(ret >= 0);
    return ret;
}

void linux_message_hub_t::store_message_sometime(unsigned int nthread, linux_thread_message_t *msg) {
#ifndef NDEBUG
    msg->reloop_count_ = rand_reloop_count();
#endif
    do_store_message(nthread, msg);
}

void linux_message_hub_t::insert_external_message(linux_thread_message_t *msg) {
    pthread_spin_lock(&incoming_messages_lock_);
    incoming_messages_.push_back(msg);
    pthread_spin_unlock(&incoming_messages_lock_);

    // Wakey wakey eggs and bakey
    notify_[current_thread_].event.write(1);
}

void linux_message_hub_t::notify_t::on_event(int events) {

    if (events != poll_event_in) {
        logERR("Unexpected event mask: %d", events);
    }

    // Read from the event so level-triggered mechanism such as poll
    // don't pester us and use 100% cpu
    event.read();

    msg_list_t msg_list;

    pthread_spin_lock(&parent->incoming_messages_lock_);
    // Pull the messages
    //msg_list.append_and_clear(parent->thread_pool_->threads[parent->current_thread_]->message_hub);
    msg_list.append_and_clear(&parent->incoming_messages_);
    pthread_spin_unlock(&parent->incoming_messages_lock_);

#ifndef NDEBUG
    start_watchdog(); // Initialize watchdog before handling messages
#endif

    while (linux_thread_message_t *m = msg_list.head()) {
        msg_list.remove(m);
#ifndef NDEBUG
        if (m->reloop_count_ > 0) {
            --m->reloop_count_;
            parent->do_store_message(parent->current_thread_, m);
            continue;
        }
#endif

        m->on_thread_switch();

#ifndef NDEBUG
        pet_watchdog(); // Verify that each message completes in the acceptable time range
#endif
    }
}

// Pushes messages collected locally global lists available to all
// threads.
void linux_message_hub_t::push_messages() {
    for (int i = 0; i < thread_pool_->n_threads; i++) {
        // Append the local list for ith thread to that thread's global
        // message list.
        thread_queue_t *queue = &queues_[i];
        if(!queue->msg_local_list.empty()) {
            // Transfer messages to the other core

            pthread_spin_lock(&thread_pool_->threads[i]->message_hub.incoming_messages_lock_);

            //We only need to do a wake up if the global
            bool do_wake_up = thread_pool_->threads[i]->message_hub.incoming_messages_.empty();

            thread_pool_->threads[i]->message_hub.incoming_messages_.append_and_clear(&queue->msg_local_list);

            pthread_spin_unlock(&thread_pool_->threads[i]->message_hub.incoming_messages_lock_);

            // Wakey wakey, perhaps eggs and bakey
            if (do_wake_up) {
                thread_pool_->threads[i]->message_hub.notify_[current_thread_].event.write(1);
            }
        }

        // TODO: we should use regular mutexes on single core CPU
        // instead of spinlocks
    }
}
<commit_msg>Added RDB_RELOOP_MESSAGES constant and made us default to _not_ relooping by default (only relevant to debug mode).<commit_after>#include "arch/runtime/message_hub.hpp"

#include <math.h>
#include <unistd.h>

#include "config/args.hpp"
#include "arch/runtime/event_queue.hpp"
#include "arch/runtime/thread_pool.hpp"
#include "logger.hpp"

// Set this to 1 if you would like some "unordered" messages to be unordered.
#define RDB_RELOOP_MESSAGES 0

linux_message_hub_t::linux_message_hub_t(linux_event_queue_t *queue, linux_thread_pool_t *thread_pool, int current_thread)
    : queue_(queue), thread_pool_(thread_pool), current_thread_(current_thread) {

    // We have to do this through dynamically, otherwise we might
    // allocate far too many file descriptors since this is what the
    // constructor of the system_event_t object (which is a member of
    // notify_t) does.
    notify_ = new notify_t[thread_pool_->n_threads];

    for (int i = 0; i < thread_pool_->n_threads; i++) {
        int res = pthread_spin_init(&incoming_messages_lock_, PTHREAD_PROCESS_PRIVATE);
        guarantee(res == 0, "Could not initialize spin lock");

        // Create notify fd for other cores that send work to us
        notify_[i].notifier_thread = i;
        notify_[i].parent = this;

        queue_->watch_resource(notify_[i].event.get_notify_fd(), poll_event_in, &notify_[i]);
    }
}

linux_message_hub_t::~linux_message_hub_t() {
    int res;

    for (int i = 0; i < thread_pool_->n_threads; i++) {
        rassert(queues_[i].msg_local_list.empty());

        res = pthread_spin_destroy(&incoming_messages_lock_);
        guarantee(res == 0, "Could not destroy spin lock");
    }

    rassert(incoming_messages_.empty());

    delete[] notify_;
}

void linux_message_hub_t::do_store_message(unsigned int nthread, linux_thread_message_t *msg) {
    rassert(nthread < (unsigned)thread_pool_->n_threads);
    queues_[nthread].msg_local_list.push_back(msg);
}

// Collects a message for a given thread onto a local list.
void linux_message_hub_t::store_message(unsigned int nthread, linux_thread_message_t *msg) {
#ifndef NDEBUG
#if RDB_RELOOP_MESSAGES
    // We default to 1, not zero, to allow store_message_sometime messages to sometimes jump ahead of
    // store_message messages.
    msg->reloop_count_ = 1;
#else
    msg->reloop_count_ = 0;
#endif
#endif  // NDEBUG
    do_store_message(nthread, msg);
}

int rand_reloop_count() {
    int x;
    frexp(randint(10000) / 10000.0, &x);
    int ret = -x;
    rassert(ret >= 0);
    return ret;
}

void linux_message_hub_t::store_message_sometime(unsigned int nthread, linux_thread_message_t *msg) {
#ifndef NDEBUG
#if RDB_RELOOP_MESSAGES
    msg->reloop_count_ = rand_reloop_count();
#else
    msg->reloop_count_ = 0;
#endif
#endif  // NDEBUG
    do_store_message(nthread, msg);
}

void linux_message_hub_t::insert_external_message(linux_thread_message_t *msg) {
    pthread_spin_lock(&incoming_messages_lock_);
    incoming_messages_.push_back(msg);
    pthread_spin_unlock(&incoming_messages_lock_);

    // Wakey wakey eggs and bakey
    notify_[current_thread_].event.write(1);
}

void linux_message_hub_t::notify_t::on_event(int events) {

    if (events != poll_event_in) {
        logERR("Unexpected event mask: %d", events);
    }

    // Read from the event so level-triggered mechanism such as poll
    // don't pester us and use 100% cpu
    event.read();

    msg_list_t msg_list;

    pthread_spin_lock(&parent->incoming_messages_lock_);
    // Pull the messages
    //msg_list.append_and_clear(parent->thread_pool_->threads[parent->current_thread_]->message_hub);
    msg_list.append_and_clear(&parent->incoming_messages_);
    pthread_spin_unlock(&parent->incoming_messages_lock_);

#ifndef NDEBUG
    start_watchdog(); // Initialize watchdog before handling messages
#endif

    while (linux_thread_message_t *m = msg_list.head()) {
        msg_list.remove(m);
#ifndef NDEBUG
        if (m->reloop_count_ > 0) {
            --m->reloop_count_;
            parent->do_store_message(parent->current_thread_, m);
            continue;
        }
#endif

        m->on_thread_switch();

#ifndef NDEBUG
        pet_watchdog(); // Verify that each message completes in the acceptable time range
#endif
    }
}

// Pushes messages collected locally global lists available to all
// threads.
void linux_message_hub_t::push_messages() {
    for (int i = 0; i < thread_pool_->n_threads; i++) {
        // Append the local list for ith thread to that thread's global
        // message list.
        thread_queue_t *queue = &queues_[i];
        if(!queue->msg_local_list.empty()) {
            // Transfer messages to the other core

            pthread_spin_lock(&thread_pool_->threads[i]->message_hub.incoming_messages_lock_);

            //We only need to do a wake up if the global
            bool do_wake_up = thread_pool_->threads[i]->message_hub.incoming_messages_.empty();

            thread_pool_->threads[i]->message_hub.incoming_messages_.append_and_clear(&queue->msg_local_list);

            pthread_spin_unlock(&thread_pool_->threads[i]->message_hub.incoming_messages_lock_);

            // Wakey wakey, perhaps eggs and bakey
            if (do_wake_up) {
                thread_pool_->threads[i]->message_hub.notify_[current_thread_].event.write(1);
            }
        }

        // TODO: we should use regular mutexes on single core CPU
        // instead of spinlocks
    }
}
<|endoftext|>


<commit_before><commit_msg>spline steps is the number of points, not the number of segments<commit_after><|endoftext|>


<commit_before>#include <condition_variable>
#include "gtest/gtest.h"
#include <memory>
#include <mutex>
#include <rapidjson/document.h>

#include "MediaLibrary.h"
#include "IAlbum.h"
#include "IArtist.h"
#include "IMedia.h"
#include "IAlbumTrack.h"

static std::string SamplesDirectory = ".";
static std::string TestCaseDirectory = SRC_DIR "/test/samples/testcases";

static const char* testCases[] = {
    "simple",
};

class TestEnv : public ::testing::Environment
{
    public:
        virtual void SetUp()
        {
            // Always clean the DB in case a previous test crashed
            unlink("test.db");
        }
};

class MockCallback : public IMediaLibraryCb
{
public:
    MockCallback();
    bool waitForParsingComplete();

private:
    void onFileAdded(MediaPtr) {}
    void onFileUpdated(MediaPtr) {}
    void onDiscoveryStarted(const std::string&) {}
    void onDiscoveryCompleted(const std::string&) {}
    void onReloadStarted() {}
    void onReloadCompleted() {}
    void onParsingStatsUpdated(uint32_t nbParsed, uint32_t nbToParse);

    std::condition_variable m_parsingCompleteVar;
    std::mutex m_parsingMutex;
    bool m_done;
};

class Tests : public ::testing::TestWithParam<const char*>
{
protected:
    std::unique_ptr<MediaLibrary> m_ml;
    std::unique_ptr<MockCallback> m_cb;

    virtual void SetUp() override
    {
        m_cb.reset( new MockCallback );
        m_ml.reset( new MediaLibrary );
        m_ml->setVerbosity( LogLevel::Error );
        m_ml->initialize( "test.db", "/tmp", m_cb.get() );
    }

    virtual void TearDown() override
    {
        m_ml.reset();
        m_cb.reset();
    }

    void checkAlbums( const rapidjson::Value& expectedAlbums);
    void checkTracks( const IAlbum* album, const std::vector<MediaPtr>& tracks, const rapidjson::Value& expectedTracks );
};

MockCallback::MockCallback()
{
    // Start locked. The locked will be released when waiting for parsing to be completed
    m_parsingMutex.lock();
}

bool MockCallback::waitForParsingComplete()
{
    std::unique_lock<std::mutex> lock( m_parsingMutex, std::adopt_lock );
    m_done = false;
    // Wait for a while, generating snapshots can be heavy...
    return m_parsingCompleteVar.wait_for( lock, std::chrono::seconds( 30 ), [this]() {
        return m_done;
    });
}

void MockCallback::onParsingStatsUpdated(uint32_t nbParsed, uint32_t nbToParse)
{
    if ( nbParsed == nbToParse && nbToParse > 0 )
    {
        std::lock_guard<std::mutex> lock( m_parsingMutex );
        m_done = true;
        m_parsingCompleteVar.notify_all();
    }
}

void Tests::checkAlbums(const rapidjson::Value& expectedAlbums )
{
    ASSERT_TRUE( expectedAlbums.IsArray() );
    auto albums = m_ml->albums();
    ASSERT_EQ( expectedAlbums.Size(), albums.size() );
    for ( auto i = 0u; i < expectedAlbums.Size(); ++i )
    {
        const auto& expectedAlbum = expectedAlbums[i];
        ASSERT_TRUE( expectedAlbum.HasMember( "title" ) );
        // Start by checking if the album was found
        const auto title = expectedAlbum["title"].GetString();
        auto it = std::find_if( begin( albums ), end( albums ), [title](const AlbumPtr& a) {
            return strcasecmp( a->title().c_str(), title ) == 0;
        });
        ASSERT_NE( end( albums ), it );
        auto album = *it;
        // Now check if we have matching metadata
        if ( expectedAlbum.HasMember( "artist" ) )
        {
            auto expectedArtist = expectedAlbum["artist"].GetString();
            auto artist = album->albumArtist();
            ASSERT_NE( nullptr, artist );
            ASSERT_STRCASEEQ( expectedArtist, artist->name().c_str() );
        }
        if ( expectedAlbum.HasMember( "nbTracks" ) || expectedAlbum.HasMember( "tracks" ) )
        {
            const auto tracks = album->tracks();
            if ( expectedAlbum.HasMember( "nbTracks" ) )
            {
                ASSERT_EQ( expectedAlbum["nbTracks"].GetUint(), tracks.size() );
            }
            if ( expectedAlbum.HasMember( "tracks" ) )
            {
                checkTracks( album.get(), tracks, expectedAlbum["tracks"] );
            }
        }
    }
}

void Tests::checkTracks( const IAlbum* album, const std::vector<MediaPtr>& tracks, const rapidjson::Value& expectedTracks)
{
    // Don't mandate all tracks to be defined
    for ( auto i = 0u; i < expectedTracks.Size(); ++i )
    {
        auto& expectedTrack = expectedTracks[i];
        ASSERT_TRUE( expectedTrack.HasMember( "title" ) );
        auto expectedTitle = expectedTrack["title"].GetString();
        auto it = std::find_if( begin( tracks ), end( tracks ), [expectedTitle](const MediaPtr& media) {
            return strcasecmp( expectedTitle, media->title().c_str() ) == 0;
        });
        ASSERT_NE( end( tracks ), it );
        const auto track = *it;
        const auto albumTrack = track->albumTrack();
        if ( expectedTrack.HasMember( "number" ) )
        {
            ASSERT_EQ( expectedTrack["number"].GetUint(), albumTrack->trackNumber() );
        }
        const auto trackAlbum = albumTrack->album();
        ASSERT_NE( nullptr, trackAlbum );
        ASSERT_EQ( album->id(), trackAlbum->id() );
    }
}

TEST_P( Tests, Parse )
{
    auto casePath = TestCaseDirectory + "/" + GetParam() + ".json";
    std::unique_ptr<FILE, int(*)(FILE*)> f( fopen( casePath.c_str(), "rb" ), &fclose );
    ASSERT_NE( nullptr, f );
    char buff[65536]; // That's how ugly I am!
    auto ret = fread( buff, sizeof(buff[0]), sizeof(buff), f.get() );
    ASSERT_NE( 0u, ret );
    buff[ret] = 0;
    rapidjson::Document doc;
    doc.Parse( buff );

    ASSERT_TRUE( doc.HasMember( "input" ) );
    const auto& input = doc["input"];
    for ( auto i = 0u; i < input.Size(); ++i )
    {
        // Quick and dirty check to ensure we're discovering something that exists
        auto samplesDir = SamplesDirectory + "/" + input[i].GetString();
        struct stat s;
        auto res = stat( samplesDir.c_str(), &s );
        ASSERT_EQ( 0, res );

        m_ml->discover( samplesDir );
    }
    ASSERT_TRUE( m_cb->waitForParsingComplete() );

    if ( doc.HasMember( "expected" ) == false )
    {
        // That's a lousy test case with no assumptions, but ok.
        return;
    }
    const auto& expected = doc["expected"];

    if ( expected.HasMember( "albums" ) == true )
        checkAlbums( expected["albums" ] );
}

int main(int ac, char** av)
{
    ::testing::InitGoogleTest(&ac, av);
    const std::string samplesArg = "--samples-directory=";
    const std::string testCasesArg = "--testcases-directory=";
    for ( auto i = 1; i < ac; ++i )
    {
        if ( strncmp( samplesArg.c_str(), av[i], samplesArg.length() ) == 0 )
            SamplesDirectory = av[i] + samplesArg.size();
        else if ( strncmp( testCasesArg.c_str(), av[i], testCasesArg.length() ) == 0 )
            TestCaseDirectory = av[i] + testCasesArg.size();
    }
    return RUN_ALL_TESTS();
}

INSTANTIATE_TEST_CASE_P(SamplesTests, Tests,
                        ::testing::ValuesIn(testCases),
                        // gtest default parameter name displayer (testing::PrintToStringParamName)
                        // seems to add " " around the parameter name, making it invalid.
                        [](::testing::TestParamInfo<const char*> i){ return i.param; } );

::testing::Environment* const env = ::testing::AddGlobalTestEnvironment(new TestEnv);
<commit_msg>tests: samples: Allow checking for albums artist<commit_after>#include <condition_variable>
#include "gtest/gtest.h"
#include <memory>
#include <mutex>
#include <rapidjson/document.h>

#include "MediaLibrary.h"
#include "IAlbum.h"
#include "IArtist.h"
#include "IMedia.h"
#include "IAlbumTrack.h"

static std::string SamplesDirectory = ".";
static std::string TestCaseDirectory = SRC_DIR "/test/samples/testcases";

static const char* testCases[] = {
    "simple",
};

class TestEnv : public ::testing::Environment
{
    public:
        virtual void SetUp()
        {
            // Always clean the DB in case a previous test crashed
            unlink("test.db");
        }
};

class MockCallback : public IMediaLibraryCb
{
public:
    MockCallback();
    bool waitForParsingComplete();

private:
    void onFileAdded(MediaPtr) {}
    void onFileUpdated(MediaPtr) {}
    void onDiscoveryStarted(const std::string&) {}
    void onDiscoveryCompleted(const std::string&) {}
    void onReloadStarted() {}
    void onReloadCompleted() {}
    void onParsingStatsUpdated(uint32_t nbParsed, uint32_t nbToParse);

    std::condition_variable m_parsingCompleteVar;
    std::mutex m_parsingMutex;
    bool m_done;
};

class Tests : public ::testing::TestWithParam<const char*>
{
protected:
    std::unique_ptr<MediaLibrary> m_ml;
    std::unique_ptr<MockCallback> m_cb;

    virtual void SetUp() override
    {
        m_cb.reset( new MockCallback );
        m_ml.reset( new MediaLibrary );
        m_ml->setVerbosity( LogLevel::Error );
        m_ml->initialize( "test.db", "/tmp", m_cb.get() );
    }

    virtual void TearDown() override
    {
        m_ml.reset();
        m_cb.reset();
    }

    void checkAlbums( const rapidjson::Value& expectedAlbums);
    void checkTracks( const IAlbum* album, const std::vector<MediaPtr>& tracks, const rapidjson::Value& expectedTracks );
};

MockCallback::MockCallback()
{
    // Start locked. The locked will be released when waiting for parsing to be completed
    m_parsingMutex.lock();
}

bool MockCallback::waitForParsingComplete()
{
    std::unique_lock<std::mutex> lock( m_parsingMutex, std::adopt_lock );
    m_done = false;
    // Wait for a while, generating snapshots can be heavy...
    return m_parsingCompleteVar.wait_for( lock, std::chrono::seconds( 30 ), [this]() {
        return m_done;
    });
}

void MockCallback::onParsingStatsUpdated(uint32_t nbParsed, uint32_t nbToParse)
{
    if ( nbParsed == nbToParse && nbToParse > 0 )
    {
        std::lock_guard<std::mutex> lock( m_parsingMutex );
        m_done = true;
        m_parsingCompleteVar.notify_all();
    }
}

void Tests::checkAlbums(const rapidjson::Value& expectedAlbums )
{
    ASSERT_TRUE( expectedAlbums.IsArray() );
    auto albums = m_ml->albums();
    ASSERT_EQ( expectedAlbums.Size(), albums.size() );
    for ( auto i = 0u; i < expectedAlbums.Size(); ++i )
    {
        const auto& expectedAlbum = expectedAlbums[i];
        ASSERT_TRUE( expectedAlbum.HasMember( "title" ) );
        // Start by checking if the album was found
        const auto title = expectedAlbum["title"].GetString();
        auto it = std::find_if( begin( albums ), end( albums ), [title](const AlbumPtr& a) {
            return strcasecmp( a->title().c_str(), title ) == 0;
        });
        ASSERT_NE( end( albums ), it );
        auto album = *it;
        // Now check if we have matching metadata
        if ( expectedAlbum.HasMember( "artist" ) )
        {
            auto expectedArtist = expectedAlbum["artist"].GetString();
            auto artist = album->albumArtist();
            ASSERT_NE( nullptr, artist );
            ASSERT_STRCASEEQ( expectedArtist, artist->name().c_str() );
        }
        if ( expectedAlbum.HasMember( "artists" ) )
        {
            const auto& expectedArtists = expectedAlbum["artists"];
            auto artists = album->artists();
            ASSERT_EQ( expectedArtists.Size(), artists.size() );
            for ( auto i = 0u; i < expectedArtists.Size(); ++i )
            {
                auto expectedArtist = expectedArtists[i].GetString();
                auto it = std::find_if( begin( artists ), end( artists), [expectedArtist](const ArtistPtr& a) {
                    return strcasecmp( expectedArtist, a->name().c_str() ) == 0;
                });
                ASSERT_NE( end( artists ), it );
            }
        }
        if ( expectedAlbum.HasMember( "nbTracks" ) || expectedAlbum.HasMember( "tracks" ) )
        {
            const auto tracks = album->tracks();
            if ( expectedAlbum.HasMember( "nbTracks" ) )
            {
                ASSERT_EQ( expectedAlbum["nbTracks"].GetUint(), tracks.size() );
            }
            if ( expectedAlbum.HasMember( "tracks" ) )
            {
                checkTracks( album.get(), tracks, expectedAlbum["tracks"] );
            }
        }
    }
}

void Tests::checkTracks( const IAlbum* album, const std::vector<MediaPtr>& tracks, const rapidjson::Value& expectedTracks)
{
    // Don't mandate all tracks to be defined
    for ( auto i = 0u; i < expectedTracks.Size(); ++i )
    {
        auto& expectedTrack = expectedTracks[i];
        ASSERT_TRUE( expectedTrack.HasMember( "title" ) );
        auto expectedTitle = expectedTrack["title"].GetString();
        auto it = std::find_if( begin( tracks ), end( tracks ), [expectedTitle](const MediaPtr& media) {
            return strcasecmp( expectedTitle, media->title().c_str() ) == 0;
        });
        ASSERT_NE( end( tracks ), it );
        const auto track = *it;
        const auto albumTrack = track->albumTrack();
        if ( expectedTrack.HasMember( "number" ) )
        {
            ASSERT_EQ( expectedTrack["number"].GetUint(), albumTrack->trackNumber() );
        }
        const auto trackAlbum = albumTrack->album();
        ASSERT_NE( nullptr, trackAlbum );
        ASSERT_EQ( album->id(), trackAlbum->id() );
    }
}

TEST_P( Tests, Parse )
{
    auto casePath = TestCaseDirectory + "/" + GetParam() + ".json";
    std::unique_ptr<FILE, int(*)(FILE*)> f( fopen( casePath.c_str(), "rb" ), &fclose );
    ASSERT_NE( nullptr, f );
    char buff[65536]; // That's how ugly I am!
    auto ret = fread( buff, sizeof(buff[0]), sizeof(buff), f.get() );
    ASSERT_NE( 0u, ret );
    buff[ret] = 0;
    rapidjson::Document doc;
    doc.Parse( buff );

    ASSERT_TRUE( doc.HasMember( "input" ) );
    const auto& input = doc["input"];
    for ( auto i = 0u; i < input.Size(); ++i )
    {
        // Quick and dirty check to ensure we're discovering something that exists
        auto samplesDir = SamplesDirectory + "/" + input[i].GetString();
        struct stat s;
        auto res = stat( samplesDir.c_str(), &s );
        ASSERT_EQ( 0, res );

        m_ml->discover( samplesDir );
    }
    ASSERT_TRUE( m_cb->waitForParsingComplete() );

    if ( doc.HasMember( "expected" ) == false )
    {
        // That's a lousy test case with no assumptions, but ok.
        return;
    }
    const auto& expected = doc["expected"];

    if ( expected.HasMember( "albums" ) == true )
        checkAlbums( expected["albums" ] );
}

int main(int ac, char** av)
{
    ::testing::InitGoogleTest(&ac, av);
    const std::string samplesArg = "--samples-directory=";
    const std::string testCasesArg = "--testcases-directory=";
    for ( auto i = 1; i < ac; ++i )
    {
        if ( strncmp( samplesArg.c_str(), av[i], samplesArg.length() ) == 0 )
            SamplesDirectory = av[i] + samplesArg.size();
        else if ( strncmp( testCasesArg.c_str(), av[i], testCasesArg.length() ) == 0 )
            TestCaseDirectory = av[i] + testCasesArg.size();
    }
    return RUN_ALL_TESTS();
}

INSTANTIATE_TEST_CASE_P(SamplesTests, Tests,
                        ::testing::ValuesIn(testCases),
                        // gtest default parameter name displayer (testing::PrintToStringParamName)
                        // seems to add " " around the parameter name, making it invalid.
                        [](::testing::TestParamInfo<const char*> i){ return i.param; } );

::testing::Environment* const env = ::testing::AddGlobalTestEnvironment(new TestEnv);
<|endoftext|>


<commit_before>/** Copyright (C) 2018 European Spallation Source */

#include <prototype2/test/TestBase.h>
#include <common/Socket.h>

class SocketTest : public ::testing::Test {
protected:
};

TEST_F(SocketTest, ConstructorValid) {
  Socket udpsocket(Socket::type::UDP);
  ASSERT_TRUE(udpsocket.isValidSocket());

  Socket tcpsocket(Socket::type::TCP);
  ASSERT_TRUE(tcpsocket.isValidSocket());
}

TEST_F(SocketTest, SendUninitialized) {
  char buffer[100];
  Socket udpsocket(Socket::type::UDP);
  ASSERT_TRUE(udpsocket.isValidSocket());
  auto res = udpsocket.send(buffer, 100);
  ASSERT_TRUE(res < 0);
  ASSERT_FALSE(udpsocket.isValidSocket());

  Socket tcpsocket(Socket::type::TCP);
  ASSERT_TRUE(tcpsocket.isValidSocket());
  res = tcpsocket.send(buffer, 100);
  ASSERT_TRUE(res < 0);
  ASSERT_FALSE(tcpsocket.isValidSocket());
}

TEST_F(SocketTest, ValidInvalidIp) {
  std::vector<std::string> ipOk = {"0.0.0.0", "10.10.10.10", "127.0.0.1", "224.1.2.3", "255.255.255.255"};
  std::vector<std::string> ipNotOk = {"a.0.0.0", "1.2.3", "1.2", "", "127.0.0.256", "metrics"};

  for (auto ipaddr : ipOk) {
    ASSERT_TRUE(Socket::isValidIp(ipaddr));
    auto res = Socket::getHostByName(ipaddr);
    ASSERT_TRUE(res == ipaddr);
  }
  for (auto ipaddr : ipNotOk) {
    ASSERT_FALSE(Socket::isValidIp(ipaddr));
  }
}

TEST_F(SocketTest, GetHostByName) {
  std::string name {"localhost"};
  auto res = Socket::getHostByName(name);
  ASSERT_TRUE(res == "127.0.0.1");
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>add weird cornercase - either its a feature or its a bug in gethostbyname()<commit_after>/** Copyright (C) 2018 European Spallation Source */

#include <prototype2/test/TestBase.h>
#include <common/Socket.h>

std::vector<std::string> ipOk = {"0.0.0.0", "10.10.10.10", "127.0.0.1", "224.1.2.3", "255.255.255.255"};
std::vector<std::string> ipNotOk = {"a.0.0.0", "1.2.3", "1.2", "", "127.0.0.256", "metrics"};

class SocketTest : public ::testing::Test {
protected:
};

TEST_F(SocketTest, ConstructorValid) {
  Socket udpsocket(Socket::type::UDP);
  ASSERT_TRUE(udpsocket.isValidSocket());

  Socket tcpsocket(Socket::type::TCP);
  ASSERT_TRUE(tcpsocket.isValidSocket());
}

TEST_F(SocketTest, SendUninitialized) {
  char buffer[100];
  Socket udpsocket(Socket::type::UDP);
  ASSERT_TRUE(udpsocket.isValidSocket());
  auto res = udpsocket.send(buffer, 100);
  ASSERT_TRUE(res < 0);
  ASSERT_FALSE(udpsocket.isValidSocket());

  Socket tcpsocket(Socket::type::TCP);
  ASSERT_TRUE(tcpsocket.isValidSocket());
  res = tcpsocket.send(buffer, 100);
  ASSERT_TRUE(res < 0);
  ASSERT_FALSE(tcpsocket.isValidSocket());
}

TEST_F(SocketTest, ValidInvalidIp) {
  for (auto ipaddr : ipOk) {
    ASSERT_TRUE(Socket::isValidIp(ipaddr));
    auto res = Socket::getHostByName(ipaddr);
    ASSERT_TRUE(res == ipaddr);
  }
  for (auto ipaddr : ipNotOk) {
    ASSERT_FALSE(Socket::isValidIp(ipaddr));
  }
}

TEST_F(SocketTest, GetHostByName) {
  std::string name {"localhost"};
  auto res = Socket::getHostByName(name);
  ASSERT_TRUE(res == "127.0.0.1");
  for (auto ipaddr : ipOk) {
    auto res = Socket::getHostByName(ipaddr);
    ASSERT_TRUE(res == ipaddr);
  }
  // Checking weird case - not sure if this is right
  // this step can be deleted if it causes problems later
  std::string weirdIp {"8.8.8"};
  res = Socket::getHostByName(weirdIp);
  ASSERT_TRUE(res == "8.8.0.8");
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#pragma once

#include <list>
#include <cassert>
#include <unordered_map>

template <typename _Kty, typename _Ty, size_t _Size>
class LRUCache
{
public:
    using value_type = std::pair<const _Kty, _Ty>;

private:
    size_t maxSize_ = _Size;
    std::list<value_type> values_;

public:
    using value_iterator = decltype(values_.begin());
    using mapping_type = std::unordered_map<_Kty, value_iterator>;
    using mapping_iterator = typename mapping_type::iterator;

private:
    mapping_type mapping_;

public:
    LRUCache() = default;
    ~LRUCache() = default;
    LRUCache(const LRUCache&) = delete;
    LRUCache& operator=(const LRUCache&) = delete;
    LRUCache(LRUCache&&) = default;
    LRUCache& operator=(LRUCache&&) = default;

    std::pair<mapping_iterator, bool> insert(const value_type& value)
    {
        static_assert(_Size > 0, "Size must be greater than zero.");

        // Trying to insert dummy value
        auto result = mapping_.insert({ value.first, values_.end() });
        if (result.second == false)
        {
            return std::make_pair(result.first, false);
        }

        // Replace by input value
        values_.push_back(value);
        result.first->second = --values_.end();

        // Erase oldest value
        if (values_.size() > _Size)
        {
            const auto& oldestValue = values_.front();
            mapping_.erase(oldestValue.first);
            values_.pop_front();
        }

        return std::make_pair(result.first, true);
    }

    _Ty& operator[](const _Kty& key)
    {
        auto it = mapping_.find(key);
        if (it != mapping_.cend())
        {
            return it->second->second;
        }
        auto result = insert({ key , _Ty{} });
        return result.first->second->second;
    }

    size_t size() const
    {
        assert(values_.size() == mapping_.size());
        return values_.size();
    }

    bool empty() const
    {
        return values_.empty();
    }
};
<commit_msg>Implement clear method<commit_after>#pragma once

#include <list>
#include <cassert>
#include <unordered_map>

template <typename _Kty, typename _Ty, size_t _Size>
class LRUCache
{
public:
    using value_type = std::pair<const _Kty, _Ty>;

private:
    size_t maxSize_ = _Size;
    std::list<value_type> values_;

public:
    using value_iterator = decltype(values_.begin());
    using mapping_type = std::unordered_map<_Kty, value_iterator>;
    using mapping_iterator = typename mapping_type::iterator;

private:
    mapping_type mapping_;

public:
    LRUCache() = default;
    ~LRUCache() = default;
    LRUCache(const LRUCache&) = delete;
    LRUCache& operator=(const LRUCache&) = delete;
    LRUCache(LRUCache&&) = default;
    LRUCache& operator=(LRUCache&&) = default;

    std::pair<mapping_iterator, bool> insert(const value_type& value)
    {
        static_assert(_Size > 0, "Size must be greater than zero.");

        // Trying to insert dummy value
        auto result = mapping_.insert({ value.first, values_.end() });
        if (result.second == false)
        {
            return std::make_pair(result.first, false);
        }

        // Replace by input value
        values_.push_back(value);
        result.first->second = --values_.end();

        // Erase oldest value
        if (values_.size() > _Size)
        {
            const auto& oldestValue = values_.front();
            mapping_.erase(oldestValue.first);
            values_.pop_front();
        }

        return std::make_pair(result.first, true);
    }

    _Ty& operator[](const _Kty& key)
    {
        auto it = mapping_.find(key);
        if (it != mapping_.cend())
        {
            return it->second->second;
        }
        auto result = insert({ key , _Ty{} });
        return result.first->second->second;
    }

    size_t size() const
    {
        assert(values_.size() == mapping_.size());
        return values_.size();
    }

    bool empty() const
    {
        return values_.empty();
    }

    void clear()
    {
        values_.clear();
        mapping_.clear();
    }
};
<|endoftext|>