2012-11-14 23:39:56 +00:00
|
|
|
#pragma once
|
|
|
|
#include "Array.h"
|
2013-07-12 12:42:17 +00:00
|
|
|
#include <functional>
|
|
|
|
#include <thread>
|
2014-04-09 22:54:32 +00:00
|
|
|
#include <vector>
|
2013-07-12 12:42:17 +00:00
|
|
|
#include <mutex>
|
2014-01-31 18:40:18 +00:00
|
|
|
#include <atomic>
|
2013-07-12 12:42:17 +00:00
|
|
|
#include <condition_variable>
|
2012-11-14 23:39:56 +00:00
|
|
|
|
|
|
|
class ThreadExec;
|
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
class NamedThreadBase
|
2012-11-14 23:39:56 +00:00
|
|
|
{
|
2013-11-27 19:16:19 +00:00
|
|
|
std::string m_name;
|
2012-11-14 23:39:56 +00:00
|
|
|
|
2013-06-30 08:46:29 +00:00
|
|
|
public:
|
2014-01-31 18:40:18 +00:00
|
|
|
NamedThreadBase(const std::string& name) : m_name(name)
|
|
|
|
{
|
|
|
|
}
|
2012-11-14 23:39:56 +00:00
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
NamedThreadBase()
|
|
|
|
{
|
|
|
|
}
|
2013-06-30 08:46:29 +00:00
|
|
|
|
2013-11-27 19:16:19 +00:00
|
|
|
virtual std::string GetThreadName() const;
|
|
|
|
virtual void SetThreadName(const std::string& name);
|
2012-11-14 23:39:56 +00:00
|
|
|
};
|
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
NamedThreadBase* GetCurrentNamedThread();
|
2013-06-30 08:46:29 +00:00
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
class ThreadBase : public NamedThreadBase
|
2012-11-14 23:39:56 +00:00
|
|
|
{
|
2014-01-31 18:40:18 +00:00
|
|
|
protected:
|
|
|
|
std::atomic<bool> m_destroy;
|
|
|
|
std::atomic<bool> m_alive;
|
|
|
|
std::thread* m_executor;
|
2012-11-14 23:39:56 +00:00
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
mutable std::mutex m_main_mutex;
|
2013-06-30 08:46:29 +00:00
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
ThreadBase(const std::string& name);
|
|
|
|
~ThreadBase();
|
2012-11-14 23:39:56 +00:00
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
public:
|
|
|
|
void Start();
|
2014-02-14 19:50:02 +00:00
|
|
|
void Stop(bool wait = true, bool send_destroy = true);
|
2013-06-30 08:46:29 +00:00
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
bool Join() const;
|
|
|
|
bool IsAlive() const;
|
|
|
|
bool TestDestroy() const;
|
2012-11-14 23:39:56 +00:00
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
virtual void Task() = 0;
|
2012-11-14 23:39:56 +00:00
|
|
|
};
|
|
|
|
|
2014-01-31 18:40:18 +00:00
|
|
|
class thread
|
|
|
|
{
|
|
|
|
std::string m_name;
|
|
|
|
std::thread m_thr;
|
|
|
|
|
|
|
|
public:
|
|
|
|
thread(const std::string& name, std::function<void()> func);
|
|
|
|
thread(const std::string& name);
|
|
|
|
thread();
|
|
|
|
|
2014-02-19 17:27:52 +00:00
|
|
|
|
|
|
|
public:
|
2014-01-31 18:40:18 +00:00
|
|
|
void start(std::function<void()> func);
|
|
|
|
void detach();
|
|
|
|
void join();
|
|
|
|
bool joinable() const;
|
|
|
|
};
|
2013-06-30 08:46:29 +00:00
|
|
|
|
2012-11-14 23:39:56 +00:00
|
|
|
template<typename T> class MTPacketBuffer
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
volatile bool m_busy;
|
|
|
|
volatile u32 m_put, m_get;
|
2014-04-09 22:54:32 +00:00
|
|
|
std::vector<u8> m_buffer;
|
2012-11-14 23:39:56 +00:00
|
|
|
u32 m_max_buffer_size;
|
2013-11-27 19:16:19 +00:00
|
|
|
mutable std::recursive_mutex m_cs_main;
|
2012-11-14 23:39:56 +00:00
|
|
|
|
|
|
|
void CheckBusy()
|
|
|
|
{
|
|
|
|
m_busy = m_put >= m_max_buffer_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
MTPacketBuffer(u32 max_buffer_size)
|
|
|
|
: m_max_buffer_size(max_buffer_size)
|
|
|
|
{
|
|
|
|
Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
~MTPacketBuffer()
|
|
|
|
{
|
|
|
|
Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Flush()
|
|
|
|
{
|
2013-11-27 19:16:19 +00:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(m_cs_main);
|
2012-11-14 23:39:56 +00:00
|
|
|
m_put = m_get = 0;
|
2014-04-09 22:54:32 +00:00
|
|
|
m_buffer.clear();
|
2012-11-14 23:39:56 +00:00
|
|
|
m_busy = false;
|
|
|
|
}
|
|
|
|
|
2013-06-30 08:46:29 +00:00
|
|
|
private:
|
|
|
|
virtual void _push(const T& v) = 0;
|
|
|
|
virtual T _pop() = 0;
|
2012-11-14 23:39:56 +00:00
|
|
|
|
2013-06-30 08:46:29 +00:00
|
|
|
public:
|
|
|
|
void Push(const T& v)
|
|
|
|
{
|
2013-11-27 19:16:19 +00:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(m_cs_main);
|
2013-06-30 08:46:29 +00:00
|
|
|
_push(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
T Pop()
|
|
|
|
{
|
2013-11-27 19:16:19 +00:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(m_cs_main);
|
2013-06-30 08:46:29 +00:00
|
|
|
return _pop();
|
|
|
|
}
|
|
|
|
|
2013-11-27 19:16:19 +00:00
|
|
|
bool HasNewPacket() const { std::lock_guard<std::recursive_mutex> lock(m_cs_main); return m_put != m_get; }
|
2012-11-14 23:39:56 +00:00
|
|
|
bool IsBusy() const { return m_busy; }
|
|
|
|
};
|
|
|
|
|
2013-06-30 08:46:29 +00:00
|
|
|
static __forceinline bool SemaphorePostAndWait(wxSemaphore& sem)
|
|
|
|
{
|
|
|
|
if(sem.TryWait() != wxSEMA_BUSY) return false;
|
|
|
|
|
|
|
|
sem.Post();
|
|
|
|
sem.Wait();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-11-14 23:39:56 +00:00
|
|
|
/*
|
|
|
|
class StepThread : public ThreadBase
|
|
|
|
{
|
|
|
|
wxSemaphore m_main_sem;
|
|
|
|
wxSemaphore m_destroy_sem;
|
|
|
|
volatile bool m_exit;
|
|
|
|
|
|
|
|
protected:
|
2014-02-23 16:52:52 +00:00
|
|
|
StepThread(const std::string& name = "Unknown StepThread")
|
2012-11-14 23:39:56 +00:00
|
|
|
: ThreadBase(true, name)
|
|
|
|
, m_exit(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~StepThread() throw()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void Task()
|
|
|
|
{
|
|
|
|
m_exit = false;
|
|
|
|
|
|
|
|
while(!TestDestroy())
|
|
|
|
{
|
|
|
|
m_main_sem.Wait();
|
|
|
|
|
|
|
|
if(TestDestroy() || m_exit) break;
|
|
|
|
|
|
|
|
Step();
|
|
|
|
}
|
|
|
|
|
|
|
|
while(!TestDestroy()) Sleep(0);
|
|
|
|
if(m_destroy_sem.TryWait() != wxSEMA_NO_ERROR) m_destroy_sem.Post();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Step()=0;
|
|
|
|
|
|
|
|
public:
|
|
|
|
void DoStep()
|
|
|
|
{
|
|
|
|
if(IsRunning()) m_main_sem.Post();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WaitForExit()
|
|
|
|
{
|
|
|
|
if(TestDestroy()) m_destroy_sem.Wait();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WaitForNextStep()
|
|
|
|
{
|
|
|
|
if(!IsRunning()) return;
|
|
|
|
|
|
|
|
while(m_main_sem.TryWait() != wxSEMA_NO_ERROR) Sleep(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Exit(bool wait = false)
|
|
|
|
{
|
|
|
|
if(!IsAlive()) return;
|
|
|
|
|
|
|
|
if(m_main_sem.TryWait() != wxSEMA_NO_ERROR)
|
|
|
|
{
|
|
|
|
m_exit = true;
|
|
|
|
m_main_sem.Post();
|
|
|
|
}
|
|
|
|
|
|
|
|
Delete();
|
|
|
|
|
|
|
|
if(wait) WaitForExit();
|
|
|
|
}
|
|
|
|
};
|
2013-11-19 10:30:58 +00:00
|
|
|
*/
|