<commit_before>#ifndef DUNE_STUFF_TUPLE_HH
#define DUNE_STUFF_TUPLE_HH

#include <dune/common/tuples.hh>
#include <dune/common/typetraits.hh>

#define TMAX( t_, no_ ) (Dune::tuple_size<t_>::value <= (no_+1) ? 0 : no_)
#define TELE(t_,s_,no_) typename Dune::tuple_element< TMAX(t_,no_),t_>::type::s_
#define TCOND(t_,no_) (Dune::tuple_size<t_>::value <= no_)
#define TUPLE_TYPEDEFS_2_TUPLE( t_, s_ ) \
    typename Dune::SelectType< TCOND(t_,1), Dune::tuple< TELE(t_,s_,0) >, \
    typename Dune::SelectType< TCOND(t_,2), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1) >,  \
    typename Dune::SelectType< TCOND(t_,3), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2) >,  \
    typename Dune::SelectType< TCOND(t_,4), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3) >, \
    typename Dune::SelectType< TCOND(t_,5), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4) >, \
    typename Dune::SelectType< TCOND(t_,6), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5) >,  \
    typename Dune::SelectType< TCOND(t_,7), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6) >,  \
    typename Dune::SelectType< TCOND(t_,8), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6), TELE(t_,s_,7) >,  \
    typename Dune::SelectType< TCOND(t_,9), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6), TELE(t_,s_,7), TELE(t_,s_,8) >,  \
                                      Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6), TELE(t_,s_,7), TELE(t_,s_,8) > \
                                        >::Type>::Type>::Type>::Type>::Type>::Type>::Type>::Type>::Type
/**
 * @def TUPLE_TYPEDEFS_2_TUPLE( t_, s_ )
 *
 * @brief extracts types of the elements of a Dune::tuple and
 * creates a new Dune::tuple with these extracted types.
 *
 * first argument: the tuple type
 * second argument: the typedef of the elements of the tuple
 *
 * example:
 * Let two classes be given:
 *
 * @code
 * class A
 * {
 *   public:
 *   typedef int MyFancyType;
 * };
 *
 * class B
 * {
 *   public:
 *   typedef int MyFancyType;
 * };
 * @endcode
 *
 * Define a tuple, i.e.
 *
 * @code
 * typedef Dune::tuple< A, B, B >
 *   MyTuple;
 * @endcode
 *
 * Instead of writing
 *
 * @code
 * typedef Dune::tuple< typename tuple_element<0,MyTuple>::type::MyFancyType,
 *                      typename tuple_element<1,MyTuple>::type::MyFancyType,
 *                      typename tuple_element<2,MyTuple>::type::MyFancyType >
 *   MySubTupleType;
 * @endcode
 *
 * just write
 *
 * @code
 * typedef TUPLE_TYPEDEFS_2_TUPLE( MyTuple, MyFancyType )
 *   MySubTupleType;
 * @endcode
 *
 * without (general) restriction to the size
 * of the tuple @c MyTuple. Enjoy it!
 */

namespace Dune {
namespace Stuff {
namespace Common {

  //! split our function wrapper into sep pointers for Datawriter input
template< class T1, class T2 = T1, class T3 = T2, class T4 = T3 >
struct TupleSerializer
{
  typedef Dune::tuple< const typename T1::DiscreteVelocityFunctionType*,
                       const typename T1::DiscretePressureFunctionType*,
                       const typename T2::DiscreteVelocityFunctionType*,
                       const typename T2::DiscretePressureFunctionType*,
                       const typename T3::DiscreteVelocityFunctionType*,
                       const typename T3::DiscretePressureFunctionType*,
                       const typename T4::DiscreteVelocityFunctionType*,
                       const typename T4::DiscretePressureFunctionType* >
  TupleType;

  static TupleType& getTuple(T1& t1,
                             T2& t2,
                             T3& t3,
                             T4& t4) {
    // yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
    TupleType* t = new  TupleType( &( t1.discreteVelocity() ),
                                   &( t1.discretePressure() ),
                                   &( t2.discreteVelocity() ),
                                   &( t2.discretePressure() ),
                                   &( t3.discreteVelocity() ),
                                   &( t3.discretePressure() ),
                                   &( t4.discreteVelocity() ),
                                   &( t4.discretePressure() ) );

    return *t;
  } // getTuple

  static TupleType& getTuple(T1& t1,
                             T2& t2,
                             T3& t3) {
    // yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
    TupleType* t = new  TupleType(&( t1.discreteVelocity() ),
                                  &( t1.discretePressure() ),
                                  &( t2.discreteVelocity() ),
                                  &( t2.discretePressure() ),
                                  &( t3.discreteVelocity() ),
                                  &( t3.discretePressure() ),
                                  nullptr, nullptr);

    return *t;
  } // getTuple

  static TupleType& getTuple(T1& t1,
                             T2& t2) {
    // yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
    TupleType* t = new  TupleType(&( t1.discreteVelocity() ),
                                  &( t1.discretePressure() ),
                                  &( t2.discreteVelocity() ),
                                  &( t2.discretePressure() ),
                                  nullptr, nullptr, nullptr, nullptr);

    return *t;
  } // getTuple

  static TupleType& getTuple(T1& t1) {
    // yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
    TupleType* t = new  TupleType(&( t1.discreteVelocity() ),
                                  &( t1.discretePressure() ),
                                  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);

    return *t;
  } // getTuple
};

template< class T1, class T2 = T1, class T3 = T1,
          class T4 = T1, class T5 = T1, class T6 = T1,
          class T7 = T1, class T8 = T1, class T9 = T1 >
struct FullTuple
  : public Dune::tuple< T1, T2, T3, T4, T5, T6, T7, T8, T9 >
{
  FullTuple(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
    : Dune::tuple< T1, T2, T3, T4, T5, T6, T7, T8, T9 >(t1, t2, t3, t4, t5, t6, t7, t8, t9)
  {}
};

} // namespace Common
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_TUPLE_HH

/** Copyright (c) 2012, Rene Milk, Stefan Girke
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of source code must retain the above copyright notice, this
   *    list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright notice,
   *    this list of conditions and the following disclaimer in the documentation
   *    and/or other materials provided with the distribution.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * The views and conclusions contained in the software and documentation are those
   * of the authors and should not be interpreted as representing official policies,
   * either expressed or implied, of the FreeBSD Project.
   **/
<commit_msg>Added a new implementation for TUPLE_TYPEDEFS_2_TUPLE. This should be more compiler friendly for huge tuples, I hope... Only 8 tuple elements at the moment.<commit_after>#ifndef DUNE_STUFF_TUPLE_HH
#define DUNE_STUFF_TUPLE_HH

#include <dune/common/tuples.hh>
#include <dune/common/typetraits.hh>

//uncomment if you want to use a more(?) optimized version
//#define NEWTUPLE_TYPEDEFS_2_TUPLE

#ifndef NEWTUPLE_TYPEDEFS_2_TUPLE

/////// old version

#define TMAX( t_, no_ ) (Dune::tuple_size<t_>::value <= (no_+1) ? 0 : no_)
#define TELE(t_,s_,no_) typename Dune::tuple_element< TMAX(t_,no_),t_>::type::s_
#define TCOND(t_,no_) (Dune::tuple_size<t_>::value <= no_)
#define TUPLE_TYPEDEFS_2_TUPLE( t_, s_ ) \
    typename Dune::SelectType< TCOND(t_,1), Dune::tuple< TELE(t_,s_,0) >, \
    typename Dune::SelectType< TCOND(t_,2), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1) >,  \
    typename Dune::SelectType< TCOND(t_,3), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2) >,  \
    typename Dune::SelectType< TCOND(t_,4), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3) >, \
    typename Dune::SelectType< TCOND(t_,5), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4) >, \
    typename Dune::SelectType< TCOND(t_,6), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5) >,  \
    typename Dune::SelectType< TCOND(t_,7), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6) >,  \
    typename Dune::SelectType< TCOND(t_,8), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6), TELE(t_,s_,7) >,  \
    typename Dune::SelectType< TCOND(t_,9), Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6), TELE(t_,s_,7), TELE(t_,s_,8) >,  \
                                      Dune::tuple< TELE(t_,s_,0), TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6), TELE(t_,s_,7), TELE(t_,s_,8) > \
                                        >::Type>::Type>::Type>::Type>::Type>::Type>::Type>::Type>::Type

#else

////// new version

struct NoElement{};
#define TMAX( t_, no_ ) (Dune::tuple_size<t_>::value <= (no_+1) ? Dune::tuple_size<t_>::value  : no_)
#define TELE(t_,s_,no_) typename Dune::tuple_element< TMAX(t_,no_), typename Dune::PushFrontTuple<t_,NoElement>::type >::type
#define TCOND(t_,no_) (Dune::tuple_size<t_>::value <= no_)

template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8 >
struct RightTrimTuple
{ typedef Dune::tuple<T1,T2,T3,T4,T5,T6,T7,T8> type; };

template< class T1 >
struct RightTrimTuple<  T1, NoElement, NoElement, NoElement, NoElement, NoElement, NoElement, NoElement >
{	typedef Dune::tuple<T1> type; };

template< class T1, class T2 >
struct RightTrimTuple< T1, T2, NoElement, NoElement, NoElement, NoElement, NoElement, NoElement >
{ typedef Dune::tuple<T1, T2> type; };

template< class T1, class T2, class T3 >
struct RightTrimTuple< T1, T2, T3, NoElement, NoElement, NoElement, NoElement, NoElement >
{ typedef Dune::tuple<T1,T2,T3> type; };

template< class T1, class T2, class T3, class T4 >
struct RightTrimTuple< T1, T2, T3, T4, NoElement, NoElement, NoElement, NoElement >
{ typedef Dune::tuple<T1,T2,T3,T4> type; };

template< class T1, class T2, class T3, class T4, class T5 >
struct RightTrimTuple< T1, T2, T3, T4, T5, NoElement, NoElement, NoElement >
{ typedef Dune::tuple<T1,T2,T3,T4,T5> type; };

template< class T1, class T2, class T3, class T4, class T5, class T6 >
struct RightTrimTuple< T1, T2, T3, T4, T5, T6, NoElement, NoElement >
{ typedef Dune::tuple<T1,T2,T3,T4,T5,T6> type; };

template< class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
struct RightTrimTuple< T1, T2, T3, T4, T5, T6, T7, NoElement >
{ typedef Dune::tuple<T1,T2,T3,T4,T5,T6,T7> type; };

#define TUPLE_TYPEDEFS_2_TUPLE( t_, s_ ) \
  typename RightTrimTuple< TELE(t_,s_,1), TELE(t_,s_,2), TELE(t_,s_,3), TELE(t_,s_,4), TELE(t_,s_,5), TELE(t_,s_,6), TELE(t_,s_,7), TEL(t_,s_,8) >::type

#endif
/**
 * @def TUPLE_TYPEDEFS_2_TUPLE( t_, s_ )
 *
 * @brief extracts types of the elements of a Dune::tuple and
 * creates a new Dune::tuple with these extracted types.
 *
 * first argument: the tuple type
 * second argument: the typedef of the elements of the tuple
 *
 * example:
 * Let two classes be given:
 *
 * @code
 * class A
 * {
 *   public:
 *   typedef int MyFancyType;
 * };
 *
 * class B
 * {
 *   public:
 *   typedef int MyFancyType;
 * };
 * @endcode
 *
 * Define a tuple, i.e.
 *
 * @code
 * typedef Dune::tuple< A, B, B >
 *   MyTuple;
 * @endcode
 *
 * Instead of writing
 *
 * @code
 * typedef Dune::tuple< typename tuple_element<0,MyTuple>::type::MyFancyType,
 *                      typename tuple_element<1,MyTuple>::type::MyFancyType,
 *                      typename tuple_element<2,MyTuple>::type::MyFancyType >
 *   MySubTupleType;
 * @endcode
 *
 * just write
 *
 * @code
 * typedef TUPLE_TYPEDEFS_2_TUPLE( MyTuple, MyFancyType )
 *   MySubTupleType;
 * @endcode
 *
 * without (general) restriction to the size
 * of the tuple @c MyTuple. Enjoy it!
 */

namespace Dune {
namespace Stuff {
namespace Common {

  //! split our function wrapper into sep pointers for Datawriter input
template< class T1, class T2 = T1, class T3 = T2, class T4 = T3 >
struct TupleSerializer
{
  typedef Dune::tuple< const typename T1::DiscreteVelocityFunctionType*,
                       const typename T1::DiscretePressureFunctionType*,
                       const typename T2::DiscreteVelocityFunctionType*,
                       const typename T2::DiscretePressureFunctionType*,
                       const typename T3::DiscreteVelocityFunctionType*,
                       const typename T3::DiscretePressureFunctionType*,
                       const typename T4::DiscreteVelocityFunctionType*,
                       const typename T4::DiscretePressureFunctionType* >
  TupleType;

  static TupleType& getTuple(T1& t1,
                             T2& t2,
                             T3& t3,
                             T4& t4) {
    // yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
    TupleType* t = new  TupleType( &( t1.discreteVelocity() ),
                                   &( t1.discretePressure() ),
                                   &( t2.discreteVelocity() ),
                                   &( t2.discretePressure() ),
                                   &( t3.discreteVelocity() ),
                                   &( t3.discretePressure() ),
                                   &( t4.discreteVelocity() ),
                                   &( t4.discretePressure() ) );

    return *t;
  } // getTuple

  static TupleType& getTuple(T1& t1,
                             T2& t2,
                             T3& t3) {
    // yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
    TupleType* t = new  TupleType(&( t1.discreteVelocity() ),
                                  &( t1.discretePressure() ),
                                  &( t2.discreteVelocity() ),
                                  &( t2.discretePressure() ),
                                  &( t3.discreteVelocity() ),
                                  &( t3.discretePressure() ),
                                  nullptr, nullptr);

    return *t;
  } // getTuple

  static TupleType& getTuple(T1& t1,
                             T2& t2) {
    // yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
    TupleType* t = new  TupleType(&( t1.discreteVelocity() ),
                                  &( t1.discretePressure() ),
                                  &( t2.discreteVelocity() ),
                                  &( t2.discretePressure() ),
                                  nullptr, nullptr, nullptr, nullptr);

    return *t;
  } // getTuple

  static TupleType& getTuple(T1& t1) {
    // yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
    TupleType* t = new  TupleType(&( t1.discreteVelocity() ),
                                  &( t1.discretePressure() ),
                                  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);

    return *t;
  } // getTuple
};

template< class T1, class T2 = T1, class T3 = T1,
          class T4 = T1, class T5 = T1, class T6 = T1,
          class T7 = T1, class T8 = T1, class T9 = T1 >
struct FullTuple
  : public Dune::tuple< T1, T2, T3, T4, T5, T6, T7, T8, T9 >
{
  FullTuple(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
    : Dune::tuple< T1, T2, T3, T4, T5, T6, T7, T8, T9 >(t1, t2, t3, t4, t5, t6, t7, t8, t9)
  {}
};

} // namespace Common
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_TUPLE_HH

/** Copyright (c) 2012, Rene Milk, Stefan Girke
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of source code must retain the above copyright notice, this
   *    list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright notice,
   *    this list of conditions and the following disclaimer in the documentation
   *    and/or other materials provided with the distribution.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * The views and conclusions contained in the software and documentation are those
   * of the authors and should not be interpreted as representing official policies,
   * either expressed or implied, of the FreeBSD Project.
   **/
<|endoftext|>


<commit_before>/*
 * GPUOdroid.cpp
 *
 *  Created on: 1 Feb, 2015
 *      Author: yeokm1
 */

#include <gpu/GPUOdroid.h>

#define FILE_GPU_UTIL "/sys/module/pvrsrvkm/parameters/sgx_gpu_utilization"
#define FILE_GPU_CURRENT_FREQ "/sys/devices/platform/pvrsrvkm.0/sgx_dvfs_cur_clk"
#define FILE_GPU_MIN_FREQ "/sys/devices/platform/pvrsrvkm.0/sgx_dvfs_min_lock"
#define FILE_GPU_MAX_FREQ "/sys/devices/platform/pvrsrvkm.0/sgx_dvfs_max_lock"
#define FILE_GPU_AVAILABLE_FREQS "/sys/devices/platform/pvrsrvkm.0/sgx_dvfs_table"

GPUOdroid::GPUOdroid() {
	// TODO Auto-generated constructor stub

	initGPUFreqValues();
	setGPUFreq(0);

}

GPUOdroid::~GPUOdroid() {
	void initGPUFreqValues();
}

void GPUOdroid::initGPUFreqValues(){
	//Do nothing here
}

void GPUOdroid::setGPUFreq(int position){
	//Do nothing here
}

<commit_msg>don't anyhow declare functions<commit_after>/*
 * GPUOdroid.cpp
 *
 *  Created on: 1 Feb, 2015
 *      Author: yeokm1
 */

#include <gpu/GPUOdroid.h>

#define FILE_GPU_UTIL "/sys/module/pvrsrvkm/parameters/sgx_gpu_utilization"
#define FILE_GPU_CURRENT_FREQ "/sys/devices/platform/pvrsrvkm.0/sgx_dvfs_cur_clk"
#define FILE_GPU_MIN_FREQ "/sys/devices/platform/pvrsrvkm.0/sgx_dvfs_min_lock"
#define FILE_GPU_MAX_FREQ "/sys/devices/platform/pvrsrvkm.0/sgx_dvfs_max_lock"
#define FILE_GPU_AVAILABLE_FREQS "/sys/devices/platform/pvrsrvkm.0/sgx_dvfs_table"

GPUOdroid::GPUOdroid() {
	// TODO Auto-generated constructor stub

	initGPUFreqValues();
	setGPUFreq(0);

}

GPUOdroid::~GPUOdroid() {
}

void GPUOdroid::initGPUFreqValues(){
	//Do nothing here
}

void GPUOdroid::setGPUFreq(int position){
	//Do nothing here
}

<|endoftext|>


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

#include <folly/Singleton.h>

#ifndef _WIN32
#include <dlfcn.h>
#endif

#include <atomic>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>

#include <folly/ScopeGuard.h>

#if !defined(_WIN32) && !defined(__APPLE__)
static void hs_init_weak(int* argc, char** argv[])
    __attribute__((__weakref__("hs_init")));
#endif

namespace folly {

SingletonVault::Type SingletonVault::defaultVaultType() {
#if !defined(_WIN32) && !defined(__APPLE__)
  bool isPython = dlsym(RTLD_DEFAULT, "Py_Main");
  bool isHaskel = &::hs_init_weak || dlsym(RTLD_DEFAULT, "hs_init");
  bool isJVM = dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs");
  bool isD = dlsym(RTLD_DEFAULT, "_d_run_main");

  return isPython || isHaskel || isJVM || isD ? Type::Relaxed : Type::Strict;
#else
  return Type::Relaxed;
#endif
}

namespace detail {

[[noreturn]] void singletonWarnDoubleRegistrationAndAbort(
    const TypeDescriptor& type) {
  // Ensure the availability of std::cerr
  std::ios_base::Init ioInit;
  std::cerr << "Double registration of singletons of the same "
               "underlying type; check for multiple definitions "
               "of type folly::Singleton<"
            << type.name() << ">\n";
  std::abort();
}
}

namespace {

struct FatalHelper {
  ~FatalHelper() {
    if (!leakedSingletons_.empty()) {
      std::string leakedTypes;
      for (const auto& singleton : leakedSingletons_) {
        leakedTypes += "\t" + singleton.name() + "\n";
      }
      LOG(DFATAL) << "Singletons of the following types had living references "
                  << "after destroyInstances was finished:\n" << leakedTypes
                  << "beware! It is very likely that those singleton instances "
                  << "are leaked.";
    }
  }

  std::vector<detail::TypeDescriptor> leakedSingletons_;
};

#if defined(__APPLE__) || defined(_MSC_VER)
// OS X doesn't support constructor priorities.
FatalHelper fatalHelper;
#else
FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper;
#endif

}

SingletonVault::~SingletonVault() { destroyInstances(); }

void SingletonVault::registerSingleton(detail::SingletonHolderBase* entry) {
  auto state = state_.rlock();
  stateCheck(SingletonVaultState::Running, *state);

  if (UNLIKELY(state->registrationComplete)) {
    LOG(ERROR) << "Registering singleton after registrationComplete().";
  }

  auto singletons = singletons_.wlock();
  CHECK_THROW(
      singletons->emplace(entry->type(), entry).second, std::logic_error);
}

void SingletonVault::addEagerInitSingleton(detail::SingletonHolderBase* entry) {
  auto state = state_.rlock();
  stateCheck(SingletonVaultState::Running, *state);

  if (UNLIKELY(state->registrationComplete)) {
    LOG(ERROR) << "Registering for eager-load after registrationComplete().";
  }

  CHECK_THROW(singletons_.rlock()->count(entry->type()), std::logic_error);

  auto eagerInitSingletons = eagerInitSingletons_.wlock();
  eagerInitSingletons->insert(entry);
}

void SingletonVault::registrationComplete() {
  std::atexit([](){ SingletonVault::singleton()->destroyInstances(); });

  auto state = state_.wlock();
  stateCheck(SingletonVaultState::Running, *state);

  if (state->registrationComplete) {
    return;
  }

  auto singletons = singletons_.rlock();
  if (type_ == Type::Strict) {
    for (const auto& p : *singletons) {
      if (p.second->hasLiveInstance()) {
        throw std::runtime_error(
            "Singleton " + p.first.name() +
            " created before registration was complete.");
      }
    }
  }

  state->registrationComplete = true;
}

void SingletonVault::doEagerInit() {
  {
    auto state = state_.rlock();
    stateCheck(SingletonVaultState::Running, *state);
    if (UNLIKELY(!state->registrationComplete)) {
      throw std::logic_error("registrationComplete() not yet called");
    }
  }

  auto eagerInitSingletons = eagerInitSingletons_.rlock();
  for (auto* single : *eagerInitSingletons) {
    single->createInstance();
  }
}

void SingletonVault::doEagerInitVia(Executor& exe, folly::Baton<>* done) {
  {
    auto state = state_.rlock();
    stateCheck(SingletonVaultState::Running, *state);
    if (UNLIKELY(!state->registrationComplete)) {
      throw std::logic_error("registrationComplete() not yet called");
    }
  }

  auto eagerInitSingletons = eagerInitSingletons_.rlock();
  auto countdown =
      std::make_shared<std::atomic<size_t>>(eagerInitSingletons->size());
  for (auto* single : *eagerInitSingletons) {
    // countdown is retained by shared_ptr, and will be alive until last lambda
    // is done.  notifyBaton is provided by the caller, and expected to remain
    // present (if it's non-nullptr).  singletonSet can go out of scope but
    // its values, which are SingletonHolderBase pointers, are alive as long as
    // SingletonVault is not being destroyed.
    exe.add([=] {
      // decrement counter and notify if requested, whether initialization
      // was successful, was skipped (already initialized), or exception thrown.
      SCOPE_EXIT {
        if (--(*countdown) == 0) {
          if (done != nullptr) {
            done->post();
          }
        }
      };
      // if initialization is in progress in another thread, don't try to init
      // here.  Otherwise the current thread will block on 'createInstance'.
      if (!single->creationStarted()) {
        single->createInstance();
      }
    });
  }
}

void SingletonVault::destroyInstances() {
  auto stateW = state_.wlock();
  if (stateW->state == SingletonVaultState::Quiescing) {
    return;
  }
  stateW->state = SingletonVaultState::Quiescing;

  auto stateR = stateW.moveFromWriteToRead();
  {
    auto singletons = singletons_.rlock();
    auto creationOrder = creationOrder_.rlock();

    CHECK_GE(singletons->size(), creationOrder->size());

    // Release all ReadMostlyMainPtrs at once
    {
      ReadMostlyMainPtrDeleter<> deleter;
      for (auto& singleton_type : *creationOrder) {
        singletons->at(singleton_type)->preDestroyInstance(deleter);
      }
    }

    for (auto type_iter = creationOrder->rbegin();
         type_iter != creationOrder->rend();
         ++type_iter) {
      singletons->at(*type_iter)->destroyInstance();
    }

    for (auto& singleton_type : *creationOrder) {
      auto singleton = singletons->at(singleton_type);
      if (!singleton->hasLiveInstance()) {
        continue;
      }

      fatalHelper.leakedSingletons_.push_back(singleton->type());
    }
  }

  {
    auto creationOrder = creationOrder_.wlock();
    creationOrder->clear();
  }
}

void SingletonVault::reenableInstances() {
  auto state = state_.wlock();

  stateCheck(SingletonVaultState::Quiescing, *state);

  state->state = SingletonVaultState::Running;
}

void SingletonVault::scheduleDestroyInstances() {
  // Add a dependency on folly::ThreadLocal to make sure all its static
  // singletons are initalized first.
  threadlocal_detail::StaticMeta<void, void>::instance();

  class SingletonVaultDestructor {
   public:
    ~SingletonVaultDestructor() {
      SingletonVault::singleton()->destroyInstances();
    }
  };

  // Here we intialize a singleton, which calls destroyInstances in its
  // destructor. Because of singleton destruction order - it will be destroyed
  // before all the singletons, which were initialized before it and after all
  // the singletons initialized after it.
  static SingletonVaultDestructor singletonVaultDestructor;
}

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

#include <folly/Singleton.h>

#ifndef _WIN32
#include <dlfcn.h>
#endif

#include <atomic>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>

#include <folly/ScopeGuard.h>

#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__ANDROID__)
static void hs_init_weak(int* argc, char** argv[])
    __attribute__((__weakref__("hs_init")));
#endif

namespace folly {

SingletonVault::Type SingletonVault::defaultVaultType() {
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__ANDROID__)
  bool isPython = dlsym(RTLD_DEFAULT, "Py_Main");
  bool isHaskel = &::hs_init_weak || dlsym(RTLD_DEFAULT, "hs_init");
  bool isJVM = dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs");
  bool isD = dlsym(RTLD_DEFAULT, "_d_run_main");

  return isPython || isHaskel || isJVM || isD ? Type::Relaxed : Type::Strict;
#else
  return Type::Relaxed;
#endif
}

namespace detail {

[[noreturn]] void singletonWarnDoubleRegistrationAndAbort(
    const TypeDescriptor& type) {
  // Ensure the availability of std::cerr
  std::ios_base::Init ioInit;
  std::cerr << "Double registration of singletons of the same "
               "underlying type; check for multiple definitions "
               "of type folly::Singleton<"
            << type.name() << ">\n";
  std::abort();
}
}

namespace {

struct FatalHelper {
  ~FatalHelper() {
    if (!leakedSingletons_.empty()) {
      std::string leakedTypes;
      for (const auto& singleton : leakedSingletons_) {
        leakedTypes += "\t" + singleton.name() + "\n";
      }
      LOG(DFATAL) << "Singletons of the following types had living references "
                  << "after destroyInstances was finished:\n" << leakedTypes
                  << "beware! It is very likely that those singleton instances "
                  << "are leaked.";
    }
  }

  std::vector<detail::TypeDescriptor> leakedSingletons_;
};

#if defined(__APPLE__) || defined(_MSC_VER)
// OS X doesn't support constructor priorities.
FatalHelper fatalHelper;
#else
FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper;
#endif

}

SingletonVault::~SingletonVault() { destroyInstances(); }

void SingletonVault::registerSingleton(detail::SingletonHolderBase* entry) {
  auto state = state_.rlock();
  stateCheck(SingletonVaultState::Running, *state);

  if (UNLIKELY(state->registrationComplete)) {
    LOG(ERROR) << "Registering singleton after registrationComplete().";
  }

  auto singletons = singletons_.wlock();
  CHECK_THROW(
      singletons->emplace(entry->type(), entry).second, std::logic_error);
}

void SingletonVault::addEagerInitSingleton(detail::SingletonHolderBase* entry) {
  auto state = state_.rlock();
  stateCheck(SingletonVaultState::Running, *state);

  if (UNLIKELY(state->registrationComplete)) {
    LOG(ERROR) << "Registering for eager-load after registrationComplete().";
  }

  CHECK_THROW(singletons_.rlock()->count(entry->type()), std::logic_error);

  auto eagerInitSingletons = eagerInitSingletons_.wlock();
  eagerInitSingletons->insert(entry);
}

void SingletonVault::registrationComplete() {
  std::atexit([](){ SingletonVault::singleton()->destroyInstances(); });

  auto state = state_.wlock();
  stateCheck(SingletonVaultState::Running, *state);

  if (state->registrationComplete) {
    return;
  }

  auto singletons = singletons_.rlock();
  if (type_ == Type::Strict) {
    for (const auto& p : *singletons) {
      if (p.second->hasLiveInstance()) {
        throw std::runtime_error(
            "Singleton " + p.first.name() +
            " created before registration was complete.");
      }
    }
  }

  state->registrationComplete = true;
}

void SingletonVault::doEagerInit() {
  {
    auto state = state_.rlock();
    stateCheck(SingletonVaultState::Running, *state);
    if (UNLIKELY(!state->registrationComplete)) {
      throw std::logic_error("registrationComplete() not yet called");
    }
  }

  auto eagerInitSingletons = eagerInitSingletons_.rlock();
  for (auto* single : *eagerInitSingletons) {
    single->createInstance();
  }
}

void SingletonVault::doEagerInitVia(Executor& exe, folly::Baton<>* done) {
  {
    auto state = state_.rlock();
    stateCheck(SingletonVaultState::Running, *state);
    if (UNLIKELY(!state->registrationComplete)) {
      throw std::logic_error("registrationComplete() not yet called");
    }
  }

  auto eagerInitSingletons = eagerInitSingletons_.rlock();
  auto countdown =
      std::make_shared<std::atomic<size_t>>(eagerInitSingletons->size());
  for (auto* single : *eagerInitSingletons) {
    // countdown is retained by shared_ptr, and will be alive until last lambda
    // is done.  notifyBaton is provided by the caller, and expected to remain
    // present (if it's non-nullptr).  singletonSet can go out of scope but
    // its values, which are SingletonHolderBase pointers, are alive as long as
    // SingletonVault is not being destroyed.
    exe.add([=] {
      // decrement counter and notify if requested, whether initialization
      // was successful, was skipped (already initialized), or exception thrown.
      SCOPE_EXIT {
        if (--(*countdown) == 0) {
          if (done != nullptr) {
            done->post();
          }
        }
      };
      // if initialization is in progress in another thread, don't try to init
      // here.  Otherwise the current thread will block on 'createInstance'.
      if (!single->creationStarted()) {
        single->createInstance();
      }
    });
  }
}

void SingletonVault::destroyInstances() {
  auto stateW = state_.wlock();
  if (stateW->state == SingletonVaultState::Quiescing) {
    return;
  }
  stateW->state = SingletonVaultState::Quiescing;

  auto stateR = stateW.moveFromWriteToRead();
  {
    auto singletons = singletons_.rlock();
    auto creationOrder = creationOrder_.rlock();

    CHECK_GE(singletons->size(), creationOrder->size());

    // Release all ReadMostlyMainPtrs at once
    {
      ReadMostlyMainPtrDeleter<> deleter;
      for (auto& singleton_type : *creationOrder) {
        singletons->at(singleton_type)->preDestroyInstance(deleter);
      }
    }

    for (auto type_iter = creationOrder->rbegin();
         type_iter != creationOrder->rend();
         ++type_iter) {
      singletons->at(*type_iter)->destroyInstance();
    }

    for (auto& singleton_type : *creationOrder) {
      auto singleton = singletons->at(singleton_type);
      if (!singleton->hasLiveInstance()) {
        continue;
      }

      fatalHelper.leakedSingletons_.push_back(singleton->type());
    }
  }

  {
    auto creationOrder = creationOrder_.wlock();
    creationOrder->clear();
  }
}

void SingletonVault::reenableInstances() {
  auto state = state_.wlock();

  stateCheck(SingletonVaultState::Quiescing, *state);

  state->state = SingletonVaultState::Running;
}

void SingletonVault::scheduleDestroyInstances() {
  // Add a dependency on folly::ThreadLocal to make sure all its static
  // singletons are initalized first.
  threadlocal_detail::StaticMeta<void, void>::instance();

  class SingletonVaultDestructor {
   public:
    ~SingletonVaultDestructor() {
      SingletonVault::singleton()->destroyInstances();
    }
  };

  // Here we intialize a singleton, which calls destroyInstances in its
  // destructor. Because of singleton destruction order - it will be destroyed
  // before all the singletons, which were initialized before it and after all
  // the singletons initialized after it.
  static SingletonVaultDestructor singletonVaultDestructor;
}

}
<|endoftext|>


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

#include "cyber/scheduler/policy/scheduler_choreography.h"

#include <memory>
#include <string>
#include <utility>

#include "cyber/common/environment.h"
#include "cyber/common/file.h"
#include "cyber/scheduler/policy/choreography_context.h"
#include "cyber/scheduler/policy/classic_context.h"
#include "cyber/scheduler/processor.h"

namespace apollo {
namespace cyber {
namespace scheduler {

using apollo::cyber::base::AtomicRWLock;
using apollo::cyber::base::ReadLockGuard;
using apollo::cyber::base::WriteLockGuard;
using apollo::cyber::common::GetAbsolutePath;
using apollo::cyber::common::GetProtoFromFile;
using apollo::cyber::common::GlobalData;
using apollo::cyber::common::PathExists;
using apollo::cyber::common::WorkRoot;
using apollo::cyber::croutine::RoutineState;

SchedulerChoreography::SchedulerChoreography() {
  std::string conf("conf/");
  conf.append(GlobalData::Instance()->ProcessGroup()).append(".conf");
  auto cfg_file = GetAbsolutePath(WorkRoot(), conf);

  apollo::cyber::proto::CyberConfig cfg;
  if (PathExists(cfg_file) && GetProtoFromFile(cfg_file, &cfg)) {
    for (auto& thr : cfg.scheduler_conf().threads()) {
      inner_thr_confs_[thr.name()] = thr;
    }

    if (cfg.scheduler_conf().has_process_level_cpuset()) {
      process_level_cpuset_ = cfg.scheduler_conf().process_level_cpuset();
      ProcessLevelResourceControl();
    }

    const apollo::cyber::proto::ChoreographyConf& choreography_conf =
        cfg.scheduler_conf().choreography_conf();
    proc_num_ = choreography_conf.choreography_processor_num();
    choreography_affinity_ = choreography_conf.choreography_affinity();
    choreography_processor_policy_ =
        choreography_conf.choreography_processor_policy();

    choreography_processor_prio_ =
        choreography_conf.choreography_processor_prio();
    ParseCpuset(choreography_conf.choreography_cpuset(), &choreography_cpuset_);

    task_pool_size_ = choreography_conf.pool_processor_num();
    pool_affinity_ = choreography_conf.pool_affinity();
    pool_processor_policy_ = choreography_conf.pool_processor_policy();
    pool_processor_prio_ = choreography_conf.pool_processor_prio();
    ParseCpuset(choreography_conf.pool_cpuset(), &pool_cpuset_);

    for (const auto& task : choreography_conf.tasks()) {
      cr_confs_[task.name()] = task;
    }
  }

  if (proc_num_ == 0) {
    auto& global_conf = GlobalData::Instance()->Config();
    if (global_conf.has_scheduler_conf() &&
        global_conf.scheduler_conf().has_default_proc_num()) {
      proc_num_ = global_conf.scheduler_conf().default_proc_num();
    } else {
      proc_num_ = 2;
    }
    task_pool_size_ = proc_num_;
  }

  CreateProcessor();
}

void SchedulerChoreography::CreateProcessor() {
  for (uint32_t i = 0; i < proc_num_; i++) {
    auto proc = std::make_shared<Processor>();
    auto ctx = std::make_shared<ChoreographyContext>();

    proc->BindContext(ctx);
    SetSchedAffinity(proc->Thread(), choreography_cpuset_,
                     choreography_affinity_, i);
    SetSchedPolicy(proc->Thread(), choreography_processor_policy_,
                   choreography_processor_prio_, proc->Tid());
    pctxs_.emplace_back(ctx);
    processors_.emplace_back(proc);
  }

  for (uint32_t i = 0; i < task_pool_size_; i++) {
    auto proc = std::make_shared<Processor>();
    auto ctx = std::make_shared<ClassicContext>();

    proc->BindContext(ctx);
    SetSchedAffinity(proc->Thread(), pool_cpuset_, pool_affinity_, i);
    SetSchedPolicy(proc->Thread(), pool_processor_policy_, pool_processor_prio_,
                   proc->Tid());
    pctxs_.emplace_back(ctx);
    processors_.emplace_back(proc);
  }
}

bool SchedulerChoreography::DispatchTask(const std::shared_ptr<CRoutine>& cr) {
  // we use multi-key mutex to prevent race condition
  // when del && add cr with same crid
  MutexWrapper* wrapper = nullptr;
  if (!id_map_mutex_.Get(cr->id(), &wrapper)) {
    {
      std::lock_guard<std::mutex> wl_lg(cr_wl_mtx_);
      if (!id_map_mutex_.Get(cr->id(), &wrapper)) {
        wrapper = new MutexWrapper();
        id_map_mutex_.Set(cr->id(), wrapper);
      }
    }
  }
  std::lock_guard<std::mutex> lg(wrapper->Mutex());

  // Assign sched cfg to tasks according to configuration.
  if (cr_confs_.find(cr->name()) != cr_confs_.end()) {
    ChoreographyTask taskconf = cr_confs_[cr->name()];
    cr->set_priority(taskconf.prio());

    if (taskconf.has_processor()) {
      cr->set_processor_id(taskconf.processor());
    }
  }

  {
    WriteLockGuard<AtomicRWLock> lk(id_cr_lock_);
    if (id_cr_.find(cr->id()) != id_cr_.end()) {
      return false;
    }
    id_cr_[cr->id()] = cr;
  }

  // Enqueue task.
  uint32_t pid = cr->processor_id();
  if (pid < proc_num_) {
    // Enqueue task to Choreo Policy.
    static_cast<ChoreographyContext*>(pctxs_[pid].get())->Enqueue(cr);
  } else {
    // Check if task prio is reasonable.
    if (cr->priority() >= MAX_PRIO) {
      AWARN << cr->name() << " prio great than MAX_PRIO.";
      cr->set_priority(MAX_PRIO - 1);
    }

    cr->set_group_name(DEFAULT_GROUP_NAME);

    // Enqueue task to pool runqueue.
    {
      WriteLockGuard<AtomicRWLock> lk(
          ClassicContext::rq_locks_[DEFAULT_GROUP_NAME].at(cr->priority()));
      ClassicContext::cr_group_[DEFAULT_GROUP_NAME]
          .at(cr->priority())
          .emplace_back(cr);
    }
  }
  return true;
}

bool SchedulerChoreography::RemoveTask(const std::string& name) {
  if (cyber_unlikely(stop_)) {
    return true;
  }

  auto crid = GlobalData::GenerateHashId(name);
  return RemoveCRoutine(crid);
}

bool SchedulerChoreography::RemoveCRoutine(uint64_t crid) {
  // we use multi-key mutex to prevent race condition
  // when del && add cr with same crid
  MutexWrapper* wrapper = nullptr;
  if (!id_map_mutex_.Get(crid, &wrapper)) {
    {
      std::lock_guard<std::mutex> wl_lg(cr_wl_mtx_);
      if (!id_map_mutex_.Get(crid, &wrapper)) {
        wrapper = new MutexWrapper();
        id_map_mutex_.Set(crid, wrapper);
      }
    }
  }
  std::lock_guard<std::mutex> lg(wrapper->Mutex());

  std::shared_ptr<CRoutine> cr = nullptr;
  int pid;
  {
    WriteLockGuard<AtomicRWLock> lk(id_cr_lock_);
    auto p = id_cr_.find(crid);
    if (p != id_cr_.end()) {
      cr = p->second;
      pid = cr->processor_id();
      id_cr_[crid]->Stop();
      id_cr_.erase(crid);
    } else {
      return false;
    }
  }

  // rm cr from pool if rt not in choreo context
  if (pid == -1) {
    return ClassicContext::RemoveCRoutine(cr);
  } else {
    return static_cast<ChoreographyContext*>(pctxs_[pid].get())
        ->RemoveCRoutine(crid);
  }
}

bool SchedulerChoreography::NotifyProcessor(uint64_t crid) {
  if (cyber_unlikely(stop_)) {
    return true;
  }

  std::shared_ptr<CRoutine> cr;
  // find cr from id_cr && Update cr Flag
  // policies will handle ready-state CRoutines
  {
    ReadLockGuard<AtomicRWLock> lk(id_cr_lock_);
    auto it = id_cr_.find(crid);
    if (it != id_cr_.end()) {
      cr = it->second;
      if (cr->state() == RoutineState::DATA_WAIT ||
          cr->state() == RoutineState::IO_WAIT) {
        cr->SetUpdateFlag();
      }
    } else {
      return false;
    }
  }

  if (cr->processor_id() != -1) {
    auto pid = cr->processor_id();
    static_cast<ChoreographyContext*>(pctxs_[pid].get())->Notify();
  } else {
    ClassicContext::Notify(cr->group_name());
  }

  return true;
}

}  // namespace scheduler
}  // namespace cyber
}  // namespace apollo
<commit_msg>Fixed processor_id range overflow (#10948)<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "cyber/scheduler/policy/scheduler_choreography.h"

#include <memory>
#include <string>
#include <utility>

#include "cyber/common/environment.h"
#include "cyber/common/file.h"
#include "cyber/scheduler/policy/choreography_context.h"
#include "cyber/scheduler/policy/classic_context.h"
#include "cyber/scheduler/processor.h"

namespace apollo {
namespace cyber {
namespace scheduler {

using apollo::cyber::base::AtomicRWLock;
using apollo::cyber::base::ReadLockGuard;
using apollo::cyber::base::WriteLockGuard;
using apollo::cyber::common::GetAbsolutePath;
using apollo::cyber::common::GetProtoFromFile;
using apollo::cyber::common::GlobalData;
using apollo::cyber::common::PathExists;
using apollo::cyber::common::WorkRoot;
using apollo::cyber::croutine::RoutineState;

SchedulerChoreography::SchedulerChoreography() {
  std::string conf("conf/");
  conf.append(GlobalData::Instance()->ProcessGroup()).append(".conf");
  auto cfg_file = GetAbsolutePath(WorkRoot(), conf);

  apollo::cyber::proto::CyberConfig cfg;
  if (PathExists(cfg_file) && GetProtoFromFile(cfg_file, &cfg)) {
    for (auto& thr : cfg.scheduler_conf().threads()) {
      inner_thr_confs_[thr.name()] = thr;
    }

    if (cfg.scheduler_conf().has_process_level_cpuset()) {
      process_level_cpuset_ = cfg.scheduler_conf().process_level_cpuset();
      ProcessLevelResourceControl();
    }

    const apollo::cyber::proto::ChoreographyConf& choreography_conf =
        cfg.scheduler_conf().choreography_conf();
    proc_num_ = choreography_conf.choreography_processor_num();
    choreography_affinity_ = choreography_conf.choreography_affinity();
    choreography_processor_policy_ =
        choreography_conf.choreography_processor_policy();

    choreography_processor_prio_ =
        choreography_conf.choreography_processor_prio();
    ParseCpuset(choreography_conf.choreography_cpuset(), &choreography_cpuset_);

    task_pool_size_ = choreography_conf.pool_processor_num();
    pool_affinity_ = choreography_conf.pool_affinity();
    pool_processor_policy_ = choreography_conf.pool_processor_policy();
    pool_processor_prio_ = choreography_conf.pool_processor_prio();
    ParseCpuset(choreography_conf.pool_cpuset(), &pool_cpuset_);

    for (const auto& task : choreography_conf.tasks()) {
      cr_confs_[task.name()] = task;
    }
  }

  if (proc_num_ == 0) {
    auto& global_conf = GlobalData::Instance()->Config();
    if (global_conf.has_scheduler_conf() &&
        global_conf.scheduler_conf().has_default_proc_num()) {
      proc_num_ = global_conf.scheduler_conf().default_proc_num();
    } else {
      proc_num_ = 2;
    }
    task_pool_size_ = proc_num_;
  }

  CreateProcessor();
}

void SchedulerChoreography::CreateProcessor() {
  for (uint32_t i = 0; i < proc_num_; i++) {
    auto proc = std::make_shared<Processor>();
    auto ctx = std::make_shared<ChoreographyContext>();

    proc->BindContext(ctx);
    SetSchedAffinity(proc->Thread(), choreography_cpuset_,
                     choreography_affinity_, i);
    SetSchedPolicy(proc->Thread(), choreography_processor_policy_,
                   choreography_processor_prio_, proc->Tid());
    pctxs_.emplace_back(ctx);
    processors_.emplace_back(proc);
  }

  for (uint32_t i = 0; i < task_pool_size_; i++) {
    auto proc = std::make_shared<Processor>();
    auto ctx = std::make_shared<ClassicContext>();

    proc->BindContext(ctx);
    SetSchedAffinity(proc->Thread(), pool_cpuset_, pool_affinity_, i);
    SetSchedPolicy(proc->Thread(), pool_processor_policy_, pool_processor_prio_,
                   proc->Tid());
    pctxs_.emplace_back(ctx);
    processors_.emplace_back(proc);
  }
}

bool SchedulerChoreography::DispatchTask(const std::shared_ptr<CRoutine>& cr) {
  // we use multi-key mutex to prevent race condition
  // when del && add cr with same crid
  MutexWrapper* wrapper = nullptr;
  if (!id_map_mutex_.Get(cr->id(), &wrapper)) {
    {
      std::lock_guard<std::mutex> wl_lg(cr_wl_mtx_);
      if (!id_map_mutex_.Get(cr->id(), &wrapper)) {
        wrapper = new MutexWrapper();
        id_map_mutex_.Set(cr->id(), wrapper);
      }
    }
  }
  std::lock_guard<std::mutex> lg(wrapper->Mutex());

  // Assign sched cfg to tasks according to configuration.
  if (cr_confs_.find(cr->name()) != cr_confs_.end()) {
    ChoreographyTask taskconf = cr_confs_[cr->name()];
    cr->set_priority(taskconf.prio());

    if (taskconf.has_processor()) {
      cr->set_processor_id(taskconf.processor());
    }
  }

  {
    WriteLockGuard<AtomicRWLock> lk(id_cr_lock_);
    if (id_cr_.find(cr->id()) != id_cr_.end()) {
      return false;
    }
    id_cr_[cr->id()] = cr;
  }

  // Enqueue task.
  uint32_t pid = cr->processor_id();
  if (pid < proc_num_) {
    // Enqueue task to Choreo Policy.
    static_cast<ChoreographyContext*>(pctxs_[pid].get())->Enqueue(cr);
  } else {
    // Check if task prio is reasonable.
    if (cr->priority() >= MAX_PRIO) {
      AWARN << cr->name() << " prio great than MAX_PRIO.";
      cr->set_priority(MAX_PRIO - 1);
    }

    cr->set_group_name(DEFAULT_GROUP_NAME);

    // Enqueue task to pool runqueue.
    {
      WriteLockGuard<AtomicRWLock> lk(
          ClassicContext::rq_locks_[DEFAULT_GROUP_NAME].at(cr->priority()));
      ClassicContext::cr_group_[DEFAULT_GROUP_NAME]
          .at(cr->priority())
          .emplace_back(cr);
    }
  }
  return true;
}

bool SchedulerChoreography::RemoveTask(const std::string& name) {
  if (cyber_unlikely(stop_)) {
    return true;
  }

  auto crid = GlobalData::GenerateHashId(name);
  return RemoveCRoutine(crid);
}

bool SchedulerChoreography::RemoveCRoutine(uint64_t crid) {
  // we use multi-key mutex to prevent race condition
  // when del && add cr with same crid
  MutexWrapper* wrapper = nullptr;
  if (!id_map_mutex_.Get(crid, &wrapper)) {
    {
      std::lock_guard<std::mutex> wl_lg(cr_wl_mtx_);
      if (!id_map_mutex_.Get(crid, &wrapper)) {
        wrapper = new MutexWrapper();
        id_map_mutex_.Set(crid, wrapper);
      }
    }
  }
  std::lock_guard<std::mutex> lg(wrapper->Mutex());

  std::shared_ptr<CRoutine> cr = nullptr;
  uint32_t pid;
  {
    WriteLockGuard<AtomicRWLock> lk(id_cr_lock_);
    auto p = id_cr_.find(crid);
    if (p != id_cr_.end()) {
      cr = p->second;
      pid = cr->processor_id();
      id_cr_[crid]->Stop();
      id_cr_.erase(crid);
    } else {
      return false;
    }
  }

  // rm cr from pool if rt not in choreo context
  if (pid < proc_num_) {
    return static_cast<ChoreographyContext*>(pctxs_[pid].get())
        ->RemoveCRoutine(crid);
  } else {
    return ClassicContext::RemoveCRoutine(cr);
  }
}

bool SchedulerChoreography::NotifyProcessor(uint64_t crid) {
  if (cyber_unlikely(stop_)) {
    return true;
  }

  std::shared_ptr<CRoutine> cr;
  uint32_t pid;
  // find cr from id_cr && Update cr Flag
  // policies will handle ready-state CRoutines
  {
    ReadLockGuard<AtomicRWLock> lk(id_cr_lock_);
    auto it = id_cr_.find(crid);
    if (it != id_cr_.end()) {
      cr = it->second;
      pid = cr->processor_id();
      if (cr->state() == RoutineState::DATA_WAIT ||
          cr->state() == RoutineState::IO_WAIT) {
        cr->SetUpdateFlag();
      }
    } else {
      return false;
    }
  }

  if (pid < proc_num_) {
    static_cast<ChoreographyContext*>(pctxs_[pid].get())->Notify();
  } else {
    ClassicContext::Notify(cr->group_name());
  }

  return true;
}

}  // namespace scheduler
}  // namespace cyber
}  // namespace apollo
<|endoftext|>


<commit_before>/*
    Kopete Yahoo Protocol
    Stealth/Unstealth a buddy

    Copyright (c) 2005 André Duffeck <duffeck@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include "stealthtask.h"
#include "transfer.h"
#include "ymsgtransfer.h"
#include "yahootypes.h"
#include "client.h"
#include <qstring.h>

StealthTask::StealthTask(Task* parent) : Task(parent)
{
	kDebug(YAHOO_RAW_DEBUG) ;
}

StealthTask::~StealthTask()
{
}

void StealthTask::onGo()
{
	YMSGTransfer *t = new YMSGTransfer();
	if( m_mode == Yahoo::StealthOnline )
	{
		t->setService( Yahoo::ServiceStealthOnline );
		t->setParam( 13, "1" );
		t->setParam( 31, m_state );
	}
	else if( m_mode == Yahoo::StealthOffline )
	{
		t->setService( Yahoo::ServiceStealthOffline );
		t->setParam( 13, "1" );
		t->setParam( 31, m_state );
	}
	else if( m_mode == Yahoo::StealthPermOffline )
	{
		t->setService( Yahoo::ServiceStealthOffline );
		t->setParam( 13, "2" );
		t->setParam( 31, m_state );
	}
	t->setId( client()->sessionID() );
	t->setParam( 1, client()->userId().toLocal8Bit());
	if( !m_target.isEmpty() )
		t->setParam( 7, m_target.toLocal8Bit() );
	send( t );

	setSuccess();
}

void StealthTask::setTarget( const QString &to )
{
	m_target = to;
}

void StealthTask::setState( Yahoo::StealthStatus state)
{
	m_state = state;
}

void StealthTask::setMode( Yahoo::StealthMode mode )
{
	m_mode = mode;
}
<commit_msg>fix stealth feature<commit_after>/*
    Kopete Yahoo Protocol
    Stealth/Unstealth a buddy

    Copyright (c) 2005 André Duffeck <duffeck@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include "stealthtask.h"
#include "transfer.h"
#include "ymsgtransfer.h"
#include "yahootypes.h"
#include "client.h"
#include <qstring.h>

StealthTask::StealthTask(Task* parent) : Task(parent)
{
	kDebug(YAHOO_RAW_DEBUG) ;
}

StealthTask::~StealthTask()
{
}

void StealthTask::onGo()
{
	YMSGTransfer *t = new YMSGTransfer();
	if( m_mode == Yahoo::StealthOnline )
	{
		t->setService( Yahoo::ServiceStealthOnline );
		t->setParam( 13, "1" );
		t->setParam( 31, m_state );
	}
	else if( m_mode == Yahoo::StealthOffline )
	{
		t->setService( Yahoo::ServiceStealthOffline );
		t->setParam( 13, "1" );
		t->setParam( 31, m_state );
	}
	else if( m_mode == Yahoo::StealthPermOffline )
	{
		t->setService( Yahoo::ServiceStealthOffline );
		t->setParam( 13, "2" );
		t->setParam( 31, m_state );
	}
	t->setId( client()->sessionID() );
	t->setParam( 1, client()->userId().toLocal8Bit());
	if( !m_target.isEmpty() ) {
		t->setParam( 302, 319 );
		t->setParam( 300, 319 );
		t->setParam( 7, m_target.toLocal8Bit() );
		t->setParam( 301, 319 );
		t->setParam( 303, 319 );
	}
	send( t );

	setSuccess();
}

void StealthTask::setTarget( const QString &to )
{
	m_target = to;
}

void StealthTask::setState( Yahoo::StealthStatus state)
{
	m_state = state;
}

void StealthTask::setMode( Yahoo::StealthMode mode )
{
	m_mode = mode;
}
<|endoftext|>


<commit_before>/*
MIT License
Copyright (c) 2017 Arlen Keshabyan (arlen.albert@gmail.com)
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 <iostream>

#include "planar_movements_recognizer.hpp"
#include "platform.hpp"
#include "platform_utilities.hpp"
#include "strings.hpp"
#include "utilities.hpp"
#include "cmdline_options.hpp"
#include "process.hpp"

int main(int argc, char **argv)
{
    using namespace nstd::str;
    using namespace nstd::platform;
    using namespace nstd::platform::utilities;
    using namespace nstd::utilities;
    using namespace nstd::process;

    set_console_utf8();

    std::cout << u8"Консоль поддерживает UTF-8..." << std::endl;

    Process proc("echo \"Redirected output\"", "", [](auto a, auto b){ std::cout << std::endl << ">> " << std::string(a, b) << std::endl; }, [](auto a, auto b){});

    (void)proc.get_exit_status();

    nstd::po::parser p;
    std::string shell_cmd;
    auto help_callback { [&p]{ std::cout << p << std::endl; } };

    p["execute"].abbreviation('E').type(nstd::po::string).description("Executes the provided shell command (not actually)").bind(shell_cmd);
    p["help"].abbreviation('?').callback(help_callback).description("Prints the help screen");

    auto pres { p(argc, argv) };

    auto &&exe = p["execute"];

    if (argc == 1 || !pres) help_callback();
    if (exe.was_set() && !is_empty_or_ws(shell_cmd)) { std::cout << "command to execute: " << shell_cmd << std::endl; return 0; }

    const std::string app_name { "pmr_example" };
    at_scope_exit execute { [&app_name]() { std::cout << std::endl << "exitting " << app_name << "..." << std::endl;} };

    constexpr const bool if_windows { current_os_family == os_family::Windows };

    auto cmd { compose_string(if_windows ? "where" : "which", " gcc 2>&1") };
    auto res { shell_execute(cmd) };

    std::cout << "shell execution result: \"" << trim(res) << "\"" << std::endl << std::endl;

    std::cout << "Is Little Endian: "   << boolalpha[is_little_endian]  << std::endl;
    std::cout << "Is 64 bit: "          << boolalpha[is_64bit]          << std::endl;
    std::cout << "      OS: "           << get_current_os_type_name()   << std::endl;
    std::cout << "Platform: "           << get_current_os_family_name() << std::endl;
    std::cout << "Compiler: "           << get_current_compiler_name()  << std::endl << std::endl;

    using namespace std::string_literals;
    using namespace nstd::pmr;

    enum command : uint8_t
    {
        open_file = 100, close_file,
        go_back, go_forward,
        reload
    };

    std::map<uint8_t, std::string> command_map
    {
        {0, "Unknown"s},
        {command::open_file, "Open file"s},
        {command::close_file, "Close file"s},
        {command::go_back, "Go back"s},
        {command::go_forward, "Go forward"s},
        {command::reload, "Reload"s}
    };

    using event = planar_movements_event_provider::event;

    planar_movements_event_provider pmep;
    command_recognizer<event, command> cr;
    remove_noise_filter rnf;

    cr. add_command(command::open_file,  { event::up }).
        add_command(command::close_file, { event::down }).
        add_command(command::go_back,    { event::left }).
        add_command(command::go_forward, { event::right }).
        add_command(command::reload,     { event::down, event::up })
    ;

    {
        std::vector<event> coords { pmep(100., 100.), pmep(150., 105.), pmep(200., 103.), pmep(250., 102.), pmep(300., 95.) }; // moving right

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        event_filter<event> ef(true);
        ef.set(event::right, event::left);

         // moving right, but mapping the right event to the left one using event_filter
        std::vector<event> coords { ef(pmep(100., 100.)), ef(pmep(150., 105.)), ef(pmep(200., 103.)), ef(pmep(250., 102.)), ef(pmep(300., 95.)) }; // moving right

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(295., 239.), pmep(310., 202.), pmep(300., 150.), pmep(300., 120.), pmep(300., 95.) }; // moving up

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(300., 95.), pmep(300., 120.), pmep(300., 150.), pmep(310., 202.), pmep(295., 239.) }; // moving down

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(300., 95.), pmep(300., 120.), pmep(300., 150.), pmep(310., 202.), pmep(295., 239.),
                                                                     pmep(295., 239.), pmep(310., 202.), pmep(300., 150.), pmep(300., 120.), pmep(300., 95.) }; // moving down & up

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    return 0;
}
<commit_msg>minor change<commit_after>/*
MIT License
Copyright (c) 2017 Arlen Keshabyan (arlen.albert@gmail.com)
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 <iostream>

#include "planar_movements_recognizer.hpp"
#include "platform.hpp"
#include "platform_utilities.hpp"
#include "strings.hpp"
#include "utilities.hpp"
#include "cmdline_options.hpp"
#include "process.hpp"

int main(int argc, char **argv)
{
    using namespace nstd::str;
    using namespace nstd::platform;
    using namespace nstd::platform::utilities;
    using namespace nstd::utilities;
    using namespace nstd::process;

    scoped_console_utf8 set_console_utf8;

    std::cout << u8"Консоль поддерживает UTF-8..." << std::endl;

    Process proc("echo \"Redirected output\"", "", [](auto a, auto b){ std::cout << std::endl << ">> " << std::string(a, b) << std::endl; }, [](auto a, auto b){});

    (void)proc.get_exit_status();

    nstd::po::parser p;
    std::string shell_cmd;
    auto help_callback { [&p]{ std::cout << p << std::endl; } };

    p["execute"].abbreviation('E').type(nstd::po::string).description("Executes the provided shell command (not actually)").bind(shell_cmd);
    p["help"].abbreviation('?').callback(help_callback).description("Prints the help screen");

    auto pres { p(argc, argv) };

    auto &&exe = p["execute"];

    if (argc == 1 || !pres) help_callback();
    if (exe.was_set() && !is_empty_or_ws(shell_cmd)) { std::cout << "command to execute: " << shell_cmd << std::endl; return 0; }

    const std::string app_name { "pmr_example" };
    at_scope_exit execute { [&app_name]() { std::cout << std::endl << "exitting " << app_name << "..." << std::endl;} };

    constexpr const bool if_windows { current_os_family == os_family::Windows };

    auto cmd { compose_string(if_windows ? "where" : "which", " gcc 2>&1") };
    auto res { shell_execute(cmd) };

    std::cout << "shell execution result: \"" << trim(res) << "\"" << std::endl << std::endl;

    std::cout << "Is Little Endian: "   << boolalpha[is_little_endian]  << std::endl;
    std::cout << "Is 64 bit: "          << boolalpha[is_64bit]          << std::endl;
    std::cout << "      OS: "           << get_current_os_type_name()   << std::endl;
    std::cout << "Platform: "           << get_current_os_family_name() << std::endl;
    std::cout << "Compiler: "           << get_current_compiler_name()  << std::endl << std::endl;

    using namespace std::string_literals;
    using namespace nstd::pmr;

    enum command : uint8_t
    {
        open_file = 100, close_file,
        go_back, go_forward,
        reload
    };

    std::map<uint8_t, std::string> command_map
    {
        {0, "Unknown"s},
        {command::open_file, "Open file"s},
        {command::close_file, "Close file"s},
        {command::go_back, "Go back"s},
        {command::go_forward, "Go forward"s},
        {command::reload, "Reload"s}
    };

    using event = planar_movements_event_provider::event;

    planar_movements_event_provider pmep;
    command_recognizer<event, command> cr;
    remove_noise_filter rnf;

    cr. add_command(command::open_file,  { event::up }).
        add_command(command::close_file, { event::down }).
        add_command(command::go_back,    { event::left }).
        add_command(command::go_forward, { event::right }).
        add_command(command::reload,     { event::down, event::up })
    ;

    {
        std::vector<event> coords { pmep(100., 100.), pmep(150., 105.), pmep(200., 103.), pmep(250., 102.), pmep(300., 95.) }; // moving right

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        event_filter<event> ef(true);
        ef.set(event::right, event::left);

         // moving right, but mapping the right event to the left one using event_filter
        std::vector<event> coords { ef(pmep(100., 100.)), ef(pmep(150., 105.)), ef(pmep(200., 103.)), ef(pmep(250., 102.)), ef(pmep(300., 95.)) }; // moving right

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(295., 239.), pmep(310., 202.), pmep(300., 150.), pmep(300., 120.), pmep(300., 95.) }; // moving up

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(300., 95.), pmep(300., 120.), pmep(300., 150.), pmep(310., 202.), pmep(295., 239.) }; // moving down

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    {
        std::vector<event> coords { pmep(300., 95.), pmep(300., 120.), pmep(300., 150.), pmep(310., 202.), pmep(295., 239.),
                                                                     pmep(295., 239.), pmep(310., 202.), pmep(300., 150.), pmep(300., 120.), pmep(300., 95.) }; // moving down & up

        std::cout << command_map[cr(rnf(std::move(coords)))] << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>#define KDTREE_DEFINE_OSTREAM_OPERATORS

#include <kdtree++/kdtree.hpp>

#include <iostream>
#include <vector>
#include <limits>
#include <functional>

struct triplet {
  typedef int value_type;

  inline value_type operator[](KDTREE_SIZE_T const N) const { return d[N]; }

  value_type d[3];
};

inline bool operator==(triplet const& A, triplet const& B) {
  return A.d[0] == B.d[0] && A.d[1] == B.d[1] && A.d[2] == B.d[2];
}

std::ostream& operator<<(std::ostream& out, triplet const& T)
{
  return out << '(' << T.d[0] << ',' << T.d[1] << ',' << T.d[2] << ')';
}

inline double tac( triplet t, KDTREE_SIZE_T k ) { return t[k]; }

typedef KDTree::KDTree<3, triplet, std::pointer_to_binary_function<triplet,KDTREE_SIZE_T,double> > tree_type;

int main()
{

  tree_type t(std::ptr_fun(tac));

  triplet c0 = { {5, 4, 0} }; t.insert(c0);
  triplet c1 = { {4, 2, 1} }; t.insert(c1);
  triplet c2 = { {7, 6, 9} }; t.insert(c2);
  triplet c3 = { {2, 2, 1} }; t.insert(c3);
  triplet c4 = { {8, 0, 5} }; t.insert(c4);
  triplet c5 = { {5, 7, 0} }; t.insert(c5);
  triplet c6 = { {3, 3, 8} }; t.insert(c6);
  triplet c7 = { {9, 7, 3} }; t.insert(c7);
  triplet c8 = { {2, 2, 6} }; t.insert(c8);
  triplet c9 = { {2, 0, 6} }; t.insert(c9);

  std::cout << t << std::endl;

  t.erase(c0);
  t.erase(c1);
  t.erase(c3);
  t.erase(c5);

  t.optimise();

  std::cout << std::endl << t << std::endl;

  int i=0;
  for (tree_type::const_iterator iter=t.begin(); iter!=t.end(); ++iter, ++i);
  std::cout << "iterator walked through " << i << " nodes in total" << std::endl;
  if (i!=6)
    {
      std::cerr << "Error: does not tally with the expected number of nodes (6)" << std::endl;
      return 1;
    }
  i=0;
  for (tree_type::const_reverse_iterator iter=t.rbegin(); iter!=t.rend(); ++iter, ++i);
  std::cout << "reverse_iterator walked through " << i << " nodes in total" << std::endl;
  if (i!=6)
    {
      std::cerr << "Error: does not tally with the expected number of nodes (6)" << std::endl;
      return 1;
    }

  triplet s = { {5, 4, 3} };
  std::vector<triplet> v;
  unsigned int const RANGE = 3;

  KDTREE_SIZE_T count = t.count_within_range(s, RANGE);
  std::cout << "counted " << count
	    << " nodes within range " << RANGE << " of " << s << ".\n";
  t.find_within_range(s, RANGE, std::back_inserter(v));

  std::cout << "found   " << v.size() << " nodes within range " << RANGE
	    << " of " << s << ":\n";
  std::vector<triplet>::const_iterator ci = v.begin();
  for (; ci != v.end(); ++ci)
    std::cout << *ci << " ";
  std::cout << "\n" << std::endl;

  std::cout << "Nearest to " << s << ": " <<
     *t.find_nearest(s,std::numeric_limits<double>::max()).first << std::endl;

  triplet s2 = { {10, 10, 2} };
  std::cout << "Nearest to " << s2 << ": " <<
     *t.find_nearest(s2,std::numeric_limits<double>::max()).first << std::endl;

  std::cout << std::endl;

  std::cout << t << std::endl;

  // Testing iterators
  {
    std::cout << "Testing iterators" << std::endl;

    t.erase(c2);
    t.erase(c4);
    t.erase(c6);
    t.erase(c7);
    t.erase(c8);
//    t.erase(c9);

    std::cout << std::endl << t << std::endl;

    std::cout << "Forward iterator test..." << std::endl;
    std::vector<triplet> forwards;
    for (tree_type::iterator i = t.begin(); i != t.end(); ++i)
    { std::cout << *i << " " << std::flush; forwards.push_back(*i); }
    std::cout << std::endl;
    std::cout << "Reverse iterator test..." << std::endl;
    std::vector<triplet> backwards;
    for (tree_type::reverse_iterator i = t.rbegin(); i != t.rend(); ++i)
    { std::cout << *i << " " << std::flush; backwards.push_back(*i); }
    std::cout << std::endl;
    std::reverse(backwards.begin(),backwards.end());
    assert(backwards == forwards);
  }

  return 0;
}

/* COPYRIGHT --
 *
 * This file is part of libkdtree++, a C++ template KD-Tree sorting container.
 * libkdtree++ is (c) 2004-2007 Martin F. Krafft <libkdtree@pobox.madduck.net>
 * and Sylvain Bougerel <sylvain.bougerel.devel@gmail.com> distributed under the
 * terms of the Artistic License 2.0. See the ./COPYING file in the source tree
 * root for more information.
 *
 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
 * OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
<commit_msg>Added a test to test_kdtree which checks that all nodes that are passed to operator<<() are initialised.<commit_after>#define KDTREE_DEFINE_OSTREAM_OPERATORS

#include <kdtree++/kdtree.hpp>

#include <iostream>
#include <vector>
#include <limits>
#include <functional>
#include <set>

// used to ensure all triplets that are accessed via the operator<< are initialised.
std::set<const void*> registered;

struct triplet
{
  typedef int value_type;

   triplet(value_type a, value_type b, value_type c)
   {
      d[0] = a;
      d[1] = b;
      d[2] = c;
      bool reg_ok = (registered.find(this) == registered.end());
      assert(reg_ok);
      registered.insert(this).second;
   }

   triplet(const triplet & x)
   {
      d[0] = x.d[0];
      d[1] = x.d[1];
      d[2] = x.d[2];
      bool reg_ok = (registered.find(this) == registered.end());
      assert(reg_ok);
      registered.insert(this).second;
   }

   ~triplet()
   {
      bool unreg_ok = (registered.find(this) != registered.end());
      assert(unreg_ok);
      registered.erase(this);
   }

  inline value_type operator[](KDTREE_SIZE_T const N) const { return d[N]; }

  value_type d[3];
};

inline bool operator==(triplet const& A, triplet const& B) {
  return A.d[0] == B.d[0] && A.d[1] == B.d[1] && A.d[2] == B.d[2];
}

std::ostream& operator<<(std::ostream& out, triplet const& T)
{
   assert(registered.find(&T) != registered.end());
  return out << '(' << T.d[0] << ',' << T.d[1] << ',' << T.d[2] << ')';
}

inline double tac( triplet t, KDTREE_SIZE_T k ) { return t[k]; }

typedef KDTree::KDTree<3, triplet, std::pointer_to_binary_function<triplet,KDTREE_SIZE_T,double> > tree_type;

int main()
{

  tree_type t(std::ptr_fun(tac));

  triplet c0(5, 4, 0); t.insert(c0);
  triplet c1(4, 2, 1); t.insert(c1);
  triplet c2(7, 6, 9); t.insert(c2);
  triplet c3(2, 2, 1); t.insert(c3);
  triplet c4(8, 0, 5); t.insert(c4);
  triplet c5(5, 7, 0); t.insert(c5);
  triplet c6(3, 3, 8); t.insert(c6);
  triplet c7(9, 7, 3); t.insert(c7);
  triplet c8(2, 2, 6); t.insert(c8);
  triplet c9(2, 0, 6); t.insert(c9);

  std::cout << t << std::endl;

  t.erase(c0);
  t.erase(c1);
  t.erase(c3);
  t.erase(c5);

  t.optimise();

  std::cout << std::endl << t << std::endl;

  int i=0;
  for (tree_type::const_iterator iter=t.begin(); iter!=t.end(); ++iter, ++i);
  std::cout << "iterator walked through " << i << " nodes in total" << std::endl;
  if (i!=6)
    {
      std::cerr << "Error: does not tally with the expected number of nodes (6)" << std::endl;
      return 1;
    }
  i=0;
  for (tree_type::const_reverse_iterator iter=t.rbegin(); iter!=t.rend(); ++iter, ++i);
  std::cout << "reverse_iterator walked through " << i << " nodes in total" << std::endl;
  if (i!=6)
    {
      std::cerr << "Error: does not tally with the expected number of nodes (6)" << std::endl;
      return 1;
    }

  triplet s(5, 4, 3);
  std::vector<triplet> v;
  unsigned int const RANGE = 3;

  KDTREE_SIZE_T count = t.count_within_range(s, RANGE);
  std::cout << "counted " << count
	    << " nodes within range " << RANGE << " of " << s << ".\n";
  t.find_within_range(s, RANGE, std::back_inserter(v));

  std::cout << "found   " << v.size() << " nodes within range " << RANGE
	    << " of " << s << ":\n";
  std::vector<triplet>::const_iterator ci = v.begin();
  for (; ci != v.end(); ++ci)
    std::cout << *ci << " ";
  std::cout << "\n" << std::endl;

  std::cout << "Nearest to " << s << ": " <<
     *t.find_nearest(s,std::numeric_limits<double>::max()).first << std::endl;

  triplet s2(10, 10, 2);
  std::cout << "Nearest to " << s2 << ": " <<
     *t.find_nearest(s2,std::numeric_limits<double>::max()).first << std::endl;

  std::cout << std::endl;

  std::cout << t << std::endl;

  // Testing iterators
  {
    std::cout << "Testing iterators" << std::endl;

    t.erase(c2);
    t.erase(c4);
    t.erase(c6);
    t.erase(c7);
    t.erase(c8);
//    t.erase(c9);

    std::cout << std::endl << t << std::endl;

    std::cout << "Forward iterator test..." << std::endl;
    std::vector<triplet> forwards;
    for (tree_type::iterator i = t.begin(); i != t.end(); ++i)
    { std::cout << *i << " " << std::flush; forwards.push_back(*i); }
    std::cout << std::endl;
    std::cout << "Reverse iterator test..." << std::endl;
    std::vector<triplet> backwards;
    for (tree_type::reverse_iterator i = t.rbegin(); i != t.rend(); ++i)
    { std::cout << *i << " " << std::flush; backwards.push_back(*i); }
    std::cout << std::endl;
    std::reverse(backwards.begin(),backwards.end());
    assert(backwards == forwards);
  }

  return 0;
}

/* COPYRIGHT --
 *
 * This file is part of libkdtree++, a C++ template KD-Tree sorting container.
 * libkdtree++ is (c) 2004-2007 Martin F. Krafft <libkdtree@pobox.madduck.net>
 * and Sylvain Bougerel <sylvain.bougerel.devel@gmail.com> distributed under the
 * terms of the Artistic License 2.0. See the ./COPYING file in the source tree
 * root for more information.
 *
 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
 * OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
<|endoftext|>


<commit_before>#include <QApplication>
#include <QWebPage>
#include <QWebFrame>
#include "sunscraperthread.h"
#include "sunscraperproxy.h"

SunscraperThread *SunscraperThread::_instance;

SunscraperThread::SunscraperThread()
{
}

SunscraperThread *SunscraperThread::instance()
{
    return _instance;
}

void SunscraperThread::invoke()
{
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
    pthread_t thread;

    pthread_create(&thread, NULL, &SunscraperThread::thread_routine, NULL);
#else
#error Your platform is unsupported. Implement SunscraperThread::invoke() and send a pull request.
#endif
}

void *SunscraperThread::thread_routine(void *)
{
    static int argc;
    static char **argv = {NULL};

    QApplication app(argc, argv);

    _instance = new SunscraperThread();

    app.exec();

    qFatal("Sunscraper apartment thread event loop should never end");

    return NULL;
}

void SunscraperThread::loadHtml(unsigned queryId, QString html)
{
    QWebPage *webPage = initializeWebPage(queryId);
    webPage->mainFrame()->setHtml(html);
}

void SunscraperThread::loadUrl(unsigned queryId, QString url)
{
    QWebPage *webPage = initializeWebPage(queryId);
    webPage->mainFrame()->load(url);
}

void SunscraperThread::finalize(unsigned queryId)
{
    Q_ASSERT(_webPages[queryId] != NULL);

    _webPages[queryId]->deleteLater();
    _webPages.remove(queryId);
}

QWebPage *SunscraperThread::initializeWebPage(unsigned queryId)
{
    Q_ASSERT(_webPages[queryId] == NULL);

    QWebPage *webPage = new QWebPage(this);
    connect(webPage->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
        this, SLOT(attachAPI()));

    _webPages[queryId] = webPage;

    return webPage;
}

void SunscraperThread::attachAPI()
{
    QWebFrame *origin = static_cast<QWebFrame *>(QObject::sender());
    QWebPage *page = origin->page();

    unsigned queryId = _webPages.key(page, 0);
    Q_ASSERT(queryId != 0);

    SunscraperProxy *proxy = new SunscraperProxy(page, queryId);
    connect(proxy, SIGNAL(finished(uint,QString)), this, SIGNAL(finished(uint,QString)));

    origin->addToJavaScriptWindowObject("Sunscraper", proxy, QScriptEngine::QtOwnership);
}
<commit_msg>Improve error messages.<commit_after>#include <QApplication>
#include <QWebPage>
#include <QWebFrame>
#include "sunscraperthread.h"
#include "sunscraperproxy.h"

SunscraperThread *SunscraperThread::_instance;

SunscraperThread::SunscraperThread()
{
}

SunscraperThread *SunscraperThread::instance()
{
    return _instance;
}

void SunscraperThread::invoke()
{
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
    pthread_t thread;

    pthread_create(&thread, NULL, &SunscraperThread::thread_routine, NULL);
#else
#error Your platform is unsupported. Implement SunscraperThread::invoke() and send a pull request.
#endif
}

void *SunscraperThread::thread_routine(void *)
{
    /* Better error messages. */
    int   argc   = 1;
    char *argv[] = { (char*) "Sunscraper", NULL};

    /* Why (char*)? Because argv can (theoretically) be modified. *
     * But Qt won't do that with argv[0]. I know, trust me.       */

    QApplication app(argc, argv);

    _instance = new SunscraperThread();

    app.exec();

    qFatal("Sunscraper apartment thread event loop should never end");

    return NULL;
}

void SunscraperThread::loadHtml(unsigned queryId, QString html)
{
    QWebPage *webPage = initializeWebPage(queryId);
    webPage->mainFrame()->setHtml(html);
}

void SunscraperThread::loadUrl(unsigned queryId, QString url)
{
    QWebPage *webPage = initializeWebPage(queryId);
    webPage->mainFrame()->load(url);
}

void SunscraperThread::finalize(unsigned queryId)
{
    Q_ASSERT(_webPages[queryId] != NULL);

    _webPages[queryId]->deleteLater();
    _webPages.remove(queryId);
}

QWebPage *SunscraperThread::initializeWebPage(unsigned queryId)
{
    Q_ASSERT(_webPages[queryId] == NULL);

    QWebPage *webPage = new QWebPage(this);
    connect(webPage->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
        this, SLOT(attachAPI()));

    _webPages[queryId] = webPage;

    return webPage;
}

void SunscraperThread::attachAPI()
{
    QWebFrame *origin = static_cast<QWebFrame *>(QObject::sender());
    QWebPage *page = origin->page();

    unsigned queryId = _webPages.key(page, 0);
    Q_ASSERT(queryId != 0);

    SunscraperProxy *proxy = new SunscraperProxy(page, queryId);
    connect(proxy, SIGNAL(finished(uint,QString)), this, SIGNAL(finished(uint,QString)));

    origin->addToJavaScriptWindowObject("Sunscraper", proxy, QScriptEngine::QtOwnership);
}
<|endoftext|>


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

#include <algorithm>
#include <map>
#include <memory>
#include <queue>
#include <unordered_map>
#include <utility>
#include <vector>

#include <cassert>
#include <cmath>
#include <cstdlib>

#include "lcsk.h"
#include "match_events_queue.h"
#include "match_maker.h"
#include "match_pair.h"
using namespace std;

namespace {

void FillLcskReconstruction(const int k, std::shared_ptr<MatchPair> best,
                            vector<pair<int, int>>* lcsk_recon) {
  assert(lcsk_recon != nullptr);
  lcsk_recon->clear();

  for (auto ft = best; ft != nullptr; ft = ft->prev) {
    int r = ft->end_row;
    int c = ft->end_col;

    if (ft->prev == nullptr ||
        (ft->prev->end_row + k <= ft->end_row &&
         ft->prev->end_col + k <= ft->end_col)) {
      for (int j = 0; j < k; ++j, --r, --c) {
        lcsk_recon->push_back(make_pair(r, c));
      }
    } else {
      assert(ft->prev->end_row + 1 == ft->end_row &&
             ft->prev->end_col + 1 == ft->end_col);
      lcsk_recon->push_back(make_pair(r, c));
    }
  }
  reverse(lcsk_recon->begin(), lcsk_recon->end());
}

bool CompareByCol(const std::shared_ptr<MatchPair>& a,
                  const std::shared_ptr<MatchPair>& b) {
  return a->end_col < b->end_col;
}

void RowUpdate(
    const int k, const int row, MatchEventsQueue* events_ptr,
    vector<std::shared_ptr<MatchPair>>* compressed_table_ptr,
    vector<std::shared_ptr<MatchPair>>* prev_row_match_pairs,
    bool lcskpp) {
  auto& events = *events_ptr;
  auto& compressed_table = *compressed_table_ptr;
  auto& prev_row = *prev_row_match_pairs;

  std::tuple<int, int, std::shared_ptr<MatchPair>> event;

  vector<std::shared_ptr<MatchPair>> curr_row;
  int curr_continuation_index = 0;

  while (events.PopEnd(row, &event)) {
    int i = get<0>(event);
    int j = get<1>(event);
    assert(i == row);
    auto match_pair_end = get<2>(event);

    if (lcskpp) { // LCSk++
      while (curr_continuation_index < prev_row.size() &&
             prev_row[curr_continuation_index]->end_col + 1 < match_pair_end->end_col) {
        curr_continuation_index++;
      }

      if (curr_continuation_index < prev_row.size() &&
          prev_row[curr_continuation_index]->end_col + 1 == match_pair_end->end_col) {
        int continuation_dp = prev_row[curr_continuation_index]->dp + 1;
        if (continuation_dp > match_pair_end->dp) {
          match_pair_end->dp = continuation_dp;
          match_pair_end->prev = prev_row[curr_continuation_index];
        }
      }

      curr_row.emplace_back(match_pair_end);

      int dp = match_pair_end->dp;
      while (compressed_table.size() <= dp) {
        // fill with dummy values which will be overwritten in for loop below anyway.
        int idx = compressed_table.size();
        compressed_table.push_back(std::make_shared<MatchPair>(i+1, j+1, idx, nullptr));
      }

      for (int idx = dp; idx > dp - k && j < compressed_table[idx]->end_col; --idx) {
        compressed_table[idx] = match_pair_end;
      }
    } else { // LCSk
      int idx = match_pair_end->dp / k;
      if (idx == compressed_table.size()) {
        compressed_table.emplace_back(match_pair_end);
      } else if (j < compressed_table[idx]->end_col) {
        compressed_table[idx] = match_pair_end;
      }
    }
  }

  prev_row.swap(curr_row);
}

void AmortizedRowQuery(
    const int k, const int row, MatchEventsQueue* events_ptr,
    vector<std::shared_ptr<MatchPair>>* compressed_table_ptr) {
  auto& events = *events_ptr;
  auto& compressed_table = *compressed_table_ptr;

  int curr_threshold_index = 0;
  std::tuple<int, int, std::shared_ptr<MatchPair>> event;

  while (events.PopBegin(row, &event)) {
    int i = get<0>(event);
    int j = get<1>(event);
    assert(i == row);
    while (curr_threshold_index < compressed_table.size() &&
           compressed_table[curr_threshold_index]->end_col < j) {
      ++curr_threshold_index;
    }

    auto prev_best = compressed_table[curr_threshold_index - 1];
    auto match_pair = std::make_shared<MatchPair>(i + k - 1, j + k - 1, k, nullptr);
    if (prev_best->dp > 0) {
      match_pair->dp = prev_best->dp + k;
      match_pair->prev = prev_best;
    }
    events.AddEnd(make_tuple(i + k - 1, j + k - 1, match_pair));
  }
}

void ElementwiseRowQuery(
    const int k, const int row, MatchEventsQueue* events_ptr,
    vector<std::shared_ptr<MatchPair>>* compressed_table_ptr) {
  auto& events = *events_ptr;
  auto& compressed_table = *compressed_table_ptr;

  tuple<int, int, std::shared_ptr<MatchPair>> event;

  while (events.PopBegin(row, &event)) {
    int i = get<0>(event);
    int j = get<1>(event);
    assert(i == row);

    auto dummy_match_pair = std::make_shared<MatchPair>(0, j, 0, nullptr);
    auto prev_best =
      lower_bound(compressed_table.begin(), compressed_table.end(),
                  dummy_match_pair, CompareByCol) -
      1;
    auto match_pair = std::make_shared<MatchPair>(i + k - 1, j + k - 1, k, nullptr);

    if ((*prev_best)->dp > 0) {
      match_pair->dp = (*prev_best)->dp + k;
      match_pair->prev = *prev_best;
    }
    events.AddEnd(make_tuple(i + k - 1, j + k - 1, match_pair));
  }
}

}  // namespace

void LcsKSparseFast(const string& a, const string& b, int k,
                    vector<pair<int, int>>* lcsk_reconstruction,
                    const bool lcskpp) {
  lcsk_reconstruction->clear();

  MatchEventsQueue events;
  auto match_maker = MatchMaker::Create(a, b, k, PERFECT_HASH);

  vector<std::shared_ptr<MatchPair>> compressed_table;
  compressed_table.emplace_back(std::make_shared<MatchPair>(-1, -1, 0, nullptr));
  // following invariants hold:
  //    LCSk++: compressed_table[i]->dp == i
  //    LCSk:   compressed_table[i]->dp == k*i
  vector<std::shared_ptr<MatchPair>> prev_row_match_pairs;

  for (int row = 0; row <= a.size(); ++row) {
    vector<int> row_matches;
    match_maker->GetNextMatches(&row_matches);
    for (int col : row_matches) {
      events.AddBegin(make_tuple(row, col, nullptr));
    }

    int table_row_size = compressed_table.size();
    int num_begin_events = row_matches.size();
    bool use_amortized_row_update = (table_row_size + num_begin_events <
                                     6 * num_begin_events * log(table_row_size) / log(2));

    if (use_amortized_row_update) {
      AmortizedRowQuery(k, row, &events, &compressed_table);
    } else {
      ElementwiseRowQuery(k, row, &events, &compressed_table);
    }

    RowUpdate(k, row, &events, &compressed_table, &prev_row_match_pairs, lcskpp);
  }

  auto best = compressed_table.back()->end_row != -1 ? compressed_table.back() : nullptr;
  FillLcskReconstruction(k, best, lcsk_reconstruction);
}

// exposed functions

void LcsKSparseFast(const std::string &a, const std::string &b, int k,
                    std::vector<std::pair<int, int>> *lcsk_reconstruction) {
  LcsKSparseFast(a, b, k, lcsk_reconstruction, false);
}

void LcsKppSparseFast(const std::string &a, const std::string &b, int k,
                      std::vector<std::pair<int, int>> *lcsk_reconstruction) {
  LcsKSparseFast(a, b, k, lcsk_reconstruction, true);
}
<commit_msg>move the implementation function into anonymous namespace<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>
#include <map>
#include <memory>
#include <queue>
#include <unordered_map>
#include <utility>
#include <vector>

#include <cassert>
#include <cmath>
#include <cstdlib>

#include "lcsk.h"
#include "match_events_queue.h"
#include "match_maker.h"
#include "match_pair.h"
using namespace std;

namespace {

void FillLcskReconstruction(const int k, std::shared_ptr<MatchPair> best,
                            vector<pair<int, int>>* lcsk_recon) {
  assert(lcsk_recon != nullptr);
  lcsk_recon->clear();

  for (auto ft = best; ft != nullptr; ft = ft->prev) {
    int r = ft->end_row;
    int c = ft->end_col;

    if (ft->prev == nullptr ||
        (ft->prev->end_row + k <= ft->end_row &&
         ft->prev->end_col + k <= ft->end_col)) {
      for (int j = 0; j < k; ++j, --r, --c) {
        lcsk_recon->push_back(make_pair(r, c));
      }
    } else {
      assert(ft->prev->end_row + 1 == ft->end_row &&
             ft->prev->end_col + 1 == ft->end_col);
      lcsk_recon->push_back(make_pair(r, c));
    }
  }
  reverse(lcsk_recon->begin(), lcsk_recon->end());
}

bool CompareByCol(const std::shared_ptr<MatchPair>& a,
                  const std::shared_ptr<MatchPair>& b) {
  return a->end_col < b->end_col;
}

void RowUpdate(
    const int k, const int row, MatchEventsQueue* events_ptr,
    vector<std::shared_ptr<MatchPair>>* compressed_table_ptr,
    vector<std::shared_ptr<MatchPair>>* prev_row_match_pairs,
    bool lcsk_plus) {
  auto& events = *events_ptr;
  auto& compressed_table = *compressed_table_ptr;
  auto& prev_row = *prev_row_match_pairs;

  std::tuple<int, int, std::shared_ptr<MatchPair>> event;

  vector<std::shared_ptr<MatchPair>> curr_row;
  int curr_continuation_index = 0;

  while (events.PopEnd(row, &event)) {
    int i = get<0>(event);
    int j = get<1>(event);
    assert(i == row);
    auto match_pair_end = get<2>(event);

    if (lcsk_plus) { // LCSk++
      while (curr_continuation_index < prev_row.size() &&
             prev_row[curr_continuation_index]->end_col + 1 < match_pair_end->end_col) {
        curr_continuation_index++;
      }

      if (curr_continuation_index < prev_row.size() &&
          prev_row[curr_continuation_index]->end_col + 1 == match_pair_end->end_col) {
        int continuation_dp = prev_row[curr_continuation_index]->dp + 1;
        if (continuation_dp > match_pair_end->dp) {
          match_pair_end->dp = continuation_dp;
          match_pair_end->prev = prev_row[curr_continuation_index];
        }
      }

      curr_row.emplace_back(match_pair_end);

      int dp = match_pair_end->dp;
      while (compressed_table.size() <= dp) {
        // fill with dummy values which will be overwritten in for loop below anyway.
        int idx = compressed_table.size();
        compressed_table.push_back(std::make_shared<MatchPair>(i+1, j+1, idx, nullptr));
      }

      for (int idx = dp; idx > dp - k && j < compressed_table[idx]->end_col; --idx) {
        compressed_table[idx] = match_pair_end;
      }
    } else { // LCSk
      int idx = match_pair_end->dp / k;
      if (idx == compressed_table.size()) {
        compressed_table.emplace_back(match_pair_end);
      } else if (j < compressed_table[idx]->end_col) {
        compressed_table[idx] = match_pair_end;
      }
    }
  }

  prev_row.swap(curr_row);
}

void AmortizedRowQuery(
    const int k, const int row, MatchEventsQueue* events_ptr,
    vector<std::shared_ptr<MatchPair>>* compressed_table_ptr) {
  auto& events = *events_ptr;
  auto& compressed_table = *compressed_table_ptr;

  int curr_threshold_index = 0;
  std::tuple<int, int, std::shared_ptr<MatchPair>> event;

  while (events.PopBegin(row, &event)) {
    int i = get<0>(event);
    int j = get<1>(event);
    assert(i == row);
    while (curr_threshold_index < compressed_table.size() &&
           compressed_table[curr_threshold_index]->end_col < j) {
      ++curr_threshold_index;
    }

    auto prev_best = compressed_table[curr_threshold_index - 1];
    auto match_pair = std::make_shared<MatchPair>(i + k - 1, j + k - 1, k, nullptr);
    if (prev_best->dp > 0) {
      match_pair->dp = prev_best->dp + k;
      match_pair->prev = prev_best;
    }
    events.AddEnd(make_tuple(i + k - 1, j + k - 1, match_pair));
  }
}

void ElementwiseRowQuery(
    const int k, const int row, MatchEventsQueue* events_ptr,
    vector<std::shared_ptr<MatchPair>>* compressed_table_ptr) {
  auto& events = *events_ptr;
  auto& compressed_table = *compressed_table_ptr;

  tuple<int, int, std::shared_ptr<MatchPair>> event;

  while (events.PopBegin(row, &event)) {
    int i = get<0>(event);
    int j = get<1>(event);
    assert(i == row);

    auto dummy_match_pair = std::make_shared<MatchPair>(0, j, 0, nullptr);
    auto prev_best =
      lower_bound(compressed_table.begin(), compressed_table.end(),
                  dummy_match_pair, CompareByCol) -
      1;
    auto match_pair = std::make_shared<MatchPair>(i + k - 1, j + k - 1, k, nullptr);

    if ((*prev_best)->dp > 0) {
      match_pair->dp = (*prev_best)->dp + k;
      match_pair->prev = *prev_best;
    }
    events.AddEnd(make_tuple(i + k - 1, j + k - 1, match_pair));
  }
}

void LcsKSparseFastImpl(const string& a, const string& b, int k,
                        vector<pair<int, int>>* lcsk_reconstruction,
                        const bool lcsk_plus) {
  lcsk_reconstruction->clear();

  MatchEventsQueue events;
  auto match_maker = MatchMaker::Create(a, b, k, PERFECT_HASH);

  vector<std::shared_ptr<MatchPair>> compressed_table;
  compressed_table.emplace_back(std::make_shared<MatchPair>(-1, -1, 0, nullptr));
  // following invariants hold:
  //    LCSk++: compressed_table[i]->dp == i
  //    LCSk:   compressed_table[i]->dp == k*i
  vector<std::shared_ptr<MatchPair>> prev_row_match_pairs;

  for (int row = 0; row <= a.size(); ++row) {
    vector<int> row_matches;
    match_maker->GetNextMatches(&row_matches);
    for (int col : row_matches) {
      events.AddBegin(make_tuple(row, col, nullptr));
    }

    int table_row_size = compressed_table.size();
    int num_begin_events = row_matches.size();
    bool use_amortized_row_update = (table_row_size + num_begin_events <
                                     6 * num_begin_events * log(table_row_size) / log(2));

    if (use_amortized_row_update) {
      AmortizedRowQuery(k, row, &events, &compressed_table);
    } else {
      ElementwiseRowQuery(k, row, &events, &compressed_table);
    }

    RowUpdate(k, row, &events, &compressed_table, &prev_row_match_pairs, lcsk_plus);
  }

  auto best = compressed_table.back()->end_row != -1 ? compressed_table.back() : nullptr;
  FillLcskReconstruction(k, best, lcsk_reconstruction);
}

}  // namespace

// exposed functions

void LcsKSparseFast(const std::string& a, const std::string& b, int k,
                    std::vector<std::pair<int, int>>* lcsk_reconstruction) {
  LcsKSparseFastImpl(a, b, k, lcsk_reconstruction, /*lcsk_plus=*/false);
}

void LcsKppSparseFast(const std::string& a, const std::string& b, int k,
                        std::vector<std::pair<int, int>>* lcsk_reconstruction) {
  LcsKSparseFastImpl(a, b, k, lcsk_reconstruction, /*lcsk_plus=*/true);
}
<|endoftext|>