mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07: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
This commit is contained in:
@@ -41,6 +41,8 @@
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="_LIB"
|
||||
ExceptionHandling="2"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="PrecompiledHeader.h"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
@@ -96,6 +98,8 @@
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="_LIB"
|
||||
ExceptionHandling="2"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="PrecompiledHeader.h"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
@@ -151,6 +155,8 @@
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="_LIB"
|
||||
ExceptionHandling="2"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="PrecompiledHeader.h"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
@@ -213,6 +219,34 @@
|
||||
RelativePath="..\..\src\Utilities\PathUtils.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\Utilities\PrecompiledHeader.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Devel|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\Utilities\StringHelpers.cpp"
|
||||
>
|
||||
@@ -367,6 +401,10 @@
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\include\Utilities\Assertions.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\Utilities\Console.h"
|
||||
>
|
||||
|
||||
@@ -59,7 +59,10 @@
|
||||
// jASSUME - give hints to the optimizer
|
||||
// This is primarily useful for the default case switch optimizer, which enables VC to
|
||||
// generate more compact switches.
|
||||
|
||||
//
|
||||
// Note: When using the PCSX2 Utilities library, this is deprecated. Use pxAssert instead,
|
||||
// which itself optimizes to an __assume() hint in release mode builds.
|
||||
//
|
||||
#ifndef jASSUME
|
||||
# ifdef NDEBUG
|
||||
# define jBREAKPOINT() ((void) 0)
|
||||
@@ -224,8 +227,9 @@ This theoretically unoptimizes. Not having much luck so far.
|
||||
# define PCSX2_ALIGNED_EXTERN(alig,x) extern x __attribute((aligned(alig)))
|
||||
# define PCSX2_ALIGNED16_EXTERN(x) extern x __attribute((aligned(16)))
|
||||
|
||||
# define __naked // GCC lacks the naked specifier
|
||||
# define CALLBACK // CALLBACK is a win32-specific mess
|
||||
# define __naked // GCC lacks the naked specifier
|
||||
# define __assume(cond) // GCC has no equivalent for __assume
|
||||
# define CALLBACK __stdcall
|
||||
|
||||
// Inlining note: GCC needs ((unused)) attributes defined on inlined functions to suppress
|
||||
// warnings when a static inlined function isn't used in the scope of a single file (which
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// pxAssert / pxAssertDev / pxFail / pxFailDev
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Standard debug-ony "nothrow" (pxAssert) and devel-style "throw" (pxAssertDev) style
|
||||
// assertions. All assertions act as valid conditional statements that return the result
|
||||
// of the specified conditional; useful for handling failed assertions in a "graceful" fashion
|
||||
// when utilizing the "ignore" feature of assertion debugging. (Release builds *always* return
|
||||
// true for assertion success, but no actual assertion check is performed).
|
||||
//
|
||||
// Performance: All assertion types optimize into __assume() directives in Release builds.
|
||||
//
|
||||
// pxAssertDev is an assertion tool for Devel builds, intended for sanity checking and/or
|
||||
// bounds checking variables in areas which are not performance critical.
|
||||
//
|
||||
// How it works: pxAssertDev throws an exception of type Exception::LogicError if the assertion
|
||||
// conditional is false. Typically for the end-user, this exception is handled by the general
|
||||
// exception handler defined by the application, which (should eventually) create some state
|
||||
// dumps and other information for troubleshooting purposes.
|
||||
//
|
||||
// From a debugging environment, you can trap your pxAssertDev by either breakpointing the
|
||||
// exception throw code in pxOnAssert, or by adding Exception::LogicError to your First-Chance
|
||||
// Exception catch list (Visual Studio, under the Debug->Exceptions menu/dialog). You should
|
||||
// have LogicErrors enabled as First-Chance exceptions regardless, so do it now. :)
|
||||
//
|
||||
// Credits Notes: These macros are based on a combination of wxASSERT, MSVCRT's assert
|
||||
// and the ATL's Assertion/Assumption macros. the best of all worlds!
|
||||
|
||||
#if defined(PCSX2_DEBUG)
|
||||
|
||||
# define pxAssertMsg(cond, msg) ( ((!!(cond)) || \
|
||||
(pxOnAssert(__TFILE__, __LINE__, __WXFUNCTION__, _T(#cond), msg), 0)), !!(cond) )
|
||||
|
||||
# define pxAssertDev(cond,msg) pxAssertMsg(cond, msg)
|
||||
|
||||
# define pxFail(msg) pxAssertMsg(false, msg)
|
||||
# define pxFailDev(msg) pxAssertDev(false, msg)
|
||||
|
||||
#elif defined(PCSX2_DEVBUILD)
|
||||
|
||||
// Devel builds use __assume for standard assertions and call pxOnAssertDevel
|
||||
// for AssertDev brand assertions (which typically throws a LogicError exception).
|
||||
|
||||
# define pxAssertMsg(cond, msg) (!!(cond))
|
||||
|
||||
# define pxAssertDev(cond, msg) ( ((!!(cond)) || \
|
||||
(pxOnAssert(__TFILE__, __LINE__, __WXFUNCTION__, _T(#cond), msg), 0)), !!(cond) )
|
||||
|
||||
# define pxFail(msg) __assume(false)
|
||||
# define pxFailDev(msg ) pxAssertDev(false, msg)
|
||||
|
||||
#else
|
||||
|
||||
// Release Builds just use __assume as an optimization, and always return 'true'
|
||||
// indicating the assertion check succeeded (no actual check is performed).
|
||||
|
||||
# define pxAssertMsg(cond, msg) (__assume(cond), true)
|
||||
# define pxAssertDev(cond, msg) (__assume(cond), true)
|
||||
# define pxFail(msg) (__assume(false), true)
|
||||
# define pxFailDev(msg) (__assume(false), true)
|
||||
|
||||
#endif
|
||||
|
||||
#define pxAssert(cond) pxAssertMsg(cond, (wxChar*)NULL)
|
||||
|
||||
extern void pxOnAssert( const wxChar* file, int line, const char* func, const wxChar* cond, const wxChar* msg);
|
||||
extern void pxOnAssert( const wxChar* file, int line, const char* func, const wxChar* cond, const char* msg);
|
||||
|
||||
@@ -17,103 +17,99 @@
|
||||
|
||||
#include "StringHelpers.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Console Namespace -- For printing messages to the console.
|
||||
//
|
||||
|
||||
enum ConsoleColors
|
||||
{
|
||||
Color_Black = 0,
|
||||
Color_Red,
|
||||
Color_Green,
|
||||
Color_Yellow,
|
||||
Color_Blue,
|
||||
Color_Magenta,
|
||||
Color_Cyan,
|
||||
Color_White
|
||||
};
|
||||
|
||||
// Use fastcall for the console; should be helpful in most cases
|
||||
#define __concall __fastcall
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// IConsole -- For printing messages to the console.
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// SysPrintf is depreciated; We should phase these in over time.
|
||||
//
|
||||
namespace Console
|
||||
struct IConsoleWriter
|
||||
{
|
||||
enum Colors
|
||||
{
|
||||
Color_Black = 0,
|
||||
Color_Red,
|
||||
Color_Green,
|
||||
Color_Yellow,
|
||||
Color_Blue,
|
||||
Color_Magenta,
|
||||
Color_Cyan,
|
||||
Color_White
|
||||
};
|
||||
// Write implementation for internal use only.
|
||||
void (__concall *DoWrite)( const wxString& fmt );
|
||||
|
||||
// va_args version of WriteLn, mostly for internal use only.
|
||||
extern void __fastcall _WriteLn( Colors color, const char* fmt, va_list args );
|
||||
// WriteLn implementation for internal use only.
|
||||
void (__concall *DoWriteLn)( const wxString& fmt );
|
||||
|
||||
extern void __fastcall SetTitle( const wxString& title );
|
||||
void (__concall *Newline)();
|
||||
|
||||
void (__concall *SetTitle)( const wxString& title );
|
||||
|
||||
// Changes the active console color.
|
||||
// This color will be unset by calls to colored text methods
|
||||
// such as ErrorMsg and Notice.
|
||||
extern void __fastcall SetColor( Colors color );
|
||||
void (__concall *SetColor)( ConsoleColors color );
|
||||
|
||||
// Restores the console color to default (usually low-intensity white on Win32)
|
||||
extern void ClearColor();
|
||||
void (__concall *ClearColor)();
|
||||
|
||||
// The following Write functions return bool so that we can use macros to exclude
|
||||
// them from different build types. The return values are always zero.
|
||||
// ----------------------------------------------------------------------------
|
||||
// Public members; call these to print stuff to console!
|
||||
|
||||
// Writes a newline to the console.
|
||||
extern bool Newline();
|
||||
void Write( ConsoleColors color, const char* fmt, ... ) const;
|
||||
void Write( const char* fmt, ... ) const;
|
||||
void Write( ConsoleColors color, const wxString& fmt ) const;
|
||||
void Write( const wxString& fmt ) const;
|
||||
|
||||
// Writes a line of colored text to the console, with automatic newline appendage.
|
||||
// The console color is reset to default when the operation is complete.
|
||||
extern bool WriteLn( Colors color, const char* fmt, ... );
|
||||
void WriteLn( ConsoleColors color, const char* fmt, ... ) const;
|
||||
void WriteLn( const char* fmt, ... ) const;
|
||||
void WriteLn( ConsoleColors color, const wxString& fmt ) const;
|
||||
void WriteLn( const wxString& fmt ) const;
|
||||
|
||||
// Writes a formatted message to the console, with appended newline.
|
||||
extern bool WriteLn( const char* fmt, ... );
|
||||
void Error( const char* fmt, ... ) const;
|
||||
void Notice( const char* fmt, ... ) const;
|
||||
void Status( const char* fmt, ... ) const;
|
||||
|
||||
// Writes a line of colored text to the console (no newline).
|
||||
// The console color is reset to default when the operation is complete.
|
||||
extern bool Write( Colors color, const char* fmt, ... );
|
||||
void Error( const wxString& src ) const;
|
||||
void Notice( const wxString& src ) const;
|
||||
void Status( const wxString& src ) const;
|
||||
|
||||
// Writes a formatted message to the console (no newline)
|
||||
extern bool Write( const char* fmt, ... );
|
||||
// ----------------------------------------------------------------------------
|
||||
// Private Members; for internal use only.
|
||||
|
||||
// Displays a message in the console with red emphasis.
|
||||
// Newline is automatically appended.
|
||||
extern bool Error( const char* fmt, ... );
|
||||
void _Write( const char* fmt, va_list args ) const;
|
||||
void _WriteLn( const char* fmt, va_list args ) const;
|
||||
void _WriteLn( ConsoleColors color, const char* fmt, va_list args ) const;
|
||||
};
|
||||
|
||||
// Displays a message in the console with yellow emphasis.
|
||||
// Newline is automatically appended.
|
||||
extern bool Notice( const char* fmt, ... );
|
||||
extern void Console_SetActiveHandler( const IConsoleWriter& writer, FILE* flushfp=NULL );
|
||||
extern const wxString& ConsoleBuffer_Get();
|
||||
extern void ConsoleBuffer_Clear();
|
||||
extern void ConsoleBuffer_FlushToFile( FILE *fp );
|
||||
|
||||
// Displays a message in the console with yellow emphasis.
|
||||
// Newline is automatically appended.
|
||||
extern bool Status( const char* fmt, ... );
|
||||
extern const IConsoleWriter ConsoleWriter_Null;
|
||||
extern const IConsoleWriter ConsoleWriter_Assert;
|
||||
extern const IConsoleWriter ConsoleWriter_Buffered;
|
||||
extern const IConsoleWriter ConsoleWriter_wxError;
|
||||
|
||||
|
||||
extern bool __fastcall Write( const wxString& text );
|
||||
extern bool __fastcall Write( Colors color, const wxString& text );
|
||||
extern bool __fastcall WriteLn( const wxString& text );
|
||||
extern bool __fastcall WriteLn( Colors color, const wxString& text );
|
||||
|
||||
extern bool __fastcall Error( const wxString& text );
|
||||
extern bool __fastcall Notice( const wxString& text );
|
||||
extern bool __fastcall Status( const wxString& text );
|
||||
}
|
||||
|
||||
using Console::Color_Black;
|
||||
using Console::Color_Red;
|
||||
using Console::Color_Green;
|
||||
using Console::Color_Blue;
|
||||
using Console::Color_Magenta;
|
||||
using Console::Color_Cyan;
|
||||
using Console::Color_Yellow;
|
||||
using Console::Color_White;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DevCon / DbgCon
|
||||
extern IConsoleWriter Console;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
# define DevCon Console
|
||||
# define DevMsg MsgBox
|
||||
extern IConsoleWriter DevConWriter;
|
||||
# define DevCon DevConWriter
|
||||
#else
|
||||
# define DevCon 0&&Console
|
||||
# define DevMsg
|
||||
# define DevCon ConsoleWriter_Null
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
# define DbgCon Console
|
||||
extern IConsoleWriter DbgConWriter;
|
||||
# define DbgCon DbgConWriter
|
||||
#else
|
||||
# define DbgCon 0&&Console
|
||||
# define DbgCon ConsoleWriter_Null
|
||||
#endif
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// Dependencies.h : Contains classes required by all Utilities headers.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DeclareNoncopyableObject
|
||||
// This macro provides an easy and clean method for ensuring objects are not copyable.
|
||||
@@ -73,17 +75,15 @@ protected:
|
||||
//
|
||||
#define wxLt(a) (a)
|
||||
|
||||
#ifndef wxASSERT_MSG_A
|
||||
# define wxASSERT_MSG_A( cond, msg ) wxASSERT_MSG( cond, wxString::FromAscii( msg ).c_str() )
|
||||
#endif
|
||||
|
||||
// must include wx/setup.h first, otherwise we get warnings/errors regarding __LINUX__
|
||||
#include <wx/setup.h>
|
||||
|
||||
class wxString;
|
||||
|
||||
#include "Pcsx2Defs.h"
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/tokenzr.h>
|
||||
//#include <wx/tokenzr.h>
|
||||
#include <wx/gdicmn.h> // for wxPoint/wxRect stuff
|
||||
#include <wx/intl.h>
|
||||
#include <wx/log.h>
|
||||
@@ -94,3 +94,5 @@ protected:
|
||||
#include <cstring> // string.h under c++
|
||||
#include <cstdio> // stdio.h under c++
|
||||
#include <cstdlib>
|
||||
|
||||
#include "Utilities/Assertions.h"
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
#include "Dependencies.h"
|
||||
|
||||
extern bool DevAssert( bool condition, const char* msg );
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// DESTRUCTOR_CATCHALL - safe destructor helper
|
||||
// --------------------------------------------------------------------------------------
|
||||
@@ -30,13 +28,13 @@ extern bool DevAssert( bool condition, const char* msg );
|
||||
#define __DESTRUCTOR_CATCHALL( funcname ) \
|
||||
catch( Exception::BaseException& ex ) \
|
||||
{ \
|
||||
Console::Error( "Unhandled BaseException in %s (ignored!):", funcname ); \
|
||||
Console::Error( ex.FormatDiagnosticMessage() ); \
|
||||
Console.Error( "Unhandled BaseException in %s (ignored!):", funcname ); \
|
||||
Console.Error( ex.FormatDiagnosticMessage() ); \
|
||||
} \
|
||||
catch( std::exception& ex ) \
|
||||
{ \
|
||||
Console::Error( "Unhandled std::exception in %s (ignored!):", funcname ); \
|
||||
Console::Error( ex.what() ); \
|
||||
Console.Error( "Unhandled std::exception in %s (ignored!):", funcname ); \
|
||||
Console.Error( ex.what() ); \
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
@@ -15,6 +15,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// RecursionGuard - Basic protection against function recursion
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Thread safety note: If used in a threaded environment, you shoud use a handle to a __threadlocal
|
||||
// storage variable (protects aaginst race conditions and, in *most* cases, is more desirable
|
||||
// behavior as well.
|
||||
//
|
||||
// Rationale: wxWidgets has its own wxRecursionGuard, but it has a sloppy implementation with
|
||||
// entirely unnecessary assertion checks.
|
||||
//
|
||||
class RecursionGuard
|
||||
{
|
||||
public:
|
||||
int& Counter;
|
||||
|
||||
RecursionGuard( int& counter ) : Counter( counter )
|
||||
{ ++Counter; }
|
||||
|
||||
virtual ~RecursionGuard() throw()
|
||||
{ --Counter; }
|
||||
|
||||
bool IsReentrant() const { return Counter > 1; }
|
||||
};
|
||||
|
||||
|
||||
enum PageProtectionMode
|
||||
{
|
||||
Protect_NoAccess = 0,
|
||||
|
||||
@@ -15,13 +15,48 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Dependencies.h"
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/gdicmn.h> // for wxPoint/wxRect stuff
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers for wxWidgets stuff!
|
||||
//
|
||||
extern void px_fputs( FILE* fp, const char* src );
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// toUTF8 - shortcut for str.ToUTF8().data()
|
||||
// --------------------------------------------------------------------------------------
|
||||
class toUTF8
|
||||
{
|
||||
DeclareNoncopyableObject( toUTF8 );
|
||||
|
||||
protected:
|
||||
wxCharBuffer m_charbuffer;
|
||||
|
||||
public:
|
||||
toUTF8( const wxString& str ) : m_charbuffer( str.ToUTF8().data() ) { }
|
||||
virtual ~toUTF8() throw() {}
|
||||
|
||||
operator const char*() { return m_charbuffer.data(); }
|
||||
};
|
||||
|
||||
// This class provided for completeness sake. You probably should use toUTF8 instead.
|
||||
class toAscii
|
||||
{
|
||||
DeclareNoncopyableObject( toAscii );
|
||||
|
||||
protected:
|
||||
wxCharBuffer m_charbuffer;
|
||||
|
||||
public:
|
||||
toAscii( const wxString& str ) : m_charbuffer( str.ToAscii().data() ) { }
|
||||
virtual ~toAscii() throw() {}
|
||||
|
||||
operator const char*() { return m_charbuffer.data(); }
|
||||
};
|
||||
|
||||
extern wxString fromUTF8( const char* src );
|
||||
extern wxString fromAscii( const char* src );
|
||||
|
||||
// wxWidgets lacks one of its own...
|
||||
extern const wxRect wxDefaultRect;
|
||||
|
||||
@@ -120,25 +120,33 @@ namespace Threading
|
||||
|
||||
virtual bool IsSelf() const { return false; }
|
||||
virtual bool IsRunning() { return false; }
|
||||
virtual int GetReturnCode() const
|
||||
{
|
||||
DevAssert( false, "Cannot obtain a return code from a placebo thread." );
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void Start() {}
|
||||
virtual void Cancel( bool isBlocking = true ) {}
|
||||
virtual sptr Block() { return NULL; }
|
||||
virtual void Block() {}
|
||||
virtual bool Detach() { return false; }
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// PersistentThread - Helper class for the basics of starting/managing persistent threads.
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Use this as a base class for your threaded procedure, and implement the 'int ExecuteTask()'
|
||||
// method. Use 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).
|
||||
// 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).
|
||||
//
|
||||
// Notes:
|
||||
// * Constructing threads as static global vars isn't recommended since it can potentially
|
||||
@@ -159,7 +167,6 @@ namespace Threading
|
||||
Semaphore m_sem_event; // general wait event that's needed by most threads.
|
||||
Semaphore m_sem_finished; // used for canceling and closing threads in a deadlock-safe manner
|
||||
MutexLock m_lock_start; // used to lock the Start() code from starting simutaneous threads accidentally.
|
||||
sptr m_returncode; // value returned from the thread on close.
|
||||
|
||||
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.
|
||||
@@ -176,18 +183,23 @@ namespace Threading
|
||||
virtual void Start();
|
||||
virtual void Cancel( bool isBlocking = true );
|
||||
virtual bool Detach();
|
||||
virtual sptr Block();
|
||||
|
||||
virtual int GetReturnCode() const;
|
||||
virtual void Block();
|
||||
virtual void RethrowException() const;
|
||||
|
||||
bool IsRunning() const;
|
||||
bool IsSelf() const;
|
||||
wxString GetName() const;
|
||||
|
||||
virtual void DoThreadCleanup();
|
||||
void _ThreadCleanup();
|
||||
|
||||
protected:
|
||||
|
||||
// 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;
|
||||
|
||||
void DoSetThreadName( const wxString& name );
|
||||
void DoSetThreadName( __unused const char* name );
|
||||
void _internal_execute();
|
||||
@@ -198,7 +210,7 @@ namespace Threading
|
||||
static void* _internal_callback( void* func );
|
||||
|
||||
// Implemented by derived class to handle threading actions!
|
||||
virtual sptr ExecuteTask()=0;
|
||||
virtual void ExecuteTask()=0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -295,7 +307,7 @@ namespace Threading
|
||||
{
|
||||
}
|
||||
|
||||
sptr Block();
|
||||
void Block();
|
||||
void PostTask();
|
||||
void WaitForResult();
|
||||
|
||||
@@ -304,7 +316,7 @@ namespace Threading
|
||||
// all your necessary processing work here.
|
||||
virtual void Task()=0;
|
||||
|
||||
sptr ExecuteTask();
|
||||
virtual void ExecuteTask();
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -55,36 +55,3 @@ public:
|
||||
wxLog::EnableLogging( m_prev );
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// wxToUTF8 - shortcut for str.ToUTF8().data()
|
||||
// --------------------------------------------------------------------------------------
|
||||
class wxToUTF8
|
||||
{
|
||||
DeclareNoncopyableObject( wxToUTF8 );
|
||||
|
||||
protected:
|
||||
wxCharBuffer m_charbuffer;
|
||||
|
||||
public:
|
||||
wxToUTF8( const wxString& str ) : m_charbuffer( str.ToUTF8().data() ) { }
|
||||
virtual ~wxToUTF8() throw() {}
|
||||
|
||||
operator const char*() { return m_charbuffer.data(); }
|
||||
};
|
||||
|
||||
// This class provided for completeness sake. You probably should use ToUTF8 instead.
|
||||
class wxToAscii
|
||||
{
|
||||
DeclareNoncopyableObject( wxToAscii );
|
||||
|
||||
protected:
|
||||
wxCharBuffer m_charbuffer;
|
||||
|
||||
public:
|
||||
wxToAscii( const wxString& str ) : m_charbuffer( str.ToAscii().data() ) { }
|
||||
virtual ~wxToAscii() throw() {}
|
||||
|
||||
operator const char*() { return m_charbuffer.data(); }
|
||||
};
|
||||
|
||||
|
||||
@@ -11,3 +11,7 @@ folder prefix, these files can be included the same way as other wxWidgets inclu
|
||||
|
||||
If/when PCSX2 upgrades to wx2.9/3.0 these files will be removed and the wxWidgets
|
||||
distribution files will automatically be used instead.
|
||||
|
||||
|
||||
NOTE: Removed wxScopedPtr in favor of our own implementation, which uses a more
|
||||
sensible API naming convention and also features better operator assignment.
|
||||
@@ -203,7 +203,7 @@ namespace x86Emitter
|
||||
Factor++;
|
||||
else
|
||||
{
|
||||
DevAssert( Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier." );
|
||||
pxAssertDev( Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier." );
|
||||
Index = src;
|
||||
Factor = 2;
|
||||
}
|
||||
@@ -287,7 +287,7 @@ namespace x86Emitter
|
||||
// Don't ask. --arcum42
|
||||
#if !defined(__LINUX__) || !defined(DEBUG)
|
||||
|
||||
Console::Error( "Emitter Error: Invalid short jump displacement = 0x%x", (int)displacement );
|
||||
Console.Error( "Emitter Error: Invalid short jump displacement = 0x%x", (int)displacement );
|
||||
#endif
|
||||
}
|
||||
BasePtr[-1] = (s8)displacement;
|
||||
|
||||
+292
-129
@@ -19,138 +19,301 @@
|
||||
using namespace Threading;
|
||||
using namespace std;
|
||||
|
||||
namespace Console
|
||||
// Important! Only Assert and Null console loggers are allowed for initial console targeting.
|
||||
// Other log targets rely on the static buffer and a threaded mutex lock, which are only valid
|
||||
// after C++ initialization has finished.
|
||||
void Console_SetActiveHandler( const IConsoleWriter& writer, FILE* flushfp )
|
||||
{
|
||||
MutexLock m_writelock;
|
||||
pxAssertDev(
|
||||
(writer.DoWrite != NULL) && (writer.DoWriteLn != NULL) &&
|
||||
(writer.Newline != NULL) && (writer.SetTitle != NULL) &&
|
||||
(writer.SetColor != NULL) && (writer.ClearColor != NULL),
|
||||
"Invalid IConsoleWriter object! All function pointer interfaces must be implemented."
|
||||
);
|
||||
|
||||
if( !ConsoleBuffer_Get().IsEmpty() )
|
||||
writer.DoWriteLn( ConsoleBuffer_Get() );
|
||||
|
||||
bool __fastcall Write( Colors color, const wxString& fmt )
|
||||
{
|
||||
SetColor( color );
|
||||
Write( fmt );
|
||||
ClearColor();
|
||||
Console = writer;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool __fastcall WriteLn( Colors color, const wxString& fmt )
|
||||
{
|
||||
SetColor( color );
|
||||
WriteLn( fmt );
|
||||
ClearColor();
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
__forceinline void __fastcall _Write( const char* fmt, va_list args )
|
||||
{
|
||||
std::string m_format_buffer;
|
||||
vssprintf( m_format_buffer, fmt, args );
|
||||
Write( wxString::FromUTF8( m_format_buffer.c_str() ) );
|
||||
}
|
||||
|
||||
__forceinline void __fastcall _WriteLn( const char* fmt, va_list args )
|
||||
{
|
||||
std::string m_format_buffer;
|
||||
vssprintf( m_format_buffer, fmt, args );
|
||||
WriteLn( wxString::FromUTF8( m_format_buffer.c_str() ) );
|
||||
}
|
||||
|
||||
__forceinline void __fastcall _WriteLn( Colors color, const char* fmt, va_list args )
|
||||
{
|
||||
SetColor( color );
|
||||
_WriteLn( fmt, args );
|
||||
ClearColor();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool Write( const char* fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
_Write( fmt, args );
|
||||
va_end(args);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Write( Colors color, const char* fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
SetColor( color );
|
||||
_Write( fmt, args );
|
||||
ClearColor();
|
||||
va_end(args);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool WriteLn( const char* fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
_WriteLn( fmt, args );
|
||||
va_end(args);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WriteLn( Colors color, const char* fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
_WriteLn( color, fmt, args );
|
||||
va_end(args);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool Error( const char* fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
_WriteLn( Color_Red, fmt, args );
|
||||
va_end(args);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Notice( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_WriteLn( Color_Yellow, fmt, list );
|
||||
va_end(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Status( const char* fmt, ... )
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_WriteLn( Color_Green, fmt, list );
|
||||
va_end(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool __fastcall Error( const wxString& src )
|
||||
{
|
||||
WriteLn( Color_Red, src );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool __fastcall Notice( const wxString& src )
|
||||
{
|
||||
WriteLn( Color_Yellow, src );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool __fastcall Status( const wxString& src )
|
||||
{
|
||||
WriteLn( Color_Green, src );
|
||||
return false;
|
||||
}
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
DevCon = writer;
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
DbgCon = writer;
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleImpl_Null
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
static void __concall ConsoleNull_SetTitle( const wxString& title ) {}
|
||||
static void __concall ConsoleNull_SetColor( ConsoleColors color ) {}
|
||||
static void __concall ConsoleNull_ClearColor() {}
|
||||
static void __concall ConsoleNull_Newline() {}
|
||||
static void __concall ConsoleNull_DoWrite( const wxString& fmt ) {}
|
||||
static void __concall ConsoleNull_DoWriteLn( const wxString& fmt ) {}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleImpl_Assert
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
static void __concall ConsoleAssert_DoWrite( const wxString& fmt )
|
||||
{
|
||||
pxFail( L"Console class has not been initialized; Message written:\n\t" + fmt );
|
||||
}
|
||||
|
||||
static void __concall ConsoleAssert_DoWriteLn( const wxString& fmt )
|
||||
{
|
||||
pxFail( L"Console class has not been initialized; Message written:\n\t" + fmt );
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleImpl_Buffered Implementations
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
static wxString m_buffer;
|
||||
|
||||
const wxString& ConsoleBuffer_Get()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
void ConsoleBuffer_Clear()
|
||||
{
|
||||
m_buffer.Clear();
|
||||
}
|
||||
|
||||
void ConsoleBuffer_FlushToFile( FILE *fp )
|
||||
{
|
||||
if( fp == NULL || m_buffer.IsEmpty() ) return;
|
||||
px_fputs( fp, toUTF8(m_buffer) );
|
||||
m_buffer.Clear();
|
||||
}
|
||||
|
||||
static void __concall ConsoleBuffer_DoWrite( const wxString& fmt )
|
||||
{
|
||||
m_buffer += fmt;
|
||||
}
|
||||
|
||||
static void __concall ConsoleBuffer_DoWriteLn( const wxString& fmt )
|
||||
{
|
||||
m_buffer += fmt + L"\n";
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleImpl_wxLogError Implementations
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
static void __concall Console_wxLogError_DoWriteLn( const wxString& fmt )
|
||||
{
|
||||
if( !m_buffer.IsEmpty() )
|
||||
{
|
||||
wxLogError( m_buffer );
|
||||
m_buffer.Clear();
|
||||
}
|
||||
wxLogError( fmt );
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// IConsole Implementations
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// Default write action at startup and shutdown is to use the stdout.
|
||||
void IConsole_DoWrite( const wxString& fmt )
|
||||
{
|
||||
wxPrintf( fmt );
|
||||
}
|
||||
|
||||
// Default write action at startup and shutdown is to use the stdout.
|
||||
void IConsole_DoWriteLn( const wxString& fmt )
|
||||
{
|
||||
wxPrintf( fmt );
|
||||
}
|
||||
|
||||
// Writes a line of colored text to the console (no newline).
|
||||
// The console color is reset to default when the operation is complete.
|
||||
void IConsoleWriter::Write( ConsoleColors color, const wxString& fmt ) const
|
||||
{
|
||||
SetColor( color );
|
||||
Write( fmt );
|
||||
ClearColor();
|
||||
}
|
||||
|
||||
// Writes a line of colored text to the console, with automatic newline appendage.
|
||||
// The console color is reset to default when the operation is complete.
|
||||
void IConsoleWriter::WriteLn( ConsoleColors color, const wxString& fmt ) const
|
||||
{
|
||||
SetColor( color );
|
||||
WriteLn( fmt );
|
||||
ClearColor();
|
||||
}
|
||||
|
||||
void IConsoleWriter::_Write( const char* fmt, va_list args ) const
|
||||
{
|
||||
std::string m_format_buffer;
|
||||
vssprintf( m_format_buffer, fmt, args );
|
||||
Write( wxString::FromUTF8( m_format_buffer.c_str() ) );
|
||||
}
|
||||
|
||||
void IConsoleWriter::_WriteLn( const char* fmt, va_list args ) const
|
||||
{
|
||||
std::string m_format_buffer;
|
||||
vssprintf( m_format_buffer, fmt, args );
|
||||
WriteLn( wxString::FromUTF8( m_format_buffer.c_str() ) );
|
||||
}
|
||||
|
||||
void IConsoleWriter::_WriteLn( ConsoleColors color, const char* fmt, va_list args ) const
|
||||
{
|
||||
SetColor( color );
|
||||
_WriteLn( fmt, args );
|
||||
ClearColor();
|
||||
}
|
||||
|
||||
void IConsoleWriter::Write( const char* fmt, ... ) const
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
_Write( fmt, args );
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void IConsoleWriter::Write( ConsoleColors color, const char* fmt, ... ) const
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
SetColor( color );
|
||||
_Write( fmt, args );
|
||||
ClearColor();
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void IConsoleWriter::WriteLn( const char* fmt, ... ) const
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
_WriteLn( fmt, args );
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void IConsoleWriter::WriteLn( ConsoleColors color, const char* fmt, ... ) const
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
_WriteLn( color, fmt, args );
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void IConsoleWriter::Write( const wxString& src ) const
|
||||
{
|
||||
DoWrite( src );
|
||||
}
|
||||
|
||||
void IConsoleWriter::WriteLn( const wxString& src ) const
|
||||
{
|
||||
DoWriteLn( src );
|
||||
}
|
||||
|
||||
void IConsoleWriter::Error( const char* fmt, ... ) const
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
_WriteLn( Color_Red, fmt, args );
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void IConsoleWriter::Notice( const char* fmt, ... ) const
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_WriteLn( Color_Yellow, fmt, list );
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
void IConsoleWriter::Status( const char* fmt, ... ) const
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
_WriteLn( Color_Green, fmt, list );
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
void IConsoleWriter::Error( const wxString& src ) const
|
||||
{
|
||||
WriteLn( Color_Red, src );
|
||||
}
|
||||
|
||||
void IConsoleWriter::Notice( const wxString& src ) const
|
||||
{
|
||||
WriteLn( Color_Yellow, src );
|
||||
}
|
||||
|
||||
void IConsoleWriter::Status( const wxString& src ) const
|
||||
{
|
||||
WriteLn( Color_Green, src );
|
||||
}
|
||||
|
||||
const IConsoleWriter ConsoleWriter_Null =
|
||||
{
|
||||
ConsoleNull_DoWrite,
|
||||
ConsoleNull_DoWriteLn,
|
||||
|
||||
ConsoleNull_Newline,
|
||||
|
||||
ConsoleNull_SetTitle,
|
||||
ConsoleNull_SetColor,
|
||||
ConsoleNull_ClearColor,
|
||||
};
|
||||
|
||||
const IConsoleWriter ConsoleWriter_Assert =
|
||||
{
|
||||
ConsoleAssert_DoWrite,
|
||||
ConsoleAssert_DoWriteLn,
|
||||
|
||||
ConsoleNull_Newline,
|
||||
|
||||
ConsoleNull_SetTitle,
|
||||
ConsoleNull_SetColor,
|
||||
ConsoleNull_ClearColor,
|
||||
};
|
||||
|
||||
const IConsoleWriter ConsoleWriter_wxError =
|
||||
{
|
||||
ConsoleBuffer_DoWrite, // Writes without newlines go to buffer to avoid error log spam.
|
||||
Console_wxLogError_DoWriteLn,
|
||||
|
||||
ConsoleNull_Newline,
|
||||
|
||||
ConsoleNull_SetTitle,
|
||||
ConsoleNull_SetColor,
|
||||
ConsoleNull_ClearColor,
|
||||
};
|
||||
|
||||
const IConsoleWriter ConsoleWriter_Buffered =
|
||||
{
|
||||
ConsoleBuffer_DoWrite, // Writes without newlines go to buffer to avoid assertion spam.
|
||||
ConsoleBuffer_DoWriteLn,
|
||||
|
||||
ConsoleNull_Newline,
|
||||
|
||||
ConsoleNull_SetTitle,
|
||||
ConsoleNull_SetColor,
|
||||
ConsoleNull_ClearColor,
|
||||
};
|
||||
|
||||
|
||||
// Important! Only Assert and Null console loggers are allowed for initial console targeting.
|
||||
// Other log targets rely on the static buffer and a threaded mutex lock, which are only valid
|
||||
// after C++ initialization has finished.
|
||||
|
||||
IConsoleWriter Console = ConsoleWriter_Assert;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
IConsoleWriter DevConWriter= ConsoleWriter_Assert;
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
IConsoleWriter DbgConWriter= ConsoleWriter_Assert;
|
||||
#endif
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include <wx/app.h>
|
||||
|
||||
wxString GetEnglish( const char* msg )
|
||||
{
|
||||
return wxString::FromAscii(msg);
|
||||
@@ -26,11 +28,9 @@ wxString GetTranslation( const char* msg )
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Force DevAssert to *not* inline for devel/debug builds (allows using breakpoints to trap
|
||||
// assertions), and force it to inline for release builds (optimizes it out completely since
|
||||
// IsDevBuild is false). Since Devel builds typically aren't enabled with Global Optimization/
|
||||
// LTCG, this currently isn't even necessary. But might as well, in case we decide at a later
|
||||
// date to re-enable LTCG for devel.
|
||||
// Force DevAssert to *not* inline for devel builds (allows using breakpoints to trap assertions,
|
||||
// and force it to inline for release builds (optimizes it out completely since IsDevBuild is a
|
||||
// const false).
|
||||
//
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
# define DEVASSERT_INLINE __noinline
|
||||
@@ -38,37 +38,44 @@ wxString GetTranslation( const char* msg )
|
||||
# define DEVASSERT_INLINE __forceinline
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Assertion tool for Devel builds, intended for sanity checking and/or bounds checking
|
||||
// variables in areas which are not performance critical.
|
||||
//
|
||||
// How it works: This function throws an exception of type Exception::AssertionFailure if
|
||||
// the assertion conditional is false. Typically for the end-user, this exception is handled
|
||||
// by the general handler, which (should eventually) create some state dumps and other
|
||||
// information for troubleshooting purposes.
|
||||
//
|
||||
// From a debugging environment, you can trap your DevAssert by either breakpointing the
|
||||
// exception throw below, or by adding Exception::LogicError to your First-Chance Exception
|
||||
// catch list (Visual Studio, under the Debug->Exceptions menu/dialog). You should have
|
||||
// LogicErrors enabled as First-Chance exceptions regardless, so do it now. :)
|
||||
//
|
||||
// Returns:
|
||||
// TRUE if the assertion succeeded (condition is valid), or FALSE if the assertion
|
||||
// failed. The true clause is only reachable in release builds, and can be used by code
|
||||
// to provide a "stable" escape clause for unexpected behavior.
|
||||
//
|
||||
DEVASSERT_INLINE bool DevAssert( bool condition, const char* msg )
|
||||
// Using a threadlocal assertion guard. Separate threads can assert at the same time.
|
||||
// That's ok. What we don't want is the *same* thread recurse-asserting.
|
||||
static __threadlocal int s_assert_guard = 0;
|
||||
|
||||
DEVASSERT_INLINE void pxOnAssert( const wxChar* file, int line, const char* func, const wxChar* cond, const wxChar* msg)
|
||||
{
|
||||
if( condition ) return true;
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
RecursionGuard guard( s_assert_guard );
|
||||
if( guard.IsReentrant() ) return;
|
||||
|
||||
if( wxTheApp == NULL )
|
||||
{
|
||||
// Note: Format uses MSVC's syntax for output window hotlinking.
|
||||
wxsFormat( L"%s(%d): Assertion failed in %s: %s\n",
|
||||
file, line, fromUTF8(func), msg );
|
||||
|
||||
wxASSERT_MSG_A( false, msg );
|
||||
|
||||
if( IsDevBuild && !IsDebugBuild )
|
||||
throw Exception::LogicError( msg );
|
||||
|
||||
return false;
|
||||
wxLogError( msg );
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __WXDEBUG__
|
||||
wxTheApp->OnAssertFailure( file, line, fromUTF8(func), cond, msg );
|
||||
#elif wxUSE_GUI
|
||||
// FIXME: this should create a popup dialog for devel builds.
|
||||
wxLogError( msg );
|
||||
#else
|
||||
wxLogError( msg );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void pxOnAssert( const wxChar* file, int line, const char* func, const wxChar* cond, const char* msg)
|
||||
{
|
||||
pxOnAssert( file, line, func, cond, fromUTF8(msg) );
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exception Namespace Implementations (Format message handlers for general exceptions)
|
||||
// --------------------------------------------------------------------------------------
|
||||
@@ -87,7 +94,7 @@ void Exception::BaseException::InitBaseEx( const wxString& msg_eng, const wxStri
|
||||
|
||||
#ifdef __LINUX__
|
||||
//wxLogError( msg_eng.c_str() );
|
||||
Console::Error( msg_eng );
|
||||
Console.Error( msg_eng );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -100,7 +107,7 @@ void Exception::BaseException::InitBaseEx( const char* msg_eng )
|
||||
|
||||
#ifdef __LINUX__
|
||||
//wxLogError( m_message_diag.c_str() );
|
||||
Console::Error( msg_eng );
|
||||
Console.Error( msg_eng );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace HostSys
|
||||
{
|
||||
u8 *Mem;
|
||||
Mem = (u8*)mmap((uptr*)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
if (Mem == MAP_FAILED) Console::Notice("Mmap Failed!");
|
||||
if (Mem == MAP_FAILED) Console.Notice("Mmap Failed!");
|
||||
|
||||
return Mem;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using std::string;
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
#include "Assertions.h"
|
||||
#include "MemcpyFast.h"
|
||||
#include "Console.h"
|
||||
#include "Exceptions.h"
|
||||
|
||||
@@ -17,6 +17,17 @@
|
||||
|
||||
const wxRect wxDefaultRect( wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord );
|
||||
|
||||
|
||||
__forceinline wxString fromUTF8( const char* src )
|
||||
{
|
||||
return wxString::FromUTF8( src );
|
||||
}
|
||||
|
||||
__forceinline wxString fromAscii( const char* src )
|
||||
{
|
||||
return wxString::FromAscii( src );
|
||||
}
|
||||
|
||||
// Splits a string into parts and adds the parts into the given SafeList.
|
||||
// This list is not cleared, so concatenating many splits into a single large list is
|
||||
// the 'default' behavior, unless you manually clear the SafeList prior to subsequent calls.
|
||||
@@ -160,3 +171,49 @@ bool TryParse( wxRect& dest, const wxString& src, const wxRect& defval, const wx
|
||||
dest = wxRect( point, size );
|
||||
return true;
|
||||
}
|
||||
|
||||
// Performs a cross-platform puts operation, which adds CRs to naked LFs on Win32 platforms,
|
||||
// so that Notepad won't throw a fit and Rama can read the logs again! On Unix and Mac platforms,
|
||||
// the input string is written unmodified.
|
||||
//
|
||||
// PCSX2 generally uses Unix-style newlines -- LF (\n) only -- hence there's no need to strip CRs
|
||||
// from incoming data. Mac platforms may need an implementation of their own that converts
|
||||
// newlines to CRs...?
|
||||
//
|
||||
void px_fputs( FILE* fp, const char* src )
|
||||
{
|
||||
if( fp == NULL ) return;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows needs CR's partnered with all newlines, or else notepad.exe can't view
|
||||
// the stupid logfile. Best way is to write one char at a time.. >_<
|
||||
|
||||
const char* curchar = src;
|
||||
bool prevcr = false;
|
||||
while( *curchar != 0 )
|
||||
{
|
||||
if( *curchar == '\r' )
|
||||
{
|
||||
prevcr = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only write a CR/LF pair if the current LF is not prefixed nor
|
||||
// post-fixed by a CR.
|
||||
if( *curchar == '\n' && !prevcr && (*(curchar+1) != '\r') )
|
||||
fputs( "\r\n", fp );
|
||||
else
|
||||
fputc( *curchar, fp );
|
||||
|
||||
prevcr = false;
|
||||
}
|
||||
++curchar;
|
||||
}
|
||||
|
||||
#else
|
||||
// Linux is happy with plain old LFs. Not sure about Macs... does OSX still
|
||||
// go by the old school Mac style of using Crs only?
|
||||
|
||||
fputs( src, emuLog ); // fputs does not do automatic newlines, so it's ok!
|
||||
#endif
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace Threading
|
||||
|
||||
static void _pt_callback_cleanup( void* handle )
|
||||
{
|
||||
((PersistentThread*)handle)->DoThreadCleanup();
|
||||
((PersistentThread*)handle)->_ThreadCleanup();
|
||||
}
|
||||
|
||||
PersistentThread::PersistentThread() :
|
||||
@@ -43,39 +43,60 @@ namespace Threading
|
||||
, m_sem_event()
|
||||
, m_sem_finished()
|
||||
, m_lock_start( true ) // recursive mutexing!
|
||||
, m_returncode( 0 )
|
||||
, m_detached( true ) // start out with m_thread in detached/invalid state
|
||||
, m_running( false )
|
||||
{
|
||||
}
|
||||
|
||||
// This destructor performs basic "last chance" cleanup, which is a blocking
|
||||
// join against non-detached threads. Detached threads are unhandled.
|
||||
// Extending classes should always implement their own thread closure process.
|
||||
// This class must not be deleted from its own thread. That would be like marrying
|
||||
// your sister, and then cheating on her with your daughter.
|
||||
// This destructor performs basic "last chance" cleanup, which is a blocking join
|
||||
// against the thread. Extending classes should almost always implement their own
|
||||
// thread closure process, since any PersistentThread will, by design, not terminate
|
||||
// unless it has been properly canceled.
|
||||
//
|
||||
// Thread safetly: This class must not be deleted from its own thread. That would be
|
||||
// like marrying your sister, and then cheating on her with your daughter.
|
||||
PersistentThread::~PersistentThread() throw()
|
||||
{
|
||||
if( m_running )
|
||||
try
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
m_sem_finished.WaitGui();
|
||||
#else
|
||||
m_sem_finished.Wait();
|
||||
#endif
|
||||
}
|
||||
wxString logfix = L"Thread Destructor for " + m_name;
|
||||
|
||||
Detach();
|
||||
if( m_running )
|
||||
{
|
||||
Console.WriteLn( logfix + L": Waiting for running thread to end.");
|
||||
#if wxUSE_GUI
|
||||
m_sem_finished.WaitGui();
|
||||
#else
|
||||
m_sem_finished.Wait();
|
||||
#endif
|
||||
// Need to lock here so that the thread can finish shutting down before
|
||||
// it gets destroyed, otherwise th mutex handle would become invalid.
|
||||
ScopedLock locker( m_lock_start );
|
||||
}
|
||||
else
|
||||
Console.WriteLn( logfix + L": thread not running.");
|
||||
Sleep( 1 );
|
||||
Detach();
|
||||
}
|
||||
DESTRUCTOR_CATCHALL
|
||||
}
|
||||
|
||||
// Main entry point for starting or e-starting a persistent thread. This function performs necessary
|
||||
// locks and checks for avoiding race conditions, and then calls OnStart() immeediately before
|
||||
// the actual thread creation. Extending classes should generally not override Start(), and should
|
||||
// instead override DoPrepStart instead.
|
||||
//
|
||||
// This function should not be called from the owner thread.
|
||||
void PersistentThread::Start()
|
||||
{
|
||||
ScopedLock startlock( m_lock_start ); // Prevents sudden parallel startup
|
||||
if( m_running ) return;
|
||||
|
||||
Detach(); // clean up previous thread, if one exists.
|
||||
Detach(); // clean up previous thread handle, if one exists.
|
||||
m_sem_finished.Reset();
|
||||
|
||||
OnStart();
|
||||
|
||||
if( pthread_create( &m_thread, NULL, _internal_callback, this ) != 0 )
|
||||
throw Exception::ThreadCreationError();
|
||||
|
||||
@@ -108,11 +129,12 @@ namespace Threading
|
||||
void PersistentThread::Cancel( bool isBlocking )
|
||||
{
|
||||
wxASSERT( !IsSelf() );
|
||||
if( !m_running ) return;
|
||||
|
||||
if( !m_running ) return;
|
||||
|
||||
if( m_detached )
|
||||
{
|
||||
Console::Notice( "Threading Warning: Attempted to cancel detached thread; Ignoring..." );
|
||||
Console.Notice( "Threading Warning: Attempted to cancel detached thread; Ignoring..." );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,9 +158,9 @@ namespace Threading
|
||||
// Returns the return code of the thread.
|
||||
// This method is roughly the equivalent of pthread_join().
|
||||
//
|
||||
sptr PersistentThread::Block()
|
||||
void PersistentThread::Block()
|
||||
{
|
||||
DevAssert( !IsSelf(), "Thread deadlock detected; Block() should never be called by the owner thread." );
|
||||
pxAssertDev( !IsSelf(), "Thread deadlock detected; Block() should never be called by the owner thread." );
|
||||
|
||||
if( m_running )
|
||||
#if wxUSE_GUI
|
||||
@@ -146,7 +168,6 @@ namespace Threading
|
||||
#else
|
||||
m_sem_finished.Wait();
|
||||
#endif
|
||||
return m_returncode;
|
||||
}
|
||||
|
||||
bool PersistentThread::IsSelf() const
|
||||
@@ -159,18 +180,6 @@ namespace Threading
|
||||
return !!m_running;
|
||||
}
|
||||
|
||||
// Gets the return code of the thread.
|
||||
// Exceptions:
|
||||
// InvalidOperation - thrown if the thread is still running or has never been started.
|
||||
//
|
||||
sptr PersistentThread::GetReturnCode() const
|
||||
{
|
||||
if( IsRunning() )
|
||||
throw Exception::InvalidOperation( "Thread.GetReturnCode : thread is still running." );
|
||||
|
||||
return m_returncode;
|
||||
}
|
||||
|
||||
// Throws an exception if the thread encountered one. Uses the BaseException's Rethrow() method,
|
||||
// which ensures the exception type remains consistent. Debuggable stacktraces will be lost, since
|
||||
// the thread will have allowed itself to terminate properly.
|
||||
@@ -180,10 +189,19 @@ namespace Threading
|
||||
m_except->Rethrow();
|
||||
}
|
||||
|
||||
// invoked when canceling or exiting the thread.
|
||||
void PersistentThread::DoThreadCleanup()
|
||||
// invoked internally when canceling or exiting the thread. Extending classes should implement
|
||||
// OnThreadCleanup() to extend clenup functionality.
|
||||
void PersistentThread::_ThreadCleanup()
|
||||
{
|
||||
wxASSERT( IsSelf() ); // only allowed from our own thread, thanks.
|
||||
|
||||
// Typically thread cleanup needs to lock against thread startup, since both
|
||||
// will perform some measure of variable inits or resets, depending on how the
|
||||
// derrived class is implemented.
|
||||
ScopedLock startlock( m_lock_start );
|
||||
|
||||
OnThreadCleanup();
|
||||
|
||||
m_running = false;
|
||||
m_sem_finished.Post();
|
||||
}
|
||||
@@ -199,7 +217,7 @@ namespace Threading
|
||||
DoSetThreadName( m_name );
|
||||
|
||||
try {
|
||||
m_returncode = ExecuteTask();
|
||||
ExecuteTask();
|
||||
}
|
||||
catch( std::logic_error& ex )
|
||||
{
|
||||
@@ -233,6 +251,9 @@ namespace Threading
|
||||
}
|
||||
}
|
||||
|
||||
void PersistentThread::OnStart() {}
|
||||
void PersistentThread::OnThreadCleanup() {}
|
||||
|
||||
void* PersistentThread::_internal_callback( void* itsme )
|
||||
{
|
||||
jASSUME( itsme != NULL );
|
||||
@@ -241,12 +262,12 @@ namespace Threading
|
||||
pthread_cleanup_push( _pt_callback_cleanup, itsme );
|
||||
owner._internal_execute();
|
||||
pthread_cleanup_pop( true );
|
||||
return (void*)owner.m_returncode;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PersistentThread::DoSetThreadName( const wxString& name )
|
||||
{
|
||||
DoSetThreadName( wxToUTF8(name) );
|
||||
DoSetThreadName( toUTF8(name) );
|
||||
}
|
||||
|
||||
void PersistentThread::DoSetThreadName( __unused const char* name )
|
||||
@@ -292,12 +313,12 @@ namespace Threading
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// Tells the thread to exit and then waits for thread termination.
|
||||
sptr BaseTaskThread::Block()
|
||||
void BaseTaskThread::Block()
|
||||
{
|
||||
if( !IsRunning() ) return m_returncode;
|
||||
if( !IsRunning() ) return;
|
||||
m_Done = true;
|
||||
m_sem_event.Post();
|
||||
return PersistentThread::Block();
|
||||
PersistentThread::Block();
|
||||
}
|
||||
|
||||
// Initiates the new task. This should be called after your own StartTask has
|
||||
@@ -326,7 +347,7 @@ namespace Threading
|
||||
m_post_TaskComplete.Reset();
|
||||
}
|
||||
|
||||
sptr BaseTaskThread::ExecuteTask()
|
||||
void BaseTaskThread::ExecuteTask()
|
||||
{
|
||||
while( !m_Done )
|
||||
{
|
||||
@@ -340,7 +361,7 @@ namespace Threading
|
||||
m_lock_TaskComplete.Unlock();
|
||||
};
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../PrecompiledHeader.h"
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Utilities/RedtapeWindows.h"
|
||||
#include <winnt.h>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../PrecompiledHeader.h"
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "RedtapeWindows.h"
|
||||
#include "WinVersion.h"
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user