#include <efsw/platform/posix/SystemImpl.hpp>
|
|
#if defined( EFSW_PLATFORM_POSIX )
|
|
#include <cstdio>
|
#include <pthread.h>
|
#include <sys/time.h>
|
#include <limits.h>
|
#include <sys/resource.h>
|
|
#include <efsw/FileSystem.hpp>
|
#include <efsw/Debug.hpp>
|
|
#if EFSW_OS == EFSW_OS_MACOSX
|
#include <CoreFoundation/CoreFoundation.h>
|
#elif EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_ANDROID
|
#include <libgen.h>
|
#include <unistd.h>
|
#elif EFSW_OS == EFSW_OS_HAIKU
|
#include <kernel/OS.h>
|
#include <kernel/image.h>
|
#elif EFSW_OS == EFSW_OS_SOLARIS
|
#include <stdlib.h>
|
#elif EFSW_OS == EFSW_OS_BSD
|
#include <sys/sysctl.h>
|
#endif
|
|
namespace efsw { namespace Platform {
|
|
void System::sleep( const unsigned long& ms )
|
{
|
// usleep( static_cast<unsigned long>( ms * 1000 ) );
|
|
// 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
|
// and taken from SFML
|
|
unsigned long long usecs = ms * 1000;
|
|
// 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 + (usecs % 1000000)) * 1000;
|
ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (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);
|
}
|
|
std::string System::getProcessPath()
|
{
|
#if EFSW_OS == EFSW_OS_MACOSX
|
char exe_file[FILENAME_MAX + 1];
|
|
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
|
if (mainBundle)
|
{
|
CFURLRef mainURL = CFBundleCopyBundleURL(mainBundle);
|
|
if (mainURL)
|
{
|
int ok = CFURLGetFileSystemRepresentation ( mainURL, (Boolean) true, (UInt8*)exe_file, FILENAME_MAX );
|
|
if (ok)
|
{
|
return std::string(exe_file) + "/";
|
}
|
}
|
}
|
|
return "./";
|
#elif EFSW_OS == EFSW_OS_LINUX
|
char exe_file[FILENAME_MAX + 1];
|
|
int size;
|
|
size = readlink("/proc/self/exe", exe_file, FILENAME_MAX);
|
|
if (size < 0)
|
{
|
return std::string( "./" );
|
}
|
else
|
{
|
exe_file[size] = '\0';
|
return std::string( dirname( exe_file ) ) + "/";
|
}
|
|
#elif EFSW_OS == EFSW_OS_BSD
|
int mib[4];
|
mib[0] = CTL_KERN;
|
mib[1] = KERN_PROC;
|
mib[2] = KERN_PROC_PATHNAME;
|
mib[3] = -1;
|
char buf[1024];
|
size_t cb = sizeof(buf);
|
sysctl(mib, 4, buf, &cb, NULL, 0);
|
|
return FileSystem::pathRemoveFileName( std::string( buf ) );
|
|
#elif EFSW_OS == EFSW_OS_SOLARIS
|
return FileSystem::pathRemoveFileName( std::string( getexecname() ) );
|
|
#elif EFSW_OS == EFSW_OS_HAIKU
|
image_info info;
|
int32 cookie = 0;
|
|
while ( B_OK == get_next_image_info( 0, &cookie, &info ) )
|
{
|
if ( info.type == B_APP_IMAGE )
|
break;
|
}
|
|
return FileSystem::pathRemoveFileName( std::string( info.name ) );
|
|
#elif EFSW_OS == EFSW_OS_ANDROID
|
return "/sdcard/";
|
|
#else
|
#warning getProcessPath() not implemented on this platform. ( will return "./" )
|
return "./";
|
|
#endif
|
}
|
|
void System::maxFD()
|
{
|
static bool maxed = false;
|
|
if ( !maxed )
|
{
|
struct rlimit limit;
|
getrlimit( RLIMIT_NOFILE, &limit );
|
limit.rlim_cur = limit.rlim_max;
|
setrlimit( RLIMIT_NOFILE, &limit );
|
|
getrlimit( RLIMIT_NOFILE, &limit );
|
|
efDEBUG( "File descriptor limit %ld\n", limit.rlim_cur );
|
|
maxed = true;
|
}
|
}
|
|
Uint64 System::getMaxFD()
|
{
|
static rlim_t max_fd = 0;
|
|
if ( max_fd == 0 )
|
{
|
struct rlimit limit;
|
getrlimit( RLIMIT_NOFILE, &limit );
|
max_fd = limit.rlim_cur;
|
}
|
|
return max_fd;
|
}
|
|
}}
|
|
#endif
|