mirror of
https://github.com/emu-russia/pureikyubu.git
synced 2025-04-02 10:42:15 -04:00
116 lines
2.1 KiB
C++
116 lines
2.1 KiB
C++
#include "pch.h"
|
|
|
|
// Thanks for the example implementation.
|
|
// https://stackoverflow.com/questions/9397068/how-to-pause-a-pthread-any-time-i-want
|
|
|
|
// Whoever removed suspend / resume from pthread is not a good person.
|
|
|
|
void* Thread::RingleaderThreadProc(void* args)
|
|
{
|
|
Thread* thread = (Thread*)args;
|
|
|
|
while (!thread->terminated)
|
|
{
|
|
pthread_mutex_lock(&thread->mutex);
|
|
|
|
switch (thread->command)
|
|
{
|
|
// command to pause thread..
|
|
case 0:
|
|
pthread_cond_wait(&thread->cond_var, &thread->mutex);
|
|
break;
|
|
|
|
// command to run..
|
|
case 1:
|
|
if (thread->ctx.proc)
|
|
{
|
|
thread->ctx.proc(thread->ctx.context);
|
|
}
|
|
break;
|
|
}
|
|
|
|
pthread_mutex_unlock(&thread->mutex);
|
|
|
|
// it's important to give main thread few time after unlock 'this'
|
|
pthread_yield();
|
|
}
|
|
|
|
thread->terminated = false;
|
|
|
|
pthread_exit(nullptr);
|
|
}
|
|
|
|
Thread::Thread(ThreadProc threadProc, bool suspended, void* context, const char* name)
|
|
{
|
|
running = !suspended;
|
|
threadName = name;
|
|
|
|
ctx.context = context;
|
|
ctx.proc = threadProc;
|
|
|
|
pthread_mutex_init(&mutex, nullptr);
|
|
pthread_cond_init(&cond_var, nullptr);
|
|
|
|
// create thread in suspended state..
|
|
command = running ? 1 : 0;
|
|
|
|
int status = pthread_create(&threadId, nullptr, Thread::RingleaderThreadProc, this);
|
|
assert(status == 0);
|
|
}
|
|
|
|
Thread::~Thread()
|
|
{
|
|
terminated = true;
|
|
|
|
// Run if suspended
|
|
if (!running)
|
|
{
|
|
Resume();
|
|
}
|
|
|
|
// Wait terminated
|
|
while (terminated)
|
|
{
|
|
Thread::Sleep(1);
|
|
}
|
|
|
|
pthread_join(threadId, nullptr);
|
|
|
|
pthread_cond_destroy(&cond_var);
|
|
pthread_mutex_destroy(&mutex);
|
|
}
|
|
|
|
void Thread::Resume()
|
|
{
|
|
resumeLock.Lock();
|
|
if (!running)
|
|
{
|
|
pthread_mutex_lock(&mutex);
|
|
command = 1;
|
|
pthread_cond_signal(&cond_var);
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
running = true;
|
|
resumeCounter++;
|
|
}
|
|
resumeLock.Unlock();
|
|
}
|
|
|
|
void Thread::Suspend()
|
|
{
|
|
if (running)
|
|
{
|
|
running = false;
|
|
suspendCounter++;
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
command = 0;
|
|
// in pause command we dont need to signal cond_var because we not in wait state now..
|
|
pthread_mutex_unlock(&mutex);
|
|
}
|
|
}
|
|
|
|
void Thread::Sleep(size_t milliseconds)
|
|
{
|
|
usleep(milliseconds * 1000);
|
|
}
|