<commit_before>#pragma once

#include <limits>
#include <algorithm>
#include <vector>
#include <map>
#include <functional>

using std::max;
using std::make_pair;
using std::min;
using std::abs;
using std::hypot;
using std::vector;
using std::map;
using std::function;

namespace search
{
    //
    //  Lifelong planning
    //
    namespace lp
    {
        constexpr auto infinity()
        {
            return std::numeric_limits<int>::max();
        }
        constexpr auto cost()
        {
            return 1;
        }

        struct Coordinate
        {
            const int x, y;

            friend auto operator== (Coordinate l, Coordinate r)
            {
                return l.x == r.x && l.y == r.y;
            }
            friend auto operator!= (Coordinate l, Coordinate r)
            {
                return !(l == r);
            }

            auto neighbours() const
            {
                struct Directions : public map< char, function< Coordinate(Coordinate) >>
                {
                    Directions()
                    {
                        (*this)['1'] = [](Coordinate c) { return Coordinate{ c.x - 1, c.y - 1 }; };
                        (*this)['2'] = [](Coordinate c) { return Coordinate{ c.x - 0, c.y - 1 }; };
                        (*this)['3'] = [](Coordinate c) { return Coordinate{ c.x + 1, c.y - 1 }; };
                        (*this)['4'] = [](Coordinate c) { return Coordinate{ c.x - 1, c.y - 0 }; };
                        (*this)['5'] = [](Coordinate c) { return Coordinate{ c.x + 1, c.y + 0 }; };
                        (*this)['6'] = [](Coordinate c) { return Coordinate{ c.x - 1, c.y + 1 }; };
                        (*this)['7'] = [](Coordinate c) { return Coordinate{ c.x - 0, c.y + 1 }; };
                        (*this)['8'] = [](Coordinate c) { return Coordinate{ c.x + 1, c.y + 1 }; };
                    }
                } static const directions;

                vector<Coordinate> result;
                for (auto n = '1'; n != '9'; ++n)
                    result.push_back(directions.at(n)(*this));
                return result;
            }
        };

        struct LpState
        {
            struct Key
            {
                const int first, second;

                friend auto operator== (Key l, Key r)
                {
                    return l.first == r.first && l.second == r.second;
                }
                friend auto operator < (Key l, Key r)
                {
                    return (l.first < r.first) || (l.first == r.first && l.second < r.second);
                }
            };

            const Coordinate coordinate;
            int g, r;

            template<typename Hfunc>
            auto key(Hfunc h) const
            {
                return Key{ min(g, r + h(coordinate)), min(g, r) };
            }
        };

        struct LpManhattanDistance
        {
            const Coordinate goal;
            auto operator()(Coordinate c) const
            {
                return max(abs(goal.x - c.x), abs(goal.y - c.y));
            }
        };

        struct LpEuclideanDistance
        {
            const Coordinate goal;
            auto operator()(Coordinate c) const
            {
                auto result = hypot(abs(goal.x - c.x), abs(goal.y - c.y));
                return static_cast<int>(round(result));
            }
        };
    }
}<commit_msg>remove const mark in Coordinate and LpState for easier constructing.<commit_after>#pragma once

#include <limits>
#include <algorithm>
#include <vector>
#include <map>
#include <functional>

using std::max;
using std::make_pair;
using std::min;
using std::abs;
using std::hypot;
using std::vector;
using std::map;
using std::function;

namespace search
{
    //
    //  Lifelong planning
    //
    namespace lp
    {
        constexpr auto infinity()
        {
            return std::numeric_limits<int>::max();
        }
        constexpr auto cost()
        {
            return 1;
        }

        struct Coordinate
        {
            int x, y;

            friend auto operator== (Coordinate l, Coordinate r)
            {
                return l.x == r.x && l.y == r.y;
            }
            friend auto operator!= (Coordinate l, Coordinate r)
            {
                return !(l == r);
            }

            auto neighbours() const
            {
                struct Directions : public map< char, function< Coordinate(Coordinate) >>
                {
                    Directions()
                    {
                        (*this)['1'] = [](Coordinate c) { return Coordinate{ c.x - 1, c.y - 1 }; };
                        (*this)['2'] = [](Coordinate c) { return Coordinate{ c.x - 0, c.y - 1 }; };
                        (*this)['3'] = [](Coordinate c) { return Coordinate{ c.x + 1, c.y - 1 }; };
                        (*this)['4'] = [](Coordinate c) { return Coordinate{ c.x - 1, c.y - 0 }; };
                        (*this)['5'] = [](Coordinate c) { return Coordinate{ c.x + 1, c.y + 0 }; };
                        (*this)['6'] = [](Coordinate c) { return Coordinate{ c.x - 1, c.y + 1 }; };
                        (*this)['7'] = [](Coordinate c) { return Coordinate{ c.x - 0, c.y + 1 }; };
                        (*this)['8'] = [](Coordinate c) { return Coordinate{ c.x + 1, c.y + 1 }; };
                    }
                } static const directions;

                vector<Coordinate> result;
                for (auto n = '1'; n != '9'; ++n)
                    result.push_back(directions.at(n)(*this));
                return result;
            }
        };

        struct LpState
        {
            struct Key
            {
                const int first, second;

                friend auto operator== (Key l, Key r)
                {
                    return l.first == r.first && l.second == r.second;
                }
                friend auto operator < (Key l, Key r)
                {
                    return (l.first < r.first) || (l.first == r.first && l.second < r.second);
                }
            };

            Coordinate coordinate;
            int g, r;

            template<typename Hfunc>
            auto key(Hfunc h) const
            {
                return Key{ min(g, r + h(coordinate)), min(g, r) };
            }
        };

        struct LpManhattanDistance
        {
            const Coordinate goal;
            auto operator()(Coordinate c) const
            {
                return max(abs(goal.x - c.x), abs(goal.y - c.y));
            }
        };

        struct LpEuclideanDistance
        {
            const Coordinate goal;
            auto operator()(Coordinate c) const
            {
                auto result = hypot(abs(goal.x - c.x), abs(goal.y - c.y));
                return static_cast<int>(round(result));
            }
        };

        //class Matrix
        //{
        //public:
        //    Matrix(unsigned width, unsigned height)
        //        : _data{ height, vector<LpState>(width)}
        //    {   }
        //private:
        //    vector<vector<LpState>> _data;
        //};
    }
}<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#ifdef __cplusplus

#include <ostream>
#include <istream>
#include <vector>
#if __cplusplus > 199711L // Necessary for NVCC
//#include <initializer_list>
#endif
#include <af/defines.h>
#include <af/seq.h>

namespace af
{
class AFAPI dim4
{
    public:
    dim_t dims[4]; //FIXME: Make this C compatiable
    dim4(); //deleted
public:
#if __cplusplus > 199711L
    //dim4(std::initializer_list<dim_t> dim_vals);
#endif
    dim4(   dim_t first,
            dim_t second = 1,
            dim_t third = 1,
            dim_t fourth = 1);
    dim4(const dim4& other);
    dim4(const unsigned ndims, const dim_t * const dims);
    dim_t elements();
    dim_t elements() const;
    dim_t ndims();
    dim_t ndims() const;
    bool operator==(const dim4& other) const;
    bool operator!=(const dim4& other) const;
    dim4& operator*=(const dim4& other);
    dim4& operator+=(const dim4& other);
    dim4& operator-=(const dim4& other);
    dim_t& operator[](const unsigned dim);
    const dim_t& operator[](const unsigned dim) const;
            dim_t* get()         { return dims; }
    const   dim_t* get() const   { return dims; }
};

AFAPI dim4 operator+(const dim4& first, const dim4& second);
AFAPI dim4 operator-(const dim4& first, const dim4& second);
AFAPI dim4 operator*(const dim4& first, const dim4& second);

static inline
std::ostream&
operator<<(std::ostream& ostr, const dim4& dims)
{
    ostr << dims[0] << " "
         << dims[1] << " "
         << dims[2] << " "
         << dims[3];
    return ostr;
}

static inline
std::istream&
operator>>(std::istream& istr, dim4& dims)
{
    istr >> dims[0]
         >> dims[1]
         >> dims[2]
         >> dims[3];
    return istr;
}

AFAPI bool isSpan(const af_seq &seq);

AFAPI size_t seqElements(const af_seq &seq);

AFAPI dim_t calcDim(const af_seq &seq, const dim_t &parentDim);
}

#endif
<commit_msg>Get rid of dead preprocessor directives.<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#ifdef __cplusplus

#include <ostream>
#include <istream>
#include <vector>
#include <af/defines.h>
#include <af/seq.h>

namespace af
{
class AFAPI dim4
{
    public:
    dim_t dims[4]; //FIXME: Make this C compatiable
    dim4(); //deleted
public:
    dim4(   dim_t first,
            dim_t second = 1,
            dim_t third = 1,
            dim_t fourth = 1);
    dim4(const dim4& other);
    dim4(const unsigned ndims, const dim_t * const dims);
    dim_t elements();
    dim_t elements() const;
    dim_t ndims();
    dim_t ndims() const;
    bool operator==(const dim4& other) const;
    bool operator!=(const dim4& other) const;
    dim4& operator*=(const dim4& other);
    dim4& operator+=(const dim4& other);
    dim4& operator-=(const dim4& other);
    dim_t& operator[](const unsigned dim);
    const dim_t& operator[](const unsigned dim) const;
            dim_t* get()         { return dims; }
    const   dim_t* get() const   { return dims; }
};

AFAPI dim4 operator+(const dim4& first, const dim4& second);
AFAPI dim4 operator-(const dim4& first, const dim4& second);
AFAPI dim4 operator*(const dim4& first, const dim4& second);

static inline
std::ostream&
operator<<(std::ostream& ostr, const dim4& dims)
{
    ostr << dims[0] << " "
         << dims[1] << " "
         << dims[2] << " "
         << dims[3];
    return ostr;
}

static inline
std::istream&
operator>>(std::istream& istr, dim4& dims)
{
    istr >> dims[0]
         >> dims[1]
         >> dims[2]
         >> dims[3];
    return istr;
}

AFAPI bool isSpan(const af_seq &seq);

AFAPI size_t seqElements(const af_seq &seq);

AFAPI dim_t calcDim(const af_seq &seq, const dim_t &parentDim);
}

#endif
<|endoftext|>


<commit_before>#include <MetaEvent.h>
#include <MetaFactory.h>
#include <ratio>

namespace test {

namespace metaEventSuite {

using namespace id::attribute;
using namespace std;

	class MetaEventSuite : public ::testing::Test {
		public:
			ID posID = Position::value();
			MetaFactory& f=MetaFactory::instance();
			MetaEvent e;
			MetaEventSuite(){
				MetaAttribute position = posID;
				position.value() = f.create({{{0,1}, {1,1}, {2,1}}});
				position.unit()  = Meter();
				position.scale() = ratio<1, 1000>();
        e.add(position);
			}
	};

	TEST_F(MetaEventSuite, findAttributeTest) {
		MetaAttribute test = posID;
		test.value() = f.create({{0, 1, 2}});
		test.unit()  = Meter();
		test.scale() = ratio<1, 1000>();
    const MetaAttribute* posPtr = e.attribute(posID);
    ASSERT_NE(posPtr, nullptr) << "Position attribute could not be retrieved";
    const MetaAttribute& pos = *posPtr;
		EXPECT_EQ(pos, test) << "Position attribute not stored correctly";
	}

	TEST_F(MetaEventSuite, typeTest) {
		EventType eT;
		eT.add(AttributeType(posID, ValueType(id::type::Double::value(), 1, 3, true), ratio<1,1000>(), Meter()));
		EXPECT_EQ((EventType)e, eT) << "Inferred MetaEvent-Type is wrong";
	}
}}
<commit_msg>Unit-Test: adapt to new MetaFactory create API<commit_after>#include <MetaEvent.h>
#include <MetaFactory.h>
#include <ratio>

namespace test {

namespace metaEventSuite {

using namespace id::attribute;
using namespace std;

	class MetaEventSuite : public ::testing::Test {
		public:
			ID posID = Position::value();
			MetaFactory& f=MetaFactory::instance();
			MetaEvent e;
			MetaEventSuite(){
				MetaAttribute position = posID;
				position.value() = f.create({{{0,1}, {1,1}, {2,1}}});
				position.unit()  = Meter();
				position.scale() = ratio<1, 1000>();
        e.add(position);
			}
	};

	TEST_F(MetaEventSuite, findAttributeTest) {
		MetaAttribute test = posID;
		test.value() = f.create({{{0,1}, {1,1}, {2,1}}});
		test.unit()  = Meter();
		test.scale() = ratio<1, 1000>();
    const MetaAttribute* posPtr = e.attribute(posID);
    ASSERT_NE(posPtr, nullptr) << "Position attribute could not be retrieved";
    const MetaAttribute& pos = *posPtr;
		EXPECT_EQ(pos, test) << "Position attribute not stored correctly";
	}

	TEST_F(MetaEventSuite, typeTest) {
		EventType eT;
		eT.add(AttributeType(posID, ValueType(id::type::Double::value(), 1, 3, true), ratio<1,1000>(), Meter()));
		EXPECT_EQ((EventType)e, eT) << "Inferred MetaEvent-Type is wrong";
	}
}}
<|endoftext|>


<commit_before>// ------------------------------------------------------------------------
// Pion is a development platform for building Reactors that process Events
// ------------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Pion is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// Pion is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
// more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Pion.  If not, see <http://www.gnu.org/licenses/>.
//

#include "QueryService.hpp"
#include <boost/bind.hpp>
#include <pion/net/HTTPResponseWriter.hpp>
#include <pion/net/PionUser.hpp>
#include "PlatformConfig.hpp"

using namespace pion;
using namespace pion::net;

namespace pion {		// begin namespace pion
namespace plugins {		// begin namespace plugins

// QueryService member functions

/// handles requests for QueryService
void QueryService::operator()(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn)
{
	// split out the path branches from the HTTP request
	PathBranches branches;
	splitPathBranches(branches, request->getResource());

	std::string xml;

/*
	for (int i = 0; i < branches.size() ; i++ )
		xml += branches[i] + "::";

	xml += "\r\n";
*/
	if (branches.empty()) {
		xml += "No branch (/reactors) defined";
	} else if (branches.front() == "reactors") {
		xml = getConfig().getReactionEngine().query(
			branches.at(1),
			branches,
			request->getQueryParams());
	} else {
		xml += "Only /reactors supported";
	}

	// Set Content-type to "text/plain" (plain ascii text)
	HTTPResponseWriterPtr writer(HTTPResponseWriter::create(tcp_conn, *request,
															boost::bind(&TCPConnection::finish, tcp_conn)));
	writer->getResponse().setContentType(HTTPTypes::CONTENT_TYPE_XML);

	writer->write(xml.c_str());

	// send the writer
	writer->send();
}

}	// end namespace plugins
}	// end namespace pion

/// creates new QueryService objects
extern "C" PION_SERVICE_API pion::server::PlatformService *pion_create_QueryService(void)
{
	return new pion::plugins::QueryService();
}

/// destroys QueryService objects
extern "C" PION_SERVICE_API void pion_destroy_QueryService(pion::plugins::QueryService *service_ptr)
{
	delete service_ptr;
}
<commit_msg>QueryService checking in a pending change -- using std::string instead of c_str() to writer<commit_after>// ------------------------------------------------------------------------
// Pion is a development platform for building Reactors that process Events
// ------------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Pion is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// Pion is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
// more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Pion.  If not, see <http://www.gnu.org/licenses/>.
//

#include "QueryService.hpp"
#include <boost/bind.hpp>
#include <pion/net/HTTPResponseWriter.hpp>
#include <pion/net/PionUser.hpp>
#include "PlatformConfig.hpp"

using namespace pion;
using namespace pion::net;

namespace pion {		// begin namespace pion
namespace plugins {		// begin namespace plugins

// QueryService member functions

/// handles requests for QueryService
void QueryService::operator()(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn)
{
	// split out the path branches from the HTTP request
	PathBranches branches;
	splitPathBranches(branches, request->getResource());

	std::string xml;

/*
	for (int i = 0; i < branches.size() ; i++ )
		xml += branches[i] + "::";

	xml += "\r\n";
*/
	if (branches.empty()) {
		xml += "No branch (/reactors) defined";
	} else if (branches.front() == "reactors") {
		xml = getConfig().getReactionEngine().query(
			branches.at(1),
			branches,
			request->getQueryParams());
	} else {
		xml += "Only /reactors supported";
	}

	// Set Content-type to "text/plain" (plain ascii text)
	HTTPResponseWriterPtr writer(HTTPResponseWriter::create(tcp_conn, *request,
															boost::bind(&TCPConnection::finish, tcp_conn)));
	writer->getResponse().setContentType(HTTPTypes::CONTENT_TYPE_XML);

	writer->write(xml);

	// send the writer
	writer->send();
}

}	// end namespace plugins
}	// end namespace pion

/// creates new QueryService objects
extern "C" PION_SERVICE_API pion::server::PlatformService *pion_create_QueryService(void)
{
	return new pion::plugins::QueryService();
}

/// destroys QueryService objects
extern "C" PION_SERVICE_API void pion_destroy_QueryService(pion::plugins::QueryService *service_ptr)
{
	delete service_ptr;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_TMP_HPP
#define ETL_TMP_HPP

template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;

template<bool B, class T = void>
using disable_if_t = typename std::enable_if<!B, T>::type;

template<typename T>
using remove_reference_t = typename std::remove_reference<T>::type;

template<typename T>
using remove_cv_t = typename std::remove_cv<T>::type;

namespace detail {

//Note: Unfortunately, CLang is bugged (Bug 11723), therefore, it is not
//possible to use universal enable_if/disable_if directly, it is necessary to
//use the dummy :( FU Clang!

enum class enabler_t { DUMMY };
constexpr const enabler_t dummy = enabler_t::DUMMY;

} //end of detail

template<bool B>
using enable_if_u = typename std::enable_if<B, detail::enabler_t>::type;

template<bool B>
using disable_if_u = typename std::enable_if<!B, detail::enabler_t>::type;

template<bool b1>
struct not_u : std::true_type {};

template<>
struct not_u<true> : std::false_type {};

template<bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true, bool b6 = true>
struct and_u : std::false_type {};

template<>
struct and_u<true, true, true, true, true, true> : std::true_type {};

template<bool b1, bool b2, bool b3 = false, bool b4 = false, bool b5 = false, bool b6 = false, bool b7 = false, bool b8 = false, bool b9 = false>
struct or_u : std::true_type {};

template<>
struct or_u<false, false, false, false, false, false, false, false, false> : std::false_type {};

template<template<typename...> class TT, typename T>
struct is_specialization_of : std::false_type {};

template<template<typename...> class TT, typename... Args>
struct is_specialization_of<TT, TT<Args...>> : std::true_type {};

//Variadic manipulations utilities

template<std::size_t N, typename... T>
struct nth_type {
    using type = typename std::tuple_element<N, std::tuple<T...>>::type;
};

template<typename... T>
struct first_type {
    using type = typename nth_type<0, T...>::type;
};

template<typename... T>
struct last_type {
    using type = typename nth_type<sizeof...(T)-1, T...>::type;
};

template<int I, typename T1, typename... T, enable_if_u<(I == 0)> = detail::dummy>
auto nth_value(T1&& t, T&&... /*args*/) -> decltype(std::forward<T1>(t)) {
    return std::forward<T1>(t);
}

template<int I, typename T1, typename... T, enable_if_u<(I > 0)> = detail::dummy>
auto nth_value(T1&& /*t*/, T&&... args)
        -> decltype(std::forward<typename nth_type<I, T1, T...>::type>(std::declval<typename nth_type<I, T1, T...>::type>())){
    return std::forward<typename nth_type<I, T1, T...>::type>(nth_value<I - 1>((std::forward<T>(args))...));
}

template<typename... T>
auto last_value(T&&... args){
    return std::forward<typename last_type<T...>::type>(nth_value<sizeof...(T) - 1>(args...));
}

template<typename... T>
auto first_value(T&&... args){
    return std::forward<typename first_type<T...>::type>(nth_value<0>(args...));
}

template<typename V, typename F, typename... S>
struct all_convertible_to  : std::integral_constant<bool, and_u<all_convertible_to<V, F>::value, all_convertible_to<V, S...>::value>::value> {};

template<typename V, typename F>
struct all_convertible_to<V, F> : std::integral_constant<bool, std::is_convertible<F, V>::value> {};

template<std::size_t I, std::size_t S, typename F, typename... T>
struct is_homogeneous_helper {
    template<std::size_t I1, std::size_t S1, typename Enable = void>
    struct helper_int : std::integral_constant<bool, and_u<std::is_same<F, typename nth_type<I1, T...>::type>::value, is_homogeneous_helper<I1+1, S1, F, T...>::value>::value> {};

    template<std::size_t I1, std::size_t S1>
    struct helper_int<I1, S1, enable_if_t<I1 == S1>> : std::integral_constant<bool, std::is_same<F, typename nth_type<I1, T...>::type>::value> {};

    static constexpr const auto value = helper_int<I, S>::value;
};

template<typename F, typename... T>
struct is_sub_homogeneous : std::integral_constant<bool, is_homogeneous_helper<0, sizeof...(T)-2, F, T...>::value> {};

template<typename F, typename... T>
struct is_homogeneous : std::integral_constant<bool, is_homogeneous_helper<0, sizeof...(T)-1, F, T...>::value> {};

#endif<commit_msg>Refactor<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_TMP_HPP
#define ETL_TMP_HPP

template<typename T>
using remove_reference_t = typename std::remove_reference<T>::type;

template<typename T>
using remove_cv_t = typename std::remove_cv<T>::type;

//enable_if utilities

template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;

template<bool B, class T = void>
using disable_if_t = typename std::enable_if<!B, T>::type;

namespace detail {

//Note: Unfortunately, CLang is bugged (Bug 11723), therefore, it is not
//possible to use universal enable_if/disable_if directly, it is necessary to
//use the dummy :( FU Clang!

enum class enabler_t { DUMMY };
constexpr const enabler_t dummy = enabler_t::DUMMY;

} //end of detail

template<bool B>
using enable_if_u = typename std::enable_if<B, detail::enabler_t>::type;

template<bool B>
using disable_if_u = typename std::enable_if<!B, detail::enabler_t>::type;

//Other TMP Utilities

template<bool b1>
struct not_u : std::true_type {};

template<>
struct not_u<true> : std::false_type {};

template<bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true, bool b6 = true>
struct and_u : std::false_type {};

template<>
struct and_u<true, true, true, true, true, true> : std::true_type {};

template<bool b1, bool b2, bool b3 = false, bool b4 = false, bool b5 = false, bool b6 = false, bool b7 = false, bool b8 = false, bool b9 = false>
struct or_u : std::true_type {};

template<>
struct or_u<false, false, false, false, false, false, false, false, false> : std::false_type {};

template<template<typename...> class TT, typename T>
struct is_specialization_of : std::false_type {};

template<template<typename...> class TT, typename... Args>
struct is_specialization_of<TT, TT<Args...>> : std::true_type {};

//Variadic manipulations utilities

template<std::size_t N, typename... T>
struct nth_type {
    using type = typename std::tuple_element<N, std::tuple<T...>>::type;
};

template<typename... T>
struct first_type {
    using type = typename nth_type<0, T...>::type;
};

template<typename... T>
struct last_type {
    using type = typename nth_type<sizeof...(T)-1, T...>::type;
};

template<int I, typename T1, typename... T, enable_if_u<(I == 0)> = detail::dummy>
auto nth_value(T1&& t, T&&... /*args*/) -> decltype(std::forward<T1>(t)) {
    return std::forward<T1>(t);
}

template<int I, typename T1, typename... T, enable_if_u<(I > 0)> = detail::dummy>
auto nth_value(T1&& /*t*/, T&&... args)
        -> decltype(std::forward<typename nth_type<I, T1, T...>::type>(std::declval<typename nth_type<I, T1, T...>::type>())){
    return std::forward<typename nth_type<I, T1, T...>::type>(nth_value<I - 1>((std::forward<T>(args))...));
}

template<typename... T>
auto last_value(T&&... args){
    return std::forward<typename last_type<T...>::type>(nth_value<sizeof...(T) - 1>(args...));
}

template<typename... T>
auto first_value(T&&... args){
    return std::forward<typename first_type<T...>::type>(nth_value<0>(args...));
}

template<typename V, typename F, typename... S>
struct all_convertible_to  : std::integral_constant<bool, and_u<all_convertible_to<V, F>::value, all_convertible_to<V, S...>::value>::value> {};

template<typename V, typename F>
struct all_convertible_to<V, F> : std::integral_constant<bool, std::is_convertible<F, V>::value> {};

template<std::size_t I, std::size_t S, typename F, typename... T>
struct is_homogeneous_helper {
    template<std::size_t I1, std::size_t S1, typename Enable = void>
    struct helper_int : std::integral_constant<bool, and_u<std::is_same<F, typename nth_type<I1, T...>::type>::value, is_homogeneous_helper<I1+1, S1, F, T...>::value>::value> {};

    template<std::size_t I1, std::size_t S1>
    struct helper_int<I1, S1, enable_if_t<I1 == S1>> : std::integral_constant<bool, std::is_same<F, typename nth_type<I1, T...>::type>::value> {};

    static constexpr const auto value = helper_int<I, S>::value;
};

template<typename F, typename... T>
struct is_sub_homogeneous : std::integral_constant<bool, is_homogeneous_helper<0, sizeof...(T)-2, F, T...>::value> {};

template<typename F, typename... T>
struct is_homogeneous : std::integral_constant<bool, is_homogeneous_helper<0, sizeof...(T)-1, F, T...>::value> {};

#endif<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <utiltime.h>

#include <atomic>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>
#include <ctime>
#include <tinyformat.h>

static std::atomic<int64_t> nMockTime(0); //!< For unit testing

int64_t GetTime()
{
    int64_t mocktime = nMockTime.load(std::memory_order_relaxed);
    if (mocktime) return mocktime;

    time_t now = time(nullptr);
    assert(now > 0);
    return now;
}

void SetMockTime(int64_t nMockTimeIn)
{
    nMockTime.store(nMockTimeIn, std::memory_order_relaxed);
}

int64_t GetMockTime()
{
    return nMockTime.load(std::memory_order_relaxed);
}

int64_t GetTimeMillis()
{
    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
    assert(now > 0);
    return now;
}

int64_t GetTimeMicros()
{
    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
    assert(now > 0);
    return now;
}

int64_t GetSystemTimeInSeconds()
{
    return GetTimeMicros()/1000000;
}

void MilliSleep(int64_t n)
{

/**
 * Boost's sleep_for was uninterruptible when backed by nanosleep from 1.50
 * until fixed in 1.52. Use the deprecated sleep method for the broken case.
 * See: https://svn.boost.org/trac/boost/ticket/7238
 */
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
    boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
#elif defined(HAVE_WORKING_BOOST_SLEEP)
    boost::this_thread::sleep(boost::posix_time::milliseconds(n));
#else
//should never get here
#error missing boost sleep implementation
#endif
}

std::string FormatISO8601DateTime(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
    gmtime_r(&time_val, &ts);
    return strprintf("%04i-%02i-%02iT%02i:%02i:%02iZ", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec);
}

std::string FormatISO8601Date(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
    gmtime_r(&time_val, &ts);
    return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday);
}

std::string FormatISO8601Time(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
    gmtime_r(&time_val, &ts);
    return strprintf("%02i:%02i:%02iZ", ts.tm_hour, ts.tm_min, ts.tm_sec);
}
<commit_msg>Fix for utiltime to compile with msvc.<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <utiltime.h>

#include <atomic>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>
#include <ctime>
#include <tinyformat.h>

static std::atomic<int64_t> nMockTime(0); //!< For unit testing

int64_t GetTime()
{
    int64_t mocktime = nMockTime.load(std::memory_order_relaxed);
    if (mocktime) return mocktime;

    time_t now = time(nullptr);
    assert(now > 0);
    return now;
}

void SetMockTime(int64_t nMockTimeIn)
{
    nMockTime.store(nMockTimeIn, std::memory_order_relaxed);
}

int64_t GetMockTime()
{
    return nMockTime.load(std::memory_order_relaxed);
}

int64_t GetTimeMillis()
{
    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
    assert(now > 0);
    return now;
}

int64_t GetTimeMicros()
{
    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
    assert(now > 0);
    return now;
}

int64_t GetSystemTimeInSeconds()
{
    return GetTimeMicros()/1000000;
}

void MilliSleep(int64_t n)
{

/**
 * Boost's sleep_for was uninterruptible when backed by nanosleep from 1.50
 * until fixed in 1.52. Use the deprecated sleep method for the broken case.
 * See: https://svn.boost.org/trac/boost/ticket/7238
 */
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
    boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
#elif defined(HAVE_WORKING_BOOST_SLEEP)
    boost::this_thread::sleep(boost::posix_time::milliseconds(n));
#else
//should never get here
#error missing boost sleep implementation
#endif
}

std::string FormatISO8601DateTime(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
#ifdef _MSC_VER
    gmtime_s(&ts, &time_val);
#else
    gmtime_r(&time_val, &ts);
#endif
    return strprintf("%04i-%02i-%02iT%02i:%02i:%02iZ", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec);
}

std::string FormatISO8601Date(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
#ifdef _MSC_VER
    gmtime_s(&ts, &time_val);
#else
    gmtime_r(&time_val, &ts);
#endif
    return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday);
}

std::string FormatISO8601Time(int64_t nTime) {
    struct tm ts;
    time_t time_val = nTime;
#ifdef _MSC_VER
    gmtime_s(&ts, &time_val);
#else
    gmtime_r(&time_val, &ts);
#endif
    return strprintf("%02i:%02i:%02iZ", ts.tm_hour, ts.tm_min, ts.tm_sec);
}
<|endoftext|>


<commit_before>//
// PROJECT CHRONO - http://projectchrono.org
//
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//
///////////////////////////////////////////////////
//
//   test the drive chain system.
//
//	 Author: Justin Madsen, 2015
///////////////////////////////////////////////////

#include "physics/ChSystem.h"
// #include "particlefactory/ChParticleEmitter.h"

#include "core/ChFileutils.h"
#include "core/ChStream.h"
#include "core/ChRealtimeStep.h"
#include "physics/ChSystem.h"
#include "physics/ChLinkDistance.h"
#include "physics/ChBodyEasy.h"

#include "utils/ChUtilsInputOutput.h"
#include "utils/ChUtilsData.h"
#include "assets/ChTexture.h"
#include "assets/ChColorAsset.h"
/*
#if IRRLICHT_ENABLED
*/
#include "unit_IRRLICHT/ChIrrApp.h"
#include "subsys/driver/ChIrrGuiTrack.h"
// Use the main namespaces of Irrlicht
using namespace irr;
using namespace core;
 /*
 # define USE_IRRLICHT
#endif
 */

#include "subsys/trackVehicle/DriveChain.h"
#include "ModelDefs.h"
// Use the main namespace of Chrono
using namespace chrono;

// =============================================================================
// User Settings
// =============================================================================
// display the 1) system heirarchy, 2) a set of subsystem hardpoints, 3) constraint violations
//#define DEBUG_LOG

// Initial vehicle position and heading. Defines the REF frame for the hull body
ChVector<> initLoc(0, 1.0, 0);
//ChQuaternion<> initRot = Q_from_AngAxis(CH_C_PI_4, VECT_Y);
ChQuaternion<> initRot(QUNIT);

// Simulation step size
double step_size = 0.002;

// Time interval between two render frames
int FPS = 40;
double render_step_size = 1.0 / FPS;   // FPS = 50
// Time interval between two output frames
double output_step_size = 1.0 / 1;    // once a second

// #ifdef USE_IRRLICHT
  // Point on chassis tracked by the camera
ChVector<> trackPoint(0, 0, 0);
// if chase cam enabled:
double chaseDist = 2.0;
double chaseHeight = 0.0;
// set a static camera position
ChVector<> cameraPos(-1, 1, 2.0);

  /*
#else
  double tend = 20.0;

  const std::string out_dir = "../test_driveChain";
  const std::string pov_dir = out_dir + "/POVRAY";
#endif
  */

int main(int argc, char* argv[])
{
  // NOTE: utils library built with this sets this statically
  // SetChronoDataPath(CHRONO_DATA_DIR);
  // --------------------------
  // Create the Chain system (drive gear, idler, chain)

  // The drive chain inherits ChSystem.
  DriveChain chainSystem("Justins driveChain system",
    VisualizationType::PRIMITIVES,
    CollisionType::PRIMITIVES);

  // set the chassis REF at the specified initial config.
  chainSystem.Initialize(ChCoordsys<>(initLoc, initRot));

/*
#ifdef USE_IRRLICHT
*/

  // --------------------------
  // Setup the Irrlicht GUI

  // Create the Irrlicht visualization applicaiton
  bool do_shadows = false; // shadow map is experimental

  ChIrrApp application(chainSystem.GetSystem(),
                      L"test driveChain demo",
                      dimension2d<u32>(1000, 800),
                      false,
                      do_shadows);
  // assumes Y-up
  application.AddTypicalSky();

  irr::scene::ILightSceneNode* mlight = 0;

  if (do_shadows)
  {
    mlight = application.AddLightWithShadow(
      irr::core::vector3df(10.f, 60.f, 30.f),
      irr::core::vector3df(0.f, 0.f, 0.f),
      150, 60, 80, 15, 512, irr::video::SColorf(1, 1, 1), false, false);
  }
  else
  {
    application.AddTypicalLights(
      irr::core::vector3df(30.f, 100.f, 30.f),
      irr::core::vector3df(30.f, 100.f, 50.f),
      250, 130);
  }

  application.SetTimestep(step_size);

  // the GUI driver
  ChIrrGuiTrack driver(application, chainSystem, trackPoint, chaseDist, chaseHeight);
  // even though using a chase camera, set the initial camera position laterally
//  driver.SetCameraPos(cameraPos);

  // Set the time response for steering and throttle keyboard inputs.
  // NOTE: this is not exact, since we do not render quite at the specified FPS.
  double throttle_time = 1.0;  // time to go from 0 to +1
  double braking_time = 0.3;	// time to go from 0 to +1
  // driver.SetSteeringDelta(render_step_size / 1);
  driver.SetThrottleDelta(render_step_size / throttle_time);
  driver.SetBrakingDelta(render_step_size / braking_time);

  // Set up the assets for rendering
  application.AssetBindAll();
  application.AssetUpdateAll();
  if (do_shadows)
  {
    application.AddShadowAll();
  }
/*
#else
  Track_FuncDriver driver;
#endif
*/

  // ---------------------
  // GUI and render settings

  // GUI driver inputs
  std::vector<double> throttle_input;
  std::vector<double> braking_input;

  // Number of simulation steps between two 3D view render frames
  int render_steps = (int)std::ceil(render_step_size / step_size);

  // Number of simulation steps between two output frames
  int output_steps = (int)std::ceil(output_step_size / step_size);

  // ---------------------
  // Simulation loop
#ifdef DEBUG_LOG
  GetLog() << "\n\n============ System Configuration ============\n";
  chainSystem.GetSystem()->ShowHierarchy(GetLog() );
#endif

  // Initialize simulation frame counter and simulation time
  int step_number = 0;
  double time = 0;
/*
#ifdef USE_IRRLICHT
*/

  ChRealtimeStepTimer realtime_timer;
  while (application.GetDevice()->run())
	{
		// keep track of the time spent calculating each sim step
    ChTimer<double> step_time;
    step_time.start();

    // Render scene
    if (step_number % render_steps == 0) {
      application.GetVideoDriver()->beginScene(true, true, irr::video::SColor(255, 140, 161, 192));
      driver.DrawAll();
      application.GetVideoDriver()->endScene();
    }

    // Collect output data from modules (for inter-module communication)
    throttle_input = driver.GetThrottle();
    braking_input = driver.GetBraking();

    // Update
    time = chainSystem.GetSystem()->GetChTime();

    driver.Update(time);

    chainSystem.Update(time, throttle_input[0], braking_input[0]);

    // Advance simulation for one timestep for all modules
    // double step = realtime_timer.SuggestSimulationStep(step_size);

//    driver.Advance(step_size, cameraPos);
    driver.Advance(step_size);

    // SETTLING FOLLOWED BY NORMAL OPERATION STEP SIZES HARDCODED
    // 1e-5 and 1e-4, respectively
    // application.SetPaused(true);
    if( !application.GetPaused() )
      chainSystem.Advance(step_size);

    step_number++;

  }

  application.GetDevice()->drop();

/*
#else

  int render_frame = 0;

  if(ChFileutils::MakeDirectory(out_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << out_dir << std::endl;
    return 1;
  }
  if(ChFileutils::MakeDirectory(pov_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << pov_dir << std::endl;
    return 1;
  }

  chainSystem.ExportMeshPovray(out_dir);

  char filename[100];

  while (time < tend)
  {
    if (step_number % render_steps == 0) {
      // Output render data
      sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), render_frame + 1);
      utils::WriteShapesPovray(chainSystem.GetSystem(), filename);
      std::cout << "Output frame:   " << render_frame << std::endl;
      std::cout << "Sim frame:      " << step_number << std::endl;
      std::cout << "Time:           " << time << std::endl;
      std::cout << " throttle: " << driver.GetThrottle() << " braking: " << driver.GetBraking() << std::endl;
      std::cout << std::endl;
      render_frame++;
    }

    // Collect output data from modules (for inter-module communication)
    throttle_input = driver.GetThrottle();
    braking_input = driver.GetBraking();

    // Update modules (process inputs from other modules)
    time = chainSystem.GetSystem()->GetChTime();

    driver.Update(time);

    chainSystem.Update(time, throttle_input, braking_input);

    // Advance simulation for one timestep for all modules
    driver.Advance(step_size);

    chainSystem.Advance(step_size);

    // Increment frame number
    step_number++;
  }

#endif

*/

	return 0;
}

<commit_msg>back to static cam<commit_after>//
// PROJECT CHRONO - http://projectchrono.org
//
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//
///////////////////////////////////////////////////
//
//   test the drive chain system.
//
//	 Author: Justin Madsen, 2015
///////////////////////////////////////////////////

#include "physics/ChSystem.h"
// #include "particlefactory/ChParticleEmitter.h"

#include "core/ChFileutils.h"
#include "core/ChStream.h"
#include "core/ChRealtimeStep.h"
#include "physics/ChSystem.h"
#include "physics/ChLinkDistance.h"
#include "physics/ChBodyEasy.h"

#include "utils/ChUtilsInputOutput.h"
#include "utils/ChUtilsData.h"
#include "assets/ChTexture.h"
#include "assets/ChColorAsset.h"
/*
#if IRRLICHT_ENABLED
*/
#include "unit_IRRLICHT/ChIrrApp.h"
#include "subsys/driver/ChIrrGuiTrack.h"
// Use the main namespaces of Irrlicht
using namespace irr;
using namespace core;
 /*
 # define USE_IRRLICHT
#endif
 */

#include "subsys/trackVehicle/DriveChain.h"
#include "ModelDefs.h"
// Use the main namespace of Chrono
using namespace chrono;

// =============================================================================
// User Settings
// =============================================================================
// display the 1) system heirarchy, 2) a set of subsystem hardpoints, 3) constraint violations
//#define DEBUG_LOG

// Initial vehicle position and heading. Defines the REF frame for the hull body
ChVector<> initLoc(0, 1.0, 0);
//ChQuaternion<> initRot = Q_from_AngAxis(CH_C_PI_4, VECT_Y);
ChQuaternion<> initRot(QUNIT);

// Simulation step size
double step_size = 0.002;

// Time interval between two render frames
int FPS = 40;
double render_step_size = 1.0 / FPS;   // FPS = 50
// Time interval between two output frames
double output_step_size = 1.0 / 1;    // once a second

// #ifdef USE_IRRLICHT
  // Point on chassis tracked by the camera
ChVector<> trackPoint(-1, 0, 0);
// if chase cam enabled:
double chaseDist = 2.0;
double chaseHeight = 0.0;
// set a static camera position
ChVector<> cameraPos(-1, 1, 2.5);

  /*
#else
  double tend = 20.0;

  const std::string out_dir = "../test_driveChain";
  const std::string pov_dir = out_dir + "/POVRAY";
#endif
  */

int main(int argc, char* argv[])
{
  // NOTE: utils library built with this sets this statically
  // SetChronoDataPath(CHRONO_DATA_DIR);
  // --------------------------
  // Create the Chain system (drive gear, idler, chain)

  // The drive chain inherits ChSystem.
  DriveChain chainSystem("Justins driveChain system",
    VisualizationType::PRIMITIVES,
    CollisionType::PRIMITIVES);

  // set the chassis REF at the specified initial config.
  chainSystem.Initialize(ChCoordsys<>(initLoc, initRot));

/*
#ifdef USE_IRRLICHT
*/

  // --------------------------
  // Setup the Irrlicht GUI

  // Create the Irrlicht visualization applicaiton
  bool do_shadows = false; // shadow map is experimental

  ChIrrApp application(chainSystem.GetSystem(),
                      L"test driveChain demo",
                      dimension2d<u32>(1000, 800),
                      false,
                      do_shadows);
  // assumes Y-up
  application.AddTypicalSky();

  irr::scene::ILightSceneNode* mlight = 0;

  if (do_shadows)
  {
    mlight = application.AddLightWithShadow(
      irr::core::vector3df(10.f, 60.f, 30.f),
      irr::core::vector3df(0.f, 0.f, 0.f),
      150, 60, 80, 15, 512, irr::video::SColorf(1, 1, 1), false, false);
  }
  else
  {
    application.AddTypicalLights(
      irr::core::vector3df(30.f, 100.f, 30.f),
      irr::core::vector3df(30.f, 100.f, 50.f),
      250, 130);
  }

  application.SetTimestep(step_size);

  // the GUI driver
  ChIrrGuiTrack driver(application, chainSystem, trackPoint, chaseDist, chaseHeight);
  // even though using a chase camera, set the initial camera position laterally
  driver.SetCameraPos(cameraPos);

  // Set the time response for steering and throttle keyboard inputs.
  // NOTE: this is not exact, since we do not render quite at the specified FPS.
  double throttle_time = 1.0;  // time to go from 0 to +1
  double braking_time = 0.3;	// time to go from 0 to +1
  // driver.SetSteeringDelta(render_step_size / 1);
  driver.SetThrottleDelta(render_step_size / throttle_time);
  driver.SetBrakingDelta(render_step_size / braking_time);

  // Set up the assets for rendering
  application.AssetBindAll();
  application.AssetUpdateAll();
  if (do_shadows)
  {
    application.AddShadowAll();
  }
/*
#else
  Track_FuncDriver driver;
#endif
*/

  // ---------------------
  // GUI and render settings

  // GUI driver inputs
  std::vector<double> throttle_input;
  std::vector<double> braking_input;

  // Number of simulation steps between two 3D view render frames
  int render_steps = (int)std::ceil(render_step_size / step_size);

  // Number of simulation steps between two output frames
  int output_steps = (int)std::ceil(output_step_size / step_size);

  // ---------------------
  // Simulation loop
#ifdef DEBUG_LOG
  GetLog() << "\n\n============ System Configuration ============\n";
  chainSystem.GetSystem()->ShowHierarchy(GetLog() );
#endif

  // Initialize simulation frame counter and simulation time
  int step_number = 0;
  double time = 0;
/*
#ifdef USE_IRRLICHT
*/

  ChRealtimeStepTimer realtime_timer;
  while (application.GetDevice()->run())
	{
		// keep track of the time spent calculating each sim step
    ChTimer<double> step_time;
    step_time.start();

    // Render scene
    if (step_number % render_steps == 0) {
      application.GetVideoDriver()->beginScene(true, true,irr::video::SColor(255, 140, 161, 192));
      driver.DrawAll();
      application.GetVideoDriver()->endScene();
    }

    // Collect output data from modules (for inter-module communication)
    throttle_input = driver.GetThrottle();
    braking_input = driver.GetBraking();

    // Update
    time = chainSystem.GetSystem()->GetChTime();

    driver.Update(time);

    chainSystem.Update(time, throttle_input[0], braking_input[0]);

    // Advance simulation for one timestep for all modules
    // double step = realtime_timer.SuggestSimulationStep(step_size);

    driver.Advance(step_size, cameraPos); // use the fixed camera
//    driver.Advance(step_size);  // use the chase camera

    // SETTLING FOLLOWED BY NORMAL OPERATION STEP SIZES HARDCODED
    // 1e-5 and 1e-4, respectively
    // application.SetPaused(true);
    if( !application.GetPaused() )
      chainSystem.Advance(step_size);

    step_number++;

  }

  application.GetDevice()->drop();

/*
#else

  int render_frame = 0;

  if(ChFileutils::MakeDirectory(out_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << out_dir << std::endl;
    return 1;
  }
  if(ChFileutils::MakeDirectory(pov_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << pov_dir << std::endl;
    return 1;
  }

  chainSystem.ExportMeshPovray(out_dir);

  char filename[100];

  while (time < tend)
  {
    if (step_number % render_steps == 0) {
      // Output render data
      sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), render_frame + 1);
      utils::WriteShapesPovray(chainSystem.GetSystem(), filename);
      std::cout << "Output frame:   " << render_frame << std::endl;
      std::cout << "Sim frame:      " << step_number << std::endl;
      std::cout << "Time:           " << time << std::endl;
      std::cout << " throttle: " << driver.GetThrottle() << " braking: " << driver.GetBraking() << std::endl;
      std::cout << std::endl;
      render_frame++;
    }

    // Collect output data from modules (for inter-module communication)
    throttle_input = driver.GetThrottle();
    braking_input = driver.GetBraking();

    // Update modules (process inputs from other modules)
    time = chainSystem.GetSystem()->GetChTime();

    driver.Update(time);

    chainSystem.Update(time, throttle_input, braking_input);

    // Advance simulation for one timestep for all modules
    driver.Advance(step_size);

    chainSystem.Advance(step_size);

    // Increment frame number
    step_number++;
  }

#endif

*/

	return 0;
}

<|endoftext|>


<commit_before>//===-- BranchProbabilityInfo.cpp - Branch Probability Analysis -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Loops should be simplified before this analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Instructions.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

INITIALIZE_PASS_BEGIN(BranchProbabilityInfo, "branch-prob",
                      "Branch Probability Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
INITIALIZE_PASS_END(BranchProbabilityInfo, "branch-prob",
                    "Branch Probability Analysis", false, true)

char BranchProbabilityInfo::ID = 0;

namespace {
// Please note that BranchProbabilityAnalysis is not a FunctionPass.
// It is created by BranchProbabilityInfo (which is a FunctionPass), which
// provides a clear interface. Thanks to that, all heuristics and other
// private methods are hidden in the .cpp file.
class BranchProbabilityAnalysis {

  typedef std::pair<BasicBlock *, BasicBlock *> Edge;

  DenseMap<Edge, uint32_t> *Weights;

  BranchProbabilityInfo *BP;

  LoopInfo *LI;

  // Weights are for internal use only. They are used by heuristics to help to
  // estimate edges' probability. Example:
  //
  // Using "Loop Branch Heuristics" we predict weights of edges for the
  // block BB2.
  //         ...
  //          |
  //          V
  //         BB1<-+
  //          |   |
  //          |   | (Weight = 128)
  //          V   |
  //         BB2--+
  //          |
  //          | (Weight = 4)
  //          V
  //         BB3
  //
  // Probability of the edge BB2->BB1 = 128 / (128 + 4) = 0.9696..
  // Probability of the edge BB2->BB3 = 4 / (128 + 4) = 0.0303..

  static const uint32_t LBH_TAKEN_WEIGHT = 128;
  static const uint32_t LBH_NONTAKEN_WEIGHT = 4;

  // Standard weight value. Used when none of the heuristics set weight for
  // the edge.
  static const uint32_t NORMAL_WEIGHT = 16;

  // Minimum weight of an edge. Please note, that weight is NEVER 0.
  static const uint32_t MIN_WEIGHT = 1;

  // Return TRUE if BB leads directly to a Return Instruction.
  static bool isReturningBlock(BasicBlock *BB) {
    SmallPtrSet<BasicBlock *, 8> Visited;

    while (true) {
      TerminatorInst *TI = BB->getTerminator();
      if (isa<ReturnInst>(TI))
        return true;

      if (TI->getNumSuccessors() > 1)
        break;

      // It is unreachable block which we can consider as a return instruction.
      if (TI->getNumSuccessors() == 0)
        return true;

      Visited.insert(BB);
      BB = TI->getSuccessor(0);

      // Stop if cycle is detected.
      if (Visited.count(BB))
        return false;
    }

    return false;
  }

  // Multiply Edge Weight by two.
  void incEdgeWeight(BasicBlock *Src, BasicBlock *Dst) {
    uint32_t Weight = BP->getEdgeWeight(Src, Dst);
    uint32_t MaxWeight = getMaxWeightFor(Src);

    if (Weight * 2 > MaxWeight)
      BP->setEdgeWeight(Src, Dst, MaxWeight);
    else
      BP->setEdgeWeight(Src, Dst, Weight * 2);
  }

  // Divide Edge Weight by two.
  void decEdgeWeight(BasicBlock *Src, BasicBlock *Dst) {
    uint32_t Weight = BP->getEdgeWeight(Src, Dst);

    assert(Weight > 0);
    if (Weight / 2 < MIN_WEIGHT)
      BP->setEdgeWeight(Src, Dst, MIN_WEIGHT);
    else
      BP->setEdgeWeight(Src, Dst, Weight / 2);
  }

  uint32_t getMaxWeightFor(BasicBlock *BB) const {
    return UINT32_MAX / BB->getTerminator()->getNumSuccessors();
  }

public:
  BranchProbabilityAnalysis(DenseMap<Edge, uint32_t> *W,
                            BranchProbabilityInfo *BP, LoopInfo *LI)
    : Weights(W), BP(BP), LI(LI) {
  }

  // Return Heuristics
  void calcReturnHeuristics(BasicBlock *BB);

  // Pointer Heuristics
  void calcPointerHeuristics(BasicBlock *BB);

  // Loop Branch Heuristics
  void calcLoopBranchHeuristics(BasicBlock *BB);

  bool runOnFunction(Function &F);
};
} // end anonymous namespace

// Calculate Edge Weights using "Return Heuristics". Predict a successor which
// leads directly to Return Instruction will not be taken.
void BranchProbabilityAnalysis::calcReturnHeuristics(BasicBlock *BB){
  if (BB->getTerminator()->getNumSuccessors() == 1)
    return;

  for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
    BasicBlock *Succ = *I;
    if (isReturningBlock(Succ)) {
      decEdgeWeight(BB, Succ);
    }
  }
}

// Calculate Edge Weights using "Pointer Heuristics". Predict a comparsion
// between two pointer or pointer and NULL will fail.
void BranchProbabilityAnalysis::calcPointerHeuristics(BasicBlock *BB) {
  BranchInst * BI = dyn_cast<BranchInst>(BB->getTerminator());
  if (!BI || !BI->isConditional())
    return;

  Value *Cond = BI->getCondition();
  ICmpInst *CI = dyn_cast<ICmpInst>(Cond);
  if (!CI || !CI->isEquality())
    return;

  Value *LHS = CI->getOperand(0);

  if (!LHS->getType()->isPointerTy())
    return;

  assert(CI->getOperand(1)->getType()->isPointerTy());

  BasicBlock *Taken = BI->getSuccessor(0);
  BasicBlock *NonTaken = BI->getSuccessor(1);

  // p != 0   ->   isProb = true
  // p == 0   ->   isProb = false
  // p != q   ->   isProb = true
  // p == q   ->   isProb = false;
  bool isProb = CI->getPredicate() == ICmpInst::ICMP_NE;
  if (!isProb)
    std::swap(Taken, NonTaken);

  incEdgeWeight(BB, Taken);
  decEdgeWeight(BB, NonTaken);
}

// Calculate Edge Weights using "Loop Branch Heuristics". Predict backedges
// as taken, exiting edges as not-taken.
void BranchProbabilityAnalysis::calcLoopBranchHeuristics(BasicBlock *BB) {
  uint32_t numSuccs = BB->getTerminator()->getNumSuccessors();

  Loop *L = LI->getLoopFor(BB);
  if (!L)
    return;

  SmallVector<BasicBlock *, 8> BackEdges;
  SmallVector<BasicBlock *, 8> ExitingEdges;

  for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
    BasicBlock *Succ = *I;
    Loop *SuccL = LI->getLoopFor(Succ);
    if (SuccL != L)
      ExitingEdges.push_back(Succ);
    else if (Succ == L->getHeader())
      BackEdges.push_back(Succ);
  }

  if (uint32_t numBackEdges = BackEdges.size()) {
    uint32_t backWeight = LBH_TAKEN_WEIGHT / numBackEdges;
    if (backWeight < NORMAL_WEIGHT)
      backWeight = NORMAL_WEIGHT;

    for (SmallVector<BasicBlock *, 8>::iterator EI = BackEdges.begin(),
         EE = BackEdges.end(); EI != EE; ++EI) {
      BasicBlock *Back = *EI;
      BP->setEdgeWeight(BB, Back, backWeight);
    }
  }

  uint32_t numExitingEdges = ExitingEdges.size();
  if (uint32_t numNonExitingEdges = numSuccs - numExitingEdges) {
    uint32_t exitWeight = LBH_NONTAKEN_WEIGHT / numNonExitingEdges;
    if (exitWeight < MIN_WEIGHT)
      exitWeight = MIN_WEIGHT;

    for (SmallVector<BasicBlock *, 8>::iterator EI = ExitingEdges.begin(),
         EE = ExitingEdges.end(); EI != EE; ++EI) {
      BasicBlock *Exiting = *EI;
      BP->setEdgeWeight(BB, Exiting, exitWeight);
    }
  }
}

bool BranchProbabilityAnalysis::runOnFunction(Function &F) {

  for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
    BasicBlock *BB = I++;

    // Only LBH uses setEdgeWeight method.
    calcLoopBranchHeuristics(BB);

    // PH and RH use only incEdgeWeight and decEwdgeWeight methods to
    // not efface LBH results.
    calcPointerHeuristics(BB);
    calcReturnHeuristics(BB);
  }

  return false;
}

void BranchProbabilityInfo::getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired<LoopInfo>();
    AU.setPreservesAll();
}

bool BranchProbabilityInfo::runOnFunction(Function &F) {
  LoopInfo &LI = getAnalysis<LoopInfo>();
  BranchProbabilityAnalysis BPA(&Weights, this, &LI);
  return BPA.runOnFunction(F);
}

uint32_t BranchProbabilityInfo::getSumForBlock(BasicBlock *BB) const {
  uint32_t Sum = 0;

  for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
    BasicBlock *Succ = *I;
    uint32_t Weight = getEdgeWeight(BB, Succ);
    uint32_t PrevSum = Sum;

    Sum += Weight;
    assert(Sum > PrevSum); (void) PrevSum;
  }

  return Sum;
}

bool BranchProbabilityInfo::isEdgeHot(BasicBlock *Src, BasicBlock *Dst) const {
  // Hot probability is at least 4/5 = 80%
  uint32_t Weight = getEdgeWeight(Src, Dst);
  uint32_t Sum = getSumForBlock(Src);

  // FIXME: Implement BranchProbability::compare then change this code to
  // compare this BranchProbability against a static "hot" BranchProbability.
  return (uint64_t)Weight * 5 > (uint64_t)Sum * 4;
}

BasicBlock *BranchProbabilityInfo::getHotSucc(BasicBlock *BB) const {
  uint32_t Sum = 0;
  uint32_t MaxWeight = 0;
  BasicBlock *MaxSucc = 0;

  for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
    BasicBlock *Succ = *I;
    uint32_t Weight = getEdgeWeight(BB, Succ);
    uint32_t PrevSum = Sum;

    Sum += Weight;
    assert(Sum > PrevSum); (void) PrevSum;

    if (Weight > MaxWeight) {
      MaxWeight = Weight;
      MaxSucc = Succ;
    }
  }

  // FIXME: Use BranchProbability::compare.
  if ((uint64_t)MaxWeight * 5 > (uint64_t)Sum * 4)
    return MaxSucc;

  return 0;
}

// Return edge's weight. If can't find it, return DEFAULT_WEIGHT value.
uint32_t
BranchProbabilityInfo::getEdgeWeight(BasicBlock *Src, BasicBlock *Dst) const {
  Edge E(Src, Dst);
  DenseMap<Edge, uint32_t>::const_iterator I = Weights.find(E);

  if (I != Weights.end())
    return I->second;

  return DEFAULT_WEIGHT;
}

void BranchProbabilityInfo::setEdgeWeight(BasicBlock *Src, BasicBlock *Dst,
                                     uint32_t Weight) {
  Weights[std::make_pair(Src, Dst)] = Weight;
  DEBUG(dbgs() << "set edge " << Src->getNameStr() << " -> "
               << Dst->getNameStr() << " weight to " << Weight
               << (isEdgeHot(Src, Dst) ? " [is HOT now]\n" : "\n"));
}

BranchProbability BranchProbabilityInfo::
getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const {

  uint32_t N = getEdgeWeight(Src, Dst);
  uint32_t D = getSumForBlock(Src);

  return BranchProbability(N, D);
}

raw_ostream &
BranchProbabilityInfo::printEdgeProbability(raw_ostream &OS, BasicBlock *Src,
                                            BasicBlock *Dst) const {

  const BranchProbability Prob = getEdgeProbability(Src, Dst);
  OS << "edge " << Src->getNameStr() << " -> " << Dst->getNameStr()
     << " probability is " << Prob
     << (isEdgeHot(Src, Dst) ? " [HOT edge]\n" : "\n");

  return OS;
}
<commit_msg>Add InEdges (edges from header to the loop) in Loop Branch Heuristics, so there is no frequency difference whether condition is in the header or in the latch.<commit_after>//===-- BranchProbabilityInfo.cpp - Branch Probability Analysis -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Loops should be simplified before this analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Instructions.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

INITIALIZE_PASS_BEGIN(BranchProbabilityInfo, "branch-prob",
                      "Branch Probability Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
INITIALIZE_PASS_END(BranchProbabilityInfo, "branch-prob",
                    "Branch Probability Analysis", false, true)

char BranchProbabilityInfo::ID = 0;

namespace {
// Please note that BranchProbabilityAnalysis is not a FunctionPass.
// It is created by BranchProbabilityInfo (which is a FunctionPass), which
// provides a clear interface. Thanks to that, all heuristics and other
// private methods are hidden in the .cpp file.
class BranchProbabilityAnalysis {

  typedef std::pair<BasicBlock *, BasicBlock *> Edge;

  DenseMap<Edge, uint32_t> *Weights;

  BranchProbabilityInfo *BP;

  LoopInfo *LI;

  // Weights are for internal use only. They are used by heuristics to help to
  // estimate edges' probability. Example:
  //
  // Using "Loop Branch Heuristics" we predict weights of edges for the
  // block BB2.
  //         ...
  //          |
  //          V
  //         BB1<-+
  //          |   |
  //          |   | (Weight = 128)
  //          V   |
  //         BB2--+
  //          |
  //          | (Weight = 4)
  //          V
  //         BB3
  //
  // Probability of the edge BB2->BB1 = 128 / (128 + 4) = 0.9696..
  // Probability of the edge BB2->BB3 = 4 / (128 + 4) = 0.0303..

  static const uint32_t LBH_TAKEN_WEIGHT = 128;
  static const uint32_t LBH_NONTAKEN_WEIGHT = 4;

  // Standard weight value. Used when none of the heuristics set weight for
  // the edge.
  static const uint32_t NORMAL_WEIGHT = 16;

  // Minimum weight of an edge. Please note, that weight is NEVER 0.
  static const uint32_t MIN_WEIGHT = 1;

  // Return TRUE if BB leads directly to a Return Instruction.
  static bool isReturningBlock(BasicBlock *BB) {
    SmallPtrSet<BasicBlock *, 8> Visited;

    while (true) {
      TerminatorInst *TI = BB->getTerminator();
      if (isa<ReturnInst>(TI))
        return true;

      if (TI->getNumSuccessors() > 1)
        break;

      // It is unreachable block which we can consider as a return instruction.
      if (TI->getNumSuccessors() == 0)
        return true;

      Visited.insert(BB);
      BB = TI->getSuccessor(0);

      // Stop if cycle is detected.
      if (Visited.count(BB))
        return false;
    }

    return false;
  }

  // Multiply Edge Weight by two.
  void incEdgeWeight(BasicBlock *Src, BasicBlock *Dst) {
    uint32_t Weight = BP->getEdgeWeight(Src, Dst);
    uint32_t MaxWeight = getMaxWeightFor(Src);

    if (Weight * 2 > MaxWeight)
      BP->setEdgeWeight(Src, Dst, MaxWeight);
    else
      BP->setEdgeWeight(Src, Dst, Weight * 2);
  }

  // Divide Edge Weight by two.
  void decEdgeWeight(BasicBlock *Src, BasicBlock *Dst) {
    uint32_t Weight = BP->getEdgeWeight(Src, Dst);

    assert(Weight > 0);
    if (Weight / 2 < MIN_WEIGHT)
      BP->setEdgeWeight(Src, Dst, MIN_WEIGHT);
    else
      BP->setEdgeWeight(Src, Dst, Weight / 2);
  }

  uint32_t getMaxWeightFor(BasicBlock *BB) const {
    return UINT32_MAX / BB->getTerminator()->getNumSuccessors();
  }

public:
  BranchProbabilityAnalysis(DenseMap<Edge, uint32_t> *W,
                            BranchProbabilityInfo *BP, LoopInfo *LI)
    : Weights(W), BP(BP), LI(LI) {
  }

  // Return Heuristics
  void calcReturnHeuristics(BasicBlock *BB);

  // Pointer Heuristics
  void calcPointerHeuristics(BasicBlock *BB);

  // Loop Branch Heuristics
  void calcLoopBranchHeuristics(BasicBlock *BB);

  bool runOnFunction(Function &F);
};
} // end anonymous namespace

// Calculate Edge Weights using "Return Heuristics". Predict a successor which
// leads directly to Return Instruction will not be taken.
void BranchProbabilityAnalysis::calcReturnHeuristics(BasicBlock *BB){
  if (BB->getTerminator()->getNumSuccessors() == 1)
    return;

  for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
    BasicBlock *Succ = *I;
    if (isReturningBlock(Succ)) {
      decEdgeWeight(BB, Succ);
    }
  }
}

// Calculate Edge Weights using "Pointer Heuristics". Predict a comparsion
// between two pointer or pointer and NULL will fail.
void BranchProbabilityAnalysis::calcPointerHeuristics(BasicBlock *BB) {
  BranchInst * BI = dyn_cast<BranchInst>(BB->getTerminator());
  if (!BI || !BI->isConditional())
    return;

  Value *Cond = BI->getCondition();
  ICmpInst *CI = dyn_cast<ICmpInst>(Cond);
  if (!CI || !CI->isEquality())
    return;

  Value *LHS = CI->getOperand(0);

  if (!LHS->getType()->isPointerTy())
    return;

  assert(CI->getOperand(1)->getType()->isPointerTy());

  BasicBlock *Taken = BI->getSuccessor(0);
  BasicBlock *NonTaken = BI->getSuccessor(1);

  // p != 0   ->   isProb = true
  // p == 0   ->   isProb = false
  // p != q   ->   isProb = true
  // p == q   ->   isProb = false;
  bool isProb = CI->getPredicate() == ICmpInst::ICMP_NE;
  if (!isProb)
    std::swap(Taken, NonTaken);

  incEdgeWeight(BB, Taken);
  decEdgeWeight(BB, NonTaken);
}

// Calculate Edge Weights using "Loop Branch Heuristics". Predict backedges
// as taken, exiting edges as not-taken.
void BranchProbabilityAnalysis::calcLoopBranchHeuristics(BasicBlock *BB) {
  uint32_t numSuccs = BB->getTerminator()->getNumSuccessors();

  Loop *L = LI->getLoopFor(BB);
  if (!L)
    return;

  SmallVector<BasicBlock *, 8> BackEdges;
  SmallVector<BasicBlock *, 8> ExitingEdges;
  SmallVector<BasicBlock *, 8> InEdges; // Edges from header to the loop.

  bool isHeader = BB == L->getHeader();

  for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
    BasicBlock *Succ = *I;
    Loop *SuccL = LI->getLoopFor(Succ);
    if (SuccL != L)
      ExitingEdges.push_back(Succ);
    else if (Succ == L->getHeader())
      BackEdges.push_back(Succ);
    else if (isHeader)
      InEdges.push_back(Succ);
  }

  if (uint32_t numBackEdges = BackEdges.size()) {
    uint32_t backWeight = LBH_TAKEN_WEIGHT / numBackEdges;
    if (backWeight < NORMAL_WEIGHT)
      backWeight = NORMAL_WEIGHT;

    for (SmallVector<BasicBlock *, 8>::iterator EI = BackEdges.begin(),
         EE = BackEdges.end(); EI != EE; ++EI) {
      BasicBlock *Back = *EI;
      BP->setEdgeWeight(BB, Back, backWeight);
    }
  }

  if (uint32_t numInEdges = InEdges.size()) {
    uint32_t inWeight = LBH_TAKEN_WEIGHT / numInEdges;
    if (inWeight < NORMAL_WEIGHT)
      inWeight = NORMAL_WEIGHT;

    for (SmallVector<BasicBlock *, 8>::iterator EI = InEdges.begin(),
         EE = InEdges.end(); EI != EE; ++EI) {
      BasicBlock *Back = *EI;
      BP->setEdgeWeight(BB, Back, inWeight);
    }
  }

  uint32_t numExitingEdges = ExitingEdges.size();
  if (uint32_t numNonExitingEdges = numSuccs - numExitingEdges) {
    uint32_t exitWeight = LBH_NONTAKEN_WEIGHT / numNonExitingEdges;
    if (exitWeight < MIN_WEIGHT)
      exitWeight = MIN_WEIGHT;

    for (SmallVector<BasicBlock *, 8>::iterator EI = ExitingEdges.begin(),
         EE = ExitingEdges.end(); EI != EE; ++EI) {
      BasicBlock *Exiting = *EI;
      BP->setEdgeWeight(BB, Exiting, exitWeight);
    }
  }
}

bool BranchProbabilityAnalysis::runOnFunction(Function &F) {

  for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
    BasicBlock *BB = I++;

    // Only LBH uses setEdgeWeight method.
    calcLoopBranchHeuristics(BB);

    // PH and RH use only incEdgeWeight and decEwdgeWeight methods to
    // not efface LBH results.
    calcPointerHeuristics(BB);
    calcReturnHeuristics(BB);
  }

  return false;
}

void BranchProbabilityInfo::getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired<LoopInfo>();
    AU.setPreservesAll();
}

bool BranchProbabilityInfo::runOnFunction(Function &F) {
  LoopInfo &LI = getAnalysis<LoopInfo>();
  BranchProbabilityAnalysis BPA(&Weights, this, &LI);
  return BPA.runOnFunction(F);
}

uint32_t BranchProbabilityInfo::getSumForBlock(BasicBlock *BB) const {
  uint32_t Sum = 0;

  for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
    BasicBlock *Succ = *I;
    uint32_t Weight = getEdgeWeight(BB, Succ);
    uint32_t PrevSum = Sum;

    Sum += Weight;
    assert(Sum > PrevSum); (void) PrevSum;
  }

  return Sum;
}

bool BranchProbabilityInfo::isEdgeHot(BasicBlock *Src, BasicBlock *Dst) const {
  // Hot probability is at least 4/5 = 80%
  uint32_t Weight = getEdgeWeight(Src, Dst);
  uint32_t Sum = getSumForBlock(Src);

  // FIXME: Implement BranchProbability::compare then change this code to
  // compare this BranchProbability against a static "hot" BranchProbability.
  return (uint64_t)Weight * 5 > (uint64_t)Sum * 4;
}

BasicBlock *BranchProbabilityInfo::getHotSucc(BasicBlock *BB) const {
  uint32_t Sum = 0;
  uint32_t MaxWeight = 0;
  BasicBlock *MaxSucc = 0;

  for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
    BasicBlock *Succ = *I;
    uint32_t Weight = getEdgeWeight(BB, Succ);
    uint32_t PrevSum = Sum;

    Sum += Weight;
    assert(Sum > PrevSum); (void) PrevSum;

    if (Weight > MaxWeight) {
      MaxWeight = Weight;
      MaxSucc = Succ;
    }
  }

  // FIXME: Use BranchProbability::compare.
  if ((uint64_t)MaxWeight * 5 > (uint64_t)Sum * 4)
    return MaxSucc;

  return 0;
}

// Return edge's weight. If can't find it, return DEFAULT_WEIGHT value.
uint32_t
BranchProbabilityInfo::getEdgeWeight(BasicBlock *Src, BasicBlock *Dst) const {
  Edge E(Src, Dst);
  DenseMap<Edge, uint32_t>::const_iterator I = Weights.find(E);

  if (I != Weights.end())
    return I->second;

  return DEFAULT_WEIGHT;
}

void BranchProbabilityInfo::setEdgeWeight(BasicBlock *Src, BasicBlock *Dst,
                                     uint32_t Weight) {
  Weights[std::make_pair(Src, Dst)] = Weight;
  DEBUG(dbgs() << "set edge " << Src->getNameStr() << " -> "
               << Dst->getNameStr() << " weight to " << Weight
               << (isEdgeHot(Src, Dst) ? " [is HOT now]\n" : "\n"));
}

BranchProbability BranchProbabilityInfo::
getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const {

  uint32_t N = getEdgeWeight(Src, Dst);
  uint32_t D = getSumForBlock(Src);

  return BranchProbability(N, D);
}

raw_ostream &
BranchProbabilityInfo::printEdgeProbability(raw_ostream &OS, BasicBlock *Src,
                                            BasicBlock *Dst) const {

  const BranchProbability Prob = getEdgeProbability(Src, Dst);
  OS << "edge " << Src->getNameStr() << " -> " << Dst->getNameStr()
     << " probability is " << Prob
     << (isEdgeHot(Src, Dst) ? " [HOT edge]\n" : "\n");

  return OS;
}
<|endoftext|>


<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkGraphics.h"
#include "Test.h"

using namespace skiatest;

// need to explicitly declare this, or we get some weird infinite loop llist
template TestRegistry* TestRegistry::gHead;

class Iter {
public:
    Iter(Reporter* r) : fReporter(r) {
        r->ref();
        fReg = TestRegistry::Head();
    }

    ~Iter() {
        fReporter->unref();
    }

    Test* next() {
        if (fReg) {
            TestRegistry::Factory fact = fReg->factory();
            fReg = fReg->next();
            Test* test = fact(NULL);
            test->setReporter(fReporter);
            return test;
        }
        return NULL;
    }

    static int Count() {
        const TestRegistry* reg = TestRegistry::Head();
        int count = 0;
        while (reg) {
            count += 1;
            reg = reg->next();
        }
        return count;
    }

private:
    Reporter* fReporter;
    const TestRegistry* fReg;
};

static const char* result2string(Reporter::Result result) {
    return result == Reporter::kPassed ? "passed" : "FAILED";
}

class DebugfReporter : public Reporter {
public:
    DebugfReporter(bool androidMode) : fAndroidMode(androidMode) {}

    void setIndexOfTotal(int index, int total) {
        fIndex = index;
        fTotal = total;
    }
protected:
    virtual void onStart(Test* test) {
        this->dumpState(test, kStarting_State);
    }
    virtual void onReport(const char desc[], Reporter::Result result) {
        if (!fAndroidMode) {
            SkDebugf("\t%s: %s\n", result2string(result), desc);
        }
    }
    virtual void onEnd(Test* test) {
        this->dumpState(test, this->getCurrSuccess() ?
                        kSucceeded_State : kFailed_State);
    }
private:
    enum State {
        kStarting_State = 1,
        kSucceeded_State = 0,
        kFailed_State = -2
    };

    void dumpState(Test* test, State state) {
        if (fAndroidMode) {
            SkDebugf("INSTRUMENTATION_STATUS: test=%s\n", test->getName());
            SkDebugf("INSTRUMENTATION_STATUS: class=com.skia\n");
            SkDebugf("INSTRUMENTATION_STATUS: current=%d\n", fIndex+1);
            SkDebugf("INSTRUMENTATION_STATUS: numtests=%d\n", fTotal);
            SkDebugf("INSTRUMENTATION_STATUS_CODE: %d\n", state);
        } else {
            if (kStarting_State == state) {
                SkDebugf("[%d/%d] %s...\n", fIndex+1, fTotal, test->getName());
            } else if (kFailed_State == state) {
                SkDebugf("---- FAILED\n");
            }
        }
    }

    int fIndex, fTotal;
    bool fAndroidMode;
};

int main (int argc, char * const argv[]) {
    SkAutoGraphics ag;

    bool androidMode = false;
    const char* matchStr = NULL;

    char* const* stop = argv + argc;
    for (++argv; argv < stop; ++argv) {
        if (strcmp(*argv, "-android") == 0) {
            androidMode = true;

        } else if (strcmp(*argv, "--match") == 0) {
            ++argv;
            if (argv < stop && **argv) {
                matchStr = *argv;
            }
        }
    }

    {
        SkString header("Skia UnitTests:");
        if (matchStr) {
            header.appendf(" --match %s", matchStr);
        }
#ifdef SK_DEBUG
        header.append(" SK_DEBUG");
#else
        header.append(" SK_RELEASE");
#endif
#ifdef SK_SCALAR_IS_FIXED
        header.append(" SK_SCALAR_IS_FIXED");
#else
        header.append(" SK_SCALAR_IS_FLOAT");
#endif
        if (!androidMode) {
            SkDebugf("%s\n", header.c_str());
        }
    }

    DebugfReporter reporter(androidMode);
    Iter iter(&reporter);
    Test* test;

    const int count = Iter::Count();
    int index = 0;
    int failCount = 0;
    int skipCount = 0;
    while ((test = iter.next()) != NULL) {
        reporter.setIndexOfTotal(index, count);
        if (NULL != matchStr && !strstr(test->getName(), matchStr)) {
            ++skipCount;
        } else {
            if (!test->run()) {
                ++failCount;
            }
        }
        SkDELETE(test);
        index += 1;
    }

    if (!androidMode) {
        SkDebugf("Finished %d tests, %d failures, %d skipped.\n",
                 count, failCount, skipCount);
    }
    return (failCount == 0) ? 0 : 1;
}
<commit_msg>check for memory leaks in debug-build<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkGraphics.h"
#include "Test.h"

using namespace skiatest;

// need to explicitly declare this, or we get some weird infinite loop llist
template TestRegistry* TestRegistry::gHead;

class Iter {
public:
    Iter(Reporter* r) : fReporter(r) {
        r->ref();
        fReg = TestRegistry::Head();
    }

    ~Iter() {
        fReporter->unref();
    }

    Test* next() {
        if (fReg) {
            TestRegistry::Factory fact = fReg->factory();
            fReg = fReg->next();
            Test* test = fact(NULL);
            test->setReporter(fReporter);
            return test;
        }
        return NULL;
    }

    static int Count() {
        const TestRegistry* reg = TestRegistry::Head();
        int count = 0;
        while (reg) {
            count += 1;
            reg = reg->next();
        }
        return count;
    }

private:
    Reporter* fReporter;
    const TestRegistry* fReg;
};

static const char* result2string(Reporter::Result result) {
    return result == Reporter::kPassed ? "passed" : "FAILED";
}

class DebugfReporter : public Reporter {
public:
    DebugfReporter(bool androidMode) : fAndroidMode(androidMode) {}

    void setIndexOfTotal(int index, int total) {
        fIndex = index;
        fTotal = total;
    }
protected:
    virtual void onStart(Test* test) {
        this->dumpState(test, kStarting_State);
    }
    virtual void onReport(const char desc[], Reporter::Result result) {
        if (!fAndroidMode) {
            SkDebugf("\t%s: %s\n", result2string(result), desc);
        }
    }
    virtual void onEnd(Test* test) {
        this->dumpState(test, this->getCurrSuccess() ?
                        kSucceeded_State : kFailed_State);
    }
private:
    enum State {
        kStarting_State = 1,
        kSucceeded_State = 0,
        kFailed_State = -2
    };

    void dumpState(Test* test, State state) {
        if (fAndroidMode) {
            SkDebugf("INSTRUMENTATION_STATUS: test=%s\n", test->getName());
            SkDebugf("INSTRUMENTATION_STATUS: class=com.skia\n");
            SkDebugf("INSTRUMENTATION_STATUS: current=%d\n", fIndex+1);
            SkDebugf("INSTRUMENTATION_STATUS: numtests=%d\n", fTotal);
            SkDebugf("INSTRUMENTATION_STATUS_CODE: %d\n", state);
        } else {
            if (kStarting_State == state) {
                SkDebugf("[%d/%d] %s...\n", fIndex+1, fTotal, test->getName());
            } else if (kFailed_State == state) {
                SkDebugf("---- FAILED\n");
            }
        }
    }

    int fIndex, fTotal;
    bool fAndroidMode;
};

int main (int argc, char * const argv[]) {
#ifdef SK_ENABLE_INST_COUNT
    gPrintInstCount = true;
#endif
    SkGraphics::Init();

    bool androidMode = false;
    const char* matchStr = NULL;

    char* const* stop = argv + argc;
    for (++argv; argv < stop; ++argv) {
        if (strcmp(*argv, "-android") == 0) {
            androidMode = true;

        } else if (strcmp(*argv, "--match") == 0) {
            ++argv;
            if (argv < stop && **argv) {
                matchStr = *argv;
            }
        }
    }

    {
        SkString header("Skia UnitTests:");
        if (matchStr) {
            header.appendf(" --match %s", matchStr);
        }
#ifdef SK_DEBUG
        header.append(" SK_DEBUG");
#else
        header.append(" SK_RELEASE");
#endif
#ifdef SK_SCALAR_IS_FIXED
        header.append(" SK_SCALAR_IS_FIXED");
#else
        header.append(" SK_SCALAR_IS_FLOAT");
#endif
        if (!androidMode) {
            SkDebugf("%s\n", header.c_str());
        }
    }

    DebugfReporter reporter(androidMode);
    Iter iter(&reporter);
    Test* test;

    const int count = Iter::Count();
    int index = 0;
    int failCount = 0;
    int skipCount = 0;
    while ((test = iter.next()) != NULL) {
        reporter.setIndexOfTotal(index, count);
        if (NULL != matchStr && !strstr(test->getName(), matchStr)) {
            ++skipCount;
        } else {
            if (!test->run()) {
                ++failCount;
            }
        }
        SkDELETE(test);
        index += 1;
    }

    if (!androidMode) {
        SkDebugf("Finished %d tests, %d failures, %d skipped.\n",
                 count, failCount, skipCount);
    }

    SkGraphics::Term();

    return (failCount == 0) ? 0 : 1;
}
<|endoftext|>


<commit_before>/**
 * main of session manager
 *
 * Copyright 2013 Thincast Technologies GmbH
 * Copyright 2013 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <signal.h>
#include <fcntl.h>

#include <appcontext/ApplicationContext.h>

#include <winpr/wtypes.h>
#include <winpr/synch.h>
#include <winpr/cmdline.h>
#include <winpr/path.h>

#include <iostream>

using namespace std;

static HANDLE gTermEvent;

void shutdown(int signal)
{
	fprintf(stderr, "Shutdown due to signal %d\n", signal);
	SetEvent(gTermEvent);
}

COMMAND_LINE_ARGUMENT_A freerds_session_manager_args[] =
{
	{ "kill", COMMAND_LINE_VALUE_FLAG, "", NULL, NULL, -1, NULL, "kill daemon" },
	{ "nodaemon", COMMAND_LINE_VALUE_FLAG, "", NULL, NULL, -1, NULL, "no daemon" },
	{ "config", COMMAND_LINE_VALUE_REQUIRED, "<configfile>", "1024x768", NULL, -1, NULL, "set config file" },
	{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};

int main(int argc, char** argv)
{
	int pid;
	FILE* fd;
	int status;
	DWORD flags;
	int no_daemon;
	int kill_process;
	char text[256];
	char pid_file[256];
	COMMAND_LINE_ARGUMENT_A* arg;
	char * configFileName = 0;

	no_daemon = kill_process = 0;

	flags = 0;
	flags |= COMMAND_LINE_SIGIL_DASH;
	flags |= COMMAND_LINE_SIGIL_DOUBLE_DASH;
	flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
	flags |= COMMAND_LINE_SEPARATOR_COLON;

	status = CommandLineParseArgumentsA(argc, (const char**) argv,
			freerds_session_manager_args, flags, NULL, NULL, NULL);

	arg = freerds_session_manager_args;

	do
	{
		if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
			continue;

		CommandLineSwitchStart(arg)

		CommandLineSwitchCase(arg, "kill")
		{
			kill_process = 1;
		}
		CommandLineSwitchCase(arg, "nodaemon")
		{
			no_daemon = 1;
		}
		CommandLineSwitchCase(arg, "config")
		{
			configFileName = arg->Value;
		}
		CommandLineSwitchEnd(arg)
	}
	while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);

	sprintf_s(pid_file, 255, "%s/freerds-sessionmanager.pid", FREERDS_PID_PATH);

	if (kill_process)
	{
		printf("stopping FreeRDS\n");

		fd = NULL;

		if (PathFileExistsA(pid_file))
		{
			fd = fopen(pid_file, "r");
		}

		if (!fd)
		{
			printf("problem opening freerds-sessionmanager.pid [%s]\n", pid_file);
			printf("maybe its not running\n");
		}
		else
		{
			ZeroMemory(text, 32);
			fread((void*) text, 31, 1, fd);
			pid = atoi(text);
			printf("stopping process id %d\n", pid);

			if (pid > 0)
			{
				kill(pid, SIGTERM);
			}

			fclose(fd);
		}

		return 0;
	}

	if (PathFileExistsA(pid_file))
	{
		printf("It looks like FreeRDS Session Manager is already running,\n");
		printf("if not delete the freerds-sessionmanager.pid file and try again\n");
		return 0;
	}

	if (!no_daemon)
	{
		if (!PathFileExistsA(FREERDS_VAR_PATH))
			CreateDirectoryA(FREERDS_VAR_PATH, NULL);

		if (!PathFileExistsA(FREERDS_PID_PATH))
			CreateDirectoryA(FREERDS_PID_PATH, NULL);

		/* make sure we can write to pid file */
		fd = fopen(pid_file, "w+");

		if (!fd)
		{
			printf("running in daemon mode with no access to pid files, quitting\n");
			return 0;
		}

		if (fwrite((void*) "0", 1, 1, fd) == -1)
		{
			printf("running in daemon mode with no access to pid files, quitting\n");
			return 0;
		}

		fclose(fd);
		DeleteFileA(pid_file);
	}

	if (!no_daemon)
	{
		/* start of daemonizing code */
		pid = fork();

		if (pid == -1)
		{
			printf("problem forking\n");
			return 1;
		}

		if (0 != pid)
		{
			printf("process %d started\n", pid);
			return 0;
		}

		Sleep(1000);

		/* write the pid to file */
		pid = GetCurrentProcessId();
		fd = fopen(pid_file, "w+");

		if (!fd)
		{
			printf("trying to write process id to freerds.pid\n");
			printf("problem opening freerds.pid\n");
		}
		else
		{
			sprintf_s(text, sizeof(text), "%d", pid);
			fwrite((void*) text, strlen(text), 1, fd);
			fclose(fd);
		}

		Sleep(1000);
		close(0);
		close(1);
		close(2);
		open("/dev/null", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
		open("/dev/null", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
		open("/dev/null", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
		/* end of daemonizing code */
	}

	signal(SIGINT, shutdown);
	signal(SIGKILL, shutdown);
	signal(SIGTERM, shutdown);

	/*
	 * Ignore SIGPIPE - This can occur normally due to the use of
	 * named pipes as a means of interprocess communication.  It
	 * shouldn't result in terminating the entire process.
	 */
	signal(SIGPIPE, SIG_IGN);

	pid = GetCurrentProcessId();

	APP_CONTEXT.startRPCEngine();
	APP_CONTEXT.loadModulesFromPath(APP_CONTEXT.getLibraryPath());

	if (configFileName) {
		std::string name(configFileName);
		APP_CONTEXT.getPropertyManager()->loadProperties(configFileName);

	} else {
		APP_CONTEXT.getPropertyManager()->loadProperties(APP_CONTEXT.getSystemConfigPath() + "/config.ini");
	}
	//APP_CONTEXT.getPropertyManager()->saveProperties(APP_CONTEXT.getSystemConfigPath() + "/config.ini");

	APP_CONTEXT.startTaskExecutor();
	APP_CONTEXT.startSessionTimoutMonitor();

	cout << "Hello session manager" << endl;

	gTermEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	WaitForSingleObject(gTermEvent, INFINITE);
	CloseHandle(gTermEvent);

	APP_CONTEXT.stopTaskExecutor();
	APP_CONTEXT.stopRPCEngine();

	/* only main process should delete pid file */
	if ((!no_daemon) && (pid == GetCurrentProcessId()))
	{
		DeleteFileA(pid_file);
	}

	return 0;
}
<commit_msg>freerds-manager: cleanup main.cpp<commit_after>/**
 * main of session manager
 *
 * Copyright 2013 Thincast Technologies GmbH
 * Copyright 2013 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <signal.h>
#include <fcntl.h>

#include <iostream>

#include <appcontext/ApplicationContext.h>

#include <winpr/wtypes.h>
#include <winpr/synch.h>
#include <winpr/cmdline.h>
#include <winpr/path.h>

#define FREERDS_PID_FILE	"freerds-manager.pid"

static HANDLE g_TermEvent = NULL;

void shutdown(int signal)
{
	fprintf(stderr, "shutdown due to signal %d\n", signal);

	if (g_TermEvent)
		SetEvent(g_TermEvent);
}

COMMAND_LINE_ARGUMENT_A freerds_session_manager_args[] =
{
	{ "kill", COMMAND_LINE_VALUE_FLAG, "", NULL, NULL, -1, NULL, "kill daemon" },
	{ "no-daemon", COMMAND_LINE_VALUE_FLAG, "", NULL, NULL, -1, "nodaemon", "no daemon" },
	{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};

int freerds_kill_daemon(const char* pid_file)
{
	int pid;
	char text[32];
	FILE* fd = NULL;

	if (PathFileExistsA(pid_file))
	{
		fd = fopen(pid_file, "r");
	}

	if (!fd)
		return -1;

	ZeroMemory(text, sizeof(text));
	fread((void*) text, sizeof(text) - 1, 1, fd);
	fclose(fd);

	pid = atoi(text);

	if (pid <= 0)
		return -1;

	fprintf(stderr, "stopping FreeRDS manager (pid %d)\n", pid);

	kill(pid, SIGTERM);

	return 1;
}

int freerds_daemonize_process(const char* pid_file)
{
	int pid;
	FILE* fd;
	char text[32];

	if (!PathFileExistsA(FREERDS_VAR_PATH))
		CreateDirectoryA(FREERDS_VAR_PATH, NULL);

	if (!PathFileExistsA(FREERDS_PID_PATH))
		CreateDirectoryA(FREERDS_PID_PATH, NULL);

	/* make sure we can write to pid file */

	fd = fopen(pid_file, "w+");

	if (!fd)
		return -1;

	if (fwrite((void*) "0", 1, 1, fd) == -1)
		return -1;

	fclose(fd);
	DeleteFileA(pid_file);

	/* start of daemonizing code */

	pid = fork();

	if (pid < 0)
		return -1;

	if (0 != pid)
	{
		/* parent process */
		fprintf(stderr, "starting FreeRDS manager (pid %d)\n", pid);
		return 0;
	}

	/* write the pid to file */

	pid = GetCurrentProcessId();

	fd = fopen(pid_file, "w+");

	if (!fd)
	{
		fprintf(stderr, "problem opening pid file: %s\n", pid_file);
	}
	else
	{
		sprintf_s(text, sizeof(text) - 1, "%d", pid);
		fwrite((void*) text, strlen(text), 1, fd);
		fclose(fd);
	}

	close(0);
	close(1);
	close(2);

	open("/dev/null", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
	open("/dev/null", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
	open("/dev/null", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

	/* end of daemonizing code */

	return 1;
}

int main(int argc, char** argv)
{
	int status;
	DWORD flags;
	BOOL daemon;
	BOOL kill_process;
	char pid_file[256];
	COMMAND_LINE_ARGUMENT_A* arg;

	daemon = TRUE;
	kill_process = FALSE;

	flags = 0;
	flags |= COMMAND_LINE_SIGIL_DASH;
	flags |= COMMAND_LINE_SIGIL_DOUBLE_DASH;
	flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
	flags |= COMMAND_LINE_SEPARATOR_COLON;

	status = CommandLineParseArgumentsA(argc, (const char**) argv,
			freerds_session_manager_args, flags, NULL, NULL, NULL);

	arg = freerds_session_manager_args;

	do
	{
		if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
			continue;

		CommandLineSwitchStart(arg)

		CommandLineSwitchCase(arg, "kill")
		{
			kill_process = TRUE;
		}
		CommandLineSwitchCase(arg, "no-daemon")
		{
			daemon = FALSE;
		}
		CommandLineSwitchEnd(arg)
	}
	while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);

	sprintf_s(pid_file, sizeof(pid_file), "%s/%s", FREERDS_PID_PATH, FREERDS_PID_FILE);

	if (kill_process)
	{
		status = freerds_kill_daemon(pid_file);
		return 0;
	}

	if (PathFileExistsA(pid_file))
	{
		fprintf(stderr, "The FreeRDS manager appears to be running\n");
		fprintf(stderr, "If this is not the case, delete %s and try again\n", pid_file);
		return 0;
	}

	if (daemon)
	{
		status = freerds_daemonize_process(pid_file);

		if (!status)
			return 0; /* parent process */

		if (status < 0)
			return 1;
	}

	g_TermEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	signal(SIGINT, shutdown);
	signal(SIGKILL, shutdown);
	signal(SIGTERM, shutdown);

	/*
	 * Ignore SIGPIPE - This can occur normally due to the use of
	 * named pipes as a means of interprocess communication.
	 * It shouldn't result in terminating the entire process.
	 */
	signal(SIGPIPE, SIG_IGN);

	APP_CONTEXT.startRPCEngine();
	APP_CONTEXT.loadModulesFromPath(APP_CONTEXT.getLibraryPath());

	APP_CONTEXT.getPropertyManager()->loadProperties(APP_CONTEXT.getSystemConfigPath() + "/config.ini");
	APP_CONTEXT.getPropertyManager()->saveProperties(APP_CONTEXT.getSystemConfigPath() + "/config.ini");

	APP_CONTEXT.startTaskExecutor();
	APP_CONTEXT.startSessionTimoutMonitor();

	WaitForSingleObject(g_TermEvent, INFINITE);
	CloseHandle(g_TermEvent);
	g_TermEvent = NULL;

	APP_CONTEXT.stopTaskExecutor();
	APP_CONTEXT.stopRPCEngine();

	DeleteFileA(pid_file);

	return 0;
}
<|endoftext|>