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:
Jake.Stine
2009-10-04 08:27:27 +00:00
parent 638740b53d
commit 653d09e821
153 changed files with 7312 additions and 6715 deletions
+38
View File
@@ -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"
>
+7 -3
View File
@@ -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
+84
View File
@@ -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);
+67 -71
View File
@@ -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
+7 -5
View File
@@ -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"
+4 -6
View File
@@ -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__
+25
View File
@@ -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,
+38 -3
View File
@@ -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;
+30 -18
View File
@@ -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();
};
//////////////////////////////////////////////////////////////////////////////////////////
-33
View File
@@ -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(); }
};
+4
View File
@@ -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.
+2 -2
View File
@@ -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
View File
@@ -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
+41 -34
View File
@@ -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
}
+1 -1
View File
@@ -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;
}
+1
View File
@@ -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"
+57
View File
@@ -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
}
+64 -43
View File
@@ -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;
}
// --------------------------------------------------------------------------------------
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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