mirror of
https://git.intern.spaceteamaachen.de/ALPAKA/rtos2-utils.git
synced 2025-06-10 01:55:59 +00:00
Updated implementation of barrier pattern
This commit is contained in:
parent
1a8f8c5dff
commit
ad3e3c44ee
@ -11,20 +11,71 @@
|
||||
#include <sta/rtos/mutex.hpp>
|
||||
#include <sta/rtos/event.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
|
||||
namespace sta
|
||||
{
|
||||
class Barrier {
|
||||
public:
|
||||
Barrier(const char* name, uint8_t n_threads);
|
||||
/**
|
||||
* @brief Construct a new Barrier object
|
||||
*
|
||||
* @param name The name of the mutex used for this barrier.
|
||||
* @param waitTime The minimum time that needs to pass until the barrier can open again.
|
||||
*/
|
||||
Barrier(const char* name, uint32_t waitTime = 0);
|
||||
|
||||
/**
|
||||
* @brief Adds the currently running thread to the threads the barrier waits for.
|
||||
*
|
||||
*/
|
||||
void subscribe();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return uint8_t Returns the number of threads currently subscribed to this barrier
|
||||
*/
|
||||
uint8_t getNumSubscribedThreads();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return uint8_t Returns the number of threads that have entered the barrier and are waiting now.
|
||||
*/
|
||||
uint8_t getNumEntered();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return uint8_t Returns the number of threads that have left the barrier so far.
|
||||
*/
|
||||
uint8_t getNumLeft();
|
||||
|
||||
void setMinimumWaitDuration(uint32_t duration);
|
||||
|
||||
/**
|
||||
* @brief Wait for the barrier to open again. Sets this state into waiting state.
|
||||
*
|
||||
*/
|
||||
void wait();
|
||||
|
||||
/**
|
||||
* @brief Method for an external thread to wait for the barrier to open without subscribing to it.
|
||||
*
|
||||
* @note This means that the barrier doesn't wait for this thread.
|
||||
*
|
||||
*/
|
||||
void externalWait();
|
||||
private:
|
||||
RtosMutex mutex_;
|
||||
RtosEvent flag_;
|
||||
const uint8_t n_threads_;
|
||||
uint8_t n_entered_;
|
||||
uint8_t n_left_;
|
||||
|
||||
uint32_t waitTime_;
|
||||
uint32_t lastTime_;
|
||||
|
||||
std::set<osThreadId_t> threads_;
|
||||
uint8_t nThreads_;
|
||||
uint8_t nEntered_;
|
||||
uint8_t nLeft_;
|
||||
};
|
||||
} // namespace sta
|
||||
|
||||
|
@ -82,6 +82,13 @@ namespace sta
|
||||
*/
|
||||
RtosThread(const char* name, osPriority_t prio, uint32_t stack_size = 0, uint32_t cb_size = 0);
|
||||
|
||||
/**
|
||||
* @brief Static method for obtaining the ID of the currently running RtosThread.
|
||||
*
|
||||
* @return osThreadId_t The ID of the currently running Rtos-Thread.
|
||||
*/
|
||||
static osThreadId_t getCurrentlyRunningThreadID();
|
||||
|
||||
/**
|
||||
* @brief Get the currently running instance.
|
||||
*
|
||||
|
@ -6,20 +6,72 @@
|
||||
*/
|
||||
|
||||
#include <sta/rtos/patterns/barrier.hpp>
|
||||
#include <sta/rtos/thread.hpp>
|
||||
|
||||
#include <sta/time.hpp>
|
||||
#include <sta/debug/assert.hpp>
|
||||
|
||||
|
||||
namespace sta
|
||||
{
|
||||
Barrier::Barrier(const char* name, uint8_t n_threads)
|
||||
Barrier::Barrier(const char * name, uint32_t waitTime /* = 0 */)
|
||||
: mutex_{name},
|
||||
flag_{},
|
||||
n_threads_{n_threads},
|
||||
n_entered_{0},
|
||||
n_left_{n_threads}
|
||||
waitTime_{waitTime},
|
||||
lastTime_{now()},
|
||||
threads_{},
|
||||
nThreads_{0},
|
||||
nEntered_{0},
|
||||
nLeft_{0}
|
||||
{
|
||||
STA_ASSERT(name != nullptr);
|
||||
STA_ASSERT(n_threads >= 1);
|
||||
}
|
||||
|
||||
void Barrier::subscribe()
|
||||
{
|
||||
mutex_.acquire();
|
||||
threads_.insert(RtosThread::getCurrentlyRunningThreadID());
|
||||
nThreads_ += 1;
|
||||
nLeft_ += 1;
|
||||
mutex_.release();
|
||||
}
|
||||
|
||||
uint8_t Barrier::getNumSubscribedThreads()
|
||||
{
|
||||
mutex_.acquire();
|
||||
uint8_t rslt = nThreads_;
|
||||
mutex_.release();
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
uint8_t Barrier::getNumEntered()
|
||||
{
|
||||
mutex_.acquire();
|
||||
uint8_t rslt = nEntered_;
|
||||
mutex_.release();
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return uint8_t Returns the number of threads that have left the barrier so far.
|
||||
*/
|
||||
uint8_t Barrier::getNumLeft()
|
||||
{
|
||||
mutex_.acquire();
|
||||
uint8_t rslt = nLeft_;
|
||||
mutex_.release();
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
void Barrier::setMinimumWaitDuration(uint32_t duration)
|
||||
{
|
||||
mutex_.acquire();
|
||||
waitTime_ = duration;
|
||||
mutex_.release();
|
||||
}
|
||||
|
||||
void Barrier::wait()
|
||||
@ -29,9 +81,13 @@ namespace sta
|
||||
*/
|
||||
mutex_.acquire();
|
||||
|
||||
if (n_entered_ == 0)
|
||||
// Make sure the current thread is actually subscribed to this barrier.
|
||||
STA_ASSERT(threads_.find(RtosThread::getCurrentlyRunningThreadID()) != threads_.end());
|
||||
|
||||
// Is this the first thread entering the barrier?
|
||||
if (nEntered_ == 0)
|
||||
{
|
||||
if (n_left_ == n_threads_)
|
||||
if (nLeft_ == nThreads_)
|
||||
{
|
||||
// First thread to arrive clears the flag.
|
||||
flag_.clear();
|
||||
@ -43,7 +99,7 @@ namespace sta
|
||||
mutex_.release();
|
||||
|
||||
// Busy waiting until the last thread leaves.
|
||||
while (n_left_ != n_threads_)
|
||||
while (nLeft_ != nThreads_)
|
||||
{
|
||||
osThreadYield();
|
||||
}
|
||||
@ -56,28 +112,41 @@ namespace sta
|
||||
}
|
||||
|
||||
// Register this thread entering the barrier.
|
||||
++n_entered_;
|
||||
mutex_.release();
|
||||
++nEntered_;
|
||||
|
||||
if (n_entered_ == n_threads_)
|
||||
if (nEntered_ == nThreads_)
|
||||
{
|
||||
// If all threads are waiting in the barrier, set the flag allowing threads to leave.
|
||||
n_entered_ = 0;
|
||||
n_left_ = 1;
|
||||
if (now() - lastTime_ < waitTime_)
|
||||
{
|
||||
// Let the thread sleep for the remaining time.
|
||||
osDelay(waitTime_ - (now() - lastTime_));
|
||||
}
|
||||
|
||||
// If all threads are waiting in the barrier, set the flag allowing threads to leave.
|
||||
nEntered_ = 0;
|
||||
nLeft_ = 1;
|
||||
|
||||
mutex_.release();
|
||||
flag_.set();
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex_.release();
|
||||
|
||||
// Wait in the barrier until the flag is set.
|
||||
flag_.wait();
|
||||
|
||||
// Register this thread leaving the barrier.
|
||||
// Register that this thread left the barrier.
|
||||
mutex_.acquire();
|
||||
n_left_++;
|
||||
nLeft_++;
|
||||
mutex_.release();
|
||||
}
|
||||
}
|
||||
|
||||
void Barrier::externalWait()
|
||||
{
|
||||
flag_.wait();
|
||||
}
|
||||
} // namespace sta
|
||||
|
||||
|
||||
|
@ -12,6 +12,11 @@ namespace sta
|
||||
attribs_{ .name = name, .cb_size = cb_size, .stack_size = stack_size, .priority = prio }
|
||||
{}
|
||||
|
||||
osThreadId_t RtosThread::getCurrentlyRunningThreadID()
|
||||
{
|
||||
return osThreadGetId();
|
||||
}
|
||||
|
||||
osThreadId_t RtosThread::getInstance()
|
||||
{
|
||||
return instance_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user