Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
Release 2.0.0
  • Loading branch information
malikalhack committed Feb 19, 2022
2 parents d1bc863 + 7f8e897 commit f43527b
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 40 deletions.
28 changes: 18 additions & 10 deletions include/TimeManager.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* @file TimeManager.h
* @version 1.0.0
* @version 2.0.0
* @authors Anton Chernov
* @date 19/10/2021
* @date 03/11/2021
* @date 24/11/2021
*/

#ifndef TIME_MANAGER_H
Expand All @@ -19,9 +19,9 @@
#define TICKS_PER_SECOND 1000u / MILLISECONDS_PER_TICK
#define TICKS 0u
#define MILLISECONDS 1u
#define SYNC TICKS
#define SYNC MILLISECONDS

typedef void* semaphore_t;
typedef void* event_t;

struct delay_t {
uint32_t cur_time;
Expand Down Expand Up @@ -58,6 +58,12 @@ class TimeManager {
#error Type of synchronization is unknown
#endif // SYNC

/**
* @brief Public method to suspend execution of a thread until its ID is obtained
* @fn void TimeManager::wait_for_start()
*/
void wait_for_start();

/**
* @brief Public method to stop a thread and waiting for the counter
* @fn void TimeManager::wait_in_ticks(uint32_t delay)
Expand Down Expand Up @@ -89,17 +95,19 @@ class TimeManager {
std::thread::id GetPrcsId(uint8_t);

private:
volatile uint32_t sync_tick_; ///< Sync counter
bool cancel_; ///< Cancel waiting for a sync object
semaphore_t list_access_; ///< Exclusive access to the list
semaphore_t sync_tick_access_; ///< Exclusive access to the sync counter
volatile uint32_t sync_tick_; ///< Sync counter
bool cancel_; ///< Cancel waiting for a sync object
event_t start_allowed_; ///< Event to start the thread

prcs prcs_list_[BUF_SIZE]; ///< Array of process objects
semaphore_t prcs_blocks_[BUF_SIZE]; ///< Array of synchronization objects
event_t prcs_blocks_[BUF_SIZE]; ///< Array of synchronization objects
std::thread::id prcs_id_[BUF_SIZE]; ///< Array of process IDs
std::wstring temp_event_name;

void Init_();
semaphore_t CreateBinSemaphore_(bool blocked = false);
void CloseTmEvent_(event_t);
const wchar_t* name_expander_(const wchar_t *, uint16_t);
event_t CreateTmEvent_(const wchar_t* name = NULL);
uint8_t get_dscr_(std::thread::id);
uint16_t get_time_();
};
Expand Down
84 changes: 54 additions & 30 deletions source/TimeManager.cpp
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
/**
* @file TimeManager.cpp
* @version 1.0.0
* @version 2.0.0
* @authors Anton Chernov
* @date 19/10/2021
* @date 03/11/2021
* @date 24/11/2021
*/

/****************************** Included files ********************************/
#include <stdio.h>
#include <Windows.h>
#include "TimeManager.h"
/******************************************************************************/
static CRITICAL_SECTION list_access_; ///< Exclusive access to the list
static CRITICAL_SECTION sync_tick_access_;///< Exclusive access to the sync counter

TimeManager::TimeManager() {
cancel_ = false;
sync_tick_ = 0;
Init_();
list_access_ = CreateBinSemaphore_();
sync_tick_access_ = CreateBinSemaphore_();
InitializeCriticalSectionAndSpinCount(&list_access_, 1024);
InitializeCriticalSectionAndSpinCount(&sync_tick_access_, 1024);
start_allowed_ = CreateTmEvent_(L"Start");
for (uint8_t i = 0; i < BUF_SIZE; i++) {
prcs_blocks_[i] = CreateBinSemaphore_(true);
prcs_blocks_[i] = CreateTmEvent_(name_expander_(L"Event", i));
}
}
/*----------------------------------------------------------------------------*/
TimeManager::~TimeManager() {
cancel_ = true;
Sleep(600);
CloseTmEvent_(start_allowed_);
for (uint8_t i = 0; i < BUF_SIZE; i++) {
CloseHandle(prcs_blocks_[i]);
CloseTmEvent_(prcs_blocks_[i]);
}
CloseHandle(list_access_);
CloseHandle(sync_tick_access_);
DeleteCriticalSection(&list_access_);
DeleteCriticalSection(&sync_tick_access_);
}
/*----------------------------------------------------------------------------*/
#if SYNC == TICKS
void TimeManager::Sync() {
WaitForSingleObject(sync_tick_access_, INFINITE);
EnterCriticalSection(&sync_tick_access_);
uint16_t curr_time = ++sync_tick_;
#elif SYNC == MILLISECONDS
void TimeManager::Sync(uint32_t elapsed_time) {
WaitForSingleObject(sync_tick_access_, INFINITE);
EnterCriticalSection(&sync_tick_access_);
{
uint32_t remainder = UINT32_MAX - sync_tick_;
if (elapsed_time >= remainder) {
Expand All @@ -53,28 +58,28 @@ TimeManager::~TimeManager() {
#else
#error Type of synchronization is unknown
#endif // SYNC
ReleaseSemaphore(sync_tick_access_, 1, NULL);
LeaveCriticalSection(&sync_tick_access_);
for (uint8_t i = 0; i < BUF_SIZE; i++) {
if (prcs_list_[i].delay.is_blocked) {
if (curr_time > prcs_list_[i].delay.cur_time) {
if (curr_time - prcs_list_[i].delay.cur_time >= prcs_list_[i].delay.wait_time) {
ReleaseSemaphore(prcs_blocks_[i], 1, NULL);
SetEvent(prcs_blocks_[i]);
}
}
else {
uint32_t res = UINT32_MAX - prcs_list_[i].delay.cur_time + prcs_list_[i].delay.cur_time;
if (res >= prcs_list_[i].delay.wait_time) {
ReleaseSemaphore(prcs_blocks_[i], 1, NULL);
SetEvent(prcs_blocks_[i]);
}
}
}
}
}
/*----------------------------------------------------------------------------*/
uint16_t TimeManager::get_time_() {
WaitForSingleObject(sync_tick_access_, INFINITE);
EnterCriticalSection(&sync_tick_access_);
uint16_t result = sync_tick_;
ReleaseSemaphore(sync_tick_access_, 1, NULL);
LeaveCriticalSection(&sync_tick_access_);
return result;
}
/*----------------------------------------------------------------------------*/
Expand All @@ -93,12 +98,16 @@ uint8_t TimeManager::get_dscr_(std::thread::id id) {
}
/*----------------------------------------------------------------------------*/
std::thread::id TimeManager::GetPrcsId(uint8_t dscr) {
WaitForSingleObject(list_access_, INFINITE);
EnterCriticalSection(&list_access_);
std::thread::id result = prcs_list_[dscr].id;
ReleaseSemaphore(list_access_, 1, NULL);
LeaveCriticalSection(&list_access_);
return result;
}
/*----------------------------------------------------------------------------*/
void TimeManager::wait_for_start() {
WaitForSingleObject(start_allowed_, INFINITE);
}
/*----------------------------------------------------------------------------*/
void TimeManager::wait_in_ticks(uint32_t delay) {
bool repeat = true;
DWORD dwWaitResult;
Expand Down Expand Up @@ -143,45 +152,60 @@ void TimeManager::Init_() {
}
}
/*----------------------------------------------------------------------------*/
semaphore_t TimeManager::CreateBinSemaphore_(bool blocked) {
uint8_t INITIAL_COUNT = (blocked) ? 0 : 1;
semaphore_t link = CreateSemaphore(
NULL, // default security attributes
INITIAL_COUNT, // initial count
1, // maximum count
NULL // unnamed semaphore
event_t TimeManager::CreateTmEvent_(const wchar_t * name) {
event_t link = CreateEvent(
NULL, // default security attributes
FALSE, // auto-reset event
FALSE, // initial state is nonsignaled
name // name of event
);
if (link == NULL) printf("Error create semaphore\n");
if (link == NULL) printf("Error create event\n");
return link;
}
/*----------------------------------------------------------------------------*/
void TimeManager::CloseTmEvent_(event_t evt) {
CloseHandle(evt);
}
/*----------------------------------------------------------------------------*/
bool TimeManager::AddPrcs(uint8_t dscr, std::function<void()> func) {
bool result = false;
if (dscr) {
WaitForSingleObject(list_access_, INFINITE);
EnterCriticalSection(&list_access_);
if (dscr < BUF_SIZE - 1) {
ResetEvent(start_allowed_);
result = true;
prcs_list_[dscr].thr = std::thread(func);
prcs_id_[dscr] = prcs_list_[dscr].thr.get_id();
result = true;
SetEvent(start_allowed_);
} else {
printf("There are no room here\n");
}
ReleaseSemaphore(list_access_, 1, NULL);
LeaveCriticalSection(&list_access_);
} else {
printf("Reserved by main thread\n");
}
return result;
}
/*----------------------------------------------------------------------------*/
void TimeManager::KillPrcs(uint8_t dscr, bool force) {
WaitForSingleObject(list_access_, INFINITE);
EnterCriticalSection(&list_access_);
cancel_ = true;
if (force) {
prcs_list_[dscr].thr.detach();
}
else {
prcs_list_[dscr].thr.join();
}
ReleaseSemaphore(list_access_, 1, NULL);
LeaveCriticalSection(&list_access_);
}
/*----------------------------------------------------------------------------*/
const wchar_t* TimeManager::name_expander_(const wchar_t *name, uint16_t i) {
temp_event_name.clear();
temp_event_name.append(name);
temp_event_name.push_back('_');
wchar_t char_count[6];
_itow(i, char_count, 10);
temp_event_name.append(char_count);
return temp_event_name.c_str();
}
/******************************************************************************/
3 changes: 3 additions & 0 deletions source/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ void TEST::Sync(uint32_t elapsed_time) {
}

void TEST::thread_1_thr_func( ) {
this->TM_->wait_for_start();
printf("THR_1: Wait 1 sec\n");
this->TM_->wait_in_ticks(1 * TICKS_PER_SECOND);
printf("THR_1: Wait 6 sec\n");
Expand All @@ -97,6 +98,7 @@ void TEST::thread_1_thr_func( ) {
}

void TEST::thread_2_thr_func() {
this->TM_->wait_for_start();
printf("THR_2: Wait 5 sec\n");
this->TM_->wait_in_ticks(5 * TICKS_PER_SECOND);
printf("THR_2: Wait 3 sec\n");
Expand All @@ -105,6 +107,7 @@ void TEST::thread_2_thr_func() {
}

void TEST::thread_3_thr_func() {
this->TM_->wait_for_start();
printf("THR_3: Wait 9 sec\n");
this->TM_->wait_in_ticks(9 * TICKS_PER_SECOND);
printf("THR_3: Finish\n");
Expand Down

0 comments on commit f43527b

Please sign in to comment.