updated host osal

This commit is contained in:
Robin Müller 2020-09-05 20:18:52 +02:00
parent c6dbce7446
commit a1155686c5
15 changed files with 1564 additions and 1564 deletions

View File

@ -1,227 +1,227 @@
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../timemanager/Clock.h"
#include <chrono>
#if defined(WIN32)
#include <windows.h>
#elif defined(LINUX)
#include <fstream>
#endif
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
using SystemClock = std::chrono::system_clock;
uint32_t Clock::getTicksPerSecond(void){
sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl;
return 0;
//return CLOCKS_PER_SEC;
//uint32_t ticks = sysconf(_SC_CLK_TCK);
//return ticks;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
// do some magic with chrono
sif::warning << "Clock::setClock: not implemented yet" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::setClock(const timeval* time) {
// do some magic with chrono
#if defined(WIN32)
return HasReturnvaluesIF::RETURN_OK;
#elif defined(LINUX)
return HasReturnvaluesIF::RETURN_OK;
#else
#endif
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
#if defined(WIN32)
auto now = std::chrono::system_clock::now();
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto epoch = now.time_since_epoch();
time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();
auto fraction = now - secondsChrono;
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
fraction).count();
return HasReturnvaluesIF::RETURN_OK;
#elif defined(LINUX)
timespec timeUnix;
int status = clock_gettime(CLOCK_REALTIME,&timeUnix);
if(status!=0){
return HasReturnvaluesIF::RETURN_FAILED;
}
time->tv_sec = timeUnix.tv_sec;
time->tv_usec = timeUnix.tv_nsec / 1000.0;
return HasReturnvaluesIF::RETURN_OK;
#else
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
#endif
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
// do some magic with chrono
sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
timeval Clock::getUptime() {
timeval timeval;
#if defined(WIN32)
auto uptime = std::chrono::milliseconds(GetTickCount64());
auto secondsChrono = std::chrono::duration_cast<std::chrono::seconds>(uptime);
timeval.tv_sec = secondsChrono.count();
auto fraction = uptime - secondsChrono;
timeval.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
fraction).count();
#elif defined(LINUX)
double uptimeSeconds;
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds)
{
// value is rounded down automatically
timeval.tv_sec = uptimeSeconds;
timeval.tv_usec = uptimeSeconds *(double) 1e6 - (timeval.tv_sec *1e6);
}
#else
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
#endif
return timeval;
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
*uptime = getUptime();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime = getUptime();
*uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
// do some magic with chrono (C++20!)
// Right now, the library doesn't have the new features yet.
// so we work around that for now.
auto now = SystemClock::now();
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds;
time_t tt = SystemClock::to_time_t(now);
struct tm* timeInfo;
timeInfo = gmtime(&tt);
time->year = timeInfo->tm_year + 1900;
time->month = timeInfo->tm_mon+1;
time->day = timeInfo->tm_mday;
time->hour = timeInfo->tm_hour;
time->minute = timeInfo->tm_min;
time->second = timeInfo->tm_sec;
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
time->usecond = usecond.count();
//sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
timeval* to) {
struct tm time_tm;
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;
time_tm.tm_mday = from->day;
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_t seconds = mktime(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
//Fails in 2038..
return HasReturnvaluesIF::RETURN_OK;
sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24.
/ 3600.;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
//SHOULDDO: works not for dates in the past (might have less leap seconds)
if (timeMutex == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
uint16_t leapSeconds;
ReturnValue_t result = getLeapSeconds(&leapSeconds);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
timeval leapSeconds_timeval = { 0, 0 };
leapSeconds_timeval.tv_sec = leapSeconds;
//initial offset between UTC and TAI
timeval UTCtoTAI1972 = { 10, 0 };
timeval TAItoTT = { 32, 184000 };
*tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
leapSeconds = leapSeconds_;
result = timeMutex->unlockMutex();
return result;
}
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if(timeMutex == nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
*leapSeconds_ = leapSeconds;
result = timeMutex->unlockMutex();
return result;
}
ReturnValue_t Clock::checkOrCreateClockMutex(){
if(timeMutex == nullptr){
MutexFactory* mutexFactory = MutexFactory::instance();
if (mutexFactory == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
timeMutex = mutexFactory->createMutex();
if (timeMutex == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../timemanager/Clock.h"
#include <chrono>
#if defined(WIN32)
#include <windows.h>
#elif defined(LINUX)
#include <fstream>
#endif
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
using SystemClock = std::chrono::system_clock;
uint32_t Clock::getTicksPerSecond(void){
sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl;
return 0;
//return CLOCKS_PER_SEC;
//uint32_t ticks = sysconf(_SC_CLK_TCK);
//return ticks;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
// do some magic with chrono
sif::warning << "Clock::setClock: not implemented yet" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::setClock(const timeval* time) {
// do some magic with chrono
#if defined(WIN32)
return HasReturnvaluesIF::RETURN_OK;
#elif defined(LINUX)
return HasReturnvaluesIF::RETURN_OK;
#else
#endif
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
#if defined(WIN32)
auto now = std::chrono::system_clock::now();
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto epoch = now.time_since_epoch();
time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();
auto fraction = now - secondsChrono;
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
fraction).count();
return HasReturnvaluesIF::RETURN_OK;
#elif defined(LINUX)
timespec timeUnix;
int status = clock_gettime(CLOCK_REALTIME,&timeUnix);
if(status!=0){
return HasReturnvaluesIF::RETURN_FAILED;
}
time->tv_sec = timeUnix.tv_sec;
time->tv_usec = timeUnix.tv_nsec / 1000.0;
return HasReturnvaluesIF::RETURN_OK;
#else
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
#endif
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
// do some magic with chrono
sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
timeval Clock::getUptime() {
timeval timeval;
#if defined(WIN32)
auto uptime = std::chrono::milliseconds(GetTickCount64());
auto secondsChrono = std::chrono::duration_cast<std::chrono::seconds>(uptime);
timeval.tv_sec = secondsChrono.count();
auto fraction = uptime - secondsChrono;
timeval.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
fraction).count();
#elif defined(LINUX)
double uptimeSeconds;
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds)
{
// value is rounded down automatically
timeval.tv_sec = uptimeSeconds;
timeval.tv_usec = uptimeSeconds *(double) 1e6 - (timeval.tv_sec *1e6);
}
#else
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
#endif
return timeval;
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
*uptime = getUptime();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime = getUptime();
*uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
// do some magic with chrono (C++20!)
// Right now, the library doesn't have the new features yet.
// so we work around that for now.
auto now = SystemClock::now();
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds;
time_t tt = SystemClock::to_time_t(now);
struct tm* timeInfo;
timeInfo = gmtime(&tt);
time->year = timeInfo->tm_year + 1900;
time->month = timeInfo->tm_mon+1;
time->day = timeInfo->tm_mday;
time->hour = timeInfo->tm_hour;
time->minute = timeInfo->tm_min;
time->second = timeInfo->tm_sec;
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
time->usecond = usecond.count();
//sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
timeval* to) {
struct tm time_tm;
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;
time_tm.tm_mday = from->day;
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_t seconds = mktime(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
//Fails in 2038..
return HasReturnvaluesIF::RETURN_OK;
sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24.
/ 3600.;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
//SHOULDDO: works not for dates in the past (might have less leap seconds)
if (timeMutex == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
uint16_t leapSeconds;
ReturnValue_t result = getLeapSeconds(&leapSeconds);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
timeval leapSeconds_timeval = { 0, 0 };
leapSeconds_timeval.tv_sec = leapSeconds;
//initial offset between UTC and TAI
timeval UTCtoTAI1972 = { 10, 0 };
timeval TAItoTT = { 32, 184000 };
*tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
leapSeconds = leapSeconds_;
result = timeMutex->unlockMutex();
return result;
}
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if(timeMutex == nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
*leapSeconds_ = leapSeconds;
result = timeMutex->unlockMutex();
return result;
}
ReturnValue_t Clock::checkOrCreateClockMutex(){
if(timeMutex == nullptr){
MutexFactory* mutexFactory = MutexFactory::instance();
if (mutexFactory == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
timeMutex = mutexFactory->createMutex();
if (timeMutex == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,191 +1,191 @@
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../ipc/MutexFactory.h"
#include "../../osal/host/Mutex.h"
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../tasks/ExecutableObjectIF.h"
#include <thread>
#include <chrono>
#if defined(WIN32)
#include <windows.h>
#elif defined(LINUX)
#include <pthread.h>
#endif
FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority,
TaskStackSize setStack, TaskPeriod setPeriod,
void (*setDeadlineMissedFunc)()) :
started(false), pollingSeqTable(setPeriod*1000), taskName(name),
period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) {
// It is propably possible to set task priorities by using the native
// task handles for Windows / Linux
mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this);
#if defined(WIN32)
/* List of possible priority classes:
* https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/
* nf-processthreadsapi-setpriorityclass
* And respective thread priority numbers:
* https://docs.microsoft.com/en-us/windows/
* win32/procthread/scheduling-priorities */
int result = SetPriorityClass(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
ABOVE_NORMAL_PRIORITY_CLASS);
if(result != 0) {
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
}
result = SetThreadPriority(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
THREAD_PRIORITY_NORMAL);
if(result != 0) {
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
}
#elif defined(LINUX)
// we can just copy and paste the code from linux here.
#endif
}
FixedTimeslotTask::~FixedTimeslotTask(void) {
//Do not delete objects, we were responsible for ptrs only.
terminateThread = true;
if(mainThread.joinable()) {
mainThread.join();
}
delete this;
}
void FixedTimeslotTask::taskEntryPoint(void* argument) {
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
if (not originalTask->started) {
// we have to suspend/block here until the task is started.
// if semaphores are implemented, use them here.
std::unique_lock<std::mutex> lock(initMutex);
initCondition.wait(lock);
}
this->taskFunctionality();
sif::debug << "FixedTimeslotTask::taskEntryPoint: "
"Returned from taskFunctionality." << std::endl;
}
ReturnValue_t FixedTimeslotTask::startTask() {
started = true;
// Notify task to start.
std::lock_guard<std::mutex> lock(initMutex);
initCondition.notify_one();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
return HasReturnvaluesIF::RETURN_OK;
}
void FixedTimeslotTask::taskFunctionality() {
// A local iterator for the Polling Sequence Table is created to
// find the start time for the first entry.
FixedSlotSequence::SlotListIter slotListIter = pollingSeqTable.current;
// Get start time for first entry.
chron_ms interval(slotListIter->pollingTimeMs);
auto currentStartTime {
std::chrono::duration_cast<chron_ms>(
std::chrono::system_clock::now().time_since_epoch())
};
if(interval.count() > 0) {
delayForInterval(&currentStartTime, interval);
}
/* Enter the loop that defines the task behavior. */
for (;;) {
if(terminateThread.load()) {
break;
}
//The component for this slot is executed and the next one is chosen.
this->pollingSeqTable.executeAndAdvance();
if (not pollingSeqTable.slotFollowsImmediately()) {
// we need to wait before executing the current slot
//this gives us the time to wait:
interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs());
delayForInterval(&currentStartTime, interval);
//TODO deadline missed check
}
}
}
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) {
pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, this);
return HasReturnvaluesIF::RETURN_OK;
}
sif::error << "Component " << std::hex << componentId <<
" not found, not adding it to pst" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t FixedTimeslotTask::checkSequence() const {
return pollingSeqTable.checkSequence();
}
uint32_t FixedTimeslotTask::getPeriodMs() const {
return period * 1000;
}
bool FixedTimeslotTask::delayForInterval(chron_ms * previousWakeTimeMs,
const chron_ms interval) {
bool shouldDelay = false;
//Get current wakeup time
auto currentStartTime =
std::chrono::duration_cast<chron_ms>(
std::chrono::system_clock::now().time_since_epoch());
/* Generate the tick time at which the task wants to wake. */
auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval;
if (currentStartTime < *previousWakeTimeMs) {
/* The tick count has overflowed since this function was
lasted called. In this case the only time we should ever
actually delay is if the wake time has also overflowed,
and the wake time is greater than the tick time. When this
is the case it is as if neither time had overflowed. */
if ((nextTimeToWake_ms < *previousWakeTimeMs)
&& (nextTimeToWake_ms > currentStartTime)) {
shouldDelay = true;
}
} else {
/* The tick time has not overflowed. In this case we will
delay if either the wake time has overflowed, and/or the
tick time is less than the wake time. */
if ((nextTimeToWake_ms < *previousWakeTimeMs)
|| (nextTimeToWake_ms > currentStartTime)) {
shouldDelay = true;
}
}
/* Update the wake time ready for the next call. */
(*previousWakeTimeMs) = nextTimeToWake_ms;
if (shouldDelay) {
auto sleepTime = std::chrono::duration_cast<chron_ms>(
nextTimeToWake_ms - currentStartTime);
std::this_thread::sleep_for(sleepTime);
return true;
}
//We are shifting the time in case the deadline was missed like rtems
(*previousWakeTimeMs) = currentStartTime;
return false;
}
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../ipc/MutexFactory.h"
#include "../../osal/host/Mutex.h"
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../tasks/ExecutableObjectIF.h"
#include <thread>
#include <chrono>
#if defined(WIN32)
#include <windows.h>
#elif defined(LINUX)
#include <pthread.h>
#endif
FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority,
TaskStackSize setStack, TaskPeriod setPeriod,
void (*setDeadlineMissedFunc)()) :
started(false), pollingSeqTable(setPeriod*1000), taskName(name),
period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) {
// It is propably possible to set task priorities by using the native
// task handles for Windows / Linux
mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this);
#if defined(WIN32)
/* List of possible priority classes:
* https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/
* nf-processthreadsapi-setpriorityclass
* And respective thread priority numbers:
* https://docs.microsoft.com/en-us/windows/
* win32/procthread/scheduling-priorities */
int result = SetPriorityClass(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
ABOVE_NORMAL_PRIORITY_CLASS);
if(result != 0) {
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
}
result = SetThreadPriority(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
THREAD_PRIORITY_NORMAL);
if(result != 0) {
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
}
#elif defined(LINUX)
// we can just copy and paste the code from linux here.
#endif
}
FixedTimeslotTask::~FixedTimeslotTask(void) {
//Do not delete objects, we were responsible for ptrs only.
terminateThread = true;
if(mainThread.joinable()) {
mainThread.join();
}
delete this;
}
void FixedTimeslotTask::taskEntryPoint(void* argument) {
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
if (not originalTask->started) {
// we have to suspend/block here until the task is started.
// if semaphores are implemented, use them here.
std::unique_lock<std::mutex> lock(initMutex);
initCondition.wait(lock);
}
this->taskFunctionality();
sif::debug << "FixedTimeslotTask::taskEntryPoint: "
"Returned from taskFunctionality." << std::endl;
}
ReturnValue_t FixedTimeslotTask::startTask() {
started = true;
// Notify task to start.
std::lock_guard<std::mutex> lock(initMutex);
initCondition.notify_one();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
return HasReturnvaluesIF::RETURN_OK;
}
void FixedTimeslotTask::taskFunctionality() {
// A local iterator for the Polling Sequence Table is created to
// find the start time for the first entry.
FixedSlotSequence::SlotListIter slotListIter = pollingSeqTable.current;
// Get start time for first entry.
chron_ms interval(slotListIter->pollingTimeMs);
auto currentStartTime {
std::chrono::duration_cast<chron_ms>(
std::chrono::system_clock::now().time_since_epoch())
};
if(interval.count() > 0) {
delayForInterval(&currentStartTime, interval);
}
/* Enter the loop that defines the task behavior. */
for (;;) {
if(terminateThread.load()) {
break;
}
//The component for this slot is executed and the next one is chosen.
this->pollingSeqTable.executeAndAdvance();
if (not pollingSeqTable.slotFollowsImmediately()) {
// we need to wait before executing the current slot
//this gives us the time to wait:
interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs());
delayForInterval(&currentStartTime, interval);
//TODO deadline missed check
}
}
}
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) {
pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, this);
return HasReturnvaluesIF::RETURN_OK;
}
sif::error << "Component " << std::hex << componentId <<
" not found, not adding it to pst" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t FixedTimeslotTask::checkAndInitializeSequence() const {
return pollingSeqTable.checkSequence();
}
uint32_t FixedTimeslotTask::getPeriodMs() const {
return period * 1000;
}
bool FixedTimeslotTask::delayForInterval(chron_ms * previousWakeTimeMs,
const chron_ms interval) {
bool shouldDelay = false;
//Get current wakeup time
auto currentStartTime =
std::chrono::duration_cast<chron_ms>(
std::chrono::system_clock::now().time_since_epoch());
/* Generate the tick time at which the task wants to wake. */
auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval;
if (currentStartTime < *previousWakeTimeMs) {
/* The tick count has overflowed since this function was
lasted called. In this case the only time we should ever
actually delay is if the wake time has also overflowed,
and the wake time is greater than the tick time. When this
is the case it is as if neither time had overflowed. */
if ((nextTimeToWake_ms < *previousWakeTimeMs)
&& (nextTimeToWake_ms > currentStartTime)) {
shouldDelay = true;
}
} else {
/* The tick time has not overflowed. In this case we will
delay if either the wake time has overflowed, and/or the
tick time is less than the wake time. */
if ((nextTimeToWake_ms < *previousWakeTimeMs)
|| (nextTimeToWake_ms > currentStartTime)) {
shouldDelay = true;
}
}
/* Update the wake time ready for the next call. */
(*previousWakeTimeMs) = nextTimeToWake_ms;
if (shouldDelay) {
auto sleepTime = std::chrono::duration_cast<chron_ms>(
nextTimeToWake_ms - currentStartTime);
std::this_thread::sleep_for(sleepTime);
return true;
}
//We are shifting the time in case the deadline was missed like rtems
(*previousWakeTimeMs) = currentStartTime;
return false;
}

View File

@ -1,130 +1,130 @@
#ifndef FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_
#define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_
#include "../../objectmanager/ObjectManagerIF.h"
#include "../../tasks/FixedSlotSequence.h"
#include "../../tasks/FixedTimeslotTaskIF.h"
#include "../../tasks/Typedef.h"
#include <vector>
#include <thread>
#include <condition_variable>
#include <atomic>
class ExecutableObjectIF;
/**
* @brief This class represents a task for periodic activities with multiple
* steps and strict timeslot requirements for these steps.
* @details
* @ingroup task_handling
*/
class FixedTimeslotTask: public FixedTimeslotTaskIF {
public:
/**
* @brief Standard constructor of the class.
* @details
* The class is initialized without allocated objects. These need to be
* added with #addComponent.
* @param priority
* @param stack_size
* @param setPeriod
* @param setDeadlineMissedFunc
* The function pointer to the deadline missed function that shall be
* assigned.
*/
FixedTimeslotTask(const char *name, TaskPriority setPriority,
TaskStackSize setStack, TaskPeriod setPeriod,
void (*setDeadlineMissedFunc)());
/**
* @brief Currently, the executed object's lifetime is not coupled with
* the task object's lifetime, so the destructor is empty.
*/
virtual ~FixedTimeslotTask(void);
/**
* @brief The method to start the task.
* @details The method starts the task with the respective system call.
* Entry point is the taskEntryPoint method described below.
* The address of the task object is passed as an argument
* to the system call.
*/
ReturnValue_t startTask(void);
/**
* Add timeslot to the polling sequence table.
* @param componentId
* @param slotTimeMs
* @param executionStep
* @return
*/
ReturnValue_t addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep);
ReturnValue_t checkSequence() const;
uint32_t getPeriodMs() const;
ReturnValue_t sleepFor(uint32_t ms);
protected:
using chron_ms = std::chrono::milliseconds;
bool started;
//!< Typedef for the List of objects.
typedef std::vector<ExecutableObjectIF*> ObjectList;
std::thread mainThread;
std::atomic<bool> terminateThread = false;
//! Polling sequence table which contains the object to execute
//! and information like the timeslots and the passed execution step.
FixedSlotSequence pollingSeqTable;
std::condition_variable initCondition;
std::mutex initMutex;
std::string taskName;
/**
* @brief The period of the task.
* @details
* The period determines the frequency of the task's execution.
* It is expressed in clock ticks.
*/
TaskPeriod period;
/**
* @brief The pointer to the deadline-missed function.
* @details
* This pointer stores the function that is executed if the task's deadline
* is missed. So, each may react individually on a timing failure.
* The pointer may be NULL, then nothing happens on missing the deadline.
* The deadline is equal to the next execution of the periodic task.
*/
void (*deadlineMissedFunc)(void);
/**
* @brief This is the function executed in the new task's context.
* @details
* It converts the argument back to the thread object type and copies the
* class instance to the task context.
* The taskFunctionality method is called afterwards.
* @param A pointer to the task object itself is passed as argument.
*/
void taskEntryPoint(void* argument);
/**
* @brief The function containing the actual functionality of the task.
* @details
* The method sets and starts the task's period, then enters a loop that is
* repeated as long as the isRunning attribute is true. Within the loop,
* all performOperation methods of the added objects are called. Afterwards
* the checkAndRestartPeriod system call blocks the task until the next
* period. On missing the deadline, the deadlineMissedFunction is executed.
*/
void taskFunctionality(void);
bool delayForInterval(chron_ms * previousWakeTimeMs,
const chron_ms interval);
};
#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */
#ifndef FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_
#define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_
#include "../../objectmanager/ObjectManagerIF.h"
#include "../../tasks/FixedSlotSequence.h"
#include "../../tasks/FixedTimeslotTaskIF.h"
#include "../../tasks/Typedef.h"
#include <vector>
#include <thread>
#include <condition_variable>
#include <atomic>
class ExecutableObjectIF;
/**
* @brief This class represents a task for periodic activities with multiple
* steps and strict timeslot requirements for these steps.
* @details
* @ingroup task_handling
*/
class FixedTimeslotTask: public FixedTimeslotTaskIF {
public:
/**
* @brief Standard constructor of the class.
* @details
* The class is initialized without allocated objects. These need to be
* added with #addComponent.
* @param priority
* @param stack_size
* @param setPeriod
* @param setDeadlineMissedFunc
* The function pointer to the deadline missed function that shall be
* assigned.
*/
FixedTimeslotTask(const char *name, TaskPriority setPriority,
TaskStackSize setStack, TaskPeriod setPeriod,
void (*setDeadlineMissedFunc)());
/**
* @brief Currently, the executed object's lifetime is not coupled with
* the task object's lifetime, so the destructor is empty.
*/
virtual ~FixedTimeslotTask(void);
/**
* @brief The method to start the task.
* @details The method starts the task with the respective system call.
* Entry point is the taskEntryPoint method described below.
* The address of the task object is passed as an argument
* to the system call.
*/
ReturnValue_t startTask(void);
/**
* Add timeslot to the polling sequence table.
* @param componentId
* @param slotTimeMs
* @param executionStep
* @return
*/
ReturnValue_t addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep);
ReturnValue_t checkAndInitializeSequence() const;
uint32_t getPeriodMs() const;
ReturnValue_t sleepFor(uint32_t ms);
protected:
using chron_ms = std::chrono::milliseconds;
bool started;
//!< Typedef for the List of objects.
typedef std::vector<ExecutableObjectIF*> ObjectList;
std::thread mainThread;
std::atomic<bool> terminateThread = false;
//! Polling sequence table which contains the object to execute
//! and information like the timeslots and the passed execution step.
FixedSlotSequence pollingSeqTable;
std::condition_variable initCondition;
std::mutex initMutex;
std::string taskName;
/**
* @brief The period of the task.
* @details
* The period determines the frequency of the task's execution.
* It is expressed in clock ticks.
*/
TaskPeriod period;
/**
* @brief The pointer to the deadline-missed function.
* @details
* This pointer stores the function that is executed if the task's deadline
* is missed. So, each may react individually on a timing failure.
* The pointer may be NULL, then nothing happens on missing the deadline.
* The deadline is equal to the next execution of the periodic task.
*/
void (*deadlineMissedFunc)(void);
/**
* @brief This is the function executed in the new task's context.
* @details
* It converts the argument back to the thread object type and copies the
* class instance to the task context.
* The taskFunctionality method is called afterwards.
* @param A pointer to the task object itself is passed as argument.
*/
void taskEntryPoint(void* argument);
/**
* @brief The function containing the actual functionality of the task.
* @details
* The method sets and starts the task's period, then enters a loop that is
* repeated as long as the isRunning attribute is true. Within the loop,
* all performOperation methods of the added objects are called. Afterwards
* the checkAndRestartPeriod system call blocks the task until the next
* period. On missing the deadline, the deadlineMissedFunction is executed.
*/
void taskFunctionality(void);
bool delayForInterval(chron_ms * previousWakeTimeMs,
const chron_ms interval);
};
#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */

View File

@ -1,155 +1,155 @@
#include "../../osal/host/MessageQueue.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../osal/host/QueueMapManager.h"
#include "../../ipc/MutexFactory.h"
#include "../../ipc/MutexHelper.h"
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize):
messageSize(maxMessageSize), messageDepth(messageDepth) {
queueLock = MutexFactory::instance()->createMutex();
auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "MessageQueue: Could not be created" << std::endl;
}
}
MessageQueue::~MessageQueue() {
MutexFactory::instance()->deleteMutex(queueLock);
}
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) {
return sendMessageFrom(this->lastPartner, message, this->getId());
} else {
return MessageQueueIF::NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom,
ignoreFault);
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
if(status == HasReturnvaluesIF::RETURN_OK) {
*receivedFrom = this->lastPartner;
}
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if(messageQueue.empty()) {
return MessageQueueIF::EMPTY;
}
// not sure this will work..
//*message = std::move(messageQueue.front());
MutexHelper mutexLock(queueLock, 20);
MessageQueueMessage* currentMessage = &messageQueue.front();
std::copy(currentMessage->getBuffer(),
currentMessage->getBuffer() + messageSize, message->getBuffer());
messageQueue.pop();
// The last partner is the first uint32_t field in the message
this->lastPartner = message->getSender();
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getLastPartner() const {
return lastPartner;
}
ReturnValue_t MessageQueue::flush(uint32_t* count) {
*count = messageQueue.size();
// Clears the queue.
messageQueue = std::queue<MessageQueueMessage>();
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getId() const {
return mqId;
}
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
defaultDestinationSet = true;
this->defaultDestination = defaultDestination;
}
MessageQueueId_t MessageQueue::getDefaultDestination() const {
return defaultDestination;
}
bool MessageQueue::isDefaultDestinationSet() const {
return defaultDestinationSet;
}
// static core function to send messages.
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
if(message->getMessageSize() > message->getMaximumMessageSize()) {
// Actually, this should never happen or an error will be emitted
// in MessageQueueMessage.
// But I will still return a failure here.
return HasReturnvaluesIF::RETURN_FAILED;
}
MessageQueue* targetQueue = dynamic_cast<MessageQueue*>(
QueueMapManager::instance()->getMessageQueue(sendTo));
if(targetQueue == nullptr) {
if(not ignoreFault) {
InternalErrorReporterIF* internalErrorReporter =
objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
}
}
// TODO: Better returnvalue
return HasReturnvaluesIF::RETURN_FAILED;
}
if(targetQueue->messageQueue.size() < targetQueue->messageDepth) {
MutexHelper mutexLock(targetQueue->queueLock, 20);
// not ideal, works for now though.
MessageQueueMessage* mqmMessage =
dynamic_cast<MessageQueueMessage*>(message);
if(message != nullptr) {
targetQueue->messageQueue.push(*mqmMessage);
}
else {
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message"
"is not MessageQueueMessage!" << std::endl;
}
}
else {
return MessageQueueIF::FULL;
}
message->setSender(sentFrom);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t MessageQueue::lockQueue(dur_millis_t lockTimeout) {
return queueLock->lockMutex(lockTimeout);
}
ReturnValue_t MessageQueue::unlockQueue() {
return queueLock->unlockMutex();
}
#include "../../osal/host/MessageQueue.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../osal/host/QueueMapManager.h"
#include "../../ipc/MutexFactory.h"
#include "../../ipc/MutexHelper.h"
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize):
messageSize(maxMessageSize), messageDepth(messageDepth) {
queueLock = MutexFactory::instance()->createMutex();
auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "MessageQueue: Could not be created" << std::endl;
}
}
MessageQueue::~MessageQueue() {
MutexFactory::instance()->deleteMutex(queueLock);
}
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) {
return sendMessageFrom(this->lastPartner, message, this->getId());
} else {
return MessageQueueIF::NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom,
ignoreFault);
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
if(status == HasReturnvaluesIF::RETURN_OK) {
*receivedFrom = this->lastPartner;
}
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if(messageQueue.empty()) {
return MessageQueueIF::EMPTY;
}
// not sure this will work..
//*message = std::move(messageQueue.front());
MutexHelper mutexLock(queueLock, 20);
MessageQueueMessage* currentMessage = &messageQueue.front();
std::copy(currentMessage->getBuffer(),
currentMessage->getBuffer() + messageSize, message->getBuffer());
messageQueue.pop();
// The last partner is the first uint32_t field in the message
this->lastPartner = message->getSender();
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getLastPartner() const {
return lastPartner;
}
ReturnValue_t MessageQueue::flush(uint32_t* count) {
*count = messageQueue.size();
// Clears the queue.
messageQueue = std::queue<MessageQueueMessage>();
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getId() const {
return mqId;
}
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
defaultDestinationSet = true;
this->defaultDestination = defaultDestination;
}
MessageQueueId_t MessageQueue::getDefaultDestination() const {
return defaultDestination;
}
bool MessageQueue::isDefaultDestinationSet() const {
return defaultDestinationSet;
}
// static core function to send messages.
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
if(message->getMessageSize() > message->getMaximumMessageSize()) {
// Actually, this should never happen or an error will be emitted
// in MessageQueueMessage.
// But I will still return a failure here.
return HasReturnvaluesIF::RETURN_FAILED;
}
MessageQueue* targetQueue = dynamic_cast<MessageQueue*>(
QueueMapManager::instance()->getMessageQueue(sendTo));
if(targetQueue == nullptr) {
if(not ignoreFault) {
InternalErrorReporterIF* internalErrorReporter =
objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
}
}
// TODO: Better returnvalue
return HasReturnvaluesIF::RETURN_FAILED;
}
if(targetQueue->messageQueue.size() < targetQueue->messageDepth) {
MutexHelper mutexLock(targetQueue->queueLock, 20);
// not ideal, works for now though.
MessageQueueMessage* mqmMessage =
dynamic_cast<MessageQueueMessage*>(message);
if(message != nullptr) {
targetQueue->messageQueue.push(*mqmMessage);
}
else {
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message"
"is not MessageQueueMessage!" << std::endl;
}
}
else {
return MessageQueueIF::FULL;
}
message->setSender(sentFrom);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t MessageQueue::lockQueue(dur_millis_t lockTimeout) {
return queueLock->lockMutex(lockTimeout);
}
ReturnValue_t MessageQueue::unlockQueue() {
return queueLock->unlockMutex();
}

View File

@ -1,230 +1,230 @@
#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#include "../../internalError/InternalErrorReporterIF.h"
#include "../../ipc/MessageQueueIF.h"
#include "../../ipc/MessageQueueMessage.h"
#include "../../ipc/MutexIF.h"
#include "../../timemanager/Clock.h"
#include <queue>
#include <memory>
/**
* @brief This class manages sending and receiving of
* message queue messages.
* @details
* Message queues are used to pass asynchronous messages between processes.
* They work like post boxes, where all incoming messages are stored in FIFO
* order. This class creates a new receiving queue and provides methods to fetch
* received messages. Being a child of MessageQueueSender, this class also
* provides methods to send a message to a user-defined or a default destination.
* In addition it also provides a reply method to answer to the queue it
* received its last message from.
*
* The MessageQueue should be used as "post box" for a single owning object.
* So all message queue communication is "n-to-one".
* For creating the queue, as well as sending and receiving messages, the class
* makes use of the operating system calls provided.
*
* Please keep in mind that FreeRTOS offers different calls for message queue
* operations if called from an ISR.
* For now, the system context needs to be switched manually.
* @ingroup osal
* @ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
friend class MessageQueueSenderIF;
public:
/**
* @brief The constructor initializes and configures the message queue.
* @details
* By making use of the according operating system call, a message queue is
* created and initialized. The message depth - the maximum number of
* messages to be buffered - may be set with the help of a parameter,
* whereas the message size is automatically set to the maximum message
* queue message size. The operating system sets the message queue id, or
* in case of failure, it is set to zero.
* @param message_depth
* The number of messages to be buffered before passing an error to the
* sender. Default is three.
* @param max_message_size
* With this parameter, the maximum message size can be adjusted.
* This should be left default.
*/
MessageQueue(size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;
MessageQueue& operator=(const MessageQueue&) = delete;
/**
* @brief The destructor deletes the formerly created message queue.
* @details This is accomplished by using the delete call provided
* by the operating system.
*/
virtual ~MessageQueue();
/**
* @brief This operation sends a message to the given destination.
<