aboutsummaryrefslogtreecommitdiffstats
path: root/include/distortos/internal/scheduler/DynamicThreadBase.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/distortos/internal/scheduler/DynamicThreadBase.hpp')
-rw-r--r--include/distortos/internal/scheduler/DynamicThreadBase.hpp231
1 files changed, 231 insertions, 0 deletions
diff --git a/include/distortos/internal/scheduler/DynamicThreadBase.hpp b/include/distortos/internal/scheduler/DynamicThreadBase.hpp
new file mode 100644
index 0000000..5ca3ff8
--- /dev/null
+++ b/include/distortos/internal/scheduler/DynamicThreadBase.hpp
@@ -0,0 +1,231 @@
+/**
+ * \file
+ * \brief DynamicThreadBase class header
+ *
+ * \author Copyright (C) 2015-2016 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/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_DYNAMICTHREADBASE_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_DYNAMICTHREADBASE_HPP_
+
+#include "distortos/DynamicSignalsReceiver.hpp"
+#include "distortos/DynamicThreadParameters.hpp"
+#include "distortos/ThreadCommon.hpp"
+
+#include "distortos/internal/memory/storageDeleter.hpp"
+
+namespace distortos
+{
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+class DynamicThread;
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+namespace internal
+{
+
+/**
+ * \brief DynamicThreadBase class is a type-erased interface for thread that has dynamic storage for bounded function,
+ * stack and internal DynamicSignalsReceiver object.
+ *
+ * If thread detachment is enabled (CONFIG_THREAD_DETACH_ENABLE is defined) then this class is dynamically allocated by
+ * DynamicThread - which allows it to be "detached". Otherwise - if thread detachment is disabled
+ * (CONFIG_THREAD_DETACH_ENABLE is not defined) - DynamicThread just inherits from this class.
+ */
+
+class DynamicThreadBase : public ThreadCommon
+{
+public:
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+ /**
+ * \brief DynamicThreadBase's constructor
+ *
+ * \tparam Function is the function that will be executed in separate thread
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] stackSize is the size of stack, bytes
+ * \param [in] canReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this
+ * thread
+ * \param [in] queuedSignals is the max number of queued signals for this thread, relevant only if
+ * \a canReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \param [in] signalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * \a canReceiveSignals == true, 0 to disable catching of signals 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] owner is a reference to owner DynamicThread object
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for \a function
+ */
+
+ template<typename Function, typename... Args>
+ DynamicThreadBase(size_t stackSize, bool canReceiveSignals, size_t queuedSignals, size_t signalActions,
+ uint8_t priority, SchedulingPolicy schedulingPolicy, DynamicThread& owner, Function&& function,
+ Args&&... args);
+
+ /**
+ * \brief Detaches the thread.
+ *
+ * Similar to std::thread::detach() - http://en.cppreference.com/w/cpp/thread/thread/detach
+ * Similar to POSIX pthread_detach() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_detach.html
+ *
+ * Detaches the executing thread from the Thread object, allowing execution to continue independently. All resources
+ * allocated for the thread will be deallocated when the thread terminates.
+ *
+ * \return 0 on success, error code otherwise:
+ * - EINVAL - this thread is already detached;
+ */
+
+ int detach() override;
+
+#else // !def CONFIG_THREAD_DETACH_ENABLE
+
+ /**
+ * \brief DynamicThreadBase's constructor
+ *
+ * \tparam Function is the function that will be executed in separate thread
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] stackSize is the size of stack, bytes
+ * \param [in] canReceiveSignals selects whether reception of signals is enabled (true) or disabled (false) for this
+ * thread
+ * \param [in] queuedSignals is the max number of queued signals for this thread, relevant only if
+ * \a canReceiveSignals == true, 0 to disable queuing of signals for this thread
+ * \param [in] signalActions is the max number of different SignalAction objects for this thread, relevant only if
+ * \a canReceiveSignals == true, 0 to disable catching of signals 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] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for \a function
+ */
+
+ template<typename Function, typename... Args>
+ DynamicThreadBase(size_t stackSize, bool canReceiveSignals, size_t queuedSignals, size_t signalActions,
+ uint8_t priority, SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args);
+
+ /**
+ * \brief DynamicThreadBase's constructor
+ *
+ * \tparam Function is the function that will be executed in separate thread
+ * \tparam Args are the arguments for \a Function
+ *
+ * \param [in] parameters is a DynamicThreadParameters struct with thread parameters
+ * \param [in] function is a function that will be executed in separate thread
+ * \param [in] args are arguments for \a function
+ */
+
+ template<typename Function, typename... Args>
+ DynamicThreadBase(const DynamicThreadParameters parameters, Function&& function, Args&&... args) :
+ DynamicThreadBase{parameters.stackSize, parameters.canReceiveSignals, parameters.queuedSignals,
+ parameters.signalActions, parameters.priority, parameters.schedulingPolicy,
+ std::forward<Function>(function), std::forward<Args>(args)...}
+ {
+
+ }
+
+#endif // !def CONFIG_THREAD_DETACH_ENABLE
+
+ DynamicThreadBase(const DynamicThreadBase&) = delete;
+ DynamicThreadBase(DynamicThreadBase&&) = default;
+ const DynamicThreadBase& operator=(const DynamicThreadBase&) = delete;
+ DynamicThreadBase& operator=(DynamicThreadBase&&) = delete;
+
+protected:
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+ /**
+ * \brief Pre-termination hook function of thread
+ *
+ * If thread is detached, locks object used for deferred deletion.
+ *
+ * \param [in] thread is a reference to Thread object, this must be DynamicThreadBase!
+ */
+
+ static void preTerminationHook(Thread& thread);
+
+ /**
+ * \brief Termination hook function of thread
+ *
+ * Calls ThreadCommon::terminationHook() and - if thread is detached - schedules itself for deferred deletion.
+ *
+ * \param [in] thread is a reference to Thread object, this must be DynamicThreadBase!
+ */
+
+ static void terminationHook(Thread& thread);
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+
+private:
+
+ /**
+ * \brief Thread's "run" function.
+ *
+ * Executes bound function object.
+ *
+ * \param [in] thread is a reference to Thread object, this must be DynamicThreadBase!
+ */
+
+ static void run(Thread& thread);
+
+ /// internal DynamicSignalsReceiver object
+ DynamicSignalsReceiver dynamicSignalsReceiver_;
+
+ /// bound function object
+ std::function<void()> boundFunction_;
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+ /// pointer to owner DynamicThread object, nullptr if thread is detached
+ DynamicThread* owner_;
+
+#endif // def CONFIG_THREAD_DETACH_ENABLE
+};
+
+#ifdef CONFIG_THREAD_DETACH_ENABLE
+
+template<typename Function, typename... Args>
+DynamicThreadBase::DynamicThreadBase(const size_t stackSize, const bool canReceiveSignals, const size_t queuedSignals,
+ const size_t signalActions, const uint8_t priority, const SchedulingPolicy schedulingPolicy,
+ DynamicThread& owner, Function&& function, Args&&... args) :
+ ThreadCommon{{{new uint8_t[stackSize], storageDeleter<uint8_t>}, stackSize, *this, run,
+ preTerminationHook, terminationHook}, priority, schedulingPolicy, nullptr,
+ canReceiveSignals == true ? &dynamicSignalsReceiver_ : nullptr},
+ dynamicSignalsReceiver_{canReceiveSignals == true ? queuedSignals : 0,
+ canReceiveSignals == true ? signalActions : 0},
+ boundFunction_{std::bind(std::forward<Function>(function), std::forward<Args>(args)...)},
+ owner_{&owner}
+{
+
+}
+
+#else // !def CONFIG_THREAD_DETACH_ENABLE
+
+template<typename Function, typename... Args>
+DynamicThreadBase::DynamicThreadBase(const size_t stackSize, const bool canReceiveSignals, const size_t queuedSignals,
+ const size_t signalActions, const uint8_t priority, const SchedulingPolicy schedulingPolicy,
+ Function&& function, Args&&... args) :
+ ThreadCommon{{{new uint8_t[stackSize], storageDeleter<uint8_t>}, stackSize, *this, run, nullptr,
+ terminationHook}, priority, schedulingPolicy, nullptr,
+ canReceiveSignals == true ? &dynamicSignalsReceiver_ : nullptr},
+ dynamicSignalsReceiver_{canReceiveSignals == true ? queuedSignals : 0,
+ canReceiveSignals == true ? signalActions : 0},
+ boundFunction_{std::bind(std::forward<Function>(function), std::forward<Args>(args)...)}
+{
+
+}
+
+#endif // !def CONFIG_THREAD_DETACH_ENABLE
+
+} // namespace internal
+
+} // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_DYNAMICTHREADBASE_HPP_