You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dvmhost/src/common/Thread.cpp

179 lines
4.1 KiB

// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - Common Library
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2023,2024 Bryan Biedenkapp, N2PLL
*
*/
#include "Thread.h"
#include "Log.h"
#include <cerrno>
#include <signal.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif // !defined(_WIN32)
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/* Initializes a new instance of the Thread class. */
Thread::Thread() :
m_thread(),
m_started(false)
{
/* stub */
}
/* Finalizes a instance of the Thread class. */
Thread::~Thread() = default;
/* Starts the thread execution. */
bool Thread::run()
{
if (m_started)
return m_started;
m_started = true;
#if defined(_WIN32)
m_thread = ::CreateThread(NULL, 0, &helper, this, 0, NULL);
if (m_thread == NULL) {
LogError(LOG_NET, "Error returned from CreateThread, err: %lu", ::GetLastError());
return false;
}
#else
int err = ::pthread_create(&m_thread, NULL, helper, this);
if (err != 0) {
LogError(LOG_NET, "Error returned from pthread_create, err: %d", errno);
return false;
}
#endif // defined(_WIN32)
return true;
}
/* Make calling thread wait for termination of the thread. */
void Thread::wait()
{
#if defined(_WIN32)
::WaitForSingleObject(m_thread, INFINITE);
::CloseHandle(m_thread);
#else
::pthread_join(m_thread, NULL);
#endif // defined(_WIN32)
}
/* Set thread name visible in the kernel and its interfaces. */
void Thread::setName(std::string name)
{
if (!m_started)
return;
#if defined(_WIN32)
// WIN32 doesn't have a way to set thread names (easily, or consistently anyway)
#else
if (pthread_kill(m_thread, 0) != 0)
return;
#ifdef _GNU_SOURCE
::pthread_setname_np(m_thread, name.c_str());
#endif // _GNU_SOURCE
#endif // defined(_WIN32)
}
/*
* Indicate that the thread is never to be joined with wait().
* The resources of thread will therefore be freed immediately when it terminates, instead
* of waiting for another thread to perform wait() on it.
*/
void Thread::detach()
{
if (!m_started)
return;
#if defined(_WIN32)
::CloseHandle(m_thread);
#else
::pthread_detach(m_thread);
#endif // defined(_WIN32)
}
/* Executes the specified start routine to run as a thread. */
bool Thread::runAsThread(void* obj, void *(*startRoutine)(void *), thread_t* thread)
{
if (thread == nullptr)
thread = new thread_t();
thread->obj = obj;
#if defined(_WIN32)
HANDLE hnd = ::CreateThread(NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>((void*)startRoutine), thread, CREATE_SUSPENDED, NULL);
if (hnd == NULL) {
LogError(LOG_NET, "Error returned from CreateThread, err: %lu", ::GetLastError());
return false;
}
thread->thread = hnd;
::ResumeThread(hnd);
#else
if (::pthread_create(&thread->thread, NULL, startRoutine, thread) != 0) {
LogError(LOG_NET, "Error returned from pthread_create, err: %d", errno);
delete thread;
return false;
}
#endif // defined(_WIN32)
return true;
}
/* Suspends the current thread for the specified amount of time. */
void Thread::sleep(uint32_t ms, uint32_t us)
{
#if defined(_WIN32)
if (us > 0U) {
::Sleep(1);
}
else {
::Sleep(ms);
}
#else
if (us > 0U) {
::usleep(us);
}
else {
::usleep(ms * 1000U);
}
#endif // defined(_WIN32)
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/* Internal helper thats used as the entry point for the thread. */
#if defined(_WIN32)
DWORD Thread::helper(LPVOID arg)
#else
void* Thread::helper(void* arg)
#endif // defined(_WIN32)
{
Thread* p = (Thread*)arg;
p->entry();
#if defined(_WIN32)
return 0UL;
#else
return nullptr;
#endif // defined(_WIN32)
}

Powered by TurnKey Linux.