2009-09-08 12:08:10 +00:00
|
|
|
/* PCSX2 - PS2 Emulator for PCs
|
|
|
|
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
|
|
|
*
|
|
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
2009-02-09 21:15:56 +00:00
|
|
|
*
|
2009-09-08 12:08:10 +00:00
|
|
|
* PCSX2 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 General Public License for more details.
|
2009-02-09 21:15:56 +00:00
|
|
|
*
|
2009-09-08 12:08:10 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
2009-02-09 21:15:56 +00:00
|
|
|
*/
|
2009-09-08 12:08:10 +00:00
|
|
|
|
|
|
|
#pragma once
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-10-07 19:20:11 +00:00
|
|
|
#include <semaphore.h>
|
2009-02-09 21:15:56 +00:00
|
|
|
#include <errno.h> // EBUSY
|
2009-07-03 00:49:40 +00:00
|
|
|
#include <pthread.h>
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-04-29 11:47:05 +00:00
|
|
|
#include "Pcsx2Defs.h"
|
2009-09-29 19:16:00 +00:00
|
|
|
#include "ScopedPtr.h"
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-10-07 19:20:11 +00:00
|
|
|
#undef Yield // release th burden of windows.h global namespace spam.
|
2009-08-25 15:38:48 +00:00
|
|
|
class wxTimeSpan;
|
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
namespace Threading
|
|
|
|
{
|
2009-08-15 06:17:43 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2009-02-09 21:15:56 +00:00
|
|
|
// Define some useful object handles - wait events, mutexes.
|
|
|
|
|
2009-07-17 03:43:45 +00:00
|
|
|
// pthread Cond is an evil api that is not suited for Pcsx2 needs.
|
|
|
|
// Let's not use it. Use mutexes and semaphores instead to create waits. (Air)
|
|
|
|
#if 0
|
2009-02-09 21:15:56 +00:00
|
|
|
struct WaitEvent
|
|
|
|
{
|
|
|
|
pthread_cond_t cond;
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
|
|
|
|
WaitEvent();
|
|
|
|
~WaitEvent();
|
|
|
|
|
|
|
|
void Set();
|
|
|
|
void Wait();
|
|
|
|
};
|
2009-07-17 03:43:45 +00:00
|
|
|
#endif
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-10-07 19:20:11 +00:00
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// NonblockingMutex
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// This is a very simple non-blocking mutex, which behaves similarly to pthread_mutex's
|
|
|
|
// trylock(), but without any of the extra overhead needed to set up a structure capable
|
|
|
|
// of blocking waits. It basically optimizes to a single InterlockedExchange.
|
|
|
|
//
|
|
|
|
// Simple use: if TryLock() returns false, the Bool is already interlocked by another thread.
|
|
|
|
// If TryLock() returns true, you've locked the object and are *responsible* for unlocking
|
|
|
|
// it later.
|
|
|
|
//
|
|
|
|
class NonblockingMutex
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
volatile long val;
|
|
|
|
|
|
|
|
public:
|
|
|
|
NonblockingMutex() : val( false ) {}
|
|
|
|
virtual ~NonblockingMutex() throw() {};
|
|
|
|
|
|
|
|
bool TryLock() throw()
|
|
|
|
{
|
|
|
|
return !_InterlockedExchange( &val, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsLocked()
|
|
|
|
{ return !!val; }
|
|
|
|
|
|
|
|
void Release()
|
|
|
|
{ val = false; }
|
|
|
|
};
|
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
struct Semaphore
|
|
|
|
{
|
|
|
|
sem_t sema;
|
|
|
|
|
|
|
|
Semaphore();
|
|
|
|
~Semaphore();
|
|
|
|
|
2009-02-28 20:55:53 +00:00
|
|
|
void Reset();
|
2009-02-09 21:15:56 +00:00
|
|
|
void Post();
|
|
|
|
void Post( int multiple );
|
2009-08-25 15:38:48 +00:00
|
|
|
|
2009-09-05 23:07:23 +00:00
|
|
|
#if wxUSE_GUI
|
|
|
|
void WaitGui();
|
2009-09-07 21:16:12 +00:00
|
|
|
bool WaitGui( const wxTimeSpan& timeout );
|
2009-09-05 23:07:23 +00:00
|
|
|
#endif
|
2009-02-09 21:15:56 +00:00
|
|
|
void Wait();
|
2009-09-07 21:16:12 +00:00
|
|
|
bool Wait( const wxTimeSpan& timeout );
|
2009-08-15 06:17:43 +00:00
|
|
|
void WaitNoCancel();
|
|
|
|
int Count();
|
2009-02-09 21:15:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct MutexLock
|
|
|
|
{
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
|
|
|
|
MutexLock();
|
2009-07-03 06:05:48 +00:00
|
|
|
MutexLock( bool isRecursive );
|
2009-02-09 21:15:56 +00:00
|
|
|
~MutexLock();
|
|
|
|
|
|
|
|
void Lock();
|
|
|
|
void Unlock();
|
2009-09-29 19:16:00 +00:00
|
|
|
bool TryLock();
|
2009-02-09 21:15:56 +00:00
|
|
|
};
|
|
|
|
|
2009-03-16 18:32:18 +00:00
|
|
|
// Returns the number of available logical CPUs (cores plus hyperthreaded cpus)
|
2009-02-09 21:15:56 +00:00
|
|
|
extern void CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhysicalCPU );
|
|
|
|
|
|
|
|
// Releases a timeslice to other threads.
|
|
|
|
extern void Timeslice();
|
|
|
|
|
|
|
|
// For use in spin/wait loops.
|
|
|
|
extern void SpinWait();
|
2009-08-20 23:05:26 +00:00
|
|
|
|
2009-02-28 20:55:53 +00:00
|
|
|
// sleeps the current thread for the given number of milliseconds.
|
|
|
|
extern void Sleep( int ms );
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-09-29 19:16:00 +00:00
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// IThread - Interface for the public access to PersistentThread.
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// Class usage: Can be used for allowing safe nullification of a thread handle. Rather
|
|
|
|
// than being NULL'd, the handle can be mapped to an IThread implementation which acts
|
|
|
|
// as a do-nothing placebo or an assertion generator.
|
|
|
|
//
|
|
|
|
class IThread
|
|
|
|
{
|
|
|
|
DeclareNoncopyableObject(IThread);
|
|
|
|
|
|
|
|
public:
|
|
|
|
IThread() {}
|
|
|
|
virtual ~IThread() throw() {}
|
|
|
|
|
|
|
|
virtual bool IsSelf() const { return false; }
|
|
|
|
virtual bool IsRunning() { return false; }
|
|
|
|
|
|
|
|
virtual void Start() {}
|
|
|
|
virtual void Cancel( bool isBlocking = true ) {}
|
Lots of new code maintenance stuffs:
* Completely new assertion macros: pxAssert, pxAssertMsg, and pxFail, pxAssertDev (both which default to using a message). These replace *all* wxASSERT, DevAssert, and jASSUME varieties of macros. New macros borrow the best of all assertion worlds: MSVCRT, wxASSERT, and AtlAssume. :)
* Rewrote the Console namespace as a structure called IConsoleWriter, and created several varieties of ConsoleWriters for handling different states of log and console availability (should help reduce overhead of console logging nicely).
* More improvements to the PersistentThread model, using safely interlocked "Do*" style callbacks for starting and cleaning up threads.
* Fixed console logs so that they're readable in Win32 notepad again (the log writer adds CRs to naked LFs).
* Added AppInit.cpp -- contains constructor, destructor, OnInit, and command line parsing mess.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1950 96395faa-99c1-11dd-bbfe-3dabce05a288
2009-10-04 08:27:27 +00:00
|
|
|
virtual void Block() {}
|
2009-09-29 19:16:00 +00:00
|
|
|
virtual bool Detach() { return false; }
|
|
|
|
};
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// PersistentThread - Helper class for the basics of starting/managing persistent threads.
|
|
|
|
// --------------------------------------------------------------------------------------
|
Lots of new code maintenance stuffs:
* Completely new assertion macros: pxAssert, pxAssertMsg, and pxFail, pxAssertDev (both which default to using a message). These replace *all* wxASSERT, DevAssert, and jASSUME varieties of macros. New macros borrow the best of all assertion worlds: MSVCRT, wxASSERT, and AtlAssume. :)
* Rewrote the Console namespace as a structure called IConsoleWriter, and created several varieties of ConsoleWriters for handling different states of log and console availability (should help reduce overhead of console logging nicely).
* More improvements to the PersistentThread model, using safely interlocked "Do*" style callbacks for starting and cleaning up threads.
* Fixed console logs so that they're readable in Win32 notepad again (the log writer adds CRs to naked LFs).
* Added AppInit.cpp -- contains constructor, destructor, OnInit, and command line parsing mess.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1950 96395faa-99c1-11dd-bbfe-3dabce05a288
2009-10-04 08:27:27 +00:00
|
|
|
// This class is meant to be a helper for the typical threading model of "start once and
|
|
|
|
// reuse many times." This class incorporates a lot of extra overhead in stopping and
|
|
|
|
// starting threads, but in turn provides most of the basic thread-safety and event-handling
|
|
|
|
// functionality needed for a threaded operation. In practice this model is usually an
|
|
|
|
// ideal one for efficiency since Operating Systems themselves typically subscribe to a
|
|
|
|
// design where sleeping, suspending, and resuming threads is very efficient, but starting
|
|
|
|
// new threads has quite a bit of overhead.
|
|
|
|
//
|
|
|
|
// To use this as a base class for your threaded procedure, overload the following virtual
|
|
|
|
// methods:
|
|
|
|
// void OnStart();
|
|
|
|
// void ExecuteTask();
|
|
|
|
// void OnThreadCleanup();
|
|
|
|
//
|
|
|
|
// Use the public methods Start() and Cancel() to start and shutdown the thread, and use
|
|
|
|
// m_sem_event internally to post/receive events for the thread (make a public accessor for
|
|
|
|
// it in your derived class if your thread utilizes the post).
|
2009-09-29 19:16:00 +00:00
|
|
|
//
|
|
|
|
// Notes:
|
|
|
|
// * Constructing threads as static global vars isn't recommended since it can potentially
|
|
|
|
// confuse w32pthreads, if the static initializers are executed out-of-order (C++ offers
|
|
|
|
// no dependency options for ensuring correct static var initializations). Use heap
|
|
|
|
// allocation to create thread objects instead.
|
|
|
|
//
|
|
|
|
class PersistentThread : public virtual IThread
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2009-09-21 03:33:35 +00:00
|
|
|
DeclareNoncopyableObject(PersistentThread);
|
2009-08-20 14:34:48 +00:00
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
protected:
|
|
|
|
typedef int (*PlainJoeFP)();
|
2009-09-29 19:16:00 +00:00
|
|
|
|
|
|
|
wxString m_name; // diagnostic name for our thread.
|
|
|
|
|
2009-08-15 06:17:43 +00:00
|
|
|
pthread_t m_thread;
|
2009-08-25 15:38:48 +00:00
|
|
|
Semaphore m_sem_event; // general wait event that's needed by most threads.
|
2009-09-07 21:16:12 +00:00
|
|
|
Semaphore m_sem_finished; // used for canceling and closing threads in a deadlock-safe manner
|
2009-10-07 19:20:11 +00:00
|
|
|
MutexLock m_lock_start; // used to lock the Start() code from starting simultaneous threads accidentally.
|
2009-09-29 19:16:00 +00:00
|
|
|
|
2009-09-03 11:59:05 +00:00
|
|
|
volatile long m_detached; // a boolean value which indicates if the m_thread handle is valid
|
|
|
|
volatile long m_running; // set true by Start(), and set false by Cancel(), Block(), etc.
|
2009-09-29 19:16:00 +00:00
|
|
|
|
|
|
|
// exception handle, set non-NULL if the thread terminated with an exception
|
|
|
|
// Use RethrowException() to re-throw the exception using its original exception type.
|
|
|
|
ScopedPtr<Exception::BaseException> m_except;
|
2009-09-03 11:59:05 +00:00
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
public:
|
2009-09-16 17:23:02 +00:00
|
|
|
virtual ~PersistentThread() throw();
|
2009-08-15 06:17:43 +00:00
|
|
|
PersistentThread();
|
2009-09-29 19:16:00 +00:00
|
|
|
PersistentThread( const char* name );
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-02-17 01:38:02 +00:00
|
|
|
virtual void Start();
|
2009-08-15 06:17:43 +00:00
|
|
|
virtual void Cancel( bool isBlocking = true );
|
2009-09-29 19:16:00 +00:00
|
|
|
virtual bool Detach();
|
Lots of new code maintenance stuffs:
* Completely new assertion macros: pxAssert, pxAssertMsg, and pxFail, pxAssertDev (both which default to using a message). These replace *all* wxASSERT, DevAssert, and jASSUME varieties of macros. New macros borrow the best of all assertion worlds: MSVCRT, wxASSERT, and AtlAssume. :)
* Rewrote the Console namespace as a structure called IConsoleWriter, and created several varieties of ConsoleWriters for handling different states of log and console availability (should help reduce overhead of console logging nicely).
* More improvements to the PersistentThread model, using safely interlocked "Do*" style callbacks for starting and cleaning up threads.
* Fixed console logs so that they're readable in Win32 notepad again (the log writer adds CRs to naked LFs).
* Added AppInit.cpp -- contains constructor, destructor, OnInit, and command line parsing mess.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1950 96395faa-99c1-11dd-bbfe-3dabce05a288
2009-10-04 08:27:27 +00:00
|
|
|
virtual void Block();
|
2009-09-29 19:16:00 +00:00
|
|
|
virtual void RethrowException() const;
|
2009-08-20 23:05:26 +00:00
|
|
|
|
2009-09-29 19:16:00 +00:00
|
|
|
bool IsRunning() const;
|
2009-08-31 03:47:05 +00:00
|
|
|
bool IsSelf() const;
|
2009-09-29 19:16:00 +00:00
|
|
|
wxString GetName() const;
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
protected:
|
Lots of new code maintenance stuffs:
* Completely new assertion macros: pxAssert, pxAssertMsg, and pxFail, pxAssertDev (both which default to using a message). These replace *all* wxASSERT, DevAssert, and jASSUME varieties of macros. New macros borrow the best of all assertion worlds: MSVCRT, wxASSERT, and AtlAssume. :)
* Rewrote the Console namespace as a structure called IConsoleWriter, and created several varieties of ConsoleWriters for handling different states of log and console availability (should help reduce overhead of console logging nicely).
* More improvements to the PersistentThread model, using safely interlocked "Do*" style callbacks for starting and cleaning up threads.
* Fixed console logs so that they're readable in Win32 notepad again (the log writer adds CRs to naked LFs).
* Added AppInit.cpp -- contains constructor, destructor, OnInit, and command line parsing mess.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1950 96395faa-99c1-11dd-bbfe-3dabce05a288
2009-10-04 08:27:27 +00:00
|
|
|
// Extending classes should always implement your own OnStart(), which is called by
|
|
|
|
// Start() once necessary locks have been obtained. Do not override Start() directly
|
|
|
|
// unless you're really sure that's what you need to do. ;)
|
|
|
|
virtual void OnStart()=0;
|
|
|
|
virtual void OnThreadCleanup()=0;
|
|
|
|
|
2009-03-16 18:32:18 +00:00
|
|
|
// Implemented by derived class to handle threading actions!
|
Lots of new code maintenance stuffs:
* Completely new assertion macros: pxAssert, pxAssertMsg, and pxFail, pxAssertDev (both which default to using a message). These replace *all* wxASSERT, DevAssert, and jASSUME varieties of macros. New macros borrow the best of all assertion worlds: MSVCRT, wxASSERT, and AtlAssume. :)
* Rewrote the Console namespace as a structure called IConsoleWriter, and created several varieties of ConsoleWriters for handling different states of log and console availability (should help reduce overhead of console logging nicely).
* More improvements to the PersistentThread model, using safely interlocked "Do*" style callbacks for starting and cleaning up threads.
* Fixed console logs so that they're readable in Win32 notepad again (the log writer adds CRs to naked LFs).
* Added AppInit.cpp -- contains constructor, destructor, OnInit, and command line parsing mess.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1950 96395faa-99c1-11dd-bbfe-3dabce05a288
2009-10-04 08:27:27 +00:00
|
|
|
virtual void ExecuteTask()=0;
|
2009-10-07 19:20:11 +00:00
|
|
|
|
|
|
|
// Inserts a thread cancellation point. If the thread has received a cancel request, this
|
|
|
|
// function will throw an SEH exception designed to exit the thread (so make sure to use C++
|
|
|
|
// object encapsulation for anything that could leak resources, to ensure object unwinding
|
|
|
|
// and cleanup, or use the DoThreadCleanup() override to perform resource cleanup).
|
|
|
|
void TestCancel();
|
|
|
|
|
|
|
|
// Yields this thread to other threads and checks for cancellation. A sleeping thread should
|
|
|
|
// always test for cancellation, however if you really don't want to, you can use Threading::Sleep()
|
|
|
|
// or better yet, disable cancellation of the thread completely with DisableCancellation().
|
|
|
|
//
|
|
|
|
// Parameters:
|
|
|
|
// ms - 'minimum' yield time in milliseconds (rough -- typically yields are longer by 1-5ms
|
|
|
|
// depending on operating system/platform). If ms is 0 or unspecified, then a single
|
|
|
|
// timeslice is yielded to other contending threads. If no threads are contending for
|
|
|
|
// time when ms==0, then no yield is done, but cancellation is still tested.
|
|
|
|
void Yield( int ms = 0 )
|
|
|
|
{
|
|
|
|
pxAssert( IsSelf() );
|
|
|
|
Threading::Sleep( ms );
|
|
|
|
TestCancel();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Section of methods for internal use only.
|
|
|
|
|
|
|
|
void _DoSetThreadName( const wxString& name );
|
|
|
|
void _DoSetThreadName( __unused const char* name );
|
|
|
|
void _internal_execute();
|
|
|
|
void _try_virtual_invoke( void (PersistentThread::*method)() );
|
|
|
|
void _ThreadCleanup();
|
|
|
|
|
|
|
|
static void* _internal_callback( void* func );
|
|
|
|
static void _pt_callback_cleanup( void* handle );
|
2009-02-09 21:15:56 +00:00
|
|
|
};
|
2009-09-29 19:16:00 +00:00
|
|
|
|
2009-03-16 18:32:18 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ScopedLock: Helper class for using Mutexes.
|
|
|
|
// Using this class provides an exception-safe (and generally clean) method of locking
|
2009-03-18 18:56:03 +00:00
|
|
|
// code inside a function or conditional block.
|
|
|
|
//
|
2009-08-20 14:34:48 +00:00
|
|
|
class ScopedLock
|
2009-03-16 18:32:18 +00:00
|
|
|
{
|
2009-09-21 03:33:35 +00:00
|
|
|
DeclareNoncopyableObject(ScopedLock);
|
2009-08-20 23:05:26 +00:00
|
|
|
|
2009-03-16 18:32:18 +00:00
|
|
|
protected:
|
|
|
|
MutexLock& m_lock;
|
2009-08-15 06:17:43 +00:00
|
|
|
bool m_IsLocked;
|
2009-03-16 18:32:18 +00:00
|
|
|
|
|
|
|
public:
|
2009-09-16 17:23:02 +00:00
|
|
|
virtual ~ScopedLock() throw()
|
2009-03-16 18:32:18 +00:00
|
|
|
{
|
2009-08-15 06:17:43 +00:00
|
|
|
if( m_IsLocked )
|
|
|
|
m_lock.Unlock();
|
2009-03-16 18:32:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ScopedLock( MutexLock& locker ) :
|
2009-08-15 06:17:43 +00:00
|
|
|
m_lock( locker )
|
|
|
|
, m_IsLocked( true )
|
|
|
|
{
|
|
|
|
m_lock.Lock();
|
|
|
|
}
|
2009-08-20 23:05:26 +00:00
|
|
|
|
2009-08-15 06:17:43 +00:00
|
|
|
// Provides manual unlocking of a scoped lock prior to object destruction.
|
|
|
|
void Unlock()
|
2009-03-16 18:32:18 +00:00
|
|
|
{
|
2009-08-15 06:17:43 +00:00
|
|
|
if( !m_IsLocked ) return;
|
|
|
|
m_IsLocked = false;
|
|
|
|
m_lock.Unlock();
|
|
|
|
}
|
2009-08-20 23:05:26 +00:00
|
|
|
|
2009-08-15 06:17:43 +00:00
|
|
|
// provides manual locking of a scoped lock, to re-lock after a manual unlocking.
|
|
|
|
void Lock()
|
|
|
|
{
|
|
|
|
if( m_IsLocked ) return;
|
2009-03-16 18:32:18 +00:00
|
|
|
m_lock.Lock();
|
2009-08-15 06:17:43 +00:00
|
|
|
m_IsLocked = true;
|
2009-03-16 18:32:18 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-03-18 18:56:03 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// BaseTaskThread - an abstract base class which provides simple parallel execution of
|
|
|
|
// single tasks.
|
|
|
|
//
|
|
|
|
// Implementation:
|
|
|
|
// To use this class your derived class will need to implement its own Task() function
|
|
|
|
// and also a "StartTask( parameters )" function which suits the need of your task, along
|
|
|
|
// with any local variables your task needs to do its job. You may additionally want to
|
|
|
|
// implement a "GetResult()" function, which would be a combination of WaitForResult()
|
|
|
|
// and a return value of the computational result.
|
|
|
|
//
|
|
|
|
// Thread Safety:
|
|
|
|
// If operating on local variables, you must execute WaitForResult() before leaving the
|
|
|
|
// variable scope -- or alternatively have your StartTask() implementation make full
|
|
|
|
// copies of dependent data. Also, by default PostTask() always assumes the previous
|
|
|
|
// task has completed. If your system can post a new task before the previous one has
|
|
|
|
// completed, then it needs to explicitly call WaitForResult() or provide a mechanism
|
|
|
|
// to cancel the previous task (which is probably more work than it's worth).
|
|
|
|
//
|
|
|
|
// Performance notes:
|
|
|
|
// * Remember that thread creation is generally slow, so you should make your object
|
|
|
|
// instance once early and then feed it tasks repeatedly over the course of program
|
|
|
|
// execution.
|
|
|
|
//
|
|
|
|
// * For threading to be a successful speedup, the task being performed should be as lock
|
|
|
|
// free as possible. For example using STL containers in parallel usually fails to
|
|
|
|
// yield any speedup due to the gratuitous amount of locking that the STL performs
|
|
|
|
// internally.
|
|
|
|
//
|
|
|
|
// * The best application of tasking threads is to divide a large loop over a linear array
|
|
|
|
// into smaller sections. For example, if you have 20,000 items to process, the task
|
|
|
|
// can be divided into two threads of 10,000 items each.
|
2009-08-20 23:05:26 +00:00
|
|
|
//
|
2009-08-15 06:17:43 +00:00
|
|
|
class BaseTaskThread : public PersistentThread
|
2009-03-18 18:56:03 +00:00
|
|
|
{
|
|
|
|
protected:
|
2009-08-15 06:17:43 +00:00
|
|
|
volatile bool m_Done;
|
2009-09-16 17:23:02 +00:00
|
|
|
volatile bool m_TaskPending;
|
2009-08-15 06:17:43 +00:00
|
|
|
Semaphore m_post_TaskComplete;
|
2009-09-16 17:23:02 +00:00
|
|
|
MutexLock m_lock_TaskComplete;
|
2009-03-18 18:56:03 +00:00
|
|
|
|
|
|
|
public:
|
2009-09-16 17:23:02 +00:00
|
|
|
virtual ~BaseTaskThread() throw() {}
|
2009-03-18 18:56:03 +00:00
|
|
|
BaseTaskThread() :
|
2009-08-15 06:17:43 +00:00
|
|
|
m_Done( false )
|
2009-09-16 17:23:02 +00:00
|
|
|
, m_TaskPending( false )
|
2009-08-15 06:17:43 +00:00
|
|
|
, m_post_TaskComplete()
|
2009-03-18 18:56:03 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
Lots of new code maintenance stuffs:
* Completely new assertion macros: pxAssert, pxAssertMsg, and pxFail, pxAssertDev (both which default to using a message). These replace *all* wxASSERT, DevAssert, and jASSUME varieties of macros. New macros borrow the best of all assertion worlds: MSVCRT, wxASSERT, and AtlAssume. :)
* Rewrote the Console namespace as a structure called IConsoleWriter, and created several varieties of ConsoleWriters for handling different states of log and console availability (should help reduce overhead of console logging nicely).
* More improvements to the PersistentThread model, using safely interlocked "Do*" style callbacks for starting and cleaning up threads.
* Fixed console logs so that they're readable in Win32 notepad again (the log writer adds CRs to naked LFs).
* Added AppInit.cpp -- contains constructor, destructor, OnInit, and command line parsing mess.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1950 96395faa-99c1-11dd-bbfe-3dabce05a288
2009-10-04 08:27:27 +00:00
|
|
|
void Block();
|
2009-09-16 17:23:02 +00:00
|
|
|
void PostTask();
|
|
|
|
void WaitForResult();
|
2009-08-20 23:05:26 +00:00
|
|
|
|
2009-03-18 18:56:03 +00:00
|
|
|
protected:
|
|
|
|
// Abstract method run when a task has been posted. Implementing classes should do
|
|
|
|
// all your necessary processing work here.
|
|
|
|
virtual void Task()=0;
|
|
|
|
|
Lots of new code maintenance stuffs:
* Completely new assertion macros: pxAssert, pxAssertMsg, and pxFail, pxAssertDev (both which default to using a message). These replace *all* wxASSERT, DevAssert, and jASSUME varieties of macros. New macros borrow the best of all assertion worlds: MSVCRT, wxASSERT, and AtlAssume. :)
* Rewrote the Console namespace as a structure called IConsoleWriter, and created several varieties of ConsoleWriters for handling different states of log and console availability (should help reduce overhead of console logging nicely).
* More improvements to the PersistentThread model, using safely interlocked "Do*" style callbacks for starting and cleaning up threads.
* Fixed console logs so that they're readable in Win32 notepad again (the log writer adds CRs to naked LFs).
* Added AppInit.cpp -- contains constructor, destructor, OnInit, and command line parsing mess.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1950 96395faa-99c1-11dd-bbfe-3dabce05a288
2009-10-04 08:27:27 +00:00
|
|
|
virtual void ExecuteTask();
|
2009-03-18 18:56:03 +00:00
|
|
|
};
|
2009-03-16 18:32:18 +00:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Our fundamental interlocking functions. All other useful interlocks can be derived
|
|
|
|
// from these little beasties!
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
extern void AtomicExchange( volatile u32& Target, u32 value );
|
|
|
|
extern void AtomicExchangeAdd( volatile u32& Target, u32 value );
|
|
|
|
extern void AtomicIncrement( volatile u32& Target );
|
|
|
|
extern void AtomicDecrement( volatile u32& Target );
|
|
|
|
extern void AtomicExchange( volatile s32& Target, s32 value );
|
|
|
|
extern void AtomicExchangeAdd( volatile s32& Target, u32 value );
|
|
|
|
extern void AtomicIncrement( volatile s32& Target );
|
|
|
|
extern void AtomicDecrement( volatile s32& Target );
|
|
|
|
|
|
|
|
extern void _AtomicExchangePointer( const void ** target, const void* value );
|
|
|
|
extern void _AtomicCompareExchangePointer( const void ** target, const void* value, const void* comparand );
|
|
|
|
|
|
|
|
#define AtomicExchangePointer( target, value ) \
|
|
|
|
_AtomicExchangePointer( (const void**)(&target), (const void*)(value) )
|
|
|
|
|
|
|
|
#define AtomicCompareExchangePointer( target, value, comparand ) \
|
|
|
|
_AtomicCompareExchangePointer( (const void**)(&target), (const void*)(value), (const void*)(comparand) )
|
|
|
|
|
|
|
|
}
|
|
|
|
|