diff --git a/src/Nazara/Core/Posix/ClockImpl.cpp b/src/Nazara/Core/Posix/ClockImpl.cpp new file mode 100644 index 000000000..3bd944b63 --- /dev/null +++ b/src/Nazara/Core/Posix/ClockImpl.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2012 Alexandre Janniaux +// 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 + +bool NzClockImplInitializeHighPrecision() +{ + return true; // No initialization needed +} + +nzUInt64 NzClockImplGetMicroseconds() +{ + timeval clock; + gettimeofday(&clock, nullptr); + return static_cast(clock.tv_sec*1000000 + (clock.tv_nsec/1000)); +} + +nzUInt64 NzClockImplGetMilliseconds() +{ + timeval clock; + gettimeofday(&clock, nullptr); + return static_cast(clock.tv_sec*1000 + (clock.tv_nsec/1000000)); +} diff --git a/src/Nazara/Core/Posix/ClockImpl.hpp b/src/Nazara/Core/Posix/ClockImpl.hpp new file mode 100644 index 000000000..c592f81df --- /dev/null +++ b/src/Nazara/Core/Posix/ClockImpl.hpp @@ -0,0 +1,16 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_CLOCKIMPL_POSIX_HPP +#define NAZARA_CLOCKIMPL_POSIX_HPP + +#include + +bool NzClockImplInitializeHighPrecision(); +nzUInt64 NzClockImplGetMicroseconds(); +nzUInt64 NzClockImplGetMilliseconds(); + +#endif // NAZARA_CLOCKIMPL_POSIX_HPP diff --git a/src/Nazara/Core/Posix/ConditionVariableImpl.cpp b/src/Nazara/Core/Posix/ConditionVariableImpl.cpp new file mode 100644 index 000000000..6094242b9 --- /dev/null +++ b/src/Nazara/Core/Posix/ConditionVariableImpl.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2012 Alexandre Janniaux +// 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 + +NzConditionVariableImpl::NzConditionVariableImpl() +{ + pthread_cond_init(&m_cv, nullptr); +} + +NzConditionVariableImpl::~NzConditionVariableImpl() +{ + pthread_cond_destroy(&m_cv); +} + +void NzConditionVariableImpl::Signal() +{ + pthread_cond_signal(&m_cv); +} + +void NzConditionVariableImpl::SignalAll() +{ + pthread_cond_broadcast(&m_cv); +} + +void NzConditionVariableImpl::Wait(NzMutexImpl* mutex) +{ + pthread_cond_wait(&m_cv, mutex); +} + +bool NzConditionVariableImpl::Wait(NzMutexImpl* mutex, nzUInt32 timeout) +{ + // get the current time + timeval tv; + gettimeofday(&tv, NULL); + + // construct the time limit (current time + time to wait) + timespec ti; + ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000; + ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000); + ti.tv_nsec %= 1000000000; + + pthread_cond_timedwait(&m_cv,mutex, &tv); +} diff --git a/src/Nazara/Core/Posix/ConditionVariableImpl.hpp b/src/Nazara/Core/Posix/ConditionVariableImpl.hpp new file mode 100644 index 000000000..e1bc13f3d --- /dev/null +++ b/src/Nazara/Core/Posix/ConditionVariableImpl.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html + +#pragma once + +#ifndef NAZARA_CONDITIONVARIABLEIMPL_HPP +#define NAZARA_CONDITIONVARIABLEIMPL_HPP + +#include +#include +#include +#include + +class NzMutexImpl; + +class NzConditionVariableImpl +{ + public: + NzConditionVariableImpl(); + ~NzConditionVariableImpl(); + + void Signal(); + void SignalAll(); + + void Wait(NzMutexImpl* mutex); + bool Wait(NzMutexImpl* mutex, nzUInt32 timeout); + + private: + pthread_cond_t m_cv; +}; + +#endif // NAZARA_CONDITIONVARIABLEIMPL_HPP diff --git a/src/Nazara/Core/Posix/DirectoryImpl.cpp b/src/Nazara/Core/Posix/DirectoryImpl.cpp new file mode 100644 index 000000000..c4fc18d0c --- /dev/null +++ b/src/Nazara/Core/Posix/DirectoryImpl.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2012 Alexandre Janniaux +// 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 + +NzDirectoryImpl::NzDirectoryImpl(const NzDirectory* parent) +{ + NazaraUnused(parent); +} + +void NzDirectoryImpl::Close() +{ + closedir(m_handle); +} + +NzString NzDirectoryImpl::GetResultName() const +{ + return m_result.d_name; +} + +nzUInt64 NzDirectoryImpl::GetResultSize() const +{ + struct stat64 resulststat; + stat64(m_result.d_name, &resulststat); + + return static_cast(resulststat.st_size); +} + +bool NzDirectoryImpl::IsResultDirectory() const +{ + return S_ISDIR(m_result.d_name); +} + +bool NzDirectoryImpl::NextResult() +{ + if ((m_result = readdir64(m_handle))) + return true; + else + { + if (errno != ENOENT) + NazaraError("Unable to get next result: " + NzGetLastSystemError()); + + return false; + } +} + +bool NzDirectoryImpl::Open(const NzString& dirPath) +{ + m_handle = opendir(dirPath.GetConstBuffer()); + if (!m_handle) + { + NazaraError("Unable to open directory: " + NzGetLastSystemError()); + return false; + } + + return true; +} + +bool NzDirectoryImpl::Create(const NzString& dirPath) +{ + mode_t permissions; // TODO: check permissions + + return mkdir(dirPath.GetConstBuffer(), permissions) != -1;; +} + +bool NzDirectoryImpl::Exists(const NzString& dirPath) +{ + if (S_ISDIR(dirPath.GetConstBuffer())) + return true; + + return false; +} + +NzString NzDirectoryImpl::GetCurrent() +{ + NzString currentPath; + char* path = new char[_PC_PATH_MAX]; + + if (getcwd(path, _PC_PATH_MAX)) + currentPath = path; + else + NazaraError("Unable to get current directory: " + NzGetLastSystemError()); + + delete[] path; + + return currentPath; +} + +bool NzDirectoryImpl::Remove(const NzString& dirPath) +{ + bool success = rmdir(dirPath.GetConstBuffer()) != -1; + + return success; +} diff --git a/src/Nazara/Core/Posix/DirectoryImpl.hpp b/src/Nazara/Core/Posix/DirectoryImpl.hpp new file mode 100644 index 000000000..090a16b3f --- /dev/null +++ b/src/Nazara/Core/Posix/DirectoryImpl.hpp @@ -0,0 +1,47 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_DIRECTORYIMPL_HPP +#define NAZARA_DIRECTORYIMPL_HPP + +#include +#include +#include +#include +#include +#include + +class NzDirectory; +class NzString; + +class NzDirectoryImpl : NzNonCopyable +{ + public: + NzDirectoryImpl(const NzDirectory* parent); + ~NzDirectoryImpl() = default; + + void Close(); + + NzString GetResultName() const; + nzUInt64 GetResultSize() const; + + bool IsResultDirectory() const; + + bool NextResult(); + + bool Open(const NzString& dirPath); + + static bool Create(const NzString& dirPath); + static bool Exists(const NzString& dirPath); + static NzString GetCurrent(); + static bool Remove(const NzString& dirPath); + + private: + DIR* m_handle; + dirent64* m_result; +}; + +#endif // NAZARA_DIRECTORYIMPL_HPP diff --git a/src/Nazara/Core/Posix/DynLibImpl.cpp b/src/Nazara/Core/Posix/DynLibImpl.cpp new file mode 100644 index 000000000..19e96bcd0 --- /dev/null +++ b/src/Nazara/Core/Posix/DynLibImpl.cpp @@ -0,0 +1,61 @@ +// Copyright (C) 2012 Alexandre Janniaux +// 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 + +NzDynLibImpl::NzDynLibImpl(NzDynLib* parent) : +m_parent(parent) +{ +} + +NzDynLibFunc NzDynLibImpl::GetSymbol(const NzString& symbol) const +{ + /* + Il n'est pas standard de cast un pointeur d'objet vers un pointeur de fonction. + Nous devons donc utiliser des techniques diaboliques venant du malin lui-même.. :D + Au moins ce n'est pas aussi terrible qu'un const_cast + -Lynix + */ + union + { + NzDynLibFunc func; + void* pointer; + } converter; + + dlerror(); // Clear error flag + + converter.pointer = reinterpret_cast(dlsym(m_handle, symbol.GetConstBuffer())); + if (!converter.pointer) + m_parent->SetLastError(dlerror()); + + return converter.func; +} + +bool NzDynLibImpl::Load(const NzString& libraryPath) +{ + NzString path = libraryPath; + if (!path.EndsWith(".so")) + path += ".so"; + + dlerror(); // Clear error flag + + m_handle = dlopen(path.GetConstBuffer()); + + if (m_handle) + return true; + else + { + m_parent->SetLastError(dlerror()); + return false; + } +} + +void NzDynLibImpl::Unload() +{ + dlclose(m_handle); +} diff --git a/src/Nazara/Core/Posix/DynLibImpl.hpp b/src/Nazara/Core/Posix/DynLibImpl.hpp new file mode 100644 index 000000000..41a0da38b --- /dev/null +++ b/src/Nazara/Core/Posix/DynLibImpl.hpp @@ -0,0 +1,31 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_DYNLIBIMPL_HPP +#define NAZARA_DYNLIBIMPL_HPP + +#include +#include +#include + +class NzString; + +class NzDynLibImpl : NzNonCopyable +{ + public: + NzDynLibImpl(NzDynLib* m_parent); + ~NzDynLibImpl() = default; + + NzDynLibFunc GetSymbol(const NzString& symbol) const; + bool Load(const NzString& libraryPath); + void Unload(); + + private: + void* m_handle; + NzDynLib* m_parent; +}; + +#endif // NAZARA_DYNLIBIMPL_HPP diff --git a/src/Nazara/Core/Posix/FileImpl.cpp b/src/Nazara/Core/Posix/FileImpl.cpp new file mode 100644 index 000000000..523c5b98e --- /dev/null +++ b/src/Nazara/Core/Posix/FileImpl.cpp @@ -0,0 +1,244 @@ +// Copyright (C) 2012 Alexandre Janniaux +// 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 + +NzFileImpl::NzFileImpl(const NzFile* parent) : +m_endOfFile(false), +m_endOfFileUpdated(true) +{ + NazaraUnused(parent); +} + +void NzFileImpl::Close() +{ + close(m_fileDescriptor); +} + +bool NzFileImpl::EndOfFile() const +{ + if (!m_endOfFileUpdated) + { + stat64 fileSize; + if (fstat64(m_fileDescriptor, &fileSize) == -1) + fileSize.st_size = 0; + + m_endOfFile = (GetCursorPos() >= static_cast(fileSize.st_size)); + m_endOfFileUpdated = true; + } + + return m_endOfFile; +} + +void NzFileImpl::Flush() +{ + if (fsync(m_fileDescriptor) == -1) + NazaraError("Unable to flush file: " + NzGetLastSystemError()); +} + +nzUInt64 NzFileImpl::GetCursorPos() const +{ + off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR); + return static_cast(position); +} + +bool NzFileImpl::Open(const NzString& filePath, unsigned int mode) +{ + int flags; + mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + + if (mode & NzFile::ReadOnly) + flags = O_RDONLY; + else if (mode & NzFile::ReadWrite) + { + flags = O_CREAT | O_RDWR; + + if (mode & NzFile::Append) + flags |= O_APPEND; + + if (mode & NzFile::Truncate) + flags |= O_TRUNC; + } + else if (mode & NzFile::WriteOnly) + { + flags = O_CREAT | O_WRONLY; + + if (mode & NzFile::Append) + flags |= O_APPEND; + + if (mode & NzFile::Truncate) + flags |= O_TRUNC; + } + else + return false; + +///TODO: lock +// if ((mode & NzFile::Lock) == 0) +// shareMode |= FILE_SHARE_WRITE; + + m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions); + return m_fileDescriptor != -1; +} + +std::size_t NzFileImpl::Read(void* buffer, std::size_t size) +{ + ssize_t bytes; + if ((bytes = read(m_fileDescriptor, buffer, size)) != -1) + { + m_endOfFile = (static_cast(bytes) != size); + m_endOfFileUpdated = true; + + return static_cast(bytes); + } + else + return 0; +} + +bool NzFileImpl::SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset) +{ + int moveMethod; + switch (pos) + { + case NzFile::AtBegin: + moveMethod = SEEK_SET; + break; + + case NzFile::AtCurrent: + moveMethod = SEEK_CUR; + break; + + case NzFile::AtEnd: + moveMethod = SEEK_END; + break; + + default: + NazaraInternalError("Cursor position not handled (0x" + NzString::Number(pos, 16) + ')'); + return false; + } + + m_endOfFileUpdated = false; + + return lseek64(m_fileDescriptor, offset, moveMethod) != -1; +} + +std::size_t NzFileImpl::Write(const void* buffer, std::size_t size) +{ + lockf64(m_fileDescriptor, F_LOCK, size); + ssize_t written = write(m_fileDescriptor, buffer, size); + lockf64(m_fileDescriptor, F_ULOCK, size); + + m_endOfFileUpdated = false; + + return written; +} + +bool NzFileImpl::Copy(const NzString& sourcePath, const NzString& targetPath) +{ + int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY); + if (fd1 == -1) + { + NazaraError("Fail to open input file (" + sourcePath + "): " + NzGetLastSystemError()); + return false; + } + + mode_t permissions; // TODO : get permission from first file + int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions); + if (fd2 == -1) + { + NazaraError("Fail to open output file (" + targetPath + "): " + NzGetLastSystemError()); // TODO: more info ? + close(fd1); + return false; + } + + char buffer[512]; + ssize_t bytes; + do + { + bytes = read(fd1,buffer,512); + if (bytes == -1) + { + close(fd1); + close(fd2); + NazaraError("An error occured from copy : " + NzGetLastSystemError()); + return false; + } + write(fd2,buffer,bytes); + } + while (bytes == 512); + + close(fd1); + close(fd2); +} + +bool NzFileImpl::Delete(const NzString& filePath) +{ + bool success = unlink(filePath.GetConstBuffer()) != -1; + + if (success) + return true; + else + { + NazaraError("Failed to delete file (" + filePath + "): " + NzGetLastSystemError()); + return false; + } +} + +bool NzFileImpl::Exists(const NzString& filePath) +{ + char* path = filePath.GetConstBuffer(); + if (access(path, F_OK) != -1) + return true; + + return false; +} + +time_t NzFileImpl::GetCreationTime(const NzString& filePath) +{ + NazaraWarning("Posix has no creation time information"); + + return 0; +} + +time_t NzFileImpl::GetLastAccessTime(const NzString& filePath) +{ + struct stat64 stats; + stat64(filePath.GetConstBuffer(), &stats); + + return stats.st_atime; +} + +time_t NzFileImpl::GetLastWriteTime(const NzString& filePath) +{ + struct stat64 stats; + stat64(filePath.GetConstBuffer(), &stats); + + return stats.st_mtime; +} + +nzUInt64 NzFileImpl::GetSize(const NzString& filePath) +{ + struct stat64 stats; + stat64(filePath.GetConstBuffer(), &stats); + + return static_cast(stats.st_size); +} + +bool NzFileImpl::Rename(const NzString& sourcePath, const NzString& targetPath) +{ + bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1; + + if (success) + return true; + else + { + NazaraError("Unable to rename file: " + NzGetLastSystemError()); + return false; + } +} diff --git a/src/Nazara/Core/Posix/FileImpl.hpp b/src/Nazara/Core/Posix/FileImpl.hpp new file mode 100644 index 000000000..408c7598c --- /dev/null +++ b/src/Nazara/Core/Posix/FileImpl.hpp @@ -0,0 +1,56 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_FILEIMPL_HPP +#define NAZARA_FILEIMPL_HPP + +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +class NzFile; +class NzString; + +class NzFileImpl : NzNonCopyable +{ + public: + NzFileImpl(const NzFile* parent); + ~NzFileImpl() = default; + + void Close(); + bool EndOfFile() const; + void Flush(); + nzUInt64 GetCursorPos() const; + bool Open(const NzString& filePath, unsigned int mode); + std::size_t Read(void* buffer, std::size_t size); + bool SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset); + std::size_t Write(const void* buffer, std::size_t size); + + static bool Copy(const NzString& sourcePath, const NzString& targetPath); + static bool Delete(const NzString& filePath); + static bool Exists(const NzString& filePath); + static time_t GetCreationTime(const NzString& filePath); + static time_t GetLastAccessTime(const NzString& filePath); + static time_t GetLastWriteTime(const NzString& filePath); + static nzUInt64 GetSize(const NzString& filePath); + static bool Rename(const NzString& sourcePath, const NzString& targetPath); + + private: + int m_fileDescriptor; + mutable bool m_endOfFile; + mutable bool m_endOfFileUpdated; +}; + +#endif // NAZARA_FILEIMPL_HPP diff --git a/src/Nazara/Core/Posix/HardwareInfoImpl.cpp b/src/Nazara/Core/Posix/HardwareInfoImpl.cpp new file mode 100644 index 000000000..3fd6d00a5 --- /dev/null +++ b/src/Nazara/Core/Posix/HardwareInfoImpl.cpp @@ -0,0 +1,55 @@ +// Copyright (C) 2012 Alexandre Janniaux +// 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 + +void NzHardwareInfoImpl::Cpuid(nzUInt32 code, nzUInt32 result[4]) +{ + #if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL) + // Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c + asm volatile ("cpuid" // Besoin d'être volatile ? + : "=a" (result[0]), "=b" (result[1]), "=c" (result[2]), "=d" (result[3]) // output + : "a" (code), "c" (0)); // input + #else + NazaraInternalError("Cpuid has been called although it is not supported"); + #endif +} + +unsigned int NzHardwareInfoImpl::GetProcessorCount() +{ + // Plus simple (et plus portable) que de passer par le CPUID + return sysconf(_SC_NPROCESSORS_CONF); +} + +bool NzHardwareInfoImpl::IsCpuidSupported() +{ + #ifdef NAZARA_PLATFORM_x64 + return true; // Toujours supporté sur un processeur 64 bits + #else + #if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL) + int supported; + asm volatile (" pushfl\n" + " pop %%eax\n" + " mov %%eax, %%ecx\n" + " xor $0x200000, %%eax\n" + " push %%eax\n" + " popfl\n" + " pushfl\n" + " pop %%eax\n" + " xor %%ecx, %%eax\n" + " mov %%eax, %0\n" + " push %%ecx\n" + " popfl" + : "=m" (supported) // output + : // input + : "eax", "ecx", "memory"); // clobbered register + + return supported != 0; + #else + return false; + #endif + #endif +} diff --git a/src/Nazara/Core/Posix/HardwareInfoImpl.hpp b/src/Nazara/Core/Posix/HardwareInfoImpl.hpp new file mode 100644 index 000000000..d3c15edd3 --- /dev/null +++ b/src/Nazara/Core/Posix/HardwareInfoImpl.hpp @@ -0,0 +1,21 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_HARDWAREINFOIMPL_POSIX_HPP +#define NAZARA_HARDWAREINFOIMPL_POSIX_HPP + +#include +#include + +class NzHardwareInfoImpl +{ + public: + static void Cpuid(nzUInt32 code, nzUInt32 result[4]); + static unsigned int GetProcessorCount(); + static bool IsCpuidSupported(); +}; + +#endif // NAZARA_HARDWAREINFOIMPL_POSIX_HPP diff --git a/src/Nazara/Core/Posix/MutexImpl.cpp b/src/Nazara/Core/Posix/MutexImpl.cpp new file mode 100644 index 000000000..a4844cd37 --- /dev/null +++ b/src/Nazara/Core/Posix/MutexImpl.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzMutexImpl::NzMutexImpl() +{ + pthread_mutex_init(&m_handle, NULL); +} + +NzMutexImpl::~NzMutexImpl() +{ + pthread_mutex_destroy(m_handle); +} + +void NzMutexImpl::Lock() +{ + pthread_mutex_lock(m_handle); +} + +bool NzMutexImpl::TryLock() +{ + return pthread_mutex_trylock(m_handle) == 0; +} + +void NzMutexImpl::Unlock() +{ + pthread_mutex_unlock(m_handle); +} diff --git a/src/Nazara/Core/Posix/MutexImpl.hpp b/src/Nazara/Core/Posix/MutexImpl.hpp new file mode 100644 index 000000000..34e833415 --- /dev/null +++ b/src/Nazara/Core/Posix/MutexImpl.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MUTEXIMPL_HPP +#define NAZARA_MUTEXIMPL_HPP + +#include + +class NzMutexImpl +{ + friend class NzConditionVariableImpl; + + public: + NzMutexImpl(); + ~NzMutexImpl(); + + void Lock(); + bool TryLock(); + void Unlock(); + + private: + pthread_mutex_t m_handle; +}; + +#endif // NAZARA_MUTEXIMPL_HPP diff --git a/src/Nazara/Core/Posix/SemaphoreImpl.cpp b/src/Nazara/Core/Posix/SemaphoreImpl.cpp new file mode 100644 index 000000000..ad94b6218 --- /dev/null +++ b/src/Nazara/Core/Posix/SemaphoreImpl.cpp @@ -0,0 +1,68 @@ +// Copyright (C) 2012 Alexandre Janniaux +// 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 + +NzSemaphoreImpl::NzSemaphoreImpl(unsigned int count) +{ + m_semaphore = sem_init(&m_semaphore, 0, count); + if (!m_semaphore) + NazaraError("Failed to create semaphore: " + NzGetLastSystemError()); +} + +NzSemaphoreImpl::~NzSemaphoreImpl() +{ + sem_destroy(&m_semaphore); +} + +unsigned int NzSemaphoreImpl::GetCount() const +{ + int count; + sem_getvalue(&m_semaphore, &count); + return static_cast(count); +} + +void NzSemaphoreImpl::Post() +{ + #if NAZARA_CORE_SAFE + if (sem_post(&m_semaphore)==-1) + NazaraError("Failed to release semaphore: " + NzGetLastSystemError()); + #else + sem_post(&m_semaphore); + #endif +} + +void NzSemaphoreImpl::Wait() +{ + #if NAZARA_CORE_SAFE + if (sem_wait(&m_semaphore) == -1 ) + NazaraError("Failed to wait for semaphore: " + NzGetLastSystemError()); + #else + sem_wait(&m_semaphore); + #endif +} + +bool NzSemaphoreImpl::Wait(nzUInt32 timeout) +{ + timespec ti; + ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000; + ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000); + ti.tv_nsec %= 1000000000; + + #if NAZARA_CORE_SAFE + if (sem_timedwait(m_semaphore, timeout) == -1) + { + NazaraError("Failed to wait for semaphore: " + NzGetLastSystemError()); + return false; + } + + return true; + #else + return sem_timedwait(&m_semaphore, ti) == 0 && errno != ETIMEDOUT; + #endif +} diff --git a/src/Nazara/Core/Posix/SemaphoreImpl.hpp b/src/Nazara/Core/Posix/SemaphoreImpl.hpp new file mode 100644 index 000000000..f5b6a3342 --- /dev/null +++ b/src/Nazara/Core/Posix/SemaphoreImpl.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SEMAPHOREIMPL_HPP +#define NAZARA_SEMAPHOREIMPL_HPP + +#include +#include + +class NzSemaphoreImpl +{ + public: + NzSemaphoreImpl(unsigned int count); + ~NzSemaphoreImpl(); + + unsigned int GetCount() const; + void Post(); + void Wait(); + bool Wait(nzUInt32 timeout); + + private: + sem_t m_semaphore; +}; + +#endif // NAZARA_SEMAPHOREIMPL_HPP diff --git a/src/Nazara/Core/Posix/ThreadImpl.cpp b/src/Nazara/Core/Posix/ThreadImpl.cpp new file mode 100644 index 000000000..fd0e0d2af --- /dev/null +++ b/src/Nazara/Core/Posix/ThreadImpl.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2012 Alexandre Janniaux +// 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 + +NzThreadImpl::NzThreadImpl(NzFunctor* functor) +{ + int error = pthread_create(&m_handle, nullptr, &NzThreadImpl::ThreadProc, functor); + if (error != 0) + NazaraInternalError("Failed to create thread: " + NzGetLastSystemError()); +} + +void NzThreadImpl::Detach() +{ + pthread_detach(m_handle); +} + +void NzThreadImpl::Join() +{ + pthread_join(m_handle, nullptr); +} + +unsigned int NzThreadImpl::ThreadProc(void* userdata) +{ + NzFunctor* func = static_cast(userdata); + func->Run(); + delete func; + + return 0; +} + +void NzThreadImpl::Sleep(nzUInt32 time) +{ + // code from SFML2 Unix SleepImpl.cpp source https://github.com/LaurentGomila/SFML/blob/master/src/SFML/System/Unix/SleepImpl.cpp + + // usleep is not reliable enough (it might block the + // whole process instead of just the current thread) + // so we must use pthread_cond_timedwait instead + + // this implementation is inspired from Qt + + // get the current time + timeval tv; + gettimeofday(&tv, NULL); + + // construct the time limit (current time + time to wait) + timespec ti; + ti.tv_nsec = (tv.tv_usec + (time % 1000)) * 1000; + ti.tv_sec = tv.tv_sec + (time / 1000) + (ti.tv_nsec / 1000000000); + ti.tv_nsec %= 1000000000; + + // create a mutex and thread condition + pthread_mutex_t mutex; + pthread_mutex_init(&mutex, 0); + pthread_cond_t condition; + pthread_cond_init(&condition, 0); + + // wait... + pthread_mutex_lock(&mutex); + pthread_cond_timedwait(&condition, &mutex, &ti); + pthread_mutex_unlock(&mutex); + + // destroy the mutex and condition + pthread_cond_destroy(&condition); + pthread_mutex_destroy(&mutex); +} diff --git a/src/Nazara/Core/Posix/ThreadImpl.hpp b/src/Nazara/Core/Posix/ThreadImpl.hpp new file mode 100644 index 000000000..2a57d021e --- /dev/null +++ b/src/Nazara/Core/Posix/ThreadImpl.hpp @@ -0,0 +1,31 @@ +// Copyright (C) 2012 Alexandre Janniaux +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_THREADIMPL_HPP +#define NAZARA_THREADIMPL_HPP + +#include +#include + +struct NzFunctor; + +class NzThreadImpl +{ + public: + NzThreadImpl(NzFunctor* threadFunc); + + void Detach(); + void Join(); + + static void Sleep(nzUInt32 time); + + private: + static unsigned int ThreadProc(void* userdata); + + pthread_t m_handle; +}; + +#endif // NAZARA_THREADIMPL_HPP