// Copyright (C) 2017 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include #include #if defined(NAZARA_PLATFORM_WINDOWS) #include #elif defined(NAZARA_PLATFORM_POSIX) #include #else #error Thread has no implementation #endif #include namespace Nz { /*! * \ingroup core * \class Nz::Thread * \brief Core class that represents a thread */ /*! * \brief Constructs a Thread object by default */ Thread::Thread() : m_impl(nullptr) { } /*! * \brief Waits that the thread ends and then destroys this */ Thread::~Thread() { if (m_impl) { m_impl->Join(); delete m_impl; m_impl = nullptr; } } /*! * \brief Detaches the thread */ void Thread::Detach() { if (m_impl) { m_impl->Detach(); delete m_impl; m_impl = nullptr; } } /*! * \brief Gets the id of the thread * \return The identifiant of the thread (PID) */ Thread::Id Thread::GetId() const { return Thread::Id(m_impl); } /*! * \brief Checks whether the thread can be joined * \return true if well formed and not detached */ bool Thread::IsJoinable() const { return m_impl != nullptr; } /*! * \brief Waits that the thread ends * * \remark Produce a NazaraError if no functor was assigned and NAZARA_CORE_SAFE is defined */ void Thread::Join() { #if NAZARA_CORE_SAFE if (!m_impl) { NazaraError("This thread is not joinable"); return; } #endif m_impl->Join(); delete m_impl; m_impl = nullptr; } /*! * \brief Changes the debugging name associated to a thread * * Changes the debugging name associated with a particular thread, and may helps with debugging tools. * * \param name The new name of the thread * * \remark Due to system limitations, thread name cannot exceed 15 characters (excluding null-terminator) * * \see SetCurrentThreadName */ void Thread::SetName(const String& name) { NazaraAssert(m_impl, "Invalid thread"); NazaraAssert(name.GetSize() < 16, "Thread name is too long"); m_impl->SetName(name); } /*! * \brief Gets the number of simulatenous threads that can run on the same cpu * \return The number of simulatenous threads */ unsigned int Thread::HardwareConcurrency() { return HardwareInfo::GetProcessorCount(); } /*! * \brief Changes the debugging name associated to the calling thread * * Changes the debugging name associated with the calling thread, and may helps with debugging tools. * * \param name The new name associated with this thread * * \remark Due to system limitations, thread name cannot exceed 15 characters (excluding null-terminator) * * \see SetName */ void Thread::SetCurrentThreadName(const String& name) { NazaraAssert(name.GetSize() < 16, "Thread name is too long"); ThreadImpl::SetCurrentName(name); } /*! * \brief Makes sleep this thread * * \param milliseconds The number of milliseconds to sleep */ void Thread::Sleep(UInt32 milliseconds) { ThreadImpl::Sleep(milliseconds); } /*! * \brief Creates the implementation of this thread * * \param functor The task the thread will represent */ void Thread::CreateImpl(Functor* functor) { m_impl = new ThreadImpl(functor); } /*********************************Thread::Id********************************/ /*! * \brief Constructs a Thread object with a thread implementation * * \param thread Thread implementation assigned to the thread */ Thread::Id::Id(ThreadImpl* thread) : m_id(thread) { } /*! * \brief Compares two Thread::Id * \return true if the two thread ids are the same * * \param lhs First id * \param rhs Second id */ bool operator==(const Thread::Id& lhs, const Thread::Id& rhs) { return lhs.m_id == rhs.m_id; } /*! * \brief Compares two Thread::Id * \return false if the two thread ids are the same * * \param lhs First id * \param rhs Second id */ bool operator!=(const Thread::Id& lhs, const Thread::Id& rhs) { return lhs.m_id != rhs.m_id; } /*! * \brief Compares two Thread::Id * \return true if the first thread id is inferior to the second one * * \param lhs First id * \param rhs Second id */ bool operator<(const Thread::Id& lhs, const Thread::Id& rhs) { return lhs.m_id < rhs.m_id; } /*! * \brief Compares two Thread::Id * \return true if the first thread id is inferior or equal to the second one * * \param lhs First id * \param rhs Second id */ bool operator<=(const Thread::Id& lhs, const Thread::Id& rhs) { return lhs.m_id <= rhs.m_id; } /*! * \brief Compares two Thread::Id * \return true if the first thread id is superior to the second one * * \param lhs First id * \param rhs Second id */ bool operator>(const Thread::Id& lhs, const Thread::Id& rhs) { return lhs.m_id > rhs.m_id; } /*! * \brief Compares two Thread::Id * \return true if the first thread id is superior or equal to the second one * * \param lhs First id * \param rhs Second id */ bool operator>=(const Thread::Id& lhs, const Thread::Id& rhs) { return lhs.m_id >= rhs.m_id; } /*! * \brief Output operator * \return The stream * * \param out The stream * \param id The thread id to output */ std::ostream& operator<<(std::ostream& o, const Nz::Thread::Id& id) { o << id.m_id; return o; } }