/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "Threading.h"
#include "Errors.h"
#include
#include
#ifdef WIN32
#include
#endif // WIN32
using namespace Acore;
Thread::Thread() : m_task(nullptr), m_iThreadId(), m_ThreadImp()
{
}
Thread::Thread(Runnable* instance) : m_task(instance), m_ThreadImp(&Thread::ThreadTask, (void*)m_task)
{
m_iThreadId = m_ThreadImp.get_id();
// register reference to m_task to prevent it deeltion until destructor
if (m_task)
{
m_task->incReference();
}
}
Thread::~Thread()
{
// Wait();
// deleted runnable object (if no other references)
if (m_task)
{
m_task->decReference();
}
}
bool Thread::wait()
{
if (m_iThreadId == std::thread::id() || !m_task)
{
return false;
}
bool res = true;
try
{
m_ThreadImp.join();
}
catch (std::system_error&)
{
res = false;
}
m_iThreadId = std::thread::id();
return res;
}
void Thread::destroy()
{
if (m_iThreadId == std::thread::id() || !m_task)
{
return;
}
// FIXME: We need to make sure that all threads can be trusted to
// halt execution on their own as this is not an interrupt
m_ThreadImp.join();
m_iThreadId = std::thread::id();
}
void Thread::ThreadTask(void* param)
{
Runnable* _task = (Runnable*)param;
_task->run();
}
std::thread::id Thread::currentId()
{
return std::this_thread::get_id();
}
void Thread::setPriority(Priority priority)
{
#ifdef WIN32
std::thread::native_handle_type handle = m_ThreadImp.native_handle();
#endif
bool _ok = true;
switch (priority)
{
#ifdef WIN32
case Priority_Realtime:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
break;
case Priority_Highest:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_HIGHEST);
break;
case Priority_High:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_ABOVE_NORMAL);
break;
case Priority_Normal:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_NORMAL);
break;
case Priority_Low:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_BELOW_NORMAL);
break;
case Priority_Lowest:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_LOWEST);
break;
case Priority_Idle:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_IDLE);
break;
#endif
default:
break;
}
// remove this ASSERT in case you don't want to know is thread priority change was successful or not
ASSERT(_ok);
}
void Thread::Sleep(unsigned long msecs)
{
std::this_thread::sleep_for(std::chrono::milliseconds(msecs));
}