<commit_before>#ifndef ENTT_META_CONTAINER_HPP
#define ENTT_META_CONTAINER_HPP

#include <array>
#include <map>
#include <set>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "../container/dense_map.hpp"
#include "../container/dense_set.hpp"
#include "meta.hpp"
#include "type_traits.hpp"

namespace entt {

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

template<typename, typename = void>
struct is_dynamic_sequence_container: std::false_type {};

template<typename Type>
struct is_dynamic_sequence_container<Type, std::void_t<decltype(&Type::reserve)>>: std::true_type {};

template<typename, typename = void>
struct is_key_only_meta_associative_container: std::true_type {};

template<typename Type>
struct is_key_only_meta_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {};

template<typename Type>
struct basic_meta_sequence_container_traits {
    using iterator = meta_sequence_container::iterator;
    using size_type = std::size_t;

    [[nodiscard]] static size_type size(const any &container) noexcept {
        return any_cast<const Type &>(container).size();
    }

    [[nodiscard]] static bool resize([[maybe_unused]] any &container, [[maybe_unused]] size_type sz) {
        if constexpr(is_dynamic_sequence_container<Type>::value) {
            if(auto *const cont = any_cast<Type>(&container); cont) {
                cont->resize(sz);
                return true;
            }
        }

        return false;
    }

    [[nodiscard]] static iterator iter(any &container, const bool as_end) {
        if(auto *const cont = any_cast<Type>(&container); cont) {
            return iterator{*cont, static_cast<typename iterator::difference_type>(as_end * cont->size())};
        }

        const Type &as_const = any_cast<const Type &>(container);
        return iterator{as_const, static_cast<typename iterator::difference_type>(as_end * as_const.size())};
    }

    [[nodiscard]] static iterator insert_or_erase([[maybe_unused]] any &container, [[maybe_unused]] const std::ptrdiff_t offset, [[maybe_unused]] meta_any &value) {
        if constexpr(is_dynamic_sequence_container<Type>::value) {
            if(auto *const cont = any_cast<Type>(&container); cont) {
                if(value) {
                    // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
                    if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
                        const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
                        const auto curr = cont->insert(cont->begin() + offset, element ? *element : value.cast<typename Type::value_type>());
                        return iterator{*cont, curr - cont->begin()};
                    }
                } else {
                    const auto curr = cont->erase(cont->begin() + offset);
                    return iterator{*cont, curr - cont->begin()};
                }
            }
        }

        return {};
    }
};

template<typename Type>
struct basic_meta_associative_container_traits {
    using iterator = meta_associative_container::iterator;
    using size_type = std::size_t;

    static constexpr auto key_only = is_key_only_meta_associative_container<Type>::value;

    [[nodiscard]] static size_type size(const any &container) noexcept {
        return any_cast<const Type &>(container).size();
    }

    [[nodiscard]] static bool clear(any &container) {
        if(auto *const cont = any_cast<Type>(&container); cont) {
            cont->clear();
            return true;
        }

        return false;
    }

    [[nodiscard]] static iterator iter(any &container, const bool as_end) {
        if(auto *const cont = any_cast<Type>(&container); cont) {
            return iterator{std::integral_constant<bool, key_only>{}, as_end ? cont->end() : cont->begin()};
        }

        const auto &as_const = any_cast<const Type &>(container);
        return iterator{std::integral_constant<bool, key_only>{}, as_end ? as_const.end() : as_const.begin()};
    }

    [[nodiscard]] static size_type insert_or_erase(any &container, meta_any &key, meta_any &value) {
        if(auto *const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
            if(value) {
                if constexpr(is_key_only_meta_associative_container<Type>::value) {
                    return cont->insert(key.cast<const typename Type::key_type &>()).second;
                } else {
                    return value.allow_cast<const typename Type::mapped_type &>() && cont->emplace(key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>()).second;
                }
            } else {
                return cont->erase(key.cast<const typename Type::key_type &>());
            }
        }

        return 0u;
    }

    [[nodiscard]] static iterator find(any &container, meta_any &key) {
        if(key.allow_cast<const typename Type::key_type &>()) {
            if(auto *const cont = any_cast<Type>(&container); cont) {
                return iterator{std::integral_constant<bool, key_only>{}, cont->find(key.cast<const typename Type::key_type &>())};
            }

            return iterator{std::integral_constant<bool, key_only>{}, any_cast<const Type &>(container).find(key.cast<const typename Type::key_type &>())};
        }

        return {};
    }
};

} // namespace internal

/**
 * Internal details not to be documented.
 * @endcond
 */

/**
 * @brief Meta sequence container traits for `std::vector`s of any type.
 * @tparam Type The type of elements.
 * @tparam Args Other arguments.
 */
template<typename Type, typename... Args>
struct meta_sequence_container_traits<std::vector<Type, Args...>>
    : internal::basic_meta_sequence_container_traits<std::vector<Type, Args...>> {};

/**
 * @brief Meta sequence container traits for `std::array`s of any type.
 * @tparam Type The type of elements.
 * @tparam N The number of elements.
 */
template<typename Type, auto N>
struct meta_sequence_container_traits<std::array<Type, N>>
    : internal::basic_meta_sequence_container_traits<std::array<Type, N>> {};

/**
 * @brief Meta associative container traits for `std::map`s of any type.
 * @tparam Key The key type of elements.
 * @tparam Value The value type of elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename Value, typename... Args>
struct meta_associative_container_traits<std::map<Key, Value, Args...>>
    : internal::basic_meta_associative_container_traits<std::map<Key, Value, Args...>> {};

/**
 * @brief Meta associative container traits for `std::unordered_map`s of any
 * type.
 * @tparam Key The key type of elements.
 * @tparam Value The value type of elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename Value, typename... Args>
struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
    : internal::basic_meta_associative_container_traits<std::unordered_map<Key, Value, Args...>> {};

/**
 * @brief Meta associative container traits for `std::set`s of any type.
 * @tparam Key The type of elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename... Args>
struct meta_associative_container_traits<std::set<Key, Args...>>
    : internal::basic_meta_associative_container_traits<std::set<Key, Args...>> {};

/**
 * @brief Meta associative container traits for `std::unordered_set`s of any
 * type.
 * @tparam Key The type of elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename... Args>
struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
    : internal::basic_meta_associative_container_traits<std::unordered_set<Key, Args...>> {};

/**
 * @brief Meta associative container traits for `dense_map`s of any type.
 * @tparam Key The key type of the elements.
 * @tparam Type The value type of the elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename Type, typename... Args>
struct meta_associative_container_traits<dense_map<Key, Type, Args...>>
    : internal::basic_meta_associative_container_traits<dense_map<Key, Type, Args...>> {};

/**
 * @brief Meta associative container traits for `dense_set`s of any type.
 * @tparam Type The value type of the elements.
 * @tparam Args Other arguments.
 */
template<typename Type, typename... Args>
struct meta_associative_container_traits<dense_set<Type, Args...>>
    : internal::basic_meta_associative_container_traits<dense_set<Type, Args...>> {};

} // namespace entt

#endif
<commit_msg>meta container: small changes<commit_after>#ifndef ENTT_META_CONTAINER_HPP
#define ENTT_META_CONTAINER_HPP

#include <array>
#include <map>
#include <set>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "../container/dense_map.hpp"
#include "../container/dense_set.hpp"
#include "meta.hpp"
#include "type_traits.hpp"

namespace entt {

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

template<typename, typename = void>
struct is_dynamic_sequence_container: std::false_type {};

template<typename Type>
struct is_dynamic_sequence_container<Type, std::void_t<decltype(&Type::reserve)>>: std::true_type {};

template<typename, typename = void>
struct is_key_only_meta_associative_container: std::true_type {};

template<typename Type>
struct is_key_only_meta_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {};

template<typename Type>
struct basic_meta_sequence_container_traits {
    using iterator = meta_sequence_container::iterator;
    using size_type = std::size_t;

    [[nodiscard]] static size_type size(const any &container) noexcept {
        return any_cast<const Type &>(container).size();
    }

    [[nodiscard]] static bool resize([[maybe_unused]] any &container, [[maybe_unused]] size_type sz) {
        if constexpr(is_dynamic_sequence_container<Type>::value) {
            if(auto *const cont = any_cast<Type>(&container); cont) {
                cont->resize(sz);
                return true;
            }
        }

        return false;
    }

    [[nodiscard]] static iterator iter(any &container, const bool as_end) {
        if(auto *const cont = any_cast<Type>(&container); cont) {
            return iterator{*cont, static_cast<typename iterator::difference_type>(as_end * cont->size())};
        }

        const Type &as_const = any_cast<const Type &>(container);
        return iterator{as_const, static_cast<typename iterator::difference_type>(as_end * as_const.size())};
    }

    [[nodiscard]] static iterator insert_or_erase([[maybe_unused]] any &container, [[maybe_unused]] const std::ptrdiff_t offset, [[maybe_unused]] meta_any &value) {
        if constexpr(is_dynamic_sequence_container<Type>::value) {
            if(auto *const cont = any_cast<Type>(&container); cont) {
                if(value) {
                    // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
                    if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
                        const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
                        const auto curr = cont->insert(cont->begin() + offset, element ? *element : value.cast<typename Type::value_type>());
                        return iterator{*cont, curr - cont->begin()};
                    }
                } else {
                    const auto curr = cont->erase(cont->begin() + offset);
                    return iterator{*cont, curr - cont->begin()};
                }
            }
        }

        return {};
    }
};

template<typename Type>
struct basic_meta_associative_container_traits {
    using iterator = meta_associative_container::iterator;
    using size_type = std::size_t;

    static constexpr auto key_only = is_key_only_meta_associative_container<Type>::value;

    [[nodiscard]] static size_type size(const any &container) noexcept {
        return any_cast<const Type &>(container).size();
    }

    [[nodiscard]] static bool clear(any &container) {
        if(auto *const cont = any_cast<Type>(&container); cont) {
            cont->clear();
            return true;
        }

        return false;
    }

    [[nodiscard]] static iterator iter(any &container, const bool as_end) {
        if(auto *const cont = any_cast<Type>(&container); cont) {
            return iterator{std::bool_constant<key_only>{}, as_end ? cont->end() : cont->begin()};
        }

        const auto &as_const = any_cast<const Type &>(container);
        return iterator{std::bool_constant<key_only>{}, as_end ? as_const.end() : as_const.begin()};
    }

    [[nodiscard]] static size_type insert_or_erase(any &container, meta_any &key, meta_any &value) {
        if(auto *const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
            if(value) {
                if constexpr(key_only) {
                    return cont->insert(key.cast<const typename Type::key_type &>()).second;
                } else {
                    return value.allow_cast<const typename Type::mapped_type &>() && cont->emplace(key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>()).second;
                }
            } else {
                return cont->erase(key.cast<const typename Type::key_type &>());
            }
        }

        return 0u;
    }

    [[nodiscard]] static iterator find(any &container, meta_any &key) {
        if(key.allow_cast<const typename Type::key_type &>()) {
            if(auto *const cont = any_cast<Type>(&container); cont) {
                return iterator{std::bool_constant<key_only>{}, cont->find(key.cast<const typename Type::key_type &>())};
            }

            return iterator{std::bool_constant<key_only>{}, any_cast<const Type &>(container).find(key.cast<const typename Type::key_type &>())};
        }

        return {};
    }
};

} // namespace internal

/**
 * Internal details not to be documented.
 * @endcond
 */

/**
 * @brief Meta sequence container traits for `std::vector`s of any type.
 * @tparam Type The type of elements.
 * @tparam Args Other arguments.
 */
template<typename Type, typename... Args>
struct meta_sequence_container_traits<std::vector<Type, Args...>>
    : internal::basic_meta_sequence_container_traits<std::vector<Type, Args...>> {};

/**
 * @brief Meta sequence container traits for `std::array`s of any type.
 * @tparam Type The type of elements.
 * @tparam N The number of elements.
 */
template<typename Type, auto N>
struct meta_sequence_container_traits<std::array<Type, N>>
    : internal::basic_meta_sequence_container_traits<std::array<Type, N>> {};

/**
 * @brief Meta associative container traits for `std::map`s of any type.
 * @tparam Key The key type of elements.
 * @tparam Value The value type of elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename Value, typename... Args>
struct meta_associative_container_traits<std::map<Key, Value, Args...>>
    : internal::basic_meta_associative_container_traits<std::map<Key, Value, Args...>> {};

/**
 * @brief Meta associative container traits for `std::unordered_map`s of any
 * type.
 * @tparam Key The key type of elements.
 * @tparam Value The value type of elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename Value, typename... Args>
struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
    : internal::basic_meta_associative_container_traits<std::unordered_map<Key, Value, Args...>> {};

/**
 * @brief Meta associative container traits for `std::set`s of any type.
 * @tparam Key The type of elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename... Args>
struct meta_associative_container_traits<std::set<Key, Args...>>
    : internal::basic_meta_associative_container_traits<std::set<Key, Args...>> {};

/**
 * @brief Meta associative container traits for `std::unordered_set`s of any
 * type.
 * @tparam Key The type of elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename... Args>
struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
    : internal::basic_meta_associative_container_traits<std::unordered_set<Key, Args...>> {};

/**
 * @brief Meta associative container traits for `dense_map`s of any type.
 * @tparam Key The key type of the elements.
 * @tparam Type The value type of the elements.
 * @tparam Args Other arguments.
 */
template<typename Key, typename Type, typename... Args>
struct meta_associative_container_traits<dense_map<Key, Type, Args...>>
    : internal::basic_meta_associative_container_traits<dense_map<Key, Type, Args...>> {};

/**
 * @brief Meta associative container traits for `dense_set`s of any type.
 * @tparam Type The value type of the elements.
 * @tparam Args Other arguments.
 */
template<typename Type, typename... Args>
struct meta_associative_container_traits<dense_set<Type, Args...>>
    : internal::basic_meta_associative_container_traits<dense_set<Type, Args...>> {};

} // namespace entt

#endif
<|endoftext|>


<commit_before>/**
 * \file
 * \brief ThreadBase class header
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-03-14
 */

#ifndef INCLUDE_DISTORTOS_THREADBASE_HPP_
#define INCLUDE_DISTORTOS_THREADBASE_HPP_

#include "distortos/scheduler/ThreadControlBlock.hpp"

#include "distortos/signals/SignalsReceiverControlBlock.hpp"

#include "distortos/Semaphore.hpp"

namespace distortos
{

/// ThreadBase class is a base for threads
class ThreadBase
{
public:

	/**
	 * \brief ThreadBase's constructor.
	 *
	 * \param [in] buffer is a pointer to stack's buffer
	 * \param [in] size is the size of stack's buffer, bytes
	 * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
	 * \param [in] schedulingPolicy is the scheduling policy of the thread
	 * \param [in] threadGroupControlBlock is a pointer to scheduler::ThreadGroupControlBlock to which this object will
	 * be added, nullptr to inherit thread group from currently running thread
	 * \param [in] signalsReceiver is a pointer to SignalsReceiver object for this thread, nullptr to disable reception
	 * of signals for this thread
	 */

	ThreadBase(void* buffer, size_t size, uint8_t priority, SchedulingPolicy schedulingPolicy,
			scheduler::ThreadGroupControlBlock* threadGroupControlBlock, SignalsReceiver* signalsReceiver);

	/**
	 * \brief ThreadBase's constructor.
	 *
	 * \param [in] stack is an rvalue reference to architecture::Stack object which will be adopted for this thread
	 * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
	 * \param [in] schedulingPolicy is the scheduling policy of the thread
	 * \param [in] threadGroupControlBlock is a pointer to scheduler::ThreadGroupControlBlock to which this object will
	 * be added, nullptr to inherit thread group from currently running thread
	 * \param [in] signalsReceiver is a pointer to SignalsReceiver object for this thread, nullptr to disable reception
	 * of signals for this thread
	 */

	ThreadBase(architecture::Stack&& stack, uint8_t priority, SchedulingPolicy schedulingPolicy,
			scheduler::ThreadGroupControlBlock* threadGroupControlBlock, SignalsReceiver* signalsReceiver);

	/**
	 * \brief Generates signal for thread.
	 *
	 * Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
	 *
	 * Adds the signalNumber to set of pending signals. If this thread is currently waiting for this signal, it will be
	 * unblocked.
	 *
	 * \param [in] signalNumber is the signal that will be generated, [0; 31]
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - \a signalNumber value is invalid;
	 * - ENOTSUP - reception of signals is disabled for this thread;
	 */

	int generateSignal(const uint8_t signalNumber)
	{
		return threadControlBlock_.generateSignal(signalNumber);
	}

	/**
	 * \return effective priority of thread
	 */

	uint8_t getEffectivePriority() const
	{
		return threadControlBlock_.getEffectivePriority();
	}

	/**
	 * \brief Gets set of currently pending signals.
	 *
	 * Similar to sigpending() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html
	 *
	 * This function shall return the set of signals that are blocked from delivery and are pending on the thread.
	 *
	 * \return set of currently pending signals
	 */

	SignalSet getPendingSignalSet() const
	{
		const auto signalsReceiverControlBlock = threadControlBlock_.getSignalsReceiverControlBlock();
		if (signalsReceiverControlBlock == nullptr)
			return SignalSet{SignalSet::empty};

		return signalsReceiverControlBlock->getPendingSignalSet();
	}

	/**
	 * \return priority of thread
	 */

	uint8_t getPriority() const
	{
		return threadControlBlock_.getPriority();
	}

	/**
	 * \return scheduling policy of the thread
	 */

	SchedulingPolicy getSchedulingPolicy() const
	{
		return threadControlBlock_.getSchedulingPolicy();
	}

	/**
	 * \return current state of thread
	 */

	scheduler::ThreadControlBlock::State getState() const
	{
		return threadControlBlock_.getState();
	}

	/**
	 * \brief Waits for thread termination.
	 *
	 * Similar to std::thread::join() - http://en.cppreference.com/w/cpp/thread/thread/join
	 * Similar to POSIX pthread_join() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html
	 *
	 * Blocks current thread until this thread finishes its execution. The results of multiple simultaneous calls to
	 * join() on the same target thread are undefined.
	 *
	 * \return 0 on success, error code otherwise:
	 * - EDEADLK - deadlock condition was detected,
	 * - EINVAL - this thread is not joinable,
	 * - ...
	 */

	int join();

	/**
	 * \brief Changes priority of thread.
	 *
	 * If the priority really changes, the position in the thread list is adjusted and context switch may be requested.
	 *
	 * \param [in] priority is the new priority of thread
	 * \param [in] alwaysBehind selects the method of ordering when lowering the priority
	 * - false - the thread is moved to the head of the group of threads with the new priority (default),
	 * - true - the thread is moved to the tail of the group of threads with the new priority.
	 */

	void setPriority(const uint8_t priority, const bool alwaysBehind = {})
	{
		threadControlBlock_.setPriority(priority, alwaysBehind);
	}

	/**
	 * param [in] schedulingPolicy is the new scheduling policy of the thread
	 */

	void setSchedulingPolicy(const SchedulingPolicy schedulingPolicy)
	{
		threadControlBlock_.setSchedulingPolicy(schedulingPolicy);
	}

	/**
	 * \brief Starts the thread.
	 *
	 * This operation can be performed on threads in "New" state only.
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - thread is already started;
	 * - error codes returned by scheduler::Scheduler::add();
	 */

	int start();

	ThreadBase(const ThreadBase&) = delete;
	ThreadBase(ThreadBase&&) = default;
	const ThreadBase& operator=(const ThreadBase&) = delete;
	ThreadBase& operator=(ThreadBase&&) = delete;

protected:

	/**
	 * \brief ThreadBase's destructor
	 *
	 * \note Polymorphic objects of ThreadBase type must not be deleted via pointer/reference
	 */

	~ThreadBase()
	{

	}

	/**
	 * \return reference to internal ThreadControlBlock object
	 */

	scheduler::ThreadControlBlock& getThreadControlBlock()
	{
		return threadControlBlock_;
	}

private:

	/**
	 * \brief Thread runner function - entry point of threads.
	 *
	 * After return from actual thread function, thread is terminated, so this function never returns.
	 *
	 * \param [in] threadBase is a reference to ThreadBase object that is being run
	 */

	static void threadRunner(ThreadBase& threadBase) __attribute__ ((noreturn));

	/**
	 * \brief "Run" function of thread
	 *
	 * This should be overridden by derived classes.
	 */

	virtual void run() = 0;

	/**
	 * \brief Termination hook function of thread
	 *
	 * This function is called after run() completes, from Scheduler::remove().
	 */

	void terminationHook();

	/// internal ThreadControlBlock object
	scheduler::ThreadControlBlock threadControlBlock_;

	/// semaphore used by join()
	Semaphore joinSemaphore_;
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_THREADBASE_HPP_
<commit_msg>ThreadBase::generateSignal(): use SignalsReceiverControlBlock::generateSignal() instead of ThreadControlBlock::generateSignal()<commit_after>/**
 * \file
 * \brief ThreadBase class header
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-03-14
 */

#ifndef INCLUDE_DISTORTOS_THREADBASE_HPP_
#define INCLUDE_DISTORTOS_THREADBASE_HPP_

#include "distortos/scheduler/ThreadControlBlock.hpp"

#include "distortos/signals/SignalsReceiverControlBlock.hpp"

#include "distortos/Semaphore.hpp"

#include <cerrno>

namespace distortos
{

/// ThreadBase class is a base for threads
class ThreadBase
{
public:

	/**
	 * \brief ThreadBase's constructor.
	 *
	 * \param [in] buffer is a pointer to stack's buffer
	 * \param [in] size is the size of stack's buffer, bytes
	 * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
	 * \param [in] schedulingPolicy is the scheduling policy of the thread
	 * \param [in] threadGroupControlBlock is a pointer to scheduler::ThreadGroupControlBlock to which this object will
	 * be added, nullptr to inherit thread group from currently running thread
	 * \param [in] signalsReceiver is a pointer to SignalsReceiver object for this thread, nullptr to disable reception
	 * of signals for this thread
	 */

	ThreadBase(void* buffer, size_t size, uint8_t priority, SchedulingPolicy schedulingPolicy,
			scheduler::ThreadGroupControlBlock* threadGroupControlBlock, SignalsReceiver* signalsReceiver);

	/**
	 * \brief ThreadBase's constructor.
	 *
	 * \param [in] stack is an rvalue reference to architecture::Stack object which will be adopted for this thread
	 * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
	 * \param [in] schedulingPolicy is the scheduling policy of the thread
	 * \param [in] threadGroupControlBlock is a pointer to scheduler::ThreadGroupControlBlock to which this object will
	 * be added, nullptr to inherit thread group from currently running thread
	 * \param [in] signalsReceiver is a pointer to SignalsReceiver object for this thread, nullptr to disable reception
	 * of signals for this thread
	 */

	ThreadBase(architecture::Stack&& stack, uint8_t priority, SchedulingPolicy schedulingPolicy,
			scheduler::ThreadGroupControlBlock* threadGroupControlBlock, SignalsReceiver* signalsReceiver);

	/**
	 * \brief Generates signal for thread.
	 *
	 * Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
	 *
	 * Adds the signalNumber to set of pending signals. If this thread is currently waiting for this signal, it will be
	 * unblocked.
	 *
	 * \param [in] signalNumber is the signal that will be generated, [0; 31]
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - \a signalNumber value is invalid;
	 * - ENOTSUP - reception of signals is disabled for this thread;
	 */

	int generateSignal(const uint8_t signalNumber) const
	{
		const auto signalsReceiverControlBlock = threadControlBlock_.getSignalsReceiverControlBlock();
		if (signalsReceiverControlBlock == nullptr)
			return ENOTSUP;

		return signalsReceiverControlBlock->generateSignal(signalNumber);
	}

	/**
	 * \return effective priority of thread
	 */

	uint8_t getEffectivePriority() const
	{
		return threadControlBlock_.getEffectivePriority();
	}

	/**
	 * \brief Gets set of currently pending signals.
	 *
	 * Similar to sigpending() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html
	 *
	 * This function shall return the set of signals that are blocked from delivery and are pending on the thread.
	 *
	 * \return set of currently pending signals
	 */

	SignalSet getPendingSignalSet() const
	{
		const auto signalsReceiverControlBlock = threadControlBlock_.getSignalsReceiverControlBlock();
		if (signalsReceiverControlBlock == nullptr)
			return SignalSet{SignalSet::empty};

		return signalsReceiverControlBlock->getPendingSignalSet();
	}

	/**
	 * \return priority of thread
	 */

	uint8_t getPriority() const
	{
		return threadControlBlock_.getPriority();
	}

	/**
	 * \return scheduling policy of the thread
	 */

	SchedulingPolicy getSchedulingPolicy() const
	{
		return threadControlBlock_.getSchedulingPolicy();
	}

	/**
	 * \return current state of thread
	 */

	scheduler::ThreadControlBlock::State getState() const
	{
		return threadControlBlock_.getState();
	}

	/**
	 * \brief Waits for thread termination.
	 *
	 * Similar to std::thread::join() - http://en.cppreference.com/w/cpp/thread/thread/join
	 * Similar to POSIX pthread_join() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html
	 *
	 * Blocks current thread until this thread finishes its execution. The results of multiple simultaneous calls to
	 * join() on the same target thread are undefined.
	 *
	 * \return 0 on success, error code otherwise:
	 * - EDEADLK - deadlock condition was detected,
	 * - EINVAL - this thread is not joinable,
	 * - ...
	 */

	int join();

	/**
	 * \brief Changes priority of thread.
	 *
	 * If the priority really changes, the position in the thread list is adjusted and context switch may be requested.
	 *
	 * \param [in] priority is the new priority of thread
	 * \param [in] alwaysBehind selects the method of ordering when lowering the priority
	 * - false - the thread is moved to the head of the group of threads with the new priority (default),
	 * - true - the thread is moved to the tail of the group of threads with the new priority.
	 */

	void setPriority(const uint8_t priority, const bool alwaysBehind = {})
	{
		threadControlBlock_.setPriority(priority, alwaysBehind);
	}

	/**
	 * param [in] schedulingPolicy is the new scheduling policy of the thread
	 */

	void setSchedulingPolicy(const SchedulingPolicy schedulingPolicy)
	{
		threadControlBlock_.setSchedulingPolicy(schedulingPolicy);
	}

	/**
	 * \brief Starts the thread.
	 *
	 * This operation can be performed on threads in "New" state only.
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - thread is already started;
	 * - error codes returned by scheduler::Scheduler::add();
	 */

	int start();

	ThreadBase(const ThreadBase&) = delete;
	ThreadBase(ThreadBase&&) = default;
	const ThreadBase& operator=(const ThreadBase&) = delete;
	ThreadBase& operator=(ThreadBase&&) = delete;

protected:

	/**
	 * \brief ThreadBase's destructor
	 *
	 * \note Polymorphic objects of ThreadBase type must not be deleted via pointer/reference
	 */

	~ThreadBase()
	{

	}

	/**
	 * \return reference to internal ThreadControlBlock object
	 */

	scheduler::ThreadControlBlock& getThreadControlBlock()
	{
		return threadControlBlock_;
	}

private:

	/**
	 * \brief Thread runner function - entry point of threads.
	 *
	 * After return from actual thread function, thread is terminated, so this function never returns.
	 *
	 * \param [in] threadBase is a reference to ThreadBase object that is being run
	 */

	static void threadRunner(ThreadBase& threadBase) __attribute__ ((noreturn));

	/**
	 * \brief "Run" function of thread
	 *
	 * This should be overridden by derived classes.
	 */

	virtual void run() = 0;

	/**
	 * \brief Termination hook function of thread
	 *
	 * This function is called after run() completes, from Scheduler::remove().
	 */

	void terminationHook();

	/// internal ThreadControlBlock object
	scheduler::ThreadControlBlock threadControlBlock_;

	/// semaphore used by join()
	Semaphore joinSemaphore_;
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_THREADBASE_HPP_
<|endoftext|>


<commit_before>#include <stdexcept>
#include <memory>
#include <cmath>
#include <cassert>
#include <iostream>

#include "gamestates/playstate.hh"
#include "gamestates/endstate.hh"
#include "settings.hh"
#include "map_reader.hh"
#include "player.hh"
#include "mouse.hh"
#include "map.hh"
#include "text_drawer.hh"
#include "turrets/basic.hh"
#include "turrets/sniper.hh"
#include "turrets/super.hh"
#include "mobs/foot_soldier.hh"
#include "mobs/horse_soldier.hh"
#include "mobs/tank_soldier.hh"
#include "pathfinding.hh"

PlayState::PlayState(std::string map)
         : turret_{nullptr}
{
    if (!MapReader::set_size(map))
        throw std::logic_error("Could not load map '" + map + "'.");
    Map::init();
    if (!MapReader::read_map(map))
        throw std::logic_error("Error reading map '" + map + "'.");
    Map::init_draw(0, 50);
    Player::init(500, 10, std::chrono::system_clock::now());
    this->levels.push_back(Level("resources/levels/1.td42"));
    ms_before_next_level = 100;
    ms_before_next_mob = TIME_BETWEEN_MOBS;
}

void PlayState::insert_mode(std::shared_ptr<Turret> t)
{
    turret_ = t;
    t->set_opacity(100);
}

void PlayState::exit_insert_mode()
{
    turret_ = nullptr;
    ms_before_next_level = 100;
}

void PlayState::exit_insert_mode_and_create()
{
    if (turret_ != nullptr)
    {
        if (!Player::remove_money(turret_->get_cost()))
        {
            turret_ = nullptr;
            return;
        }
        auto pos = turret_->get_pos();
        if (pos.first < 0 || pos.first >= Map::width || pos.second < 0
                || pos.second >= Map::height
                || Map::cells[pos.first][pos.second].type != CellType::Empty)
        {
            turret_ = nullptr;
            return;
        }
        Map::cells[pos.first][pos.second].type = CellType::Tower;
        turret_->set_opacity(255);
        Map::turrets.push_front(turret_);
        turret_ = nullptr;
        for (auto& enemy : Map::ennemies)
            enemy->update_pathfinding();
    }
}

void PlayState::draw(sf::RenderWindow& w)
{
    if (turret_ != nullptr)
    {
        auto pos = Mouse::get_mouse_pos(w);
        unsigned px;
        unsigned py;
        Map::screen_to_map(pos.first, pos.second, px, py);
        turret_->set_pos(px, py);
    }
    Map::draw(w, turret_);
    TextDrawer::display_time(w);
    TextDrawer::display_lifes(w);
    TextDrawer::display_money(w);
    TextDrawer::display_mouse_coords(w);
    TextDrawer::display_mouse_coords_on_map(w);
}

bool is_arrived(float x1, float x2, float y1, float y2)
{
    int ix1 = x1;
    int ix2 = x2;
    int iy1 = y1;
    int iy2 = y2;
    if (ix1 == ix2 && iy1 == iy2)
        return true;
    float dx = fabs(x1 - x2);
    float dy = fabs(y1 - y2);
    return dx < 0.2f && dy < 0.2f;
}

void PlayState::update(unsigned elapsed_ms)
{
    static std::chrono::time_point<std::chrono::system_clock> time;
    std::chrono::duration<double> elapsed =
        std::chrono::system_clock::now() - time;
    time = std::chrono::system_clock::now();
    std::cout << std::to_string(elapsed.count()) << std::endl;
    if (this->levels.size() == 0 && Map::ennemies.empty())
    {
        GameState::stack.pop_back();
        auto ptr = std::make_shared<EndState>();
        GameState::stack.push_back(ptr);
    }
    else if (ms_before_next_level <= 0)
    {
        if (ms_before_next_mob <= 0)
        {
            if (!this->levels.front().make_mob())
            {
                std::cout << "NEW LEVEL" << std::endl;
                this->levels.pop_front();
                ms_before_next_level = TIME_BETWEEN_LEVELS;
            }
            else
                ms_before_next_mob = TIME_BETWEEN_MOBS;
        }
        else
            ms_before_next_mob -= elapsed_ms;
    }
    else
        ms_before_next_level -= elapsed_ms;
    for (std::list<std::shared_ptr<Mob>>::iterator i = Map::ennemies.begin();
            i != Map::ennemies.end();)
    {
        if ((*i)->dead())
            i = Map::ennemies.erase(i);
        else
        {
            (*i)->move();
            auto pos = (*i)->get_pos();
            if (is_arrived(pos.first, Map::finish_mobs.first,
                           pos.second, Map::finish_mobs.second))
            {
                std::cout << "xd" << std::endl;
                (*i)->harakiri();
                if (!Player::remove_a_life())
                {
                    GameState::stack.pop_back();
                    auto ptr = std::make_shared<EndState>();
                    GameState::stack.push_back(ptr);
                }
                i = Map::ennemies.erase(i);
            }
            else
                ++i;
        }
    }
    for (std::shared_ptr<Turret> turret : Map::turrets)
        turret->attack(elapsed_ms);
    ++elapsed_ms;
}
<commit_msg>Now it's impossible to block path<commit_after>#include <stdexcept>
#include <memory>
#include <cmath>
#include <cassert>
#include <iostream>

#include "gamestates/playstate.hh"
#include "gamestates/endstate.hh"
#include "settings.hh"
#include "map_reader.hh"
#include "player.hh"
#include "mouse.hh"
#include "map.hh"
#include "text_drawer.hh"
#include "turrets/basic.hh"
#include "turrets/sniper.hh"
#include "turrets/super.hh"
#include "mobs/foot_soldier.hh"
#include "mobs/horse_soldier.hh"
#include "mobs/tank_soldier.hh"
#include "pathfinding.hh"

PlayState::PlayState(std::string map)
         : turret_{nullptr}
{
    if (!MapReader::set_size(map))
        throw std::logic_error("Could not load map '" + map + "'.");
    Map::init();
    if (!MapReader::read_map(map))
        throw std::logic_error("Error reading map '" + map + "'.");
    Map::init_draw(0, 50);
    Player::init(500, 10, std::chrono::system_clock::now());
    this->levels.push_back(Level("resources/levels/1.td42"));
    this->levels.push_back(Level("resources/levels/2.td42"));
    this->levels.push_back(Level("resources/levels/3.td42"));
    this->levels.push_back(Level("resources/levels/4.td42"));
    this->levels.push_back(Level("resources/levels/5.td42"));
    ms_before_next_level = 100;
    ms_before_next_mob = TIME_BETWEEN_MOBS;
}

void PlayState::insert_mode(std::shared_ptr<Turret> t)
{
    turret_ = t;
    t->set_opacity(100);
}

void PlayState::exit_insert_mode()
{
    turret_ = nullptr;
    ms_before_next_level = 100;
}

void PlayState::exit_insert_mode_and_create()
{
    if (turret_ != nullptr)
    {
        if (!Player::remove_money(turret_->get_cost()))
        {
            turret_ = nullptr;
            return;
        }
        auto pos = turret_->get_pos();
        if (pos.first < 0 || pos.first >= Map::width || pos.second < 0
            || pos.second >= Map::height
            || (Map::cells[pos.first][pos.second].type != CellType::Empty
           && Map::cells[pos.first][pos.second].type != Obstacle))
        {
            turret_ = nullptr;
            return;
        }
        auto t = Map::cells[pos.first][pos.second].type;
        Map::cells[pos.first][pos.second].type = CellType::Tower;
        auto list = pathfind(Map::start_mobs, Map::finish_mobs);
        if (list.size() == 0)
        {
            Map::cells[pos.first][pos.second].type = t;
            turret_ = nullptr;
            return;
        }
        turret_->set_opacity(255);
        Map::turrets.push_front(turret_);
        turret_ = nullptr;
        for (auto& enemy : Map::ennemies)
            enemy->update_pathfinding();
    }
}

void PlayState::draw(sf::RenderWindow& w)
{
    if (turret_ != nullptr)
    {
        auto pos = Mouse::get_mouse_pos(w);
        unsigned px;
        unsigned py;
        Map::screen_to_map(pos.first, pos.second, px, py);
        turret_->set_pos(px, py);
    }
    Map::draw(w, turret_);
    TextDrawer::display_time(w);
    TextDrawer::display_lifes(w);
    TextDrawer::display_money(w);
    TextDrawer::display_mouse_coords(w);
    TextDrawer::display_mouse_coords_on_map(w);
}

bool is_arrived(float x1, float x2, float y1, float y2)
{
    int ix1 = x1;
    int ix2 = x2;
    int iy1 = y1;
    int iy2 = y2;
    if (ix1 == ix2 && iy1 == iy2)
        return true;
    float dx = fabs(x1 - x2);
    float dy = fabs(y1 - y2);
    return dx < 0.2f && dy < 0.2f;
}

void PlayState::update(unsigned elapsed_ms)
{
    static std::chrono::time_point<std::chrono::system_clock> time;
    std::chrono::duration<double> elapsed =
        std::chrono::system_clock::now() - time;
    time = std::chrono::system_clock::now();
    std::cout << std::to_string(elapsed.count()) << std::endl;
    if (this->levels.size() == 0 && Map::ennemies.empty())
    {
        GameState::stack.pop_back();
        auto ptr = std::make_shared<EndState>();
        GameState::stack.push_back(ptr);
    }
    else if (ms_before_next_level <= 0)
    {
        if (ms_before_next_mob <= 0)
        {
            if (!this->levels.front().make_mob())
            {
                std::cout << "NEW LEVEL" << std::endl;
                this->levels.pop_front();
                ms_before_next_level = TIME_BETWEEN_LEVELS;
            }
            else
                ms_before_next_mob = TIME_BETWEEN_MOBS;
        }
        else
            ms_before_next_mob -= elapsed_ms;
    }
    else
        ms_before_next_level -= elapsed_ms;
    for (std::list<std::shared_ptr<Mob>>::iterator i = Map::ennemies.begin();
            i != Map::ennemies.end();)
    {
        if ((*i)->dead())
            i = Map::ennemies.erase(i);
        else
        {
            (*i)->move();
            auto pos = (*i)->get_pos();
            if (is_arrived(pos.first, Map::finish_mobs.first,
                           pos.second, Map::finish_mobs.second))
            {
                std::cout << "xd" << std::endl;
                (*i)->harakiri();
                if (!Player::remove_a_life())
                {
                    GameState::stack.pop_back();
                    auto ptr = std::make_shared<EndState>();
                    GameState::stack.push_back(ptr);
                }
                i = Map::ennemies.erase(i);
            }
            else
                ++i;
        }
    }
    for (std::shared_ptr<Turret> turret : Map::turrets)
        turret->attack(elapsed_ms);
    ++elapsed_ms;
}
<|endoftext|>


<commit_before>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef MPPP_DETAIL_QUADMATH_HPP
#define MPPP_DETAIL_QUADMATH_HPP

#include <iostream>
// NOTE: extern "C" is already included in quadmath.h since GCC 4.8:
// https://stackoverflow.com/questions/13780219/link-libquadmath-with-c-on-linux
#include <quadmath.h>
#include <stdexcept>
#include <string>

#include <mp++/config.hpp>

namespace mppp
{

inline namespace detail
{
// Machinery for low-level manipulation of __float128. Inspired by:
// https://github.com/gcc-mirror/gcc/blob/master/libquadmath/quadmath-imp.h
// Note that the union machinery is technically UB, but well-defined on GCC as
// an extension:
// https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Type%2Dpunning
// quadmath so far is limited to GCC and perhaps clang, which I'd imagine
// implements the same extension for GCC compatibility. So we should be ok.

// The ieee fields.
struct ieee_t {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    unsigned negative : 1;
    unsigned exponent : 15;
    // ull provides at least 64 bits of storage, so it is ok
    // to use it here.
    unsigned long long mant_high : 48;
    unsigned long long mant_low : 64;
#else
    unsigned long long mant_low : 64;
    unsigned long long mant_high : 48;
    unsigned exponent : 15;
    unsigned negative : 1;
#endif
}
#ifdef __MINGW32__
// On mingw targets the ms-bitfields option is active by default.
// Therefore enforce gnu-bitfield style.
__attribute__((gcc_struct))
#endif
;

// The union.
union ieee_float128 {
    ::__float128 value;
    ieee_t i_eee;
};

inline void float128_stream(std::ostream &os, const ::__float128 &x)
{
    char buf[100];
    // NOTE: 36 decimal digits ensures that reading back the string always produces the same value.
    // https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
    const auto n = ::quadmath_snprintf(buf, sizeof(buf), "%.36Qe", x);
    if (mppp_unlikely(n < 0)) {
        // TODO.
        throw;
    }
    if (mppp_unlikely(unsigned(n) >= sizeof(buf))) {
        // TODO.
        throw;
    }
    os << &buf[0];
}

inline ::__float128 str_to_float128(const char *s)
{
    char *endptr;
    auto retval = ::strtoflt128(s, &endptr);
    if (mppp_unlikely(endptr == s || *endptr != '\0')) {
        // NOTE: the first condition handles an empty string.
        // endptr will point to the first character in the string which
        // did not contribute to the construction of retval.
        throw std::invalid_argument("The string '" + std::string(s)
                                    + "' does not represent a valid quadruple-precision floating-point value");
    }
    return retval;
}
}
}

#endif
<commit_msg>Use uint_least64_t instead of ull in the union.<commit_after>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef MPPP_DETAIL_QUADMATH_HPP
#define MPPP_DETAIL_QUADMATH_HPP

#include <cstdint>
#include <iostream>
// NOTE: extern "C" is already included in quadmath.h since GCC 4.8:
// https://stackoverflow.com/questions/13780219/link-libquadmath-with-c-on-linux
#include <quadmath.h>
#include <stdexcept>
#include <string>

#include <mp++/config.hpp>

namespace mppp
{

inline namespace detail
{
// Machinery for low-level manipulation of __float128. Inspired by:
// https://github.com/gcc-mirror/gcc/blob/master/libquadmath/quadmath-imp.h
// Note that the union machinery is technically UB, but well-defined on GCC as
// an extension:
// https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Type%2Dpunning
// quadmath so far is limited to GCC and perhaps clang, which I'd imagine
// implements the same extension for GCC compatibility. So we should be ok.

// The ieee fields.
struct ieee_t {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    unsigned negative : 1;
    unsigned exponent : 15;
    std::uint_least64_t mant_high : 48;
    std::uint_least64_t mant_low : 64;
#else
    std::uint_least64_t mant_low : 64;
    std::uint_least64_t mant_high : 48;
    unsigned exponent : 15;
    unsigned negative : 1;
#endif
}
#ifdef __MINGW32__
// On mingw targets the ms-bitfields option is active by default.
// Therefore enforce gnu-bitfield style.
__attribute__((gcc_struct))
#endif
;

// The union.
union ieee_float128 {
    ::__float128 value;
    ieee_t i_eee;
};

inline void float128_stream(std::ostream &os, const ::__float128 &x)
{
    char buf[100];
    // NOTE: 36 decimal digits ensures that reading back the string always produces the same value.
    // https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
    const auto n = ::quadmath_snprintf(buf, sizeof(buf), "%.36Qe", x);
    if (mppp_unlikely(n < 0)) {
        // TODO.
        throw;
    }
    if (mppp_unlikely(unsigned(n) >= sizeof(buf))) {
        // TODO.
        throw;
    }
    os << &buf[0];
}

inline ::__float128 str_to_float128(const char *s)
{
    char *endptr;
    auto retval = ::strtoflt128(s, &endptr);
    if (mppp_unlikely(endptr == s || *endptr != '\0')) {
        // NOTE: the first condition handles an empty string.
        // endptr will point to the first character in the string which
        // did not contribute to the construction of retval.
        throw std::invalid_argument("The string '" + std::string(s)
                                    + "' does not represent a valid quadruple-precision floating-point value");
    }
    return retval;
}
}
}

#endif
<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <memory>
#include <functional>

//NOTE: Passing "-fvisibility=hidden" as a compiler option to GCC is advised!
#if defined _WIN32 || defined __CYGWIN__
# ifdef __GNUC__
#  define DLL_PUBLIC __attribute__ ((dllimport))
# else
#  define DLL_PUBLIC __declspec(dllimport)
# endif
#else
# if __GNUC__ >= 4
#  define DLL_PUBLIC __attribute__ ((visibility ("default")))
# else
#  define DLL_PUBLIC
# endif
#endif

typedef struct tagAMX AMX;

#ifdef ERROR //because Microsoft
#undef ERROR
#endif

namespace samplog
{
	enum class LogLevel : unsigned int
	{
		NONE = 0,
		DEBUG = 1,
		INFO = 2,
		WARNING = 4,
		ERROR = 8,
	};

	class IPluginLogger
	{
	public:
		virtual void Log(const LogLevel level, const char *msg) = 0;
		virtual void Log(AMX * const amx, const LogLevel level, const char *msg) = 0;
		virtual void LogEx(const LogLevel level, const char *msg, int line, const char *file, const char *function) = 0;
		virtual bool LogNativeCall(AMX * const amx, const char *name, const char *params_format) = 0;
		virtual void SetLogLevel(const LogLevel level, bool enabled) = 0;
		virtual bool IsLogLevel(const LogLevel log_level) = 0;

		virtual void Destroy() = 0;
	};

	typedef std::shared_ptr<IPluginLogger> PluginLogger_t;

	extern "C" DLL_PUBLIC IPluginLogger *CreatePluginLoggerPtr(const char *pluginname);

	inline PluginLogger_t CreatePluginLogger(const char *pluginname)
	{
		return std::shared_ptr<IPluginLogger>(CreatePluginLoggerPtr(pluginname), std::mem_fn(&IPluginLogger::Destroy));
	}
}

#undef DLL_PUBLIC
<commit_msg>use unique_ptr instead of shared_ptr<commit_after>#pragma once

#include <string>
#include <memory>
#include <functional>

//NOTE: Passing "-fvisibility=hidden" as a compiler option to GCC is advised!
#if defined _WIN32 || defined __CYGWIN__
# ifdef __GNUC__
#  define DLL_PUBLIC __attribute__ ((dllimport))
# else
#  define DLL_PUBLIC __declspec(dllimport)
# endif
#else
# if __GNUC__ >= 4
#  define DLL_PUBLIC __attribute__ ((visibility ("default")))
# else
#  define DLL_PUBLIC
# endif
#endif

typedef struct tagAMX AMX;

#ifdef ERROR //because Microsoft
#undef ERROR
#endif

namespace samplog
{
	enum class LogLevel : unsigned int
	{
		NONE = 0,
		DEBUG = 1,
		INFO = 2,
		WARNING = 4,
		ERROR = 8,
	};

	class IPluginLogger
	{
	public:
		virtual void Log(const LogLevel level, const char *msg) = 0;
		virtual void Log(AMX * const amx, const LogLevel level, const char *msg) = 0;
		virtual void LogEx(const LogLevel level, const char *msg, int line, const char *file, const char *function) = 0;
		virtual bool LogNativeCall(AMX * const amx, const char *name, const char *params_format) = 0;
		virtual void SetLogLevel(const LogLevel level, bool enabled) = 0;
		virtual bool IsLogLevel(const LogLevel log_level) = 0;

		virtual void Destroy() = 0;
	};

	namespace __internal
	{
		struct PluginLoggerDeleter
		{
			void operator()(IPluginLogger *ptr)
			{
				ptr->Destroy();
			}
		};
	}

	typedef std::unique_ptr<IPluginLogger, __internal::PluginLoggerDeleter> PluginLogger_t;

	extern "C" DLL_PUBLIC IPluginLogger *CreatePluginLoggerPtr(const char *pluginname);

	inline PluginLogger_t CreatePluginLogger(const char *pluginname)
	{
		return PluginLogger_t(CreatePluginLoggerPtr(pluginname));
	}
}

#undef DLL_PUBLIC
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right 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.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// Simple powertrain model for the M113 vehicle.
// - simple speed-torque curve
// - no torque converter
// - no transmission box
//
// =============================================================================

#include "m113/M113_SimplePowertrain.h"

using namespace chrono;
using namespace chrono::vehicle;

namespace m113 {

// -----------------------------------------------------------------------------
// Static variables
// -----------------------------------------------------------------------------
const double M113_SimplePowertrain::m_max_torque = 1000;
const double M113_SimplePowertrain::m_max_speed = 3000;
const double M113_SimplePowertrain::m_fwd_gear_ratio = 0.3;
const double M113_SimplePowertrain::m_rev_gear_ratio = -0.3;

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
M113_SimplePowertrain::M113_SimplePowertrain() : ChSimplePowertrain() {
}

}  // end namespace m113
<commit_msg>Adjust M113 simple powertrain parameters.<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right 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.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// Simple powertrain model for the M113 vehicle.
// - simple speed-torque curve
// - no torque converter
// - no transmission box
//
// =============================================================================

#include "m113/M113_SimplePowertrain.h"

using namespace chrono;
using namespace chrono::vehicle;

namespace m113 {

// -----------------------------------------------------------------------------
// Static variables
// -----------------------------------------------------------------------------
const double M113_SimplePowertrain::m_max_torque = 1000;
const double M113_SimplePowertrain::m_max_speed = 3000 * CH_C_2PI;
const double M113_SimplePowertrain::m_fwd_gear_ratio = 0.1;
const double M113_SimplePowertrain::m_rev_gear_ratio = -0.3;

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
M113_SimplePowertrain::M113_SimplePowertrain() : ChSimplePowertrain() {
}

}  // end namespace m113
<|endoftext|>


<commit_before><commit_msg>Enable MediaLeakTest.*<commit_after><|endoftext|>


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

    Copyright © 2010, 2011, 2012, 2013, 2014
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "Magnum/Context.h"
#include "Magnum/Extensions.h"

namespace Magnum {

void Context::setupDriverWorkarounds() {
    #define _setRequiredVersion(extension, version)                           \
        if(_extensionRequiredVersion[Extensions::extension::Index] < Version::version) \
            _extensionRequiredVersion[Extensions::extension::Index] = Version::version

    #ifndef MAGNUM_TARGET_GLES
    /* This extension causes crash in GLSL compiler on AMD linux drivers 13.251 */
    if(detectedDriver() & DetectedDriver::AMD)
        _setRequiredVersion(GL::ARB::explicit_uniform_location, None);
    #endif

    #ifndef MAGNUM_TARGET_GLES
    /* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL 1.30
       on NVidia and 1.40 on Mac OS X */
    /** @todo Different version on different vendors? */
    _setRequiredVersion(GL::ARB::explicit_attrib_location, GL320);
    _setRequiredVersion(GL::ARB::explicit_uniform_location, GL320);
    _setRequiredVersion(GL::ARB::shading_language_420pack, GL320);
    #endif

    /* Disable extensions not available on NaCl and Emscripten */
    #if defined(CORRADE_TARGET_NACL) || defined(CORRADE_TARGET_EMSCRIPTEN)
    _setRequiredVersion(GL::EXT::multi_draw_arrays, None);
    _setRequiredVersion(GL::EXT::debug_label, None);
    _setRequiredVersion(GL::EXT::debug_marker, None);
    _setRequiredVersion(GL::EXT::disjoint_timer_query, None);
    _setRequiredVersion(GL::EXT::separate_shader_objects, None);
    _setRequiredVersion(GL::EXT::multisampled_render_to_texture, None);
    _setRequiredVersion(GL::EXT::robustness, None);
    _setRequiredVersion(GL::KHR::debug, None);
    _setRequiredVersion(GL::NV::read_buffer_front, None);
    _setRequiredVersion(GL::OES::mapbuffer, None);
    _setRequiredVersion(GL::ANGLE::framebuffer_blit, None);
    _setRequiredVersion(GL::ANGLE::framebuffer_multisample, None);
    _setRequiredVersion(GL::ANGLE::instanced_arrays, None);
    _setRequiredVersion(GL::APPLE::framebuffer_multisample, None);
    _setRequiredVersion(GL::EXT::discard_framebuffer, None);
    _setRequiredVersion(GL::EXT::blend_minmax, None);
    _setRequiredVersion(GL::EXT::texture_storage, None);
    _setRequiredVersion(GL::EXT::map_buffer_range, None);
    _setRequiredVersion(GL::EXT::instanced_arrays, None);
    _setRequiredVersion(GL::EXT::draw_instanced, None);
    _setRequiredVersion(GL::NV::draw_buffers, None);
    _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ??
    _setRequiredVersion(GL::NV::read_buffer, None);
    _setRequiredVersion(GL::NV::draw_instanced, None);
    _setRequiredVersion(GL::NV::framebuffer_blit, None);
    _setRequiredVersion(GL::NV::framebuffer_multisample, None);
    _setRequiredVersion(GL::NV::instanced_arrays, None);
    _setRequiredVersion(GL::OES::texture_3D, None);
    _setRequiredVersion(GL::OES::vertex_array_object, None);
    #endif

    /* Disable extensions not available on Emscripten */
    #ifdef CORRADE_TARGET_EMSCRIPTEN
    _setRequiredVersion(GL::CHROMIUM::map_sub, None);
    _setRequiredVersion(GL::EXT::occlusion_query_boolean, None);
    #endif

    #undef _setRequiredVersion
}

}
<commit_msg>Disable ARB_shading_language_420pack for Intel on Windows.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "Magnum/Context.h"
#include "Magnum/Extensions.h"

namespace Magnum {

void Context::setupDriverWorkarounds() {
    #define _setRequiredVersion(extension, version)                           \
        if(_extensionRequiredVersion[Extensions::extension::Index] < Version::version) \
            _extensionRequiredVersion[Extensions::extension::Index] = Version::version

    #ifndef MAGNUM_TARGET_GLES
    /* This extension causes crash in GLSL compiler on AMD linux drivers 13.251 */
    if(detectedDriver() & DetectedDriver::AMD)
        _setRequiredVersion(GL::ARB::explicit_uniform_location, None);

    #ifdef CORRADE_TARGET_WINDOWS
    /* On Windows Intel drivers ARB_shading_language_420pack is exposed in GLSL
       even that the extension (e.g. binding keyword) is not supported */
    if((detectedDriver() & DetectedDriver::IntelWindows) && !Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>(version))
        _setRequiredVersion(GL::ARB::shading_language_420pack, None);
    #endif

    /* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL 1.30
       on NVidia and 1.40 on Mac OS X */
    /** @todo Different version on different vendors? */
    _setRequiredVersion(GL::ARB::explicit_attrib_location, GL320);
    _setRequiredVersion(GL::ARB::explicit_uniform_location, GL320);
    _setRequiredVersion(GL::ARB::shading_language_420pack, GL320);
    #endif

    /* Disable extensions not available on NaCl and Emscripten */
    #if defined(CORRADE_TARGET_NACL) || defined(CORRADE_TARGET_EMSCRIPTEN)
    _setRequiredVersion(GL::EXT::multi_draw_arrays, None);
    _setRequiredVersion(GL::EXT::debug_label, None);
    _setRequiredVersion(GL::EXT::debug_marker, None);
    _setRequiredVersion(GL::EXT::disjoint_timer_query, None);
    _setRequiredVersion(GL::EXT::separate_shader_objects, None);
    _setRequiredVersion(GL::EXT::multisampled_render_to_texture, None);
    _setRequiredVersion(GL::EXT::robustness, None);
    _setRequiredVersion(GL::KHR::debug, None);
    _setRequiredVersion(GL::NV::read_buffer_front, None);
    _setRequiredVersion(GL::OES::mapbuffer, None);
    _setRequiredVersion(GL::ANGLE::framebuffer_blit, None);
    _setRequiredVersion(GL::ANGLE::framebuffer_multisample, None);
    _setRequiredVersion(GL::ANGLE::instanced_arrays, None);
    _setRequiredVersion(GL::APPLE::framebuffer_multisample, None);
    _setRequiredVersion(GL::EXT::discard_framebuffer, None);
    _setRequiredVersion(GL::EXT::blend_minmax, None);
    _setRequiredVersion(GL::EXT::texture_storage, None);
    _setRequiredVersion(GL::EXT::map_buffer_range, None);
    _setRequiredVersion(GL::EXT::instanced_arrays, None);
    _setRequiredVersion(GL::EXT::draw_instanced, None);
    _setRequiredVersion(GL::NV::draw_buffers, None);
    _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ??
    _setRequiredVersion(GL::NV::read_buffer, None);
    _setRequiredVersion(GL::NV::draw_instanced, None);
    _setRequiredVersion(GL::NV::framebuffer_blit, None);
    _setRequiredVersion(GL::NV::framebuffer_multisample, None);
    _setRequiredVersion(GL::NV::instanced_arrays, None);
    _setRequiredVersion(GL::OES::texture_3D, None);
    _setRequiredVersion(GL::OES::vertex_array_object, None);
    #endif

    /* Disable extensions not available on Emscripten */
    #ifdef CORRADE_TARGET_EMSCRIPTEN
    _setRequiredVersion(GL::CHROMIUM::map_sub, None);
    _setRequiredVersion(GL::EXT::occlusion_query_boolean, None);
    #endif

    #undef _setRequiredVersion
}

}
<|endoftext|>


<commit_before>// Wheels - various C++ utilities
//
// Written in 2013 by Martinho Fernandes <martinho.fernandes@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related
// and neighboring rights to this software to the public domain worldwide. This software is
// distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>

// INVOKE protocol result type

#ifndef WHEELS_FUN_RESULT_OF_HPP
#define WHEELS_FUN_RESULT_OF_HPP

#include <wheels/fun/invoke.h++>
#include <wheels/fun/is_invocable.h++>

#include <wheels/meta/invoke.h++>
#include <wheels/meta/id.h++>
#include <wheels/meta/bool.h++>
#include <wheels/meta/depend_on.h++>

#include <utility> // declval

namespace wheels {
    namespace fun {
        namespace detail {
            template <typename Sig, bool Invocable>
            struct result_of {};
            template <typename Fun, typename... Args>
            struct result_of<Fun(Args...), true>
            : meta::id<decltype((invoke)(std::declval<Fun>(), std::declval<Args>()...))> {};
        } // namespace detail

        // *Requires*: `Sig` is a signature type `Fun(Args...)` [hard] and `Fun` is invocable with `Args...` [soft]
        // *Returns*: the result of calling `Fun` with the given `Args...` through the INVOKE protocol.
        template <typename Sig>
        struct result_of {
            static_assert(meta::DependOn<meta::False, Sig>(), "Sig must be a signature type");
        };
        template <typename Fun, typename... Args>
       struct result_of<Fun(Args...)> : detail::result_of<Fun(Args...), is_invocable<Fun, void(Args...)>::value> {};
        template <typename Sig>
        using ResultOf = meta::Invoke<result_of<Sig>>;
    } // namespace fun
} // namespace wheels

#endif // WHEELS_FUN_INVOKE_HPP

<commit_msg>Fixed footer<commit_after>// Wheels - various C++ utilities
//
// Written in 2013 by Martinho Fernandes <martinho.fernandes@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related
// and neighboring rights to this software to the public domain worldwide. This software is
// distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>

// INVOKE protocol result type

#ifndef WHEELS_FUN_RESULT_OF_HPP
#define WHEELS_FUN_RESULT_OF_HPP

#include <wheels/fun/invoke.h++>
#include <wheels/fun/is_invocable.h++>

#include <wheels/meta/invoke.h++>
#include <wheels/meta/id.h++>
#include <wheels/meta/bool.h++>
#include <wheels/meta/depend_on.h++>

#include <utility> // declval

namespace wheels {
    namespace fun {
        namespace detail {
            template <typename Sig, bool Invocable>
            struct result_of {};
            template <typename Fun, typename... Args>
            struct result_of<Fun(Args...), true>
            : meta::id<decltype((invoke)(std::declval<Fun>(), std::declval<Args>()...))> {};
        } // namespace detail

        // *Requires*: `Sig` is a signature type `Fun(Args...)` [hard] and `Fun` is invocable with `Args...` [soft]
        // *Returns*: the result of calling `Fun` with the given `Args...` through the INVOKE protocol.
        template <typename Sig>
        struct result_of {
            static_assert(meta::DependOn<meta::False, Sig>(), "Sig must be a signature type");
        };
        template <typename Fun, typename... Args>
       struct result_of<Fun(Args...)> : detail::result_of<Fun(Args...), is_invocable<Fun, void(Args...)>::value> {};
        template <typename Sig>
        using ResultOf = meta::Invoke<result_of<Sig>>;
    } // namespace fun
} // namespace wheels

#endif // WHEELS_FUN_RESULT_OF_HPP

<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <string>

#include "tensorflow/lite/tools/benchmark/delegate_provider.h"
#include "tensorflow/lite/tools/evaluation/utils.h"
#if defined(__APPLE__)
#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
// Only enable metal delegate when using a real iPhone device.
#define REAL_IPHONE_DEVICE
#include "tensorflow/lite/experimental/delegates/coreml/coreml_delegate.h"
#endif
#endif

namespace tflite {
namespace benchmark {

class CoreMlDelegateProvider : public DelegateProvider {
 public:
  CoreMlDelegateProvider() {
#if defined(REAL_IPHONE_DEVICE)
    default_params_.AddParam("use_coreml", BenchmarkParam::Create<bool>(true));
#endif
  }
  std::vector<Flag> CreateFlags(BenchmarkParams* params) const final;

  void LogParams(const BenchmarkParams& params) const final;

  TfLiteDelegatePtr CreateTfLiteDelegate(
      const BenchmarkParams& params) const final;

  std::string GetName() const final { return "COREML"; }
};
REGISTER_DELEGATE_PROVIDER(CoreMlDelegateProvider);

std::vector<Flag> CoreMlDelegateProvider::CreateFlags(
    BenchmarkParams* params) const {
  std::vector<Flag> flags = {
      CreateFlag<bool>("use_coreml", params, "use Core ML"),
  };
  return flags;
}

void CoreMlDelegateProvider::LogParams(const BenchmarkParams& params) const {
#if defined(REAL_IPHONE_DEVICE)
  TFLITE_LOG(INFO) << "Use Core ML : [" << params.Get<bool>("use_coreml")
                   << "]";
#endif
}

TfLiteDelegatePtr CoreMlDelegateProvider::CreateTfLiteDelegate(
    const BenchmarkParams& params) const {
  TfLiteDelegatePtr delegate(nullptr, [](TfLiteDelegate*) {});

#if defined(REAL_IPHONE_DEVICE)
  if (params.Get<bool>("use_coreml")) {
    TfLiteCoreMlDelegateOptions coreml_opts = {
        .enabled_devices = TfLiteCoreMlDelegateAllDevices};
    delegate = TfLiteDelegatePtr(TfLiteCoreMlDelegateCreate(&coreml_opts),
                                 &TfLiteCoreMlDelegateDelete);
    if (!delegate) {
      TFLITE_LOG(WARN)
          << "CoreML acceleration is unsupported on this platform.";
    }
  }
#endif

  return delegate;
}

}  // namespace benchmark
}  // namespace tflite
<commit_msg>Fixed an issue about undefined 'use_coreml' benchmark param.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <string>

#include "tensorflow/lite/tools/benchmark/delegate_provider.h"
#include "tensorflow/lite/tools/evaluation/utils.h"
#if defined(__APPLE__)
#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
// Only enable metal delegate when using a real iPhone device.
#define REAL_IPHONE_DEVICE
#include "tensorflow/lite/experimental/delegates/coreml/coreml_delegate.h"
#endif
#endif

namespace tflite {
namespace benchmark {

class CoreMlDelegateProvider : public DelegateProvider {
 public:
  CoreMlDelegateProvider() {
#if defined(REAL_IPHONE_DEVICE)
    default_params_.AddParam("use_coreml", BenchmarkParam::Create<bool>(true));
#endif
  }
  std::vector<Flag> CreateFlags(BenchmarkParams* params) const final;

  void LogParams(const BenchmarkParams& params) const final;

  TfLiteDelegatePtr CreateTfLiteDelegate(
      const BenchmarkParams& params) const final;

  std::string GetName() const final { return "COREML"; }
};
REGISTER_DELEGATE_PROVIDER(CoreMlDelegateProvider);

std::vector<Flag> CoreMlDelegateProvider::CreateFlags(
    BenchmarkParams* params) const {
#if defined(REAL_IPHONE_DEVICE)
  std::vector<Flag> flags = {
      CreateFlag<bool>("use_coreml", params, "use Core ML"),
  };
  return flags;
#else
  return {};
#endif
}

void CoreMlDelegateProvider::LogParams(const BenchmarkParams& params) const {
#if defined(REAL_IPHONE_DEVICE)
  TFLITE_LOG(INFO) << "Use Core ML : [" << params.Get<bool>("use_coreml")
                   << "]";
#endif
}

TfLiteDelegatePtr CoreMlDelegateProvider::CreateTfLiteDelegate(
    const BenchmarkParams& params) const {
  TfLiteDelegatePtr delegate(nullptr, [](TfLiteDelegate*) {});

#if defined(REAL_IPHONE_DEVICE)
  if (params.Get<bool>("use_coreml")) {
    TfLiteCoreMlDelegateOptions coreml_opts = {
        .enabled_devices = TfLiteCoreMlDelegateAllDevices};
    delegate = TfLiteDelegatePtr(TfLiteCoreMlDelegateCreate(&coreml_opts),
                                 &TfLiteCoreMlDelegateDelete);
    if (!delegate) {
      TFLITE_LOG(WARN)
          << "CoreML acceleration is unsupported on this platform.";
    }
  }
#endif

  return delegate;
}

}  // namespace benchmark
}  // namespace tflite
<|endoftext|>


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

#include <err.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#if defined(__APPLE__)
#	include <OpenGL/gl.h>
#	include <GLUT/glut.h>
#else
#	include <GL/gl.h>
#	include <GL/glut.h>
#endif

#include <vector>
#include <map>

#include <glosm/Math.hh>

#include <glosm/MercatorProjection.hh>
#include <glosm/PreloadedXmlDatasource.hh>
#include <glosm/DefaultGeometryGenerator.hh>
#include <glosm/FirstPersonViewer.hh>
#include <glosm/GeometryLayer.hh>

/* as glut has no OO concept and no feature like setUserData,
 * please forgive me using global variables pointing to
 * stack data for now */
FirstPersonViewer viewer;
Layer* layer_p = NULL;

int screenw = 1;
int screenh = 1;
int movementflags = 0;
float speed = 100.0f;
bool locktoground = false;

struct timeval prevtime, curtime, fpstime;
int nframes = 0;

void Display(void) {
	/* update scene */
	gettimeofday(&curtime, NULL);
	float dt = (float)(curtime.tv_sec - prevtime.tv_sec) + (float)(curtime.tv_usec - prevtime.tv_usec)/1000000.0f;

	/* render frame */
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	if (layer_p)
		layer_p->Render(viewer);

	glFlush();
	glutSwapBuffers();

	if (movementflags)
		viewer.Move(movementflags, speed, dt);
	if (locktoground)
		viewer.MutablePos().z = 1750;

	/* update FPS */
	float fpst = (float)(curtime.tv_sec - fpstime.tv_sec) + (float)(curtime.tv_usec - fpstime.tv_usec)/1000000.0f;

	if (fpst > 10.0) {
		fprintf(stderr, "FPS: %.3f\n", (float)nframes/fpst);
		fpstime = curtime;
		nframes = 0;
	}

	prevtime = curtime;
	nframes++;

	/* frame limiter */
	usleep(10000);
}

void Reshape(int w, int h) {
	if (w <= 0)
		w = 1;
	if (h <= 0)
		h = 1;

	screenw = w;
	screenh = h;

	float wanted_fov = 70.0f/180.0f*M_PI;
	float wanted_aspect = 4.0f/3.0f;

	float fov, aspect;

	if ((float)w/(float)h > wanted_aspect) { // wider than wanted
		fov = wanted_fov;
	} else { // narrower than wanted
		float wanted_h = (float)w/wanted_aspect;
		fov = 2.0f*atanf((float)h / wanted_h * tanf(wanted_fov/2.0f));
	}
	fov = wanted_fov;
	aspect = (float)w/(float)h;

	glViewport(0, 0, w, h);

	viewer.SetFov(fov);
	viewer.SetAspect(aspect);

	glutWarpPointer(screenw/2, screenh/2);
}

void Mouse(int x, int y) {
	int dx = x - screenw/2;
	int dy = y - screenh/2;

	float YawDelta = (float)dx / 500.0;
	float PitchDelta = -(float)dy / 500.0;

	viewer.HardRotate(YawDelta, PitchDelta);

	if (dx != 0 || dy != 0)
		glutWarpPointer(screenw/2, screenh/2);
}

void SpecialDown(int key, int, int) {
	switch (key) {
	case GLUT_KEY_UP: movementflags |= FirstPersonViewer::FORWARD; break;
	case GLUT_KEY_DOWN: movementflags |= FirstPersonViewer::BACKWARD; break;
	case GLUT_KEY_LEFT: movementflags |= FirstPersonViewer::LEFT; break;
	case GLUT_KEY_RIGHT: movementflags |= FirstPersonViewer::RIGHT; break;
	default:
		  break;
	}
}

void SpecialUp(int key, int, int) {
	switch (key) {
	case GLUT_KEY_UP: movementflags &= ~FirstPersonViewer::FORWARD; break;
	case GLUT_KEY_DOWN: movementflags &= ~FirstPersonViewer::BACKWARD; break;
	case GLUT_KEY_LEFT: movementflags &= ~FirstPersonViewer::LEFT; break;
	case GLUT_KEY_RIGHT: movementflags &= ~FirstPersonViewer::RIGHT; break;
	default:
		  break;
	}
}

void KeyDown(unsigned char key, int, int) {
	switch (key) {
	case 27: case 'q': exit(0); break;
	case 'w': movementflags |= FirstPersonViewer::FORWARD; break;
	case 's': movementflags |= FirstPersonViewer::BACKWARD; break;
	case 'a': movementflags |= FirstPersonViewer::LEFT; break;
	case 'd': movementflags |= FirstPersonViewer::RIGHT; break;
	case 'c': movementflags |= FirstPersonViewer::LOWER; break;
	case ' ': movementflags |= FirstPersonViewer::HIGHER; break;
	case 'l': locktoground = !locktoground; break;
	case '+': speed *= 10.0f; break;
	case '-': speed /= 10.0f; break;
	default:
		  break;
	}
}

void KeyUp(unsigned char key, int, int) {
	switch (key) {
	case 'w': movementflags &= ~FirstPersonViewer::FORWARD; break;
	case 's': movementflags &= ~FirstPersonViewer::BACKWARD; break;
	case 'a': movementflags &= ~FirstPersonViewer::LEFT; break;
	case 'd': movementflags &= ~FirstPersonViewer::RIGHT; break;
	case 'c': movementflags &= ~FirstPersonViewer::LOWER; break;
	case ' ': movementflags &= ~FirstPersonViewer::HIGHER; break;
	default:
		  break;
	}
}

int real_main(int argc, char** argv) {
	glutInit(&argc, argv);

	if (argc != 2)
		errx(1, "Usage: %s file.osm", argv[0]);

	/* load data */
	fprintf(stderr, "Loading...\n");
	PreloadedXmlDatasource osm_datasource;
	gettimeofday(&prevtime, NULL);
	osm_datasource.Load(argv[1]);
	gettimeofday(&curtime, NULL);
	fprintf(stderr, "Loaded XML in %.3f seconds\n", (float)(curtime.tv_sec - prevtime.tv_sec) + (float)(curtime.tv_usec - prevtime.tv_usec)/1000000.0f);
	prevtime = curtime;

	/* glut init */
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE);
	glutInitWindowSize(800, 600);
	glutCreateWindow("glosm viewer");

	glutIgnoreKeyRepeat(1);
	glutSetCursor(GLUT_CURSOR_NONE);

	glutDisplayFunc(Display);
	glutIdleFunc(Display);
	glutReshapeFunc(Reshape);
	glutPassiveMotionFunc(Mouse);
	glutKeyboardFunc(KeyDown);
	glutKeyboardUpFunc(KeyUp);
	glutSpecialFunc(SpecialDown);
	glutSpecialUpFunc(SpecialUp);

	/* opengl init */
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glShadeModel(GL_FLAT);

	glClearColor(0.5, 0.5, 0.5, 0.0);

	/* glosm init */
	gettimeofday(&prevtime, NULL);

	DefaultGeometryGenerator geometry_generator(osm_datasource);
	GeometryLayer layer(MercatorProjection(), geometry_generator);
	layer_p = &layer;

	gettimeofday(&curtime, NULL);
	fprintf(stderr, "Prepared geometry in %.3f seconds\n", (float)(curtime.tv_sec - prevtime.tv_sec) + (float)(curtime.tv_usec - prevtime.tv_usec)/1000000.0f);
	prevtime = curtime;
	fpstime = curtime;

	viewer.SetPos(Vector3i(geometry_generator.GetCenter(), 1750));

	/* with current GeometryLayer implementation, datasources are no longer needed */
	osm_datasource.Clear();

	/* main loop */
	/* note that this never returns and objects created above
	 * are never properly destroyed; should dump GLUT ASAP */
	glutMainLoop();

	return 0;
}

int main(int argc, char** argv) {
	try {
		return real_main(argc, argv);
	} catch (std::exception &e) {
		fprintf(stderr, "Exception: %s\n", e.what());
	} catch (...) {
		fprintf(stderr, "Unknown exception\n");
	}

	return 1;
}
<commit_msg>Scale movement speed depending on height, better height default<commit_after>/*
 * Copyright (C) 2010-2011 Dmitry Marakasov
 *
 * This file is part of glosm.
 *
 * glosm is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * glosm is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with glosm.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <err.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#if defined(__APPLE__)
#	include <OpenGL/gl.h>
#	include <GLUT/glut.h>
#else
#	include <GL/gl.h>
#	include <GL/glut.h>
#endif

#include <vector>
#include <map>

#include <glosm/Math.hh>

#include <glosm/MercatorProjection.hh>
#include <glosm/PreloadedXmlDatasource.hh>
#include <glosm/DefaultGeometryGenerator.hh>
#include <glosm/FirstPersonViewer.hh>
#include <glosm/GeometryLayer.hh>

/* as glut has no OO concept and no feature like setUserData,
 * please forgive me using global variables pointing to
 * stack data for now */
FirstPersonViewer viewer;
Layer* layer_p = NULL;

int screenw = 1;
int screenh = 1;
int movementflags = 0;
float speed = 200.0f;
bool locktoground = false;

struct timeval prevtime, curtime, fpstime;
int nframes = 0;

void Display(void) {
	/* update scene */
	gettimeofday(&curtime, NULL);
	float dt = (float)(curtime.tv_sec - prevtime.tv_sec) + (float)(curtime.tv_usec - prevtime.tv_usec)/1000000.0f;

	/* render frame */
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	if (layer_p)
		layer_p->Render(viewer);

	glFlush();
	glutSwapBuffers();

	if (movementflags) {
		float myspeed = speed;
		float height = viewer.MutablePos().z / 1000.0;

		if (height > 100.0 && height < 100000.0)
			myspeed *= height / 100.0;
		else if (height >= 100000.0)
			myspeed *= 1000.0;

		viewer.Move(movementflags, myspeed, dt);
	}
	if (locktoground)
		viewer.MutablePos().z = 1750;

	/* update FPS */
	float fpst = (float)(curtime.tv_sec - fpstime.tv_sec) + (float)(curtime.tv_usec - fpstime.tv_usec)/1000000.0f;

	if (fpst > 10.0) {
		fprintf(stderr, "FPS: %.3f\n", (float)nframes/fpst);
		fpstime = curtime;
		nframes = 0;
	}

	prevtime = curtime;
	nframes++;

	/* frame limiter */
	usleep(10000);
}

void Reshape(int w, int h) {
	if (w <= 0)
		w = 1;
	if (h <= 0)
		h = 1;

	screenw = w;
	screenh = h;

	float wanted_fov = 70.0f/180.0f*M_PI;
	float wanted_aspect = 4.0f/3.0f;

	float fov, aspect;

	if ((float)w/(float)h > wanted_aspect) { // wider than wanted
		fov = wanted_fov;
	} else { // narrower than wanted
		float wanted_h = (float)w/wanted_aspect;
		fov = 2.0f*atanf((float)h / wanted_h * tanf(wanted_fov/2.0f));
	}
	fov = wanted_fov;
	aspect = (float)w/(float)h;

	glViewport(0, 0, w, h);

	viewer.SetFov(fov);
	viewer.SetAspect(aspect);

	glutWarpPointer(screenw/2, screenh/2);
}

void Mouse(int x, int y) {
	int dx = x - screenw/2;
	int dy = y - screenh/2;

	float YawDelta = (float)dx / 500.0;
	float PitchDelta = -(float)dy / 500.0;

	viewer.HardRotate(YawDelta, PitchDelta);

	if (dx != 0 || dy != 0)
		glutWarpPointer(screenw/2, screenh/2);
}

void SpecialDown(int key, int, int) {
	switch (key) {
	case GLUT_KEY_UP: movementflags |= FirstPersonViewer::FORWARD; break;
	case GLUT_KEY_DOWN: movementflags |= FirstPersonViewer::BACKWARD; break;
	case GLUT_KEY_LEFT: movementflags |= FirstPersonViewer::LEFT; break;
	case GLUT_KEY_RIGHT: movementflags |= FirstPersonViewer::RIGHT; break;
	default:
		  break;
	}
}

void SpecialUp(int key, int, int) {
	switch (key) {
	case GLUT_KEY_UP: movementflags &= ~FirstPersonViewer::FORWARD; break;
	case GLUT_KEY_DOWN: movementflags &= ~FirstPersonViewer::BACKWARD; break;
	case GLUT_KEY_LEFT: movementflags &= ~FirstPersonViewer::LEFT; break;
	case GLUT_KEY_RIGHT: movementflags &= ~FirstPersonViewer::RIGHT; break;
	default:
		  break;
	}
}

void KeyDown(unsigned char key, int, int) {
	switch (key) {
	case 27: case 'q': exit(0); break;
	case 'w': movementflags |= FirstPersonViewer::FORWARD; break;
	case 's': movementflags |= FirstPersonViewer::BACKWARD; break;
	case 'a': movementflags |= FirstPersonViewer::LEFT; break;
	case 'd': movementflags |= FirstPersonViewer::RIGHT; break;
	case 'c': movementflags |= FirstPersonViewer::LOWER; break;
	case ' ': movementflags |= FirstPersonViewer::HIGHER; break;
	case 'l': locktoground = !locktoground; break;
	case '+': speed *= 5.0f; break;
	case '-': speed /= 5.0f; break;
	default:
		  break;
	}
}

void KeyUp(unsigned char key, int, int) {
	switch (key) {
	case 'w': movementflags &= ~FirstPersonViewer::FORWARD; break;
	case 's': movementflags &= ~FirstPersonViewer::BACKWARD; break;
	case 'a': movementflags &= ~FirstPersonViewer::LEFT; break;
	case 'd': movementflags &= ~FirstPersonViewer::RIGHT; break;
	case 'c': movementflags &= ~FirstPersonViewer::LOWER; break;
	case ' ': movementflags &= ~FirstPersonViewer::HIGHER; break;
	default:
		  break;
	}
}

int real_main(int argc, char** argv) {
	glutInit(&argc, argv);

	if (argc != 2)
		errx(1, "Usage: %s file.osm", argv[0]);

	/* load data */
	fprintf(stderr, "Loading...\n");
	PreloadedXmlDatasource osm_datasource;
	gettimeofday(&prevtime, NULL);
	osm_datasource.Load(argv[1]);
	gettimeofday(&curtime, NULL);
	fprintf(stderr, "Loaded XML in %.3f seconds\n", (float)(curtime.tv_sec - prevtime.tv_sec) + (float)(curtime.tv_usec - prevtime.tv_usec)/1000000.0f);
	prevtime = curtime;

	/* glut init */
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE);
	glutInitWindowSize(800, 600);
	glutCreateWindow("glosm viewer");

	glutIgnoreKeyRepeat(1);
	glutSetCursor(GLUT_CURSOR_NONE);

	glutDisplayFunc(Display);
	glutIdleFunc(Display);
	glutReshapeFunc(Reshape);
	glutPassiveMotionFunc(Mouse);
	glutKeyboardFunc(KeyDown);
	glutKeyboardUpFunc(KeyUp);
	glutSpecialFunc(SpecialDown);
	glutSpecialUpFunc(SpecialUp);

	/* opengl init */
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glShadeModel(GL_FLAT);

	glClearColor(0.5, 0.5, 0.5, 0.0);

	/* glosm init */
	gettimeofday(&prevtime, NULL);

	DefaultGeometryGenerator geometry_generator(osm_datasource);
	GeometryLayer layer(MercatorProjection(), geometry_generator);
	layer_p = &layer;

	gettimeofday(&curtime, NULL);
	fprintf(stderr, "Prepared geometry in %.3f seconds\n", (float)(curtime.tv_sec - prevtime.tv_sec) + (float)(curtime.tv_usec - prevtime.tv_usec)/1000000.0f);
	prevtime = curtime;
	fpstime = curtime;

	int height = fabs((float)geometry_generator.GetBBox().top -  (float)geometry_generator.GetBBox().bottom)/3600000000.0*40000000.0/10.0*1000.0;
	viewer.SetPos(Vector3i(geometry_generator.GetCenter(), height));

	/* with current GeometryLayer implementation, datasources are no longer needed */
	osm_datasource.Clear();

	/* main loop */
	/* note that this never returns and objects created above
	 * are never properly destroyed; should dump GLUT ASAP */
	glutMainLoop();

	return 0;
}

int main(int argc, char** argv) {
	try {
		return real_main(argc, argv);
	} catch (std::exception &e) {
		fprintf(stderr, "Exception: %s\n", e.what());
	} catch (...) {
		fprintf(stderr, "Unknown exception\n");
	}

	return 1;
}
<|endoftext|>