Switch from Nz prefix to namespace Nz for linux
Former-commit-id: 64eeaf3c633254b04910ebd4576fd9e910002be0
This commit is contained in:
@@ -8,21 +8,24 @@
|
||||
#include <sys/time.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
bool NzClockImplInitializeHighPrecision()
|
||||
namespace Nz
|
||||
{
|
||||
return true; // No initialization needed
|
||||
}
|
||||
bool ClockImplInitializeHighPrecision()
|
||||
{
|
||||
return true; // No initialization needed
|
||||
}
|
||||
|
||||
nzUInt64 NzClockImplGetMicroseconds()
|
||||
{
|
||||
timeval clock;
|
||||
gettimeofday(&clock, nullptr);
|
||||
return static_cast<nzUInt64>(clock.tv_sec*1000000 + clock.tv_usec);
|
||||
}
|
||||
UInt64 ClockImplGetElapsedMicroseconds()
|
||||
{
|
||||
timeval clock;
|
||||
gettimeofday(&clock, nullptr);
|
||||
return static_cast<UInt64>(clock.tv_sec*1000000 + clock.tv_usec);
|
||||
}
|
||||
|
||||
nzUInt64 NzClockImplGetMilliseconds()
|
||||
{
|
||||
timeval clock;
|
||||
gettimeofday(&clock, nullptr);
|
||||
return static_cast<nzUInt64>(clock.tv_sec*1000 + (clock.tv_usec/1000));
|
||||
UInt64 ClockImplGetElapsedMilliseconds()
|
||||
{
|
||||
timeval clock;
|
||||
gettimeofday(&clock, nullptr);
|
||||
return static_cast<UInt64>(clock.tv_sec*1000 + (clock.tv_usec/1000));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
|
||||
bool NzClockImplInitializeHighPrecision();
|
||||
nzUInt64 NzClockImplGetMicroseconds();
|
||||
nzUInt64 NzClockImplGetMilliseconds();
|
||||
namespace Nz
|
||||
{
|
||||
bool ClockImplInitializeHighPrecision();
|
||||
UInt64 ClockImplGetElapsedMicroseconds();
|
||||
UInt64 ClockImplGetElapsedMilliseconds();
|
||||
}
|
||||
|
||||
#endif // NAZARA_CLOCKIMPL_POSIX_HPP
|
||||
|
||||
@@ -6,42 +6,45 @@
|
||||
#include <Nazara/Core/Posix/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzConditionVariableImpl::NzConditionVariableImpl()
|
||||
namespace Nz
|
||||
{
|
||||
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->m_handle);
|
||||
}
|
||||
|
||||
bool NzConditionVariableImpl::Wait(NzMutexImpl* mutex, nzUInt32 timeout)
|
||||
{
|
||||
// get the current time
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
// 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;
|
||||
|
||||
return pthread_cond_timedwait(&m_cv,&mutex->m_handle, &ti) != 0;
|
||||
ConditionVariableImpl::ConditionVariableImpl()
|
||||
{
|
||||
pthread_cond_init(&m_cv, nullptr);
|
||||
}
|
||||
|
||||
ConditionVariableImpl::~ConditionVariableImpl()
|
||||
{
|
||||
pthread_cond_destroy(&m_cv);
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::Signal()
|
||||
{
|
||||
pthread_cond_signal(&m_cv);
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::SignalAll()
|
||||
{
|
||||
pthread_cond_broadcast(&m_cv);
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::Wait(MutexImpl* mutex)
|
||||
{
|
||||
pthread_cond_wait(&m_cv, &mutex->m_handle);
|
||||
}
|
||||
|
||||
bool ConditionVariableImpl::Wait(MutexImpl* mutex, UInt32 timeout)
|
||||
{
|
||||
// get the current time
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
// 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;
|
||||
|
||||
return pthread_cond_timedwait(&m_cv,&mutex->m_handle, &ti) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,22 +14,25 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
class NzMutexImpl;
|
||||
|
||||
class NzConditionVariableImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzConditionVariableImpl();
|
||||
~NzConditionVariableImpl();
|
||||
class MutexImpl;
|
||||
|
||||
void Signal();
|
||||
void SignalAll();
|
||||
class ConditionVariableImpl
|
||||
{
|
||||
public:
|
||||
ConditionVariableImpl();
|
||||
~ConditionVariableImpl();
|
||||
|
||||
void Wait(NzMutexImpl* mutex);
|
||||
bool Wait(NzMutexImpl* mutex, nzUInt32 timeout);
|
||||
void Signal();
|
||||
void SignalAll();
|
||||
|
||||
private:
|
||||
pthread_cond_t m_cv;
|
||||
};
|
||||
void Wait(MutexImpl* mutex);
|
||||
bool Wait(MutexImpl* mutex, UInt32 timeout);
|
||||
|
||||
private:
|
||||
pthread_cond_t m_cv;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||
|
||||
@@ -9,95 +9,98 @@
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
NzDirectoryImpl::NzDirectoryImpl(const NzDirectory* parent)
|
||||
namespace Nz
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
DirectoryImpl::DirectoryImpl(const Directory* parent)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
void NzDirectoryImpl::Close()
|
||||
{
|
||||
closedir(m_handle);
|
||||
}
|
||||
void DirectoryImpl::Close()
|
||||
{
|
||||
closedir(m_handle);
|
||||
}
|
||||
|
||||
NzString NzDirectoryImpl::GetResultName() const
|
||||
{
|
||||
return m_result->d_name;
|
||||
}
|
||||
String DirectoryImpl::GetResultName() const
|
||||
{
|
||||
return m_result->d_name;
|
||||
}
|
||||
|
||||
nzUInt64 NzDirectoryImpl::GetResultSize() const
|
||||
{
|
||||
struct stat64 resulststat;
|
||||
stat64(m_result->d_name, &resulststat);
|
||||
UInt64 DirectoryImpl::GetResultSize() const
|
||||
{
|
||||
struct stat64 resulststat;
|
||||
stat64(m_result->d_name, &resulststat);
|
||||
|
||||
return static_cast<nzUInt64>(resulststat.st_size);
|
||||
}
|
||||
return static_cast<UInt64>(resulststat.st_size);
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::IsResultDirectory() const
|
||||
{
|
||||
struct stat64 filestats;
|
||||
if (stat64(m_result->d_name, &filestats) == -1) // error
|
||||
return false;
|
||||
bool DirectoryImpl::IsResultDirectory() const
|
||||
{
|
||||
struct stat64 filestats;
|
||||
if (stat64(m_result->d_name, &filestats) == -1) // error
|
||||
return false;
|
||||
|
||||
return S_ISDIR(filestats.st_mode);
|
||||
}
|
||||
return S_ISDIR(filestats.st_mode);
|
||||
}
|
||||
|
||||
bool DirectoryImpl::NextResult()
|
||||
{
|
||||
if ((m_result = readdir64(m_handle)))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
NazaraError("Unable to get next result: " + Error::GetLastSystemError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Open(const String& dirPath)
|
||||
{
|
||||
m_handle = opendir(dirPath.GetConstBuffer());
|
||||
if (!m_handle)
|
||||
{
|
||||
NazaraError("Unable to open directory: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::NextResult()
|
||||
{
|
||||
if ((m_result = readdir64(m_handle)))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
NazaraError("Unable to get next result: " + NzError::GetLastSystemError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Open(const NzString& dirPath)
|
||||
{
|
||||
m_handle = opendir(dirPath.GetConstBuffer());
|
||||
if (!m_handle)
|
||||
{
|
||||
NazaraError("Unable to open directory: " + NzError::GetLastSystemError());
|
||||
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)
|
||||
{
|
||||
struct stat64 filestats;
|
||||
if (stat64(dirPath.GetConstBuffer(), &filestats) == -1) // error
|
||||
return false;
|
||||
|
||||
return S_ISDIR(filestats.st_mode) || S_ISREG(filestats.st_mode);
|
||||
}
|
||||
|
||||
NzString NzDirectoryImpl::GetCurrent()
|
||||
{
|
||||
NzString currentPath;
|
||||
|
||||
char path[MAXPATHLEN];
|
||||
if (getcwd(path, MAXPATHLEN))
|
||||
currentPath = path;
|
||||
else
|
||||
NazaraError("Unable to get current directory: " + NzError::GetLastSystemError()); // Bug: initialisation -> if no path for log !
|
||||
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Remove(const NzString& dirPath)
|
||||
{
|
||||
bool success = rmdir(dirPath.GetConstBuffer()) != -1;
|
||||
|
||||
return success;
|
||||
bool DirectoryImpl::Create(const String& dirPath)
|
||||
{
|
||||
mode_t permissions; // TODO: check permissions
|
||||
|
||||
return mkdir(dirPath.GetConstBuffer(), permissions) != -1;;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Exists(const String& dirPath)
|
||||
{
|
||||
struct stat64 filestats;
|
||||
if (stat64(dirPath.GetConstBuffer(), &filestats) == -1) // error
|
||||
return false;
|
||||
|
||||
return S_ISDIR(filestats.st_mode) || S_ISREG(filestats.st_mode);
|
||||
}
|
||||
|
||||
String DirectoryImpl::GetCurrent()
|
||||
{
|
||||
String currentPath;
|
||||
|
||||
char path[MAXPATHLEN];
|
||||
if (getcwd(path, MAXPATHLEN))
|
||||
currentPath = path;
|
||||
else
|
||||
NazaraError("Unable to get current directory: " + Error::GetLastSystemError()); // Bug: initialisation -> if no path for log !
|
||||
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Remove(const String& dirPath)
|
||||
{
|
||||
bool success = rmdir(dirPath.GetConstBuffer()) != -1;
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,40 +8,47 @@
|
||||
#define NAZARA_DIRECTORYIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/NonCopyable.hpp>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
class NzDirectory;
|
||||
class NzString;
|
||||
|
||||
class NzDirectoryImpl : NzNonCopyable
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzDirectoryImpl(const NzDirectory* parent);
|
||||
~NzDirectoryImpl() = default;
|
||||
class Directory;
|
||||
class String;
|
||||
|
||||
void Close();
|
||||
class DirectoryImpl
|
||||
{
|
||||
public:
|
||||
DirectoryImpl(const Directory* parent);
|
||||
DirectoryImpl(const DirectoryImpl&) = delete;
|
||||
DirectoryImpl(DirectoryImpl&&) = delete; ///TODO
|
||||
~DirectoryImpl() = default;
|
||||
|
||||
NzString GetResultName() const;
|
||||
nzUInt64 GetResultSize() const;
|
||||
void Close();
|
||||
|
||||
bool IsResultDirectory() const;
|
||||
String GetResultName() const;
|
||||
UInt64 GetResultSize() const;
|
||||
|
||||
bool NextResult();
|
||||
bool IsResultDirectory() const;
|
||||
|
||||
bool Open(const NzString& dirPath);
|
||||
bool NextResult();
|
||||
|
||||
static bool Create(const NzString& dirPath);
|
||||
static bool Exists(const NzString& dirPath);
|
||||
static NzString GetCurrent();
|
||||
static bool Remove(const NzString& dirPath);
|
||||
bool Open(const String& dirPath);
|
||||
|
||||
private:
|
||||
DIR* m_handle;
|
||||
dirent64* m_result;
|
||||
};
|
||||
DirectoryImpl& operator=(const DirectoryImpl&) = delete;
|
||||
DirectoryImpl& operator=(DirectoryImpl&&) = delete; ///TODO
|
||||
|
||||
static bool Create(const String& dirPath);
|
||||
static bool Exists(const String& dirPath);
|
||||
static String GetCurrent();
|
||||
static bool Remove(const String& dirPath);
|
||||
|
||||
private:
|
||||
DIR* m_handle;
|
||||
dirent64* m_result;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_DIRECTORYIMPL_HPP
|
||||
|
||||
@@ -8,55 +8,58 @@
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzDynLibImpl::NzDynLibImpl(NzDynLib* parent)
|
||||
namespace Nz
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
NzDynLibFunc NzDynLibImpl::GetSymbol(const NzString& symbol, NzString* errorMessage) 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
|
||||
DynLibImpl::DynLibImpl(DynLib* parent)
|
||||
{
|
||||
NzDynLibFunc func;
|
||||
void* pointer;
|
||||
} converter;
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
dlerror(); // Clear error flag
|
||||
|
||||
converter.pointer = dlsym(m_handle, symbol.GetConstBuffer());
|
||||
if (!converter.pointer)
|
||||
*errorMessage = dlerror();
|
||||
|
||||
return converter.func;
|
||||
}
|
||||
|
||||
bool NzDynLibImpl::Load(const NzString& libraryPath, NzString* errorMessage)
|
||||
{
|
||||
NzString path = libraryPath;
|
||||
|
||||
unsigned int pos = path.FindLast(".so");
|
||||
if (pos == NzString::npos || (path.GetLength() > pos+3 && path[pos+3] != '.'))
|
||||
path += ".so";
|
||||
|
||||
dlerror(); // Clear error flag
|
||||
m_handle = dlopen(path.GetConstBuffer(), RTLD_LAZY | RTLD_GLOBAL);
|
||||
|
||||
if (m_handle)
|
||||
return true;
|
||||
else
|
||||
DynLibFunc DynLibImpl::GetSymbol(const String& symbol, String* errorMessage) const
|
||||
{
|
||||
*errorMessage = dlerror();
|
||||
return false;
|
||||
/*
|
||||
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
|
||||
{
|
||||
DynLibFunc func;
|
||||
void* pointer;
|
||||
} converter;
|
||||
|
||||
dlerror(); // Clear error flag
|
||||
|
||||
converter.pointer = dlsym(m_handle, symbol.GetConstBuffer());
|
||||
if (!converter.pointer)
|
||||
*errorMessage = dlerror();
|
||||
|
||||
return converter.func;
|
||||
}
|
||||
|
||||
bool DynLibImpl::Load(const String& libraryPath, String* errorMessage)
|
||||
{
|
||||
String path = libraryPath;
|
||||
|
||||
unsigned int pos = path.FindLast(".so");
|
||||
if (pos == String::npos || (path.GetLength() > pos+3 && path[pos+3] != '.'))
|
||||
path += ".so";
|
||||
|
||||
dlerror(); // Clear error flag
|
||||
m_handle = dlopen(path.GetConstBuffer(), RTLD_LAZY | RTLD_GLOBAL);
|
||||
|
||||
if (m_handle)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
*errorMessage = dlerror();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DynLibImpl::Unload()
|
||||
{
|
||||
dlclose(m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
void NzDynLibImpl::Unload()
|
||||
{
|
||||
dlclose(m_handle);
|
||||
}
|
||||
|
||||
@@ -8,23 +8,25 @@
|
||||
#define NAZARA_DYNLIBIMPL_HPP
|
||||
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <Nazara/Core/NonCopyable.hpp>
|
||||
#include <dlfcn.h>
|
||||
|
||||
class NzString;
|
||||
|
||||
class NzDynLibImpl : NzNonCopyable
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzDynLibImpl(NzDynLib* m_parent);
|
||||
~NzDynLibImpl() = default;
|
||||
class String;
|
||||
|
||||
NzDynLibFunc GetSymbol(const NzString& symbol, NzString* errorMessage) const;
|
||||
bool Load(const NzString& libraryPath, NzString* errorMessage);
|
||||
void Unload();
|
||||
class DynLibImpl
|
||||
{
|
||||
public:
|
||||
DynLibImpl(DynLib* m_parent);
|
||||
~DynLibImpl() = default;
|
||||
|
||||
private:
|
||||
void* m_handle;
|
||||
};
|
||||
DynLibFunc GetSymbol(const String& symbol, String* errorMessage) const;
|
||||
bool Load(const String& libraryPath, String* errorMessage);
|
||||
void Unload();
|
||||
|
||||
private:
|
||||
void* m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_DYNLIBIMPL_HPP
|
||||
|
||||
@@ -7,236 +7,239 @@
|
||||
#include <cstdio>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzFileImpl::NzFileImpl(const NzFile* parent) :
|
||||
m_endOfFile(false),
|
||||
m_endOfFileUpdated(true)
|
||||
namespace Nz
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
void NzFileImpl::Close()
|
||||
{
|
||||
close(m_fileDescriptor);
|
||||
}
|
||||
|
||||
bool NzFileImpl::EndOfFile() const
|
||||
{
|
||||
if (!m_endOfFileUpdated)
|
||||
FileImpl::FileImpl(const File* parent) :
|
||||
m_endOfFile(false),
|
||||
m_endOfFileUpdated(true)
|
||||
{
|
||||
struct stat64 fileSize;
|
||||
if (fstat64(m_fileDescriptor, &fileSize) == -1)
|
||||
fileSize.st_size = 0;
|
||||
|
||||
m_endOfFile = (GetCursorPos() >= static_cast<nzUInt64>(fileSize.st_size));
|
||||
m_endOfFileUpdated = true;
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
return m_endOfFile;
|
||||
}
|
||||
|
||||
void NzFileImpl::Flush()
|
||||
{
|
||||
if (fsync(m_fileDescriptor) == -1)
|
||||
NazaraError("Unable to flush file: " + NzError::GetLastSystemError());
|
||||
}
|
||||
|
||||
nzUInt64 NzFileImpl::GetCursorPos() const
|
||||
{
|
||||
off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR);
|
||||
return static_cast<nzUInt64>(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 & nzOpenMode_ReadOnly)
|
||||
flags = O_RDONLY;
|
||||
else if (mode & nzOpenMode_ReadWrite)
|
||||
void FileImpl::Close()
|
||||
{
|
||||
flags = O_CREAT | O_RDWR;
|
||||
|
||||
if (mode & nzOpenMode_Append)
|
||||
flags |= O_APPEND;
|
||||
|
||||
if (mode & nzOpenMode_Truncate)
|
||||
flags |= O_TRUNC;
|
||||
}
|
||||
else if (mode & nzOpenMode_WriteOnly)
|
||||
{
|
||||
flags = O_CREAT | O_WRONLY;
|
||||
|
||||
if (mode & nzOpenMode_Append)
|
||||
flags |= O_APPEND;
|
||||
|
||||
if (mode & nzOpenMode_Truncate)
|
||||
flags |= O_TRUNC;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
///TODO: lock
|
||||
// if ((mode & nzOpenMode_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<std::size_t>(bytes) != size);
|
||||
m_endOfFileUpdated = true;
|
||||
|
||||
return static_cast<std::size_t>(bytes);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NzFileImpl::SetCursorPos(nzCursorPosition pos, nzInt64 offset)
|
||||
{
|
||||
int moveMethod;
|
||||
switch (pos)
|
||||
{
|
||||
case nzCursorPosition_AtBegin:
|
||||
moveMethod = SEEK_SET;
|
||||
break;
|
||||
|
||||
case nzCursorPosition_AtCurrent:
|
||||
moveMethod = SEEK_CUR;
|
||||
break;
|
||||
|
||||
case nzCursorPosition_AtEnd:
|
||||
moveMethod = SEEK_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraInternalError("Cursor position not handled (0x" + NzString::Number(pos, 16) + ')');
|
||||
return false;
|
||||
close(m_fileDescriptor);
|
||||
}
|
||||
|
||||
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)
|
||||
bool FileImpl::EndOfFile() const
|
||||
{
|
||||
NazaraError("Fail to open input file (" + sourcePath + "): " + NzError::GetLastSystemError());
|
||||
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 + "): " + NzError::GetLastSystemError()); // TODO: more info ?
|
||||
close(fd1);
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
ssize_t bytes;
|
||||
do
|
||||
{
|
||||
bytes = read(fd1,buffer,512);
|
||||
if (bytes == -1)
|
||||
if (!m_endOfFileUpdated)
|
||||
{
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
NazaraError("An error occured from copy : " + NzError::GetLastSystemError());
|
||||
struct stat64 fileSize;
|
||||
if (fstat64(m_fileDescriptor, &fileSize) == -1)
|
||||
fileSize.st_size = 0;
|
||||
|
||||
m_endOfFile = (GetCursorPos() >= static_cast<UInt64>(fileSize.st_size));
|
||||
m_endOfFileUpdated = true;
|
||||
}
|
||||
|
||||
return m_endOfFile;
|
||||
}
|
||||
|
||||
void FileImpl::Flush()
|
||||
{
|
||||
if (fsync(m_fileDescriptor) == -1)
|
||||
NazaraError("Unable to flush file: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
UInt64 FileImpl::GetCursorPos() const
|
||||
{
|
||||
off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR);
|
||||
return static_cast<UInt64>(position);
|
||||
}
|
||||
|
||||
bool FileImpl::Open(const String& filePath, unsigned int mode)
|
||||
{
|
||||
int flags;
|
||||
mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
if (mode & OpenMode_ReadOnly)
|
||||
flags = O_RDONLY;
|
||||
else if (mode & OpenMode_ReadWrite)
|
||||
{
|
||||
flags = O_CREAT | O_RDWR;
|
||||
|
||||
if (mode & OpenMode_Append)
|
||||
flags |= O_APPEND;
|
||||
|
||||
if (mode & OpenMode_Truncate)
|
||||
flags |= O_TRUNC;
|
||||
}
|
||||
else if (mode & OpenMode_WriteOnly)
|
||||
{
|
||||
flags = O_CREAT | O_WRONLY;
|
||||
|
||||
if (mode & OpenMode_Append)
|
||||
flags |= O_APPEND;
|
||||
|
||||
if (mode & OpenMode_Truncate)
|
||||
flags |= O_TRUNC;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
///TODO: lock
|
||||
// if ((mode & OpenMode_Lock) == 0)
|
||||
// shareMode |= FILE_SHARE_WRITE;
|
||||
|
||||
m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
|
||||
return m_fileDescriptor != -1;
|
||||
}
|
||||
|
||||
std::size_t FileImpl::Read(void* buffer, std::size_t size)
|
||||
{
|
||||
ssize_t bytes;
|
||||
if ((bytes = read(m_fileDescriptor, buffer, size)) != -1)
|
||||
{
|
||||
m_endOfFile = (static_cast<std::size_t>(bytes) != size);
|
||||
m_endOfFileUpdated = true;
|
||||
|
||||
return static_cast<std::size_t>(bytes);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FileImpl::SetCursorPos(CursorPosition pos, Int64 offset)
|
||||
{
|
||||
int moveMethod;
|
||||
switch (pos)
|
||||
{
|
||||
case CursorPosition_AtBegin:
|
||||
moveMethod = SEEK_SET;
|
||||
break;
|
||||
|
||||
case CursorPosition_AtCurrent:
|
||||
moveMethod = SEEK_CUR;
|
||||
break;
|
||||
|
||||
case CursorPosition_AtEnd:
|
||||
moveMethod = SEEK_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraInternalError("Cursor position not handled (0x" + String::Number(pos, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
m_endOfFileUpdated = false;
|
||||
|
||||
return lseek64(m_fileDescriptor, offset, moveMethod) != -1;
|
||||
}
|
||||
|
||||
std::size_t FileImpl::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 FileImpl::Copy(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
|
||||
if (fd1 == -1)
|
||||
{
|
||||
NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
write(fd2,buffer,bytes);
|
||||
}
|
||||
while (bytes == 512);
|
||||
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
return true;
|
||||
}
|
||||
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 + "): " + Error::GetLastSystemError()); // TODO: more info ?
|
||||
close(fd1);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzFileImpl::Delete(const NzString& filePath)
|
||||
{
|
||||
bool success = unlink(filePath.GetConstBuffer()) != -1;
|
||||
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 : " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
write(fd2,buffer,bytes);
|
||||
}
|
||||
while (bytes == 512);
|
||||
|
||||
if (success)
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
return true;
|
||||
else
|
||||
}
|
||||
|
||||
bool FileImpl::Delete(const String& filePath)
|
||||
{
|
||||
NazaraError("Failed to delete file (" + filePath + "): " + NzError::GetLastSystemError());
|
||||
bool success = unlink(filePath.GetConstBuffer()) != -1;
|
||||
|
||||
if (success)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileImpl::Exists(const String& filePath)
|
||||
{
|
||||
const char* path = filePath.GetConstBuffer();
|
||||
if (access(path, F_OK) != -1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzFileImpl::Exists(const NzString& filePath)
|
||||
{
|
||||
const 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<nzUInt64>(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
|
||||
time_t FileImpl::GetCreationTime(const String& filePath)
|
||||
{
|
||||
NazaraError("Unable to rename file: " + NzError::GetLastSystemError());
|
||||
return false;
|
||||
NazaraWarning("Posix has no creation time information");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t FileImpl::GetLastAccessTime(const String& filePath)
|
||||
{
|
||||
struct stat64 stats;
|
||||
stat64(filePath.GetConstBuffer(), &stats);
|
||||
|
||||
return stats.st_atime;
|
||||
}
|
||||
|
||||
time_t FileImpl::GetLastWriteTime(const String& filePath)
|
||||
{
|
||||
struct stat64 stats;
|
||||
stat64(filePath.GetConstBuffer(), &stats);
|
||||
|
||||
return stats.st_mtime;
|
||||
}
|
||||
|
||||
UInt64 FileImpl::GetSize(const String& filePath)
|
||||
{
|
||||
struct stat64 stats;
|
||||
stat64(filePath.GetConstBuffer(), &stats);
|
||||
|
||||
return static_cast<UInt64>(stats.st_size);
|
||||
}
|
||||
|
||||
bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;
|
||||
|
||||
if (success)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Unable to rename file: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,44 +13,51 @@
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/NonCopyable.hpp>
|
||||
#include <ctime>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class NzFile;
|
||||
class NzString;
|
||||
|
||||
class NzFileImpl : NzNonCopyable
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzFileImpl(const NzFile* parent);
|
||||
~NzFileImpl() = default;
|
||||
class File;
|
||||
class String;
|
||||
|
||||
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(nzCursorPosition pos, nzInt64 offset);
|
||||
std::size_t Write(const void* buffer, std::size_t size);
|
||||
class FileImpl
|
||||
{
|
||||
public:
|
||||
FileImpl(const File* parent);
|
||||
FileImpl(const FileImpl&) = delete;
|
||||
FileImpl(FileImpl&&) = delete; ///TODO
|
||||
~FileImpl() = default;
|
||||
|
||||
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);
|
||||
void Close();
|
||||
bool EndOfFile() const;
|
||||
void Flush();
|
||||
UInt64 GetCursorPos() const;
|
||||
bool Open(const String& filePath, unsigned int mode);
|
||||
std::size_t Read(void* buffer, std::size_t size);
|
||||
bool SetCursorPos(CursorPosition pos, Int64 offset);
|
||||
std::size_t Write(const void* buffer, std::size_t size);
|
||||
|
||||
private:
|
||||
int m_fileDescriptor;
|
||||
mutable bool m_endOfFile;
|
||||
mutable bool m_endOfFileUpdated;
|
||||
};
|
||||
FileImpl& operator=(const FileImpl&) = delete;
|
||||
FileImpl& operator=(FileImpl&&) = delete; ///TODO
|
||||
|
||||
static bool Copy(const String& sourcePath, const String& targetPath);
|
||||
static bool Delete(const String& filePath);
|
||||
static bool Exists(const String& filePath);
|
||||
static time_t GetCreationTime(const String& filePath);
|
||||
static time_t GetLastAccessTime(const String& filePath);
|
||||
static time_t GetLastWriteTime(const String& filePath);
|
||||
static UInt64 GetSize(const String& filePath);
|
||||
static bool Rename(const String& sourcePath, const String& targetPath);
|
||||
|
||||
private:
|
||||
int m_fileDescriptor;
|
||||
mutable bool m_endOfFile;
|
||||
mutable bool m_endOfFileUpdated;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_FILEIMPL_HPP
|
||||
|
||||
@@ -6,58 +6,61 @@
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
void NzHardwareInfoImpl::Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4])
|
||||
namespace Nz
|
||||
{
|
||||
#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" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
|
||||
: "a" (functionId), "c" (subFunctionId)); // 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);
|
||||
}
|
||||
|
||||
nzUInt64 NzHardwareInfoImpl::GetTotalMemory()
|
||||
{
|
||||
nzUInt64 pages = sysconf(_SC_PHYS_PAGES);
|
||||
nzUInt64 page_size = sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
return pages * page_size;
|
||||
}
|
||||
|
||||
bool NzHardwareInfoImpl::IsCpuidSupported()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_x64
|
||||
return true; // Toujours supporté sur un processeur 64 bits
|
||||
#else
|
||||
void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4])
|
||||
{
|
||||
#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;
|
||||
// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
|
||||
asm volatile ("cpuid" // Besoin d'être volatile ?
|
||||
: "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
|
||||
: "a" (functionId), "c" (subFunctionId)); // input
|
||||
#else
|
||||
return false;
|
||||
NazaraInternalError("Cpuid has been called although it is not supported");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int HardwareInfoImpl::GetProcessorCount()
|
||||
{
|
||||
// Plus simple (et plus portable) que de passer par le CPUID
|
||||
return sysconf(_SC_NPROCESSORS_CONF);
|
||||
}
|
||||
|
||||
UInt64 HardwareInfoImpl::GetTotalMemory()
|
||||
{
|
||||
UInt64 pages = sysconf(_SC_PHYS_PAGES);
|
||||
UInt64 page_size = sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
return pages * page_size;
|
||||
}
|
||||
|
||||
bool HardwareInfoImpl::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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,16 @@
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <unistd.h>
|
||||
|
||||
class NzHardwareInfoImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
static void Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4]);
|
||||
static unsigned int GetProcessorCount();
|
||||
static nzUInt64 GetTotalMemory();
|
||||
static bool IsCpuidSupported();
|
||||
};
|
||||
class HardwareInfoImpl
|
||||
{
|
||||
public:
|
||||
static void Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4]);
|
||||
static unsigned int GetProcessorCount();
|
||||
static UInt64 GetTotalMemory();
|
||||
static bool IsCpuidSupported();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_HARDWAREINFOIMPL_POSIX_HPP
|
||||
|
||||
@@ -5,31 +5,34 @@
|
||||
#include <Nazara/Core/Posix/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzMutexImpl::NzMutexImpl()
|
||||
namespace Nz
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
pthread_mutex_init(&m_handle, &attr);
|
||||
}
|
||||
pthread_mutex_init(&m_handle, &attr);
|
||||
}
|
||||
|
||||
NzMutexImpl::~NzMutexImpl()
|
||||
{
|
||||
pthread_mutex_destroy(&m_handle);
|
||||
}
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
pthread_mutex_destroy(&m_handle);
|
||||
}
|
||||
|
||||
void NzMutexImpl::Lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_handle);
|
||||
}
|
||||
void MutexImpl::Lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_handle);
|
||||
}
|
||||
|
||||
bool NzMutexImpl::TryLock()
|
||||
{
|
||||
return pthread_mutex_trylock(&m_handle) == 0;
|
||||
}
|
||||
bool MutexImpl::TryLock()
|
||||
{
|
||||
return pthread_mutex_trylock(&m_handle) == 0;
|
||||
}
|
||||
|
||||
void NzMutexImpl::Unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_handle);
|
||||
void MutexImpl::Unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,20 +9,23 @@
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class NzMutexImpl
|
||||
namespace Nz
|
||||
{
|
||||
friend class NzConditionVariableImpl;
|
||||
class MutexImpl
|
||||
{
|
||||
friend class ConditionVariableImpl;
|
||||
|
||||
public:
|
||||
NzMutexImpl();
|
||||
~NzMutexImpl();
|
||||
public:
|
||||
MutexImpl();
|
||||
~MutexImpl();
|
||||
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_handle;
|
||||
};
|
||||
private:
|
||||
pthread_mutex_t m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_MUTEXIMPL_HPP
|
||||
|
||||
@@ -9,63 +9,66 @@
|
||||
#include <sys/time.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzSemaphoreImpl::NzSemaphoreImpl(unsigned int count)
|
||||
namespace Nz
|
||||
{
|
||||
if(sem_init(&m_semaphore, 0, count) != 0)
|
||||
NazaraError("Failed to create semaphore: " + NzError::GetLastSystemError());
|
||||
}
|
||||
|
||||
NzSemaphoreImpl::~NzSemaphoreImpl()
|
||||
{
|
||||
sem_destroy(&m_semaphore);
|
||||
}
|
||||
|
||||
unsigned int NzSemaphoreImpl::GetCount() const
|
||||
{
|
||||
int count=0;
|
||||
sem_getvalue(const_cast<sem_t*>(&m_semaphore), &count);
|
||||
return static_cast<unsigned int>(count);
|
||||
}
|
||||
|
||||
void NzSemaphoreImpl::Post()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (sem_post(&m_semaphore)==-1)
|
||||
NazaraError("Failed to release semaphore: " + NzError::GetLastSystemError());
|
||||
#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: " + NzError::GetLastSystemError());
|
||||
#else
|
||||
sem_wait(&m_semaphore);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NzSemaphoreImpl::Wait(nzUInt32 timeout)
|
||||
{
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
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, &ti) != 0)
|
||||
SemaphoreImpl::SemaphoreImpl(unsigned int count)
|
||||
{
|
||||
NazaraError("Failed to wait for semaphore: " + NzError::GetLastSystemError());
|
||||
return false;
|
||||
if(sem_init(&m_semaphore, 0, count) != 0)
|
||||
NazaraError("Failed to create semaphore: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return sem_timedwait(&m_semaphore, &ti) != 0;
|
||||
#endif
|
||||
SemaphoreImpl::~SemaphoreImpl()
|
||||
{
|
||||
sem_destroy(&m_semaphore);
|
||||
}
|
||||
|
||||
unsigned int SemaphoreImpl::GetCount() const
|
||||
{
|
||||
int count=0;
|
||||
sem_getvalue(const_cast<sem_t*>(&m_semaphore), &count);
|
||||
return static_cast<unsigned int>(count);
|
||||
}
|
||||
|
||||
void SemaphoreImpl::Post()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (sem_post(&m_semaphore)==-1)
|
||||
NazaraError("Failed to release semaphore: " + Error::GetLastSystemError());
|
||||
#else
|
||||
sem_post(&m_semaphore);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SemaphoreImpl::Wait()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (sem_wait(&m_semaphore) == -1 )
|
||||
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||
#else
|
||||
sem_wait(&m_semaphore);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SemaphoreImpl::Wait(UInt32 timeout)
|
||||
{
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
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, &ti) != 0)
|
||||
{
|
||||
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return sem_timedwait(&m_semaphore, &ti) != 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,19 +10,22 @@
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <semaphore.h>
|
||||
|
||||
class NzSemaphoreImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzSemaphoreImpl(unsigned int count);
|
||||
~NzSemaphoreImpl();
|
||||
class SemaphoreImpl
|
||||
{
|
||||
public:
|
||||
SemaphoreImpl(unsigned int count);
|
||||
~SemaphoreImpl();
|
||||
|
||||
unsigned int GetCount() const;
|
||||
void Post();
|
||||
void Wait();
|
||||
bool Wait(nzUInt32 timeout);
|
||||
unsigned int GetCount() const;
|
||||
void Post();
|
||||
void Wait();
|
||||
bool Wait(UInt32 timeout);
|
||||
|
||||
private:
|
||||
sem_t m_semaphore;
|
||||
};
|
||||
private:
|
||||
sem_t m_semaphore;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_SEMAPHOREIMPL_HPP
|
||||
|
||||
@@ -7,186 +7,189 @@
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
bool NzTaskSchedulerImpl::Initialize(unsigned int workerCount)
|
||||
namespace Nz
|
||||
{
|
||||
if (IsInitialized())
|
||||
return true; // Déjà initialisé
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (workerCount == 0)
|
||||
bool TaskSchedulerImpl::Initialize(unsigned int workerCount)
|
||||
{
|
||||
NazaraError("Invalid worker count ! (0)");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (IsInitialized())
|
||||
return true; // Déjà initialisé
|
||||
|
||||
s_workerCount = workerCount;
|
||||
s_isDone = false;
|
||||
s_isWaiting = false;
|
||||
s_shouldFinish = false;
|
||||
|
||||
s_threads.reset(new pthread_t[workerCount]);
|
||||
|
||||
// On initialise les conditions variables, mutex et barrière.
|
||||
pthread_cond_init(&s_cvEmpty, nullptr);
|
||||
pthread_cond_init(&s_cvNotEmpty, nullptr);
|
||||
pthread_mutex_init(&s_mutexQueue, nullptr);
|
||||
pthread_barrier_init(&s_barrier, nullptr, workerCount + 1);
|
||||
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
// Le thread va se lancer, attendre que tous se créent et attendre d'être réveillé.
|
||||
pthread_create(&s_threads[i], nullptr, WorkerProc, nullptr);
|
||||
}
|
||||
|
||||
pthread_barrier_wait(&s_barrier); // On attend que les enfants soient bien créés.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzTaskSchedulerImpl::IsInitialized()
|
||||
{
|
||||
return s_workerCount > 0;
|
||||
}
|
||||
|
||||
void NzTaskSchedulerImpl::Run(NzFunctor** tasks, unsigned int count)
|
||||
{
|
||||
// On s'assure que des tâches ne sont pas déjà en cours
|
||||
Wait();
|
||||
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
s_isDone = false;
|
||||
|
||||
while (count--)
|
||||
s_tasks.push(*tasks++);
|
||||
|
||||
pthread_cond_signal(&s_cvNotEmpty);
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
}
|
||||
|
||||
void NzTaskSchedulerImpl::Uninitialize()
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (s_workerCount == 0)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// On réveille les threads pour qu'ils sortent de la boucle et terminent.
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
// On commence par vider la queue et demander qu'ils s'arrêtent.
|
||||
std::queue<NzFunctor*> emptyQueue;
|
||||
std::swap(s_tasks, emptyQueue);
|
||||
s_shouldFinish = true;
|
||||
pthread_cond_broadcast(&s_cvNotEmpty);
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
|
||||
// On attend que chaque thread se termine
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
pthread_join(s_threads[i], nullptr);
|
||||
|
||||
// Et on libère les ressources
|
||||
pthread_barrier_destroy(&s_barrier);
|
||||
pthread_cond_destroy(&s_cvEmpty);
|
||||
pthread_cond_destroy(&s_cvNotEmpty);
|
||||
pthread_mutex_destroy(&s_mutexQueue);
|
||||
|
||||
s_workerCount = 0;
|
||||
}
|
||||
|
||||
void NzTaskSchedulerImpl::WaitForTasks()
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (s_workerCount == 0)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Wait();
|
||||
}
|
||||
|
||||
NzFunctor* NzTaskSchedulerImpl::PopQueue()
|
||||
{
|
||||
NzFunctor* task = nullptr;
|
||||
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
|
||||
if (!s_tasks.empty())
|
||||
{
|
||||
task = s_tasks.front();
|
||||
s_tasks.pop();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
void NzTaskSchedulerImpl::Wait()
|
||||
{
|
||||
if (s_isDone)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
s_isWaiting = true;
|
||||
pthread_cond_broadcast(&s_cvNotEmpty);
|
||||
pthread_cond_wait(&s_cvEmpty, &s_mutexQueue);
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
|
||||
s_isDone = true;
|
||||
}
|
||||
|
||||
void* NzTaskSchedulerImpl::WorkerProc(void* /*userdata*/)
|
||||
{
|
||||
// On s'assure que tous les threads soient correctement lancés.
|
||||
pthread_barrier_wait(&s_barrier);
|
||||
|
||||
// On quitte s'il doit terminer.
|
||||
while (!s_shouldFinish)
|
||||
{
|
||||
NzFunctor* task = PopQueue();
|
||||
|
||||
if (task)
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (workerCount == 0)
|
||||
{
|
||||
// On exécute la tâche avant de la supprimer
|
||||
task->Run();
|
||||
delete task;
|
||||
NazaraError("Invalid worker count ! (0)");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
s_workerCount = workerCount;
|
||||
s_isDone = false;
|
||||
s_isWaiting = false;
|
||||
s_shouldFinish = false;
|
||||
|
||||
s_threads.reset(new pthread_t[workerCount]);
|
||||
|
||||
// On initialise les conditions variables, mutex et barrière.
|
||||
pthread_cond_init(&s_cvEmpty, nullptr);
|
||||
pthread_cond_init(&s_cvNotEmpty, nullptr);
|
||||
pthread_mutex_init(&s_mutexQueue, nullptr);
|
||||
pthread_barrier_init(&s_barrier, nullptr, workerCount + 1);
|
||||
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
if (s_tasks.empty())
|
||||
s_isDone = true;
|
||||
// Le thread va se lancer, attendre que tous se créent et attendre d'être réveillé.
|
||||
pthread_create(&s_threads[i], nullptr, WorkerProc, nullptr);
|
||||
}
|
||||
|
||||
while (!(!s_tasks.empty() || s_isWaiting || s_shouldFinish))
|
||||
pthread_cond_wait(&s_cvNotEmpty, &s_mutexQueue);
|
||||
pthread_barrier_wait(&s_barrier); // On attend que les enfants soient bien créés.
|
||||
|
||||
if (s_tasks.empty() && s_isWaiting)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TaskSchedulerImpl::IsInitialized()
|
||||
{
|
||||
return s_workerCount > 0;
|
||||
}
|
||||
|
||||
void TaskSchedulerImpl::Run(Functor** tasks, unsigned int count)
|
||||
{
|
||||
// On s'assure que des tâches ne sont pas déjà en cours
|
||||
Wait();
|
||||
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
s_isDone = false;
|
||||
|
||||
while (count--)
|
||||
s_tasks.push(*tasks++);
|
||||
|
||||
pthread_cond_signal(&s_cvNotEmpty);
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
}
|
||||
|
||||
void TaskSchedulerImpl::Uninitialize()
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (s_workerCount == 0)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// On réveille les threads pour qu'ils sortent de la boucle et terminent.
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
// On commence par vider la queue et demander qu'ils s'arrêtent.
|
||||
std::queue<Functor*> emptyQueue;
|
||||
std::swap(s_tasks, emptyQueue);
|
||||
s_shouldFinish = true;
|
||||
pthread_cond_broadcast(&s_cvNotEmpty);
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
|
||||
// On attend que chaque thread se termine
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
pthread_join(s_threads[i], nullptr);
|
||||
|
||||
// Et on libère les ressources
|
||||
pthread_barrier_destroy(&s_barrier);
|
||||
pthread_cond_destroy(&s_cvEmpty);
|
||||
pthread_cond_destroy(&s_cvNotEmpty);
|
||||
pthread_mutex_destroy(&s_mutexQueue);
|
||||
|
||||
s_workerCount = 0;
|
||||
}
|
||||
|
||||
void TaskSchedulerImpl::WaitForTasks()
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (s_workerCount == 0)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Wait();
|
||||
}
|
||||
|
||||
Functor* TaskSchedulerImpl::PopQueue()
|
||||
{
|
||||
Functor* task = nullptr;
|
||||
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
|
||||
if (!s_tasks.empty())
|
||||
{
|
||||
task = s_tasks.front();
|
||||
s_tasks.pop();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
void TaskSchedulerImpl::Wait()
|
||||
{
|
||||
if (s_isDone)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
s_isWaiting = true;
|
||||
pthread_cond_broadcast(&s_cvNotEmpty);
|
||||
pthread_cond_wait(&s_cvEmpty, &s_mutexQueue);
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
|
||||
s_isDone = true;
|
||||
}
|
||||
|
||||
void* TaskSchedulerImpl::WorkerProc(void* /*userdata*/)
|
||||
{
|
||||
// On s'assure que tous les threads soient correctement lancés.
|
||||
pthread_barrier_wait(&s_barrier);
|
||||
|
||||
// On quitte s'il doit terminer.
|
||||
while (!s_shouldFinish)
|
||||
{
|
||||
Functor* task = PopQueue();
|
||||
|
||||
if (task)
|
||||
{
|
||||
// On prévient le thread qui attend que les tâches soient effectuées.
|
||||
s_isWaiting = false;
|
||||
pthread_cond_signal(&s_cvEmpty);
|
||||
// On exécute la tâche avant de la supprimer
|
||||
task->Run();
|
||||
delete task;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_lock(&s_mutexQueue);
|
||||
if (s_tasks.empty())
|
||||
s_isDone = true;
|
||||
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
while (!(!s_tasks.empty() || s_isWaiting || s_shouldFinish))
|
||||
pthread_cond_wait(&s_cvNotEmpty, &s_mutexQueue);
|
||||
|
||||
if (s_tasks.empty() && s_isWaiting)
|
||||
{
|
||||
// On prévient le thread qui attend que les tâches soient effectuées.
|
||||
s_isWaiting = false;
|
||||
pthread_cond_signal(&s_cvEmpty);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s_mutexQueue);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
std::queue<Functor*> TaskSchedulerImpl::s_tasks;
|
||||
std::unique_ptr<pthread_t[]> TaskSchedulerImpl::s_threads;
|
||||
std::atomic<bool> TaskSchedulerImpl::s_isDone;
|
||||
std::atomic<bool> TaskSchedulerImpl::s_isWaiting;
|
||||
std::atomic<bool> TaskSchedulerImpl::s_shouldFinish;
|
||||
unsigned int TaskSchedulerImpl::s_workerCount;
|
||||
|
||||
pthread_mutex_t TaskSchedulerImpl::s_mutexQueue;
|
||||
pthread_cond_t TaskSchedulerImpl::s_cvEmpty;
|
||||
pthread_cond_t TaskSchedulerImpl::s_cvNotEmpty;
|
||||
pthread_barrier_t TaskSchedulerImpl::s_barrier;
|
||||
}
|
||||
|
||||
std::queue<NzFunctor*> NzTaskSchedulerImpl::s_tasks;
|
||||
std::unique_ptr<pthread_t[]> NzTaskSchedulerImpl::s_threads;
|
||||
std::atomic<bool> NzTaskSchedulerImpl::s_isDone;
|
||||
std::atomic<bool> NzTaskSchedulerImpl::s_isWaiting;
|
||||
std::atomic<bool> NzTaskSchedulerImpl::s_shouldFinish;
|
||||
unsigned int NzTaskSchedulerImpl::s_workerCount;
|
||||
|
||||
pthread_mutex_t NzTaskSchedulerImpl::s_mutexQueue;
|
||||
pthread_cond_t NzTaskSchedulerImpl::s_cvEmpty;
|
||||
pthread_cond_t NzTaskSchedulerImpl::s_cvNotEmpty;
|
||||
pthread_barrier_t NzTaskSchedulerImpl::s_barrier;
|
||||
|
||||
@@ -14,34 +14,37 @@
|
||||
#include <pthread.h>
|
||||
#include <queue>
|
||||
|
||||
class NzTaskSchedulerImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzTaskSchedulerImpl() = delete;
|
||||
~NzTaskSchedulerImpl() = delete;
|
||||
class TaskSchedulerImpl
|
||||
{
|
||||
public:
|
||||
TaskSchedulerImpl() = delete;
|
||||
~TaskSchedulerImpl() = delete;
|
||||
|
||||
static bool Initialize(unsigned int workerCount);
|
||||
static bool IsInitialized();
|
||||
static void Run(NzFunctor** tasks, unsigned int count);
|
||||
static void Uninitialize();
|
||||
static void WaitForTasks();
|
||||
static bool Initialize(unsigned int workerCount);
|
||||
static bool IsInitialized();
|
||||
static void Run(Functor** tasks, unsigned int count);
|
||||
static void Uninitialize();
|
||||
static void WaitForTasks();
|
||||
|
||||
private:
|
||||
static NzFunctor* PopQueue();
|
||||
static void Wait();
|
||||
static void* WorkerProc(void* userdata);
|
||||
private:
|
||||
static Functor* PopQueue();
|
||||
static void Wait();
|
||||
static void* WorkerProc(void* userdata);
|
||||
|
||||
static std::queue<NzFunctor*> s_tasks;
|
||||
static std::unique_ptr<pthread_t[]> s_threads;
|
||||
static std::atomic<bool> s_isDone;
|
||||
static std::atomic<bool> s_isWaiting;
|
||||
static std::atomic<bool> s_shouldFinish;
|
||||
static unsigned int s_workerCount;
|
||||
static std::queue<Functor*> s_tasks;
|
||||
static std::unique_ptr<pthread_t[]> s_threads;
|
||||
static std::atomic<bool> s_isDone;
|
||||
static std::atomic<bool> s_isWaiting;
|
||||
static std::atomic<bool> s_shouldFinish;
|
||||
static unsigned int s_workerCount;
|
||||
|
||||
static pthread_mutex_t s_mutexQueue;
|
||||
static pthread_cond_t s_cvEmpty;
|
||||
static pthread_cond_t s_cvNotEmpty;
|
||||
static pthread_barrier_t s_barrier;
|
||||
};
|
||||
static pthread_mutex_t s_mutexQueue;
|
||||
static pthread_cond_t s_cvEmpty;
|
||||
static pthread_cond_t s_cvNotEmpty;
|
||||
static pthread_barrier_t s_barrier;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_TASKSCHEDULERIMPL_HPP
|
||||
|
||||
@@ -9,64 +9,67 @@
|
||||
#include <sys/time.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzThreadImpl::NzThreadImpl(NzFunctor* functor)
|
||||
namespace Nz
|
||||
{
|
||||
int error = pthread_create(&m_handle, nullptr, &NzThreadImpl::ThreadProc, functor);
|
||||
if (error != 0)
|
||||
NazaraInternalError("Failed to create thread: " + NzError::GetLastSystemError());
|
||||
}
|
||||
|
||||
void NzThreadImpl::Detach()
|
||||
{
|
||||
pthread_detach(m_handle);
|
||||
}
|
||||
|
||||
void NzThreadImpl::Join()
|
||||
{
|
||||
pthread_join(m_handle, nullptr);
|
||||
}
|
||||
|
||||
void* NzThreadImpl::ThreadProc(void* userdata)
|
||||
{
|
||||
NzFunctor* func = static_cast<NzFunctor*>(userdata);
|
||||
func->Run();
|
||||
delete func;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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, nullptr);
|
||||
|
||||
// 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, nullptr);
|
||||
pthread_cond_t condition;
|
||||
pthread_cond_init(&condition, nullptr);
|
||||
|
||||
// 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);
|
||||
ThreadImpl::ThreadImpl(Functor* functor)
|
||||
{
|
||||
int error = pthread_create(&m_handle, nullptr, &ThreadImpl::ThreadProc, functor);
|
||||
if (error != 0)
|
||||
NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
void ThreadImpl::Detach()
|
||||
{
|
||||
pthread_detach(m_handle);
|
||||
}
|
||||
|
||||
void ThreadImpl::Join()
|
||||
{
|
||||
pthread_join(m_handle, nullptr);
|
||||
}
|
||||
|
||||
void* ThreadImpl::ThreadProc(void* userdata)
|
||||
{
|
||||
Functor* func = static_cast<Functor*>(userdata);
|
||||
func->Run();
|
||||
delete func;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ThreadImpl::Sleep(UInt32 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, nullptr);
|
||||
|
||||
// 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, nullptr);
|
||||
pthread_cond_t condition;
|
||||
pthread_cond_init(&condition, nullptr);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,22 +10,25 @@
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
struct NzFunctor;
|
||||
|
||||
class NzThreadImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzThreadImpl(NzFunctor* threadFunc);
|
||||
struct Functor;
|
||||
|
||||
void Detach();
|
||||
void Join();
|
||||
class ThreadImpl
|
||||
{
|
||||
public:
|
||||
ThreadImpl(Functor* threadFunc);
|
||||
|
||||
static void Sleep(nzUInt32 time);
|
||||
void Detach();
|
||||
void Join();
|
||||
|
||||
private:
|
||||
static void* ThreadProc(void* userdata);
|
||||
static void Sleep(UInt32 time);
|
||||
|
||||
pthread_t m_handle;
|
||||
};
|
||||
private:
|
||||
static void* ThreadProc(void* userdata);
|
||||
|
||||
pthread_t m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_THREADIMPL_HPP
|
||||
|
||||
Reference in New Issue
Block a user