Compare commits
21 Commits
main/gingo
...
hg/feature
Author | SHA1 | Date |
---|---|---|
kaetemi | 3a99de667a | 11 years ago |
kaetemi | 4e2ae9c5b0 | 11 years ago |
kaetemi | 5787bbe3b3 | 11 years ago |
kaetemi | 0b3d642870 | 11 years ago |
kaetemi | b4d5730363 | 11 years ago |
kaetemi | f779b34751 | 11 years ago |
kaetemi | 220d58442c | 11 years ago |
kaetemi | bc449abb20 | 11 years ago |
kaetemi | 87379f87a7 | 11 years ago |
kaetemi | f33cbeb7de | 11 years ago |
kaetemi | 733455b5fb | 11 years ago |
kaetemi | a307c383f9 | 11 years ago |
kaetemi | 7223a4d208 | 11 years ago |
kaetemi | 72655cd71b | 11 years ago |
kaetemi | 39d233f5eb | 11 years ago |
kaetemi | 23cbacc0c9 | 11 years ago |
kaetemi | ff1059f735 | 11 years ago |
kaetemi | b74c3cc9fa | 11 years ago |
kaetemi | 2f302e93a9 | 11 years ago |
kaetemi | cd35d14374 | 11 years ago |
kaetemi | 788ac7b9e0 | 11 years ago |
@ -0,0 +1,193 @@
|
||||
# Locate SDL2 library
|
||||
# This module defines
|
||||
# SDL2_LIBRARY, the name of the library to link against
|
||||
# SDL2_FOUND, if false, do not try to link to SDL2
|
||||
# SDL2_INCLUDE_DIR, where to find SDL.h
|
||||
#
|
||||
# This module responds to the the flag:
|
||||
# SDL2_BUILDING_LIBRARY
|
||||
# If this is defined, then no SDL2_main will be linked in because
|
||||
# only applications need main().
|
||||
# Otherwise, it is assumed you are building an application and this
|
||||
# module will attempt to locate and set the the proper link flags
|
||||
# as part of the returned SDL2_LIBRARY variable.
|
||||
#
|
||||
# Don't forget to include SDL2main.h and SDL2main.m your project for the
|
||||
# OS X framework based version. (Other versions link to -lSDL2main which
|
||||
# this module will try to find on your behalf.) Also for OS X, this
|
||||
# module will automatically add the -framework Cocoa on your behalf.
|
||||
#
|
||||
#
|
||||
# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
|
||||
# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
|
||||
# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
|
||||
# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
|
||||
# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
|
||||
# as appropriate. These values are used to generate the final SDL2_LIBRARY
|
||||
# variable, but when these values are unset, SDL2_LIBRARY does not get created.
|
||||
#
|
||||
#
|
||||
# $SDL2DIR is an environment variable that would
|
||||
# correspond to the ./configure --prefix=$SDL2DIR
|
||||
# used in building SDL2.
|
||||
# l.e.galup 9-20-02
|
||||
#
|
||||
# Modified by Eric Wing.
|
||||
# Added code to assist with automated building by using environmental variables
|
||||
# and providing a more controlled/consistent search behavior.
|
||||
# Added new modifications to recognize OS X frameworks and
|
||||
# additional Unix paths (FreeBSD, etc).
|
||||
# Also corrected the header search path to follow "proper" SDL2 guidelines.
|
||||
# Added a search for SDL2main which is needed by some platforms.
|
||||
# Added a search for threads which is needed by some platforms.
|
||||
# Added needed compile switches for MinGW.
|
||||
#
|
||||
# On OSX, this will prefer the Framework version (if found) over others.
|
||||
# People will have to manually change the cache values of
|
||||
# SDL2_LIBRARY to override this selection or set the CMake environment
|
||||
# CMAKE_INCLUDE_PATH to modify the search paths.
|
||||
#
|
||||
# Note that the header path has changed from SDL2/SDL.h to just SDL.h
|
||||
# This needed to change because "proper" SDL2 convention
|
||||
# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
|
||||
# reasons because not all systems place things in SDL2/ (see FreeBSD).
|
||||
#
|
||||
# Ported by Johnny Patterson. This is a literal port for SDL2 of the FindSDL.cmake
|
||||
# module with the minor edit of changing "SDL" to "SDL2" where necessary. This
|
||||
# was not created for redistribution, and exists temporarily pending official
|
||||
# SDL2 CMake modules.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2003-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
|
||||
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES include/SDL2 include
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/include/SDL2
|
||||
/usr/include/SDL2
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt
|
||||
)
|
||||
#MESSAGE("SDL2_INCLUDE_DIR is ${SDL2_INCLUDE_DIR}")
|
||||
|
||||
FIND_LIBRARY(SDL2_LIBRARY_TEMP
|
||||
NAMES SDL2
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
|
||||
#MESSAGE("SDL2_LIBRARY_TEMP is ${SDL2_LIBRARY_TEMP}")
|
||||
|
||||
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||
IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
# Non-OS X framework versions expect you to also dynamically link to
|
||||
# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
|
||||
# seem to provide SDL2main for compatibility even though they don't
|
||||
# necessarily need it.
|
||||
FIND_LIBRARY(SDL2MAIN_LIBRARY
|
||||
NAMES SDL2main
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||
|
||||
# SDL2 may require threads on your system.
|
||||
# The Apple build may not need an explicit flag because one of the
|
||||
# frameworks may already provide it.
|
||||
# But for non-OSX systems, I will use the CMake Threads package.
|
||||
IF(NOT APPLE)
|
||||
FIND_PACKAGE(Threads)
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# MinGW needs an additional library, mwindows
|
||||
# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
|
||||
# (Actually on second look, I think it only needs one of the m* libraries.)
|
||||
IF(MINGW)
|
||||
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
|
||||
ENDIF(MINGW)
|
||||
|
||||
SET(SDL2_FOUND "NO")
|
||||
IF(SDL2_LIBRARY_TEMP)
|
||||
# For SDL2main
|
||||
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||
IF(SDL2MAIN_LIBRARY)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(SDL2MAIN_LIBRARY)
|
||||
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||
|
||||
# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
|
||||
# CMake doesn't display the -framework Cocoa string in the UI even
|
||||
# though it actually is there if I modify a pre-used variable.
|
||||
# I think it has something to do with the CACHE STRING.
|
||||
# So I use a temporary variable until the end so I can set the
|
||||
# "real" variable in one-shot.
|
||||
IF(APPLE)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
|
||||
ENDIF(APPLE)
|
||||
|
||||
# For threads, as mentioned Apple doesn't need this.
|
||||
# In fact, there seems to be a problem if I used the Threads package
|
||||
# and try using this line, so I'm just skipping it entirely for OS X.
|
||||
IF(NOT APPLE)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# For MinGW library
|
||||
IF(MINGW)
|
||||
SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(MINGW)
|
||||
|
||||
IF(WIN32)
|
||||
SET(SDL2_LIBRARY_TEMP winmm imm32 version msimg32 ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(WIN32)
|
||||
|
||||
# Set the final string here so the GUI reflects the final state.
|
||||
SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
|
||||
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
|
||||
SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
|
||||
|
||||
SET(SDL2_FOUND "YES")
|
||||
ENDIF(SDL2_LIBRARY_TEMP)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2
|
||||
REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||
|
||||
IF(SDL2_STATIC)
|
||||
if (UNIX AND NOT APPLE)
|
||||
EXECUTE_PROCESS(COMMAND sdl2-config --static-libs OUTPUT_VARIABLE SDL2_LINK_FLAGS)
|
||||
STRING(REGEX REPLACE "(\r?\n)+$" "" SDL2_LINK_FLAGS "${SDL2_LINK_FLAGS}")
|
||||
SET(SDL2_LIBRARY ${SDL2_LINK_FLAGS})
|
||||
ENDIF()
|
||||
ENDIF(SDL2_STATIC)
|
@ -1,97 +0,0 @@
|
||||
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef NL_P_THREAD_H
|
||||
#define NL_P_THREAD_H
|
||||
|
||||
#include "types_nl.h"
|
||||
|
||||
#ifdef NL_OS_UNIX
|
||||
|
||||
#include "thread.h"
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace NLMISC {
|
||||
|
||||
|
||||
/**
|
||||
* Posix Thread
|
||||
* \author Olivier Cado
|
||||
* \author Nevrax France
|
||||
* \date 2001
|
||||
*/
|
||||
class CPThread : public IThread
|
||||
{
|
||||
public:
|
||||
enum TThreadState
|
||||
{
|
||||
ThreadStateNone,
|
||||
ThreadStateRunning,
|
||||
ThreadStateFinished,
|
||||
};
|
||||
|
||||
/// Constructor
|
||||
CPThread( IRunnable *runnable, uint32 stackSize);
|
||||
|
||||
virtual ~CPThread();
|
||||
|
||||
virtual void start();
|
||||
virtual bool isRunning();
|
||||
virtual void terminate();
|
||||
virtual void wait();
|
||||
virtual bool setCPUMask(uint64 cpuMask);
|
||||
virtual uint64 getCPUMask();
|
||||
virtual void setPriority(TThreadPriority priority);
|
||||
virtual std::string getUserName();
|
||||
|
||||
virtual IRunnable *getRunnable()
|
||||
{
|
||||
return Runnable;
|
||||
}
|
||||
|
||||
/// Internal use
|
||||
IRunnable *Runnable;
|
||||
|
||||
TThreadState _State;
|
||||
pthread_t _ThreadHandle;
|
||||
|
||||
private:
|
||||
uint32 _StackSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Posix Process
|
||||
* \author Cyril 'Hulud' Corvazier
|
||||
* \author Nevrax France
|
||||
* \date 2001
|
||||
*/
|
||||
class CPProcess : public IProcess
|
||||
{
|
||||
public:
|
||||
virtual ~CPProcess() {}
|
||||
virtual uint64 getCPUMask();
|
||||
virtual bool setCPUMask(uint64 mask);
|
||||
};
|
||||
|
||||
} // NLMISC
|
||||
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
|
||||
#endif // NL_P_THREAD_H
|
||||
|
||||
/* End of p_thread.h */
|
@ -1,145 +0,0 @@
|
||||
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef NL_WIN_THREAD_H
|
||||
#define NL_WIN_THREAD_H
|
||||
|
||||
#include "types_nl.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
|
||||
namespace NLMISC {
|
||||
|
||||
|
||||
/**
|
||||
* Windows implementation of CThread class (look thread.h)
|
||||
* \author Vianney Lecroart
|
||||
* \author Nevrax France
|
||||
* \date 2000
|
||||
*/
|
||||
class CWinThread : public IThread
|
||||
{
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
CWinThread(IRunnable *runnable, uint32 stackSize);
|
||||
|
||||
/// Don't use this constructor, only used to initialise the main thread class
|
||||
CWinThread (void* threadHandle, uint32 threadId);
|
||||
|
||||
virtual ~CWinThread();
|
||||
|
||||
virtual void start();
|
||||
virtual bool isRunning();
|
||||
virtual void terminate();
|
||||
virtual void wait();
|
||||
virtual bool setCPUMask(uint64 cpuMask);
|
||||
virtual uint64 getCPUMask();
|
||||
virtual void setPriority(TThreadPriority priority);
|
||||
virtual std::string getUserName();
|
||||
|
||||
virtual IRunnable *getRunnable()
|
||||
{
|
||||
return Runnable;
|
||||
}
|
||||
|
||||
// Win32 specific
|
||||
// Get the suspend count. Will be -1 is the thread hasn't been started yet
|
||||
int getSuspendCount() const { return _SuspendCount; }
|
||||
// Increment the suspend count, a suspend count >= 1 means the thread is suspended
|
||||
void incSuspendCount();
|
||||
/** Descrement the suspend count. Reaching 0 will resume the thread
|
||||
* An assertion is raised is the suspend count is already 0
|
||||
*/
|
||||
void decSuspendCount();
|
||||
// Suspend the thread. No-op if already suspended
|
||||
void suspend();
|
||||
// Resume the thread. No-op if already resumed
|
||||
void resume();
|
||||
// Priority boost
|
||||
void enablePriorityBoost(bool enabled);
|
||||
|
||||
/// private use
|
||||
IRunnable *Runnable;
|
||||
|
||||
private:
|
||||
int _SuspendCount;
|
||||
uint32 _StackSize;
|
||||
void *ThreadHandle; // HANDLE don't put it to avoid including windows.h
|
||||
uint32 ThreadId; // DWORD don't put it to avoid including windows.h
|
||||
bool _MainThread; // true if ths thread is the main thread, else false
|
||||
};
|
||||
|
||||
/**
|
||||
* Windows Process
|
||||
* \author Cyril 'Hulud' Corvazier
|
||||
* \author Nicolas Vizerie
|
||||
* \author Nevrax France
|
||||
* \date 2001, 2007
|
||||
*/
|
||||
class CWinProcess : public IProcess
|
||||
{
|
||||
public:
|
||||
|
||||
CWinProcess (void *handle);
|
||||
virtual ~CWinProcess() {} // TODO do something with _ProcessHandle?
|
||||
|
||||
virtual uint64 getCPUMask();
|
||||
virtual bool setCPUMask(uint64 mask);
|
||||
|
||||
// processes helpers
|
||||
static bool enumProcessesId(std::vector<uint32> &processesId);
|
||||
// get fully qualified path for all modules used by a given process
|
||||
static bool enumProcessModules(uint32 processId, std::vector<std::string> &moduleNames);
|
||||
static uint32 getProcessIdFromModuleFilename(const std::string &moduleFileName);
|
||||
static bool terminateProcess(uint32 processId, uint exitCode = 0);
|
||||
static bool terminateProcessFromModuleName(const std::string &moduleName, uint exitCode = 0);
|
||||
|
||||
private:
|
||||
void *_ProcessHandle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// I didn't use and test that code, enventually, but maybe useful in the future
|
||||
//
|
||||
// Utility class to launch a process and check if it is still running.
|
||||
// Implemented under windows only for now
|
||||
//
|
||||
class CProcessWatch
|
||||
{
|
||||
public:
|
||||
CProcessWatch();
|
||||
~CProcessWatch();
|
||||
// launch a process with the given name and arguments, return true on success
|
||||
bool launch(const std::string &programName, const std::string &arguments);
|
||||
// return true if the process is still runing
|
||||
bool isRunning() const;
|
||||
private:
|
||||
class CProcessWatchImpl *_PImpl;
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
} // NLMISC
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
||||
|
||||
#endif // NL_WIN_THREAD_H
|
||||
|
||||
/* End of win_thread.h */
|
@ -1,387 +0,0 @@
|
||||
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "stdmisc.h"
|
||||
|
||||
#include <nel/misc/types_nl.h>
|
||||
#include <nel/misc/debug.h>
|
||||
|
||||
#ifdef NL_OS_UNIX
|
||||
|
||||
#include "nel/misc/p_thread.h"
|
||||
|
||||
#include <sched.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#ifdef DEBUG_NEW
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
namespace NLMISC {
|
||||
|
||||
/* Key for thread specific storage holding IThread pointer. */
|
||||
static pthread_key_t threadSpecificKey;
|
||||
|
||||
/* Special thread type representing the main thread. */
|
||||
struct CPMainThread : public CPThread
|
||||
{
|
||||
CPMainThread() : CPThread(NULL, 0)
|
||||
{
|
||||
if(pthread_key_create(&threadSpecificKey, NULL) != 0)
|
||||
throw EThread("cannot create thread specific storage key.");
|
||||
|
||||
if(pthread_setspecific(threadSpecificKey, this) != 0)
|
||||
throw EThread("cannot set main thread ptr in thread specific storage.");
|
||||
}
|
||||
|
||||
~CPMainThread()
|
||||
{
|
||||
if(pthread_key_delete(threadSpecificKey) != 0)
|
||||
throw EThread("cannot delete thread specific storage key.");
|
||||
}
|
||||
};
|
||||
|
||||
/* Holds the thread instance representing the main thread. */
|
||||
static CPMainThread mainThread = CPMainThread();
|
||||
|
||||
/*
|
||||
* The IThread static creator
|
||||
*/
|
||||
IThread *IThread::create( IRunnable *runnable, uint32 stackSize)
|
||||
{
|
||||
return new CPThread( runnable, stackSize );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current thread
|
||||
*/
|
||||
IThread *IThread::getCurrentThread ()
|
||||
{
|
||||
return (IThread *)pthread_getspecific(threadSpecificKey);
|
||||
}
|
||||
|
||||
/*
|
||||
* Thread beginning
|
||||
*/
|
||||
static void *ProxyFunc( void *arg )
|
||||
{
|
||||
CPThread *parent = (CPThread*)arg;
|
||||
|
||||
// Set this thread's thread specific storage to IThread instance pointer
|
||||
if(pthread_setspecific(threadSpecificKey, parent) != 0)
|
||||
throw EThread("cannot set thread ptr in thread specific storage.");
|
||||
|
||||
// Allow to terminate the thread without cancellation point
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
|
||||
// Run the code of the thread
|
||||
parent->Runnable->run();
|
||||
|
||||
{
|
||||
pthread_t thread_self = pthread_self();
|
||||
// Make sure the parent still cares
|
||||
// If this thread was replaced with a new thread (which should not happen),
|
||||
// and the IThread object has been deleted, this will likely crash.
|
||||
if (parent->_ThreadHandle == thread_self)
|
||||
parent->_State = CPThread::ThreadStateFinished;
|
||||
else
|
||||
throw EThread("Thread ended after being detached, this should not happen");
|
||||
}
|
||||
|
||||
// Allow some clean
|
||||
// pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
CPThread::CPThread(IRunnable *runnable, uint32 stackSize)
|
||||
: Runnable(runnable),
|
||||
_State(ThreadStateNone),
|
||||
_StackSize(stackSize)
|
||||
{}
|
||||
|
||||
|
||||
/*
|
||||
* Destructor
|
||||
*/
|
||||
CPThread::~CPThread()
|
||||
{
|
||||
terminate(); // force the end of the thread if not already ended
|
||||
|
||||
if (_State != ThreadStateNone)
|
||||
pthread_detach(_ThreadHandle); // free allocated resources only if it was created
|
||||
}
|
||||
|
||||
/*
|
||||
* start
|
||||
*/
|
||||
void CPThread::start()
|
||||
{
|
||||
pthread_attr_t tattr;
|
||||
int ret;
|
||||
|
||||
if (_StackSize != 0)
|
||||
{
|
||||
/* initialized with default attributes */
|
||||
ret = pthread_attr_init(&tattr);
|
||||
|
||||
/* setting the size of the stack also */
|
||||
ret = pthread_attr_setstacksize(&tattr, _StackSize);
|
||||
}
|
||||
|
||||
bool detach_old_thread = false;
|
||||
pthread_t old_thread_handle;
|
||||
if (_State != ThreadStateNone)
|
||||
{
|
||||
if (_State == ThreadStateRunning)
|
||||
{
|
||||
// I don't know if this behaviour is allowed, but neither thread implementations
|
||||
// check the start function, and both simply let the existing running thread for what it is...
|
||||
// From now on, this is not allowed.
|
||||
throw EThread("Starting a thread that is already started, existing thread will continue running, this should not happen");
|
||||
}
|
||||
detach_old_thread = true;
|
||||
old_thread_handle = _ThreadHandle;
|
||||
}
|
||||
|
||||
if (pthread_create(&_ThreadHandle, _StackSize != 0 ? &tattr : NULL, ProxyFunc, this) != 0)
|
||||
{
|
||||
throw EThread("Cannot start new thread");
|
||||
}
|
||||
_State = ThreadStateRunning;
|
||||
|
||||
if (detach_old_thread)
|
||||
{
|
||||
// Docs don't say anything about what happens when pthread_create is called with existing handle referenced.
|
||||
if (old_thread_handle == _ThreadHandle)
|
||||
throw EThread("Thread handle did not change, this should not happen");
|
||||
// Don't care about old thread, free resources when it terminates.
|
||||
pthread_detach(old_thread_handle);
|
||||
}
|
||||
}
|
||||
|
||||
bool CPThread::isRunning()
|
||||
{
|
||||
return _State == ThreadStateRunning;
|
||||
}
|
||||
|
||||
/*
|
||||
* terminate
|
||||
*/
|
||||
void CPThread::terminate()
|
||||
{
|
||||
if (_State == ThreadStateRunning)
|
||||
{
|
||||
// cancel only if started
|
||||
pthread_cancel(_ThreadHandle);
|
||||
_State = ThreadStateFinished; // set to finished
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* wait
|
||||
*/
|
||||
void CPThread::wait ()
|
||||
{
|
||||
if (_State == ThreadStateRunning)
|
||||
{
|
||||
int error = pthread_join(_ThreadHandle, 0);
|
||||
switch (error)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case EINVAL:
|
||||
throw EThread("Thread is not joinable");
|
||||
case ESRCH:
|
||||
throw EThread("No thread found with this id");
|
||||
case EDEADLK:
|
||||
throw EThread("Deadlock detected or calling thread waits for itself");
|
||||
default:
|
||||
throw EThread("Unknown thread join error");
|
||||
}
|
||||
if(_State != ThreadStateFinished)
|
||||
throw EThread("Thread did not finish, this should not happen");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* setCPUMask
|
||||
*/
|
||||
bool CPThread::setCPUMask(uint64 cpuMask)
|
||||
{
|
||||
#ifdef __USE_GNU
|
||||
|
||||
nlwarning("This code does not work. May cause a segmentation fault...");
|
||||
|
||||
sint res = pthread_setaffinity_np(_ThreadHandle, sizeof(uint64), (const cpu_set_t*)&cpuMask);
|
||||
|
||||
if (res)
|
||||
{
|
||||
nlwarning("pthread_setaffinity_np() returned %d", res);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
#else // __USE_GNU
|
||||
|
||||
return false;
|
||||
|
||||
#endif // __USE_GNU
|
||||
}
|
||||
|
||||
/*
|
||||
* getCPUMask
|
||||
*/
|
||||
uint64 CPThread::getCPUMask()
|
||||
{
|
||||
#ifdef __USE_GNU
|
||||
|
||||
nlwarning("This code does not work. May cause a segmentation fault...");
|
||||
|
||||
uint64 cpuMask = 0;
|
||||
|
||||
sint res = pthread_getaffinity_np(_ThreadHandle, sizeof(uint64), (cpu_set_t*)&cpuMask);
|
||||
|
||||
if (res)
|
||||
{
|
||||
nlwarning("pthread_getaffinity_np() returned %d", res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cpuMask;
|
||||
|
||||
#else // __USE_GNU
|
||||
|
||||
return 0;
|
||||
|
||||
#endif // __USE_GNU
|
||||
}
|
||||
|
||||
void CPThread::setPriority(TThreadPriority priority)
|
||||
{
|
||||
// TODO: Test this
|
||||
sched_param sp;
|
||||
switch (priority)
|
||||
{
|
||||
case ThreadPriorityHigh:
|
||||
{
|
||||
int minPrio = sched_get_priority_min(SCHED_FIFO);
|
||||
int maxPrio = sched_get_priority_max(SCHED_FIFO);
|
||||
sp.sched_priority = ((maxPrio - minPrio) / 4) + minPrio;
|
||||
pthread_setschedparam(_ThreadHandle, SCHED_FIFO, &sp);
|
||||
break;
|
||||
}
|
||||
case ThreadPriorityHighest:
|
||||
{
|
||||
int minPrio = sched_get_priority_min(SCHED_FIFO);
|
||||
int maxPrio = sched_get_priority_max(SCHED_FIFO);
|
||||
sp.sched_priority = ((maxPrio - minPrio) / 2) + minPrio;
|
||||
pthread_setschedparam(_ThreadHandle, SCHED_FIFO, &sp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sp.sched_priority = 0;
|
||||
pthread_setschedparam(_ThreadHandle, SCHED_OTHER, &sp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getUserName
|
||||
*/
|
||||
std::string CPThread::getUserName()
|
||||
{
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
|
||||
if (!pw)
|
||||
return "";
|
||||
|
||||
return pw->pw_name;
|
||||
}
|
||||
|
||||
|
||||
// **** Process
|
||||
|
||||
// The current process
|
||||
CPProcess CurrentProcess;
|
||||
|
||||
// Get the current process
|
||||
IProcess *IProcess::getCurrentProcess ()
|
||||
{
|
||||
return &CurrentProcess;
|
||||
}
|
||||
|
||||
/*
|
||||
* getCPUMask
|
||||
*/
|
||||
uint64 CPProcess::getCPUMask()
|
||||
{
|
||||
#ifdef __USE_GNU
|
||||
|
||||
uint64 cpuMask = 0;
|
||||
sint res = sched_getaffinity(getpid(), sizeof(uint64), (cpu_set_t*)&cpuMask);
|
||||
|
||||
if (res)
|
||||
{
|
||||
nlwarning("sched_getaffinity() returned %d, errno = %d: %s", res, errno, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cpuMask;
|
||||
|
||||
#else // __USE_GNU
|
||||
|
||||
return 0;
|
||||
|
||||
#endif // __USE_GNU
|
||||
}
|
||||
|
||||
/// set the CPU mask
|
||||
bool CPProcess::setCPUMask(uint64 cpuMask)
|
||||
{
|
||||
#ifdef __USE_GNU
|
||||
|
||||
sint res = sched_setaffinity(getpid(), sizeof(uint64), (const cpu_set_t*)&cpuMask);
|
||||
|
||||
if (res)
|
||||
{
|
||||
nlwarning("sched_setaffinity() returned %d, errno = %d: %s", res, errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
#else // __USE_GNU
|
||||
|
||||
return false;
|
||||
|
||||
#endif // __USE_GNU
|
||||
}
|
||||
|
||||
|
||||
} // NLMISC
|
||||
|
||||
#else // NL_OS_UNIX
|
||||
|
||||
// remove stupid VC6 warnings
|
||||
void foo_p_thread_cpp() {}
|
||||
|
||||
#endif // NL_OS_UNIX
|
@ -0,0 +1,105 @@
|
||||
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "stdmisc.h"
|
||||
#include "nel/misc/thread.h"
|
||||
#include "nel/misc/debug.h"
|
||||
|
||||
#include <SDL_thread.h>
|
||||
|
||||
namespace NLMISC {
|
||||
|
||||
CThread::CThread(IRunnable *runnable) : m_IsRunning(false), m_SDLThread(NULL), m_Runnable(runnable)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CThread::~CThread ()
|
||||
{
|
||||
/*
|
||||
NOTE: Detach not supported, due to m_IsRunning which is referenced by the running thread
|
||||
FIX: Use a thread-safe reference counted object for the m_IsRunning flag
|
||||
if (m_SDLThread)
|
||||
{
|
||||
SDL_DetachThread(m_SDLThread);
|
||||
}
|
||||
NOTE: Currently use wait, which is much saner behaviour.
|
||||
*/
|
||||
|
||||
wait();
|
||||
}
|
||||
|
||||
void CThread::start()
|
||||
{
|
||||
nlassert(!m_SDLThread);
|
||||
nlassert(!m_IsRunning);
|
||||
std::string name;
|
||||
m_Runnable->getName(name);
|
||||
m_IsRunning = true;
|
||||
m_SDLThread = SDL_CreateThread(run, name.c_str(), (void *)this);
|
||||
}
|
||||
|
||||
int CThread::run(void *ptr)
|
||||
{
|
||||
NLMISC::CThread *thread = static_cast<NLMISC::CThread *>(ptr);
|
||||
thread->m_Runnable->run();
|
||||
thread->m_IsRunning = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CThread::setPriority(TThreadPriority priority)
|
||||
{
|
||||
switch (priority)
|
||||
{
|
||||
case ThreadPriorityLow:
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
|
||||
break;
|
||||
case ThreadPriorityNormal:
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_NORMAL);
|
||||
break;
|
||||
case ThreadPriorityHigh:
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
|
||||
break;
|
||||
default:
|
||||
nlerror("Invalid thread priority");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CThread::isRunning()
|
||||
{
|
||||
return m_IsRunning;
|
||||
}
|
||||
|
||||
int CThread::wait()
|
||||
{
|
||||
m_WaitMutex.enter();
|
||||
if (m_SDLThread)
|
||||
{
|
||||
SDL_WaitThread(m_SDLThread, &m_ThreadResult);
|
||||
m_SDLThread = NULL;
|
||||
nlassert(!m_IsRunning);
|
||||
}
|
||||
m_WaitMutex.leave();
|
||||
return m_ThreadResult;
|
||||
}
|
||||
|
||||
IRunnable *CThread::getRunnable()
|
||||
{
|
||||
return m_Runnable;
|
||||
}
|
||||
|
||||
} // NLMISC
|
@ -1,611 +0,0 @@
|
||||
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "stdmisc.h"
|
||||
#include "nel/misc/win_thread.h"
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
|
||||
#include "nel/misc/path.h"
|
||||
#ifndef NL_COMP_MINGW
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#ifdef DEBUG_NEW
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
namespace NLMISC {
|
||||
|
||||
CWinThread MainThread ((void*)GetCurrentThread (), GetCurrentThreadId());
|
||||
DWORD TLSThreadPointer = 0xFFFFFFFF;
|
||||
|
||||
// the IThread static creator
|
||||
IThread *IThread::create (IRunnable *runnable, uint32 stackSize)
|
||||
{
|
||||
return new CWinThread (runnable, stackSize);
|
||||
}
|
||||
|
||||
IThread *IThread::getCurrentThread ()
|
||||
{
|
||||
// TLS alloc must have been done
|
||||
nlassert (TLSThreadPointer != 0xffffffff);
|
||||
|
||||
// Get the thread pointer
|
||||
IThread *thread = (IThread*)TlsGetValue (TLSThreadPointer);
|
||||
|
||||
// Return current thread
|
||||
return thread;
|
||||
}
|
||||
|
||||
static unsigned long __stdcall ProxyFunc (void *arg)
|
||||
{
|
||||
CWinThread *parent = (CWinThread *) arg;
|
||||
|
||||
// TLS alloc must have been done
|
||||
nlassert (TLSThreadPointer != 0xffffffff);
|
||||
|
||||
// Set the thread pointer in TLS memory
|
||||
nlverify (TlsSetValue (TLSThreadPointer, (void*)parent) != 0);
|
||||
|
||||
// Run the thread
|
||||
parent->Runnable->run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CWinThread::CWinThread (IRunnable *runnable, uint32 stackSize)
|
||||
{
|
||||
_StackSize = stackSize;
|
||||
this->Runnable = runnable;
|
||||
ThreadHandle = NULL;
|
||||
_SuspendCount = -1;
|
||||
_MainThread = false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class CWinCriticalSection
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION cs;
|
||||
public:
|
||||
CWinCriticalSection() { InitializeCriticalSection(&cs); }
|
||||
~CWinCriticalSection() { DeleteCriticalSection(&cs); }
|
||||
inline void enter() { EnterCriticalSection(&cs); }
|
||||
inline void leave() { LeaveCriticalSection(&cs); }
|
||||
};
|
||||
CWinCriticalSection s_CS;
|
||||
}/* anonymous namespace */
|
||||
|
||||
CWinThread::CWinThread (void* threadHandle, uint32 threadId)
|
||||
{
|
||||
// Main thread
|
||||
_MainThread = true;
|
||||
this->Runnable = NULL;
|
||||
ThreadHandle = threadHandle;
|
||||
ThreadId = threadId;
|
||||
|
||||
// TLS alloc must have been done
|
||||
TLSThreadPointer = TlsAlloc ();
|
||||
nlassert (TLSThreadPointer!=0xffffffff);
|
||||
|
||||
// Set the thread pointer in TLS memory
|
||||
nlverify (TlsSetValue (TLSThreadPointer, (void*)this) != 0);
|
||||
|
||||
if (GetCurrentThreadId() == threadId)
|
||||
{
|
||||
_SuspendCount = 0; // is calling thread call this itself, well, if we reach this place
|
||||
// there are chances that it is not suspended ...
|
||||
}
|
||||
else
|
||||
{
|
||||
// initialized from another thread (very unlikely ...)
|
||||
nlassert(0); // WARNING: following code has not tested! don't know if it work fo real ...
|
||||
// This is just a suggestion of a possible solution, should this situation one day occur ...
|
||||
// Ensure that this thread don't get deleted, or we could suspend the main thread
|
||||
s_CS.enter();
|
||||
// the 2 following statement must be executed atomicaly among the threads of the current process !
|
||||
SuspendThread(threadHandle);
|
||||
_SuspendCount = ResumeThread(threadHandle);
|
||||
s_CS.leave();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CWinThread::incSuspendCount()
|
||||
{
|
||||
nlassert(ThreadHandle); // start was not called !!
|
||||
int newSuspendCount = ::SuspendThread(ThreadHandle) + 1;
|
||||
nlassert(newSuspendCount != 0xffffffff); // more infos with 'GetLastError'
|
||||
nlassert(newSuspendCount == _SuspendCount + 1); // is this assert fire , then 'SuspendThread' or 'ResumeThread'
|
||||
// have been called outside of this object interface! (on this thread handle ...)
|
||||
_SuspendCount = newSuspendCount;
|
||||
}
|
||||
|
||||
void CWinThread::decSuspendCount()
|
||||
{
|
||||
nlassert(ThreadHandle); // 'start' was not called !!
|
||||
nlassert(_SuspendCount > 0);
|
||||
int newSuspendCount = ::ResumeThread(ThreadHandle) - 1;
|
||||
nlassert(newSuspendCount != 0xffffffff); // more infos with 'GetLastError'
|
||||
nlassert(newSuspendCount == _SuspendCount - 1); // is this assert fire , then 'SuspendThread' or 'ResumeThread'
|
||||
// have been called outside of this object interface! (on this thread handle ...)
|
||||
_SuspendCount = newSuspendCount;
|
||||
}
|
||||
|
||||
void CWinThread::suspend()
|
||||
{
|
||||
if (getSuspendCount() == 0)
|
||||
{
|
||||
incSuspendCount();
|
||||
}
|
||||
}
|
||||
|
||||
void CWinThread::resume()
|
||||
{
|
||||
while (getSuspendCount() != 0)
|
||||
{
|
||||
decSuspendCount();
|
||||
}
|
||||
}
|
||||
|
||||
void CWinThread::setPriority(TThreadPriority priority)
|
||||
{
|
||||
nlassert(ThreadHandle); // 'start' was not called !!
|
||||
BOOL result = SetThreadPriority(ThreadHandle, (int)priority);
|
||||
nlassert(result);
|
||||
}
|
||||
|
||||
void CWinThread::enablePriorityBoost(bool enabled)
|
||||
{
|
||||
nlassert(ThreadHandle); // 'start' was not called !!
|
||||
SetThreadPriorityBoost(ThreadHandle, enabled ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
|
||||
CWinThread::~CWinThread ()
|
||||
{
|
||||
// If not the main thread
|
||||
if (_MainThread)
|
||||
{
|
||||
// Free TLS memory
|
||||
nlassert (TLSThreadPointer!=0xffffffff);
|
||||
TlsFree (TLSThreadPointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ThreadHandle != NULL) terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void CWinThread::start ()
|
||||
{
|
||||
if (isRunning())
|
||||
throw EThread("Starting a thread that is already started, existing thread will continue running, this should not happen");
|
||||
|
||||
// ThreadHandle = (void *) ::CreateThread (NULL, _StackSize, ProxyFunc, this, 0, (DWORD *)&ThreadId);
|
||||
ThreadHandle = (void *) ::CreateThread (NULL, 0, ProxyFunc, this, 0, (DWORD *)&ThreadId);
|
||||
// nldebug("NLMISC: thread %x started for runnable '%x'", typeid( Runnable ).name());
|
||||
// OutputDebugString(toString(NL_LOC_MSG " NLMISC: thread %x started for runnable '%s'\n", ThreadId, typeid( *Runnable ).name()).c_str());
|
||||
SetThreadPriorityBoost (ThreadHandle, TRUE); // FALSE == Enable Priority Boost
|
||||
if (ThreadHandle == NULL)
|
||||
{
|
||||
throw EThread ( "Cannot create new thread" );
|
||||
}
|
||||
|
||||
_SuspendCount = 0;
|
||||
}
|
||||
|
||||
bool CWinThread::isRunning()
|
||||
{
|
||||
if (ThreadHandle == NULL)
|
||||
return false;
|
||||
|
||||
DWORD exitCode;
|
||||
if (!GetExitCodeThread(ThreadHandle, &exitCode))
|
||||
return false;
|
||||
|
||||
return exitCode == STILL_ACTIVE;
|
||||
}
|
||||
|
||||
|
||||
void CWinThread::terminate ()
|
||||
{
|
||||
TerminateThread((HANDLE)ThreadHandle, 0);
|
||||
CloseHandle((HANDLE)ThreadHandle);
|
||||
ThreadHandle = NULL;
|
||||
_SuspendCount = -1;
|
||||
}
|
||||
|
||||
void CWinThread::wait ()
|
||||
{
|
||||
if (ThreadHandle == NULL) return;
|
||||
|
||||
WaitForSingleObject(ThreadHandle, INFINITE);
|
||||
CloseHandle(ThreadHandle);
|
||||
ThreadHandle = NULL;
|
||||
_SuspendCount = -1;
|
||||
}
|
||||
|
||||
bool CWinThread::setCPUMask(uint64 cpuMask)
|
||||
{
|
||||
// Thread must exist
|
||||
if (ThreadHandle == NULL)
|
||||
return false;
|
||||
|
||||
// Ask the system for number of processor available for this process
|
||||
return SetThreadAffinityMask ((HANDLE)ThreadHandle, (DWORD_PTR)cpuMask) != 0;
|
||||
}
|
||||
|
||||
uint64 CWinThread::getCPUMask()
|
||||
{
|
||||
// Thread must exist
|
||||
if (ThreadHandle == NULL)
|
||||
return 1;
|
||||
|
||||
// Get the current process mask
|
||||
uint64 mask=IProcess::getCurrentProcess ()->getCPUMask ();
|
||||
|
||||
// Get thread affinity mask
|
||||
DWORD_PTR old = SetThreadAffinityMask ((HANDLE)ThreadHandle, (DWORD_PTR)mask);
|
||||
nlassert (old != 0);
|
||||
if (old == 0)
|
||||
return 1;
|
||||
|
||||
// Reset it
|
||||
SetThreadAffinityMask ((HANDLE)ThreadHandle, old);
|
||||
|
||||
// Return the mask
|
||||
return (uint64)old;
|
||||
}
|
||||
|
||||
std::string CWinThread::getUserName()
|
||||
{
|
||||
char userName[512];
|
||||
DWORD size = 512;
|
||||
GetUserName (userName, &size);
|
||||
return (const char*)userName;
|
||||
}
|
||||
|
||||
// **** Process
|
||||
|
||||
// The current process
|
||||
CWinProcess CurrentProcess ((void*)GetCurrentProcess());
|
||||
|
||||
// Get the current process
|
||||
IProcess *IProcess::getCurrentProcess ()
|
||||
{
|
||||
return &CurrentProcess;
|
||||
}
|
||||
|
||||
CWinProcess::CWinProcess (void *handle)
|
||||
{
|
||||
// Get the current process handle
|
||||
_ProcessHandle = handle;
|
||||
}
|
||||
|
||||
uint64 CWinProcess::getCPUMask()
|
||||
{
|
||||
// Ask the system for number of processor available for this process
|
||||
DWORD_PTR processAffinityMask;
|
||||
DWORD_PTR systemAffinityMask;
|
||||
if (GetProcessAffinityMask((HANDLE)_ProcessHandle, &processAffinityMask, &systemAffinityMask))
|
||||
{
|
||||
// Return the CPU mask
|
||||
return (uint64)processAffinityMask;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool CWinProcess::setCPUMask(uint64 mask)
|
||||
{
|
||||
// Ask the system for number of processor available for this process
|
||||
DWORD_PTR processAffinityMask= (DWORD_PTR)mask;
|
||||
return SetProcessAffinityMask((HANDLE)_ProcessHandle, processAffinityMask)!=0;
|
||||
}
|
||||
|
||||
// ****************************************************************************************************************
|
||||
/**
|
||||
* Simple wrapper around the PSAPI library
|
||||
* \author Nicolas Vizerie
|
||||
* \author GameForge
|
||||
* \date 2007
|
||||
*/
|
||||
|
||||
class CPSAPILib
|
||||
{
|
||||
public:
|
||||
typedef BOOL (WINAPI *EnumProcessesFunPtr)(DWORD *lpidProcess, DWORD cb, DWORD *cbNeeded);
|
||||
typedef DWORD (WINAPI *GetModuleFileNameExAFunPtr)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
|
||||
typedef BOOL (WINAPI *EnumProcessModulesFunPtr)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
|
||||
EnumProcessesFunPtr EnumProcesses;
|
||||
GetModuleFileNameExAFunPtr GetModuleFileNameExA;
|
||||
EnumProcessModulesFunPtr EnumProcessModules;
|
||||
public:
|
||||
CPSAPILib();
|
||||
~CPSAPILib();
|
||||
bool init();
|
||||
private:
|
||||
HINSTANCE _PSAPILibHandle;
|
||||
bool _LoadFailed;
|
||||
};
|
||||
|
||||
// ****************************************************************************************************************
|
||||
CPSAPILib::CPSAPILib()
|
||||
{
|
||||
_LoadFailed = false;
|
||||
_PSAPILibHandle = NULL;
|
||||
EnumProcesses = NULL;
|
||||
GetModuleFileNameExA = NULL;
|
||||
EnumProcessModules = NULL;
|
||||
}
|
||||
|
||||
// ****************************************************************************************************************
|
||||
CPSAPILib::~CPSAPILib()
|
||||
{
|
||||
if (_PSAPILibHandle)
|
||||
{
|
||||
FreeLibrary(_PSAPILibHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// ****************************************************************************************************************
|
||||
bool CPSAPILib::init()
|
||||
{
|
||||
//
|
||||
if (_LoadFailed) return false;
|
||||
if (!_PSAPILibHandle)
|
||||
{
|
||||
_PSAPILibHandle = LoadLibrary("psapi.dll");
|
||||
if (!_PSAPILibHandle)
|
||||
{
|
||||
nlwarning("couldn't load psapi.dll, possibly not supported by os");
|
||||
_LoadFailed = true;
|
||||
return false;
|
||||
}
|
||||
EnumProcesses = (EnumProcessesFunPtr) GetProcAddress(_PSAPILibHandle, "EnumProcesses");
|
||||
GetModuleFileNameExA = (GetModuleFileNameExAFunPtr) GetProcAddress(_PSAPILibHandle, "GetModuleFileNameExA");
|
||||
EnumProcessModules = (EnumProcessModulesFunPtr) GetProcAddress(_PSAPILibHandle, "EnumProcessModules");
|
||||
if (!EnumProcesses ||
|
||||
!GetModuleFileNameExA ||
|
||||
!EnumProcessModules
|
||||
)
|
||||
{
|
||||
nlwarning("Failed to import functions from psapi.dll!");
|
||||
_LoadFailed = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static CPSAPILib PSAPILib;
|
||||
|
||||
|
||||
|
||||
// ****************************************************************************************************************
|
||||
bool CWinProcess::enumProcessesId(std::vector<uint32> &processesId)
|
||||
{
|
||||
if (!PSAPILib.init()) return false;
|
||||
// list of processes
|
||||
std::vector<uint32> prcIds(16);
|
||||
for (;;)
|
||||
{
|
||||
DWORD cbNeeded;
|
||||
if (!PSAPILib.EnumProcesses((DWORD *) &prcIds[0], (DWORD)(prcIds.size() * sizeof(DWORD)), &cbNeeded))
|
||||
{
|
||||
nlwarning("Processes enumeration failed!");
|
||||
return false;
|
||||
}
|
||||
if (cbNeeded < prcIds.size() * sizeof(DWORD))
|
||||
{
|
||||
prcIds.resize(cbNeeded / sizeof(DWORD));
|
||||
break;
|
||||
}
|
||||
// make some more room
|
||||
prcIds.resize(prcIds.size() * 2);
|
||||
}
|
||||
processesId.swap(prcIds);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ****************************************************************************************************************
|
||||
bool CWinProcess::enumProcessModules(uint32 processId, std::vector<std::string> &moduleNames)
|
||||
{
|
||||
if (!PSAPILib.init()) return false;
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, (DWORD) processId);
|
||||
if (!hProcess) return false;
|
||||
// list of modules
|
||||
std::vector<HMODULE> prcModules(2);
|
||||
for (;;)
|
||||
{
|
||||
DWORD cbNeeded;
|
||||
if (!PSAPILib.EnumProcessModules(hProcess, (HMODULE *) &prcModules[0], (DWORD)(prcModules.size() * sizeof(HMODULE)), &cbNeeded))
|
||||
{
|
||||
//nlwarning("Processe modules enumeration failed!");
|
||||
return false;
|
||||
}
|
||||
if (cbNeeded < prcModules.size() * sizeof(HMODULE))
|
||||
{
|
||||
prcModules.resize(cbNeeded / sizeof(HMODULE));
|
||||
break;
|
||||
}
|
||||
// make some more room
|
||||
prcModules.resize(prcModules.size() * 2);
|
||||
}
|
||||
moduleNames.clear();
|
||||
std::vector<std::string> resultModuleNames;
|
||||
char moduleName[MAX_PATH + 1];
|
||||
for (uint m = 0; m < prcModules.size(); ++m)
|
||||
{
|
||||
if (PSAPILib.GetModuleFileNameExA(hProcess, prcModules[m], moduleName, MAX_PATH))
|
||||
{
|
||||
moduleNames.push_back(moduleName);
|
||||
}
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ****************************************************************************************************************
|
||||
uint32 CWinProcess::getProcessIdFromModuleFilename(const std::string &moduleFileName)
|
||||
{
|
||||
std::vector<uint32> processesId;
|
||||
if (!enumProcessesId(processesId)) return false;
|
||||
std::vector<std::string> moduleNames;
|
||||
for (uint prc = 0; prc < processesId.size(); ++prc)
|
||||
{
|
||||
if (enumProcessModules(processesId[prc], moduleNames))
|
||||
{
|
||||
for (uint m = 0; m < moduleNames.size(); ++m)
|
||||
{
|
||||
if (nlstricmp(CFile::getFilename(moduleNames[m]), moduleFileName) == 0)
|
||||
{
|
||||
return processesId[prc];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ****************************************************************************************************************
|
||||
bool CWinProcess::terminateProcess(uint32 processId, uint exitCode)
|
||||
{
|
||||
if (!processId) return false;
|
||||
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, (DWORD) processId);
|
||||
if (!hProcess) return false;
|
||||
BOOL ok = TerminateProcess(hProcess, (UINT) exitCode);
|
||||
CloseHandle(hProcess);
|
||||
return ok != FALSE;
|
||||
}
|
||||
|
||||
// ****************************************************************************************************************
|
||||
bool CWinProcess::terminateProcessFromModuleName(const std::string &moduleName, uint exitCode)
|
||||
{
|
||||
return terminateProcess(getProcessIdFromModuleFilename(moduleName), exitCode);
|
||||
}
|
||||
|
||||
|
||||
///////////////////
|
||||
// CProcessWatch //
|
||||
///////////////////
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// I didn't use and test that code, eventually, but maybe useful in the future
|
||||
|
||||
class CProcessWatchTask : public IRunnable
|
||||
{
|
||||
public:
|
||||
HANDLE HProcess;
|
||||
public:
|
||||
CProcessWatchTask(HANDLE hProcess) : HProcess(hProcess)
|
||||
{
|
||||
}
|
||||
virtual void run()
|
||||
{
|
||||
WaitForSingleObject(HProcess, INFINITE);
|
||||
}
|
||||
};
|
||||
|
||||
class CProcessWatchImpl
|
||||
{
|
||||
public:
|
||||
bool Launched;
|
||||
IThread *WatchThread;
|
||||
CProcessWatchTask *WatchTask;
|
||||
public:
|
||||
CProcessWatchImpl() : Launched(false), WatchThread(NULL), WatchTask(NULL)
|
||||
{
|
||||
}
|
||||
~CProcessWatchImpl()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
if (WatchThread)
|
||||
{
|
||||
if (WatchThread->isRunning())
|
||||
{
|
||||
WatchThread->terminate();
|
||||
}
|
||||
delete WatchTask;
|
||||
delete WatchThread;
|
||||
WatchTask = NULL;
|
||||
WatchThread = NULL;
|
||||
Launched = false;
|
||||
}
|
||||
}
|
||||
bool launch(const std::string &programName, const std::string &arguments)
|
||||
{
|
||||
if (isRunning()) return false;
|
||||
PROCESS_INFORMATION processInfo;
|
||||
STARTUPINFO startupInfo = {0};
|
||||
startupInfo.cb = sizeof(STARTUPINFO);
|
||||
if (CreateProcess(programName.c_str(), const_cast<LPTSTR>(arguments.c_str()), NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo))
|
||||
{
|
||||
WatchTask = new CProcessWatchTask(processInfo.hProcess);
|
||||
WatchThread = IThread::create(WatchTask);
|
||||
WatchThread->start();
|
||||
Launched = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool isRunning()
|
||||
{
|
||||
if (!Launched) return false;
|
||||
nlassert(WatchThread);
|
||||
nlassert(WatchTask);
|
||||
if (WatchThread->isRunning()) return true;
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CProcessWatch::CProcessWatch()
|
||||
{
|
||||
_PImpl = new CProcessWatchImpl;
|
||||
}
|
||||
|
||||
CProcessWatch::~CProcessWatch()
|
||||
{
|
||||
delete _PImpl;
|
||||
}
|
||||
|
||||
bool CProcessWatch::launch(const std::string &programName, const std::string &arguments)
|
||||
{
|
||||
return _PImpl->launch(programName, arguments);
|
||||
}
|
||||
|
||||
bool CProcessWatch::isRunning() const
|
||||
{
|
||||
return _PImpl->isRunning();
|
||||
}
|
||||
|
||||
*/
|
||||
} // NLMISC
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,3 @@
|
||||
|
||||
ADD_SUBDIRECTORY(bin2c)
|
||||
|
@ -0,0 +1,10 @@
|
||||
FILE(GLOB SRC *.cpp *.h)
|
||||
|
||||
ADD_EXECUTABLE(bin2c ${SRC})
|
||||
|
||||
TARGET_LINK_LIBRARIES(bin2c)
|
||||
NL_DEFAULT_PROPS(bin2c "NeL, Tools: bin2c")
|
||||
NL_ADD_RUNTIME_FLAGS(bin2c)
|
||||
|
||||
INSTALL(TARGETS bin2c RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT toolsmisc)
|
||||
|
Loading…
Reference in New Issue