HLa maggior parte, anche perchè sleep() può portare una perdita di prestazioni , in effetti risulta molto meglio switcare tra i vari thread con yield(senza esagerare).. Diciamo che ci vuole un po di esperienza ,conoscere come funzionano i s.o. e conoscenza dell'assembly per avere un quadro completo della situazione .
Visto che oggi sono di buon umore e ho avuto 10 minuti liberi ho pensato per rendeti il quadro della situazione meno complicato e un po' più pratico scrivendo una piccola porzione di codice che potrebbe rivelarsi utile:
Ovviamente non garantisco che non ci possano essere errori la porzione di codice ha il solo scopo di rendere il meccanismo più chiaro
include <chrono>
#include <thread>
#include <mutex>
#include <future>
//tipi vari
enum Status_t : std::uint8_t //enumeratore che gestisce l'esecuzione // fallo gestire al main
{
Runing,
Closing,
Pause,
Reset,
In_Exception
};
typedef unsigned int FPS_t;
//Variabili gestite dal main o altri thread
Status_t Status; // gestisce lo stato del programma;
FPS_t * FPS;
// queste funzioni poi implementare nello stesso thread del Timer oppure (Meglio) farle gestire i altri thread
/* 1 */ void _stdcall RenderScreen(unsigned char * Semaphore /* passa il puntatore della variabile semaphore della classe Timer */)
{/* guarda come gestisco il codice nella terza funzione*/};
/* 2 */ void _stdcall PrintFPS(FPS_t &FPS)
{/*inserisci il tuo codice */};
/* 3 */ void _stdcall Elabora_Input(unsigned char * Semaphore /* passa il puntatore della variabile semaphore della classe Timer */ )
{ // in un thread separato
while (Status != Status_t::Closing)
{
while (Status == Status_t::Pause)
{
std::this_thread::yield();
}
while (Status == Status_t::Runing &&(( *Semaphore bitand 00000001b ) == 1))
{
thread_local register auto K = std::getchar();
switch(K){/* inserisci il codisce */}
// il primo bit ritorna a zero dopo aver elaborato l'input
*Semaphore == *Semaphore xor 00000001b;
}
std::this_thread::yield();
}
};
class Timer
{
std::thread * Thread;
public:
Timer();
~Timer();
void StartTimerThread(void) noexcept;
unsigned char * Semaphore; // ? unicamente gestito dal thread che generi dalla classe
// una cattiva implementazione pottrebe causare "race conditions"
// usa unsigned char/short/int al posto dei bool e impara a operare su bit se non lo sai fare;
////////////////////////////////////////////////////////
// Esempio
// bit. N 1 2 3 4 5 6 7 8
// Input
// Abilitato
private:
};
Timer::Timer()
{
this->Thread = nullptr;
}
Timer::~Timer()
{
while (!this->Thread->joinable()) {/* SpinLock ;) */ std::this_thread::yield(); };
this->Thread->join();
delete this->Thread;
delete this->Semaphore;
}
void Timer::StartTimerThread(){
this->Thread = new std::thread([this]() {
const std::chrono::duration<std::chrono::milliseconds> s = 1000;
const std::chrono::duration<std::chrono::milliseconds> ds = 100;
std::chrono::time_point <std::chrono::milliseconds> Point_B;
std::chrono::time_point <std::chrono::milliseconds> Point_C;
std::chrono::time_point <std::chrono::milliseconds> Point_A = std::chrono::system_clock::now();
while (Status != Status_t::Closing)
{
std::chrono::time_point <std::chrono::milliseconds> Point_B = std::chrono::system_clock::now();
if (Point_C + ds < Point_B)
{
Point_C = Point_B + ds;
*(this->Semaphore) = *(this->Semaphore) bitor 00000001b;
// ogni 0,1 sec imposta a 1 il 1? bit di semaphore abilitando la criticalsection della funzione elabora_input();
}
if (Point_A + s < Point_B)
{
Point_C = Point_B;
Point_A = Point_B;
FPS_t * Ptr = FPS;
FPS = new FPS_t;
PrintFPS(Ptr);
delete Ptr;
}
}
std::this_thread::yield();
});
}