diff --git a/Doxyfile b/Doxyfile index 5a2bcf0b..a7bf1f18 100644 --- a/Doxyfile +++ b/Doxyfile @@ -655,7 +655,8 @@ EXCLUDE_PATTERNS = .svn \ Linux \ Unix \ Attic \ - OSX* + OSX* \ + Win32 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff --git a/build/codeblocks/sfml-system.cbp b/build/codeblocks/sfml-system.cbp index 7e82b659..6ae9ecc0 100644 --- a/build/codeblocks/sfml-system.cbp +++ b/build/codeblocks/sfml-system.cbp @@ -105,18 +105,20 @@ - - + + - + + - + + diff --git a/build/vc2005/sfml-system.vcproj b/build/vc2005/sfml-system.vcproj index fa95ce48..d357c97b 100644 --- a/build/vc2005/sfml-system.vcproj +++ b/build/vc2005/sfml-system.vcproj @@ -342,11 +342,11 @@ Name="Win32" > @@ -382,6 +382,46 @@ RelativePath="..\..\include\SFML\System\Lock.hpp" > + + + + + + + + + + + + + + @@ -422,6 +462,10 @@ RelativePath="..\..\include\SFML\System\Sleep.hpp" > + + diff --git a/build/vc2008/sfml-system.vcproj b/build/vc2008/sfml-system.vcproj index aa6d8d7d..00cf086c 100644 --- a/build/vc2008/sfml-system.vcproj +++ b/build/vc2008/sfml-system.vcproj @@ -335,11 +335,11 @@ Name="Win32" > @@ -375,6 +375,10 @@ RelativePath="..\..\src\SFML\System\Lock.hpp" > + + @@ -415,6 +419,10 @@ RelativePath="..\..\src\SFML\System\Sleep.hpp" > + + diff --git a/include/SFML/System/Mutex.hpp b/include/SFML/System/Mutex.hpp index 536c5371..1e267084 100644 --- a/include/SFML/System/Mutex.hpp +++ b/include/SFML/System/Mutex.hpp @@ -29,17 +29,59 @@ // Headers //////////////////////////////////////////////////////////// #include +#include -#ifdef SFML_SYSTEM_WINDOWS +namespace sf +{ +namespace priv +{ + class MutexImpl; +} - #include +//////////////////////////////////////////////////////////// +/// Mutex defines a mutex (MUTual EXclusion) object, +/// that allows a thread to lock critical instructions +/// to avoid simultaneous access with other threads. +/// See Lock for an efficient way of using it. +//////////////////////////////////////////////////////////// +class SFML_API Mutex : NonCopyable +{ +public : -#else + //////////////////////////////////////////////////////////// + /// Default constructor + /// + //////////////////////////////////////////////////////////// + Mutex(); - #include + //////////////////////////////////////////////////////////// + /// Destructor + /// + //////////////////////////////////////////////////////////// + ~Mutex(); -#endif + //////////////////////////////////////////////////////////// + /// Lock the mutex + /// + //////////////////////////////////////////////////////////// + void Lock(); + + //////////////////////////////////////////////////////////// + /// Unlock the mutex + /// + //////////////////////////////////////////////////////////// + void Unlock(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::MutexImpl* myMutexImpl; ///< OS-specific implementation +}; + +} // namespace sf #endif // SFML_MUTEX_HPP diff --git a/include/SFML/System/Randomizer.hpp b/include/SFML/System/Randomizer.hpp index 8ed27cde..cb9585e7 100644 --- a/include/SFML/System/Randomizer.hpp +++ b/include/SFML/System/Randomizer.hpp @@ -79,13 +79,6 @@ public : /// //////////////////////////////////////////////////////////// static int Random(int Begin, int End); - -private : - - //////////////////////////////////////////////////////////// - // Static member variables - //////////////////////////////////////////////////////////// - static unsigned int ourSeed; }; } // namespace sf diff --git a/include/SFML/System/Sleep.hpp b/include/SFML/System/Sleep.hpp index 2d0ebcaf..7338cdfa 100644 --- a/include/SFML/System/Sleep.hpp +++ b/include/SFML/System/Sleep.hpp @@ -33,13 +33,13 @@ namespace sf { - //////////////////////////////////////////////////////////// - /// Make the current thread sleep for a given time - /// - /// \param Duration : Time to sleep, in seconds (must be >= 0) - /// - //////////////////////////////////////////////////////////// - void SFML_API Sleep(float Duration); +//////////////////////////////////////////////////////////// +/// Make the current thread sleep for a given time +/// +/// \param Duration : Time to sleep, in seconds (must be >= 0) +/// +//////////////////////////////////////////////////////////// +void SFML_API Sleep(float Duration); } // namespace sf diff --git a/include/SFML/System/Thread.hpp b/include/SFML/System/Thread.hpp index 1cfe1e60..4c123c73 100644 --- a/include/SFML/System/Thread.hpp +++ b/include/SFML/System/Thread.hpp @@ -29,17 +29,93 @@ // Headers //////////////////////////////////////////////////////////// #include +#include +#include -#ifdef SFML_SYSTEM_WINDOWS +namespace sf +{ +namespace priv +{ + class ThreadImpl; +} - #include +//////////////////////////////////////////////////////////// +/// Thread defines an easy way to manipulate a thread. +/// There are two ways to use Thread : +/// - Inherit from it and override the Run() virtual function +/// - Construct a Thread instance and pass it a function +/// pointer to call +//////////////////////////////////////////////////////////// +class SFML_API Thread : NonCopyable +{ +public : -#else + typedef void (*FuncType)(void*); - #include + //////////////////////////////////////////////////////////// + /// Construct the thread from a function pointer + /// + /// \param Function : Entry point of the thread + /// \param UserData : Data to pass to the thread function (NULL by default) + /// + //////////////////////////////////////////////////////////// + Thread(FuncType Function, void* UserData = NULL); -#endif + //////////////////////////////////////////////////////////// + /// Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Thread(); + + //////////////////////////////////////////////////////////// + /// Create and run the thread + /// + //////////////////////////////////////////////////////////// + void Launch(); + + //////////////////////////////////////////////////////////// + /// Wait until the thread finishes + /// + //////////////////////////////////////////////////////////// + void Wait(); + + //////////////////////////////////////////////////////////// + /// Terminate the thread + /// Terminating a thread with this function is not safe, + /// you should rather try to make the thread function + /// terminate by itself + /// + //////////////////////////////////////////////////////////// + void Terminate(); + +protected : + + //////////////////////////////////////////////////////////// + /// Default constructor + /// + //////////////////////////////////////////////////////////// + Thread(); + +private : + + friend class priv::ThreadImpl; + + //////////////////////////////////////////////////////////// + /// Function called as the thread entry point + /// + //////////////////////////////////////////////////////////// + virtual void Run(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::ThreadImpl* myThreadImpl; ///< OS-specific implementation of the thread + FuncType myFunction; ///< Function to call as the thread entry point + void* myUserData; ///< Data to pass to the thread function +}; + +} // namespace sf #endif // SFML_THREAD_HPP diff --git a/samples/sound/Sound.cpp b/samples/sound/Sound.cpp index 94314d3c..982eb99c 100644 --- a/samples/sound/Sound.cpp +++ b/samples/sound/Sound.cpp @@ -31,11 +31,11 @@ void PlaySound() // Loop while the sound is playing while (Sound.GetStatus() == sf::Sound::Playing) { - // Display the playing position - std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << Sound.GetPlayingOffset() << " sec "; - // Leave some CPU time for other processes sf::Sleep(0.1f); + + // Display the playing position + std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << Sound.GetPlayingOffset() << " sec "; } std::cout << std::endl << std::endl; } @@ -64,11 +64,11 @@ void PlayMusic() // Loop while the music is playing while (Music.GetStatus() == sf::Music::Playing) { - // Display the playing position - std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << Music.GetPlayingOffset() << " sec "; - // Leave some CPU time for other processes sf::Sleep(0.1f); + + // Display the playing position + std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << Music.GetPlayingOffset() << " sec "; } std::cout << std::endl; } diff --git a/src/SFML/System/Win32/Mutex.cpp b/src/SFML/System/Mutex.cpp similarity index 83% rename from src/SFML/System/Win32/Mutex.cpp rename to src/SFML/System/Mutex.cpp index 717062c4..8d4b49c9 100644 --- a/src/SFML/System/Win32/Mutex.cpp +++ b/src/SFML/System/Mutex.cpp @@ -25,7 +25,18 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include + + +#if defined(SFML_SYSTEM_WINDOWS) + + #include + +#else + + #include + +#endif namespace sf @@ -35,7 +46,7 @@ namespace sf //////////////////////////////////////////////////////////// Mutex::Mutex() { - InitializeCriticalSection(&myHandle); + myMutexImpl = new priv::MutexImpl; } @@ -44,7 +55,7 @@ Mutex::Mutex() //////////////////////////////////////////////////////////// Mutex::~Mutex() { - DeleteCriticalSection(&myHandle); + delete myMutexImpl; } @@ -53,7 +64,7 @@ Mutex::~Mutex() //////////////////////////////////////////////////////////// void Mutex::Lock() { - EnterCriticalSection(&myHandle); + myMutexImpl->Lock(); } @@ -62,7 +73,7 @@ void Mutex::Lock() //////////////////////////////////////////////////////////// void Mutex::Unlock() { - LeaveCriticalSection(&myHandle); + myMutexImpl->Unlock(); } } // namespace sf diff --git a/src/SFML/System/Platform.hpp b/src/SFML/System/Platform.hpp index f9b7e122..acf62c0f 100644 --- a/src/SFML/System/Platform.hpp +++ b/src/SFML/System/Platform.hpp @@ -35,7 +35,7 @@ #include -#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_MACOS) || defined(SFML_SYSTEM_FREEBSD) +#else #include diff --git a/src/SFML/System/Randomizer.cpp b/src/SFML/System/Randomizer.cpp index 93500bce..fec20964 100644 --- a/src/SFML/System/Randomizer.cpp +++ b/src/SFML/System/Randomizer.cpp @@ -33,23 +33,20 @@ namespace { // Set the random numbers sequence seed with the current system time, so that it is always different - unsigned int SetRandomSeed() + unsigned int InitializeSeed() { unsigned int Seed = static_cast(sf::priv::Platform::GetSystemTime() * 1000); srand(Seed); return Seed; } + + // Global storing the current seed + unsigned int GlobalSeed = InitializeSeed(); } namespace sf { -//////////////////////////////////////////////////////////// -// Static member variables -//////////////////////////////////////////////////////////// -unsigned int Randomizer::ourSeed = SetRandomSeed(); - - //////////////////////////////////////////////////////////// /// Set the seed for the generator. Using a known seed /// allows you to reproduce the same sequence of random number @@ -57,7 +54,7 @@ unsigned int Randomizer::ourSeed = SetRandomSeed(); void Randomizer::SetSeed(unsigned int Seed) { srand(Seed); - ourSeed = Seed; + GlobalSeed = Seed; } @@ -66,7 +63,7 @@ void Randomizer::SetSeed(unsigned int Seed) //////////////////////////////////////////////////////////// unsigned int Randomizer::GetSeed() { - return ourSeed; + return GlobalSeed; } diff --git a/src/SFML/System/Win32/Thread.cpp b/src/SFML/System/Thread.cpp similarity index 66% rename from src/SFML/System/Win32/Thread.cpp rename to src/SFML/System/Thread.cpp index d2d1d822..3a88a9fc 100644 --- a/src/SFML/System/Win32/Thread.cpp +++ b/src/SFML/System/Thread.cpp @@ -25,9 +25,18 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include -#include -#include +#include + + +#if defined(SFML_SYSTEM_WINDOWS) + + #include + +#else + + #include + +#endif namespace sf @@ -36,9 +45,9 @@ namespace sf /// Default constructor //////////////////////////////////////////////////////////// Thread::Thread() : -myHandle (NULL), -myFunction(NULL), -myUserData(NULL) +myThreadImpl(NULL), +myFunction (NULL), +myUserData (NULL) { } @@ -48,9 +57,9 @@ myUserData(NULL) /// Construct the thread from a function pointer //////////////////////////////////////////////////////////// Thread::Thread(Thread::FuncType Function, void* UserData) : -myHandle (NULL), -myFunction(Function), -myUserData(UserData) +myThreadImpl(NULL), +myFunction (Function), +myUserData (UserData) { } @@ -62,8 +71,10 @@ myUserData(UserData) Thread::~Thread() { // Wait for the thread to finish before destroying the instance - if (myHandle) - Wait(); + Wait(); + + // Destroy the implementation + delete myThreadImpl; } @@ -72,12 +83,8 @@ Thread::~Thread() //////////////////////////////////////////////////////////// void Thread::Launch() { - // Create the thread - myHandle = reinterpret_cast(_beginthreadex(NULL, 0, &Thread::ThreadFunc, this, 0, NULL)); - - // Error ? - if (myHandle == NULL) - std::cerr << "Failed to create thread" << std::endl; + delete myThreadImpl; + myThreadImpl = new priv::ThreadImpl(this); } @@ -86,15 +93,8 @@ void Thread::Launch() //////////////////////////////////////////////////////////// void Thread::Wait() { - if (myHandle) - { - // Wait for the thread to finish, no timeout - WaitForSingleObject(myHandle, INFINITE); - - // Don't forget to close the thread handle (__endthreadex doesn't do it) - CloseHandle(myHandle); - myHandle = NULL; - } + if (myThreadImpl) + myThreadImpl->Wait(); } @@ -106,11 +106,8 @@ void Thread::Wait() //////////////////////////////////////////////////////////// void Thread::Terminate() { - if (myHandle) - { - TerminateThread(myHandle, 0); - myHandle = NULL; - } + if (myThreadImpl) + myThreadImpl->Terminate(); } @@ -123,22 +120,4 @@ void Thread::Run() myFunction(myUserData); } - -//////////////////////////////////////////////////////////// -/// Actual thread entry point, dispatches to instances -//////////////////////////////////////////////////////////// -unsigned int __stdcall Thread::ThreadFunc(void* UserData) -{ - // The Thread instance is stored in the user data - Thread* ThreadInstance = reinterpret_cast(UserData); - - // Forward to the instance - ThreadInstance->Run(); - - // Optional, but it is cleaner - _endthreadex(0); - - return 0; -} - } // namespace sf diff --git a/src/SFML/System/Unix/Mutex.cpp b/src/SFML/System/Unix/MutexImpl.cpp similarity index 86% rename from src/SFML/System/Unix/Mutex.cpp rename to src/SFML/System/Unix/MutexImpl.cpp index 9614361d..cb0f7f7b 100644 --- a/src/SFML/System/Unix/Mutex.cpp +++ b/src/SFML/System/Unix/MutexImpl.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -25,15 +25,17 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include namespace sf { +namespace priv +{ //////////////////////////////////////////////////////////// /// Default constructor //////////////////////////////////////////////////////////// -Mutex::Mutex() +MutexImpl::MutexImpl() { pthread_mutex_init(&myMutex, NULL); } @@ -42,7 +44,7 @@ Mutex::Mutex() //////////////////////////////////////////////////////////// /// Destructor //////////////////////////////////////////////////////////// -Mutex::~Mutex() +MutexImpl::~MutexImpl() { pthread_mutex_destroy(&myMutex); } @@ -51,7 +53,7 @@ Mutex::~Mutex() //////////////////////////////////////////////////////////// /// Lock the mutex //////////////////////////////////////////////////////////// -void Mutex::Lock() +void MutexImpl::Lock() { pthread_mutex_lock(&myMutex); } @@ -60,9 +62,11 @@ void Mutex::Lock() //////////////////////////////////////////////////////////// /// Unlock the mutex //////////////////////////////////////////////////////////// -void Mutex::Unlock() +void MutexImpl::Unlock() { pthread_mutex_unlock(&myMutex); } +} // namespace priv + } // namespace sf diff --git a/include/SFML/System/Unix/Mutex.hpp b/src/SFML/System/Unix/MutexImpl.hpp similarity index 80% rename from include/SFML/System/Unix/Mutex.hpp rename to src/SFML/System/Unix/MutexImpl.hpp index f8f24b6b..ed4b1a8d 100644 --- a/include/SFML/System/Unix/Mutex.hpp +++ b/src/SFML/System/Unix/MutexImpl.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -22,8 +22,8 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_MUTEXUNIX_HPP -#define SFML_MUTEXUNIX_HPP +#ifndef SFML_MUTEXIMPL_HPP +#define SFML_MUTEXIMPL_HPP //////////////////////////////////////////////////////////// // Headers @@ -34,13 +34,12 @@ namespace sf { +namespace priv +{ //////////////////////////////////////////////////////////// -/// Mutex defines a mutex (MUTual EXclusion) object, -/// that allows a thread to lock critical instructions -/// to avoid simultaneous access with other threads. -/// See Lock for an efficient way of using it. +/// Unix implementation of mutexes //////////////////////////////////////////////////////////// -class SFML_API Mutex : NonCopyable +class MutexImpl : NonCopyable { public : @@ -48,13 +47,13 @@ public : /// Default constructor /// //////////////////////////////////////////////////////////// - Mutex(); + MutexImpl(); //////////////////////////////////////////////////////////// /// Destructor /// //////////////////////////////////////////////////////////// - ~Mutex(); + ~MutexImpl(); //////////////////////////////////////////////////////////// /// Lock the mutex @@ -73,10 +72,12 @@ private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - pthread_mutex_t myMutex; ///< pthread instance of the mutex + pthread_mutex_t myMutex; ///< pthread handle of the mutex }; +} // namespace priv + } // namespace sf -#endif // SFML_MUTEXUNIX_HPP +#endif // SFML_MUTEXIMPL_HPP diff --git a/src/SFML/System/Unix/Thread.cpp b/src/SFML/System/Unix/ThreadImpl.cpp similarity index 53% rename from src/SFML/System/Unix/Thread.cpp rename to src/SFML/System/Unix/ThreadImpl.cpp index 3268f610..10ec8e2b 100644 --- a/src/SFML/System/Unix/Thread.cpp +++ b/src/SFML/System/Unix/ThreadImpl.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -25,78 +25,35 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include +#include #include namespace sf { +namespace priv +{ //////////////////////////////////////////////////////////// /// Default constructor //////////////////////////////////////////////////////////// -Thread::Thread() : -myIsActive(false), -myFunction(NULL), -myUserData(NULL) +ThreadImpl::ThreadImpl(Thread* Owner) : +myIsActive(true) { + myIsActive = pthread_create(&myThread, NULL, &ThreadFunc, Owner) == 0; -} - - -//////////////////////////////////////////////////////////// -/// Construct the thread from a function pointer -//////////////////////////////////////////////////////////// -Thread::Thread(Thread::FuncType Function, void* UserData) : -myIsActive(false), -myFunction(Function), -myUserData(UserData) -{ - -} - - -//////////////////////////////////////////////////////////// -/// Virtual destructor -//////////////////////////////////////////////////////////// -Thread::~Thread() -{ - // Wait for the thread to finish before destroying the instance - if (myIsActive) - Wait(); -} - - -//////////////////////////////////////////////////////////// -/// Create and run the thread -//////////////////////////////////////////////////////////// -void Thread::Launch() -{ - // Create the thread - myIsActive = true; - int Error = pthread_create(&myThread, NULL, &Thread::ThreadFunc, this); - - // Error ? - if (Error != 0) - { + if (!myIsActive) std::cerr << "Failed to create thread" << std::endl; - myIsActive = false; - } } //////////////////////////////////////////////////////////// /// Wait until the thread finishes //////////////////////////////////////////////////////////// -void Thread::Wait() +void ThreadImpl::Wait() { if (myIsActive) - { - // Wait for the thread to finish, no timeout pthread_join(myThread, NULL); - - // Reset the thread state - myIsActive = false; - } } @@ -106,41 +63,30 @@ void Thread::Wait() /// you should rather try to make the thread function /// terminate by itself //////////////////////////////////////////////////////////// -void Thread::Terminate() +void ThreadImpl::Terminate() { if (myIsActive) - { pthread_cancel(myThread); - myIsActive = false; - } } //////////////////////////////////////////////////////////// -/// Function called as the thread entry point +/// Global entry point for all threads //////////////////////////////////////////////////////////// -void Thread::Run() +void* ThreadFunc(void* UserData) { - if (myFunction) - myFunction(myUserData); -} - - -//////////////////////////////////////////////////////////// -/// Actual thread entry point, dispatches to instances -//////////////////////////////////////////////////////////// -void* Thread::ThreadFunc(void* UserData) -{ - // The sfThread instance is stored in the user data - Thread* ThreadToRun = reinterpret_cast(UserData); + // The Thread instance is stored in the user data + Thread* Owner = static_cast(UserData); // Tell the thread to handle cancel requests immediatly pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - // Forward to the instance - ThreadToRun->Run(); + // Forward to the owner + Owner->Run(); return NULL; } +} // namespace priv + } // namespace sf diff --git a/include/SFML/System/Unix/Thread.hpp b/src/SFML/System/Unix/ThreadImpl.hpp similarity index 56% rename from include/SFML/System/Unix/Thread.hpp rename to src/SFML/System/Unix/ThreadImpl.hpp index b26d38ff..2bf3e384 100644 --- a/include/SFML/System/Unix/Thread.hpp +++ b/src/SFML/System/Unix/ThreadImpl.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -22,8 +22,8 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_THREADUNIX_HPP -#define SFML_THREADUNIX_HPP +#ifndef SFML_THREADIMPL_HPP +#define SFML_THREADIMPL_HPP //////////////////////////////////////////////////////////// // Headers @@ -34,39 +34,24 @@ namespace sf { +class Thread; + +namespace priv +{ //////////////////////////////////////////////////////////// -/// Thread defines a thread. -/// There is two ways to use Thread : -/// - Inherit from it and override the Run() virtual function -/// - Construct a sfThread instance and pass it a function -/// pointer to call +/// Unix implementation of threads //////////////////////////////////////////////////////////// -class SFML_API Thread : NonCopyable +class ThreadImpl : NonCopyable { public : - typedef void (*FuncType)(void*); - //////////////////////////////////////////////////////////// - /// Construct the thread from a function pointer + /// Default constructor, launch the thread /// - /// \param Function : Entry point of the thread - /// \param UserData : Data to pass to the thread function (NULL by default) + /// \param Owner : Owner Thread instance to run /// //////////////////////////////////////////////////////////// - Thread(FuncType Function, void* UserData = NULL); - - //////////////////////////////////////////////////////////// - /// Virtual destructor - /// - //////////////////////////////////////////////////////////// - virtual ~Thread(); - - //////////////////////////////////////////////////////////// - /// Create and run the thread - /// - //////////////////////////////////////////////////////////// - void Launch(); + ThreadImpl(Thread* Owner); //////////////////////////////////////////////////////////// /// Wait until the thread finishes @@ -83,42 +68,28 @@ public : //////////////////////////////////////////////////////////// void Terminate(); -protected : - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - Thread(); - private : //////////////////////////////////////////////////////////// - /// Function called as the thread entry point + /// Global entry point for all threads /// - //////////////////////////////////////////////////////////// - virtual void Run(); - - //////////////////////////////////////////////////////////// - /// Actual thread entry point, dispatches to instances - /// - /// \param UserData : Data to pass to the thread function + /// \param UserData : User-defined data (contains the Thread instance) /// /// \return Error code /// //////////////////////////////////////////////////////////// - static void* ThreadFunc(void* UserData); + static void* EntryPoint(void* UserData); //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - pthread_t myThread; ///< Unix thread instance + pthread_t myThread; ///< pthread thread instance bool myIsActive; ///< Thread state (active or inactive) - FuncType myFunction; ///< Function to call as the thread entry point - void* myUserData; ///< Data to pass to the thread function }; +} // namespace priv + } // namespace sf -#endif // SFML_THREADUNIX_HPP +#endif // SFML_THREADIMPL_HPP diff --git a/src/SFML/System/Win32/MutexImpl.cpp b/src/SFML/System/Win32/MutexImpl.cpp new file mode 100644 index 00000000..17b326e0 --- /dev/null +++ b/src/SFML/System/Win32/MutexImpl.cpp @@ -0,0 +1,72 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// Default constructor +//////////////////////////////////////////////////////////// +MutexImpl::MutexImpl() +{ + InitializeCriticalSection(&myMutex); +} + + +//////////////////////////////////////////////////////////// +/// Destructor +//////////////////////////////////////////////////////////// +MutexImpl::~MutexImpl() +{ + DeleteCriticalSection(&myMutex); +} + + +//////////////////////////////////////////////////////////// +/// Lock the mutex +//////////////////////////////////////////////////////////// +void MutexImpl::Lock() +{ + EnterCriticalSection(&myMutex); +} + + +//////////////////////////////////////////////////////////// +/// Unlock the mutex +//////////////////////////////////////////////////////////// +void MutexImpl::Unlock() +{ + LeaveCriticalSection(&myMutex); +} + +} // namespace priv + +} // namespace sf diff --git a/include/SFML/System/Win32/Mutex.hpp b/src/SFML/System/Win32/MutexImpl.hpp similarity index 79% rename from include/SFML/System/Win32/Mutex.hpp rename to src/SFML/System/Win32/MutexImpl.hpp index 3cf5f9da..1d7df5b6 100644 --- a/include/SFML/System/Win32/Mutex.hpp +++ b/src/SFML/System/Win32/MutexImpl.hpp @@ -22,8 +22,8 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_MUTEXWIN32_HPP -#define SFML_MUTEXWIN32_HPP +#ifndef SFML_MUTEXIMPL_HPP +#define SFML_MUTEXIMPL_HPP //////////////////////////////////////////////////////////// // Headers @@ -34,15 +34,12 @@ namespace sf { +namespace priv +{ //////////////////////////////////////////////////////////// -/// Mutex defines a mutex (MUTual EXclusion) object, -/// that allows a thread to lock critical instructions -/// to avoid simultaneous access with other threads. -/// The Win32 version uses critical sections, as it is -/// faster than mutexes.
-/// See Lock for an efficient way of using it. +/// Windows implementation of mutexes //////////////////////////////////////////////////////////// -class SFML_API Mutex : NonCopyable +class MutexImpl : NonCopyable { public : @@ -50,13 +47,13 @@ public : /// Default constructor /// //////////////////////////////////////////////////////////// - Mutex(); + MutexImpl(); //////////////////////////////////////////////////////////// /// Destructor /// //////////////////////////////////////////////////////////// - ~Mutex(); + ~MutexImpl(); //////////////////////////////////////////////////////////// /// Lock the mutex @@ -75,10 +72,12 @@ private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - CRITICAL_SECTION myHandle; ///< Win32 handle of the mutex + CRITICAL_SECTION myMutex; ///< Win32 handle of the mutex }; +} // namespace priv + } // namespace sf -#endif // SFML_MUTEXWIN32_HPP +#endif // SFML_MUTEXIMPL_HPP diff --git a/src/SFML/System/Win32/ThreadImpl.cpp b/src/SFML/System/Win32/ThreadImpl.cpp new file mode 100644 index 00000000..8faa77e6 --- /dev/null +++ b/src/SFML/System/Win32/ThreadImpl.cpp @@ -0,0 +1,102 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// Default constructor +//////////////////////////////////////////////////////////// +ThreadImpl::ThreadImpl(Thread* Owner) +{ + myThread = reinterpret_cast(_beginthreadex(NULL, 0, &ThreadImpl::EntryPoint, Owner, 0, NULL)); + + if (!myThread) + std::cerr << "Failed to create thread" << std::endl; +} + + +//////////////////////////////////////////////////////////// +/// Destructor +//////////////////////////////////////////////////////////// +ThreadImpl::~ThreadImpl() +{ + if (myThread) + CloseHandle(myThread); +} + + +//////////////////////////////////////////////////////////// +/// Wait until the thread finishes +//////////////////////////////////////////////////////////// +void ThreadImpl::Wait() +{ + if (myThread) + WaitForSingleObject(myThread, INFINITE); +} + + +//////////////////////////////////////////////////////////// +/// Terminate the thread +/// Terminating a thread with this function is not safe, +/// you should rather try to make the thread function +/// terminate by itself +//////////////////////////////////////////////////////////// +void ThreadImpl::Terminate() +{ + if (myThread) + TerminateThread(myThread, 0); +} + + +//////////////////////////////////////////////////////////// +/// Global entry point for all threads +//////////////////////////////////////////////////////////// +unsigned int __stdcall ThreadImpl::EntryPoint(void* UserData) +{ + // The Thread instance is stored in the user data + Thread* Owner = static_cast(UserData); + + // Forward to the owner + Owner->Run(); + + // Optional, but it is cleaner + _endthreadex(0); + + return 0; +} + +} // namespace priv + +} // namespace sf diff --git a/include/SFML/System/Win32/Thread.hpp b/src/SFML/System/Win32/ThreadImpl.hpp similarity index 59% rename from include/SFML/System/Win32/Thread.hpp rename to src/SFML/System/Win32/ThreadImpl.hpp index f44dfe12..baf714bb 100644 --- a/include/SFML/System/Win32/Thread.hpp +++ b/src/SFML/System/Win32/ThreadImpl.hpp @@ -22,8 +22,8 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_THREADWIN32_HPP -#define SFML_THREADWIN32_HPP +#ifndef SFML_THREADIMPL_HPP +#define SFML_THREADIMPL_HPP //////////////////////////////////////////////////////////// // Headers @@ -34,39 +34,30 @@ namespace sf { +class Thread; + +namespace priv +{ //////////////////////////////////////////////////////////// -/// Thread defines an easy way to manipulate a thread. -/// There are two ways to use Thread : -/// - Inherit from it and override the Run() virtual function -/// - Construct a Thread instance and pass it a function -/// pointer to call +/// Windows implementation of threads //////////////////////////////////////////////////////////// -class SFML_API Thread : NonCopyable +class ThreadImpl : NonCopyable { public : - typedef void (*FuncType)(void*); + //////////////////////////////////////////////////////////// + /// Default constructor, launch the thread + /// + /// \param Owner : Owner Thread instance to run + /// + //////////////////////////////////////////////////////////// + ThreadImpl(Thread* Owner); //////////////////////////////////////////////////////////// - /// Construct the thread from a function pointer - /// - /// \param Function : Entry point of the thread - /// \param UserData : Data to pass to the thread function (NULL by default) + /// Destructor /// //////////////////////////////////////////////////////////// - Thread(FuncType Function, void* UserData = NULL); - - //////////////////////////////////////////////////////////// - /// Virtual destructor - /// - //////////////////////////////////////////////////////////// - virtual ~Thread(); - - //////////////////////////////////////////////////////////// - /// Create and run the thread - /// - //////////////////////////////////////////////////////////// - void Launch(); + ~ThreadImpl(); //////////////////////////////////////////////////////////// /// Wait until the thread finishes @@ -83,41 +74,27 @@ public : //////////////////////////////////////////////////////////// void Terminate(); -protected : - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - Thread(); - private : //////////////////////////////////////////////////////////// - /// Function called as the thread entry point + /// Global entry point for all threads /// - //////////////////////////////////////////////////////////// - virtual void Run(); - - //////////////////////////////////////////////////////////// - /// Actual thread entry point, dispatches to instances - /// - /// \param UserData : Data to pass to the thread function + /// \param UserData : User-defined data (contains the Thread instance) /// /// \return Error code /// //////////////////////////////////////////////////////////// - static unsigned int __stdcall ThreadFunc(void* UserData); + static unsigned int __stdcall EntryPoint(void* UserData); //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - HANDLE myHandle; ///< Win32 thread handle - FuncType myFunction; ///< Function to call as the thread entry point - void* myUserData; ///< Data to pass to the thread function + HANDLE myThread; ///< Win32 thread handle }; +} // namespace priv + } // namespace sf -#endif // SFML_THREADWIN32_HPP +#endif // SFML_THREADIMPL_HPP