/[pcsx2_0.9.7]/trunk/common/include/Utilities/Exceptions.h
ViewVC logotype

Annotation of /trunk/common/include/Utilities/Exceptions.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File MIME type: text/plain
File size: 13621 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 william 31 /* PCSX2 - PS2 Emulator for PCs
2     * Copyright (C) 2002-2010 PCSX2 Dev Team
3     *
4     * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5     * of the GNU Lesser General Public License as published by the Free Software Found-
6     * ation, either version 3 of the License, or (at your option) any later version.
7     *
8     * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10     * PURPOSE. See the GNU General Public License for more details.
11     *
12     * You should have received a copy of the GNU General Public License along with PCSX2.
13     * If not, see <http://www.gnu.org/licenses/>.
14     */
15    
16     #pragma once
17    
18     #include "Dependencies.h"
19     #include "StringHelpers.h"
20    
21     // --------------------------------------------------------------------------------------
22     // DESTRUCTOR_CATCHALL - safe destructor helper
23     // --------------------------------------------------------------------------------------
24     // In C++ destructors *really* need to be "nothrow" garaunteed, otherwise you can have
25     // disasterous nested exception throws during the unwinding process of an originating
26     // exception. Use this macro to dispose of these dangerous exceptions, and generate a
27     // friendly error log in their wake.
28     //
29     #define __DESTRUCTOR_CATCHALL( funcname ) \
30     catch( BaseException& ex ) \
31     { \
32     Console.Error( "Unhandled BaseException in %s (ignored!):", funcname ); \
33     Console.Error( ex.FormatDiagnosticMessage() ); \
34     } \
35     catch( std::exception& ex ) \
36     { \
37     Console.Error( "Unhandled std::exception in %s (ignored!):", funcname ); \
38     Console.Error( ex.what() ); \
39     }
40    
41     #define DESTRUCTOR_CATCHALL __DESTRUCTOR_CATCHALL( __pxFUNCTION__ )
42    
43     namespace Exception
44     {
45     int MakeNewType();
46    
47     // --------------------------------------------------------------------------------------
48     // BaseException
49     // --------------------------------------------------------------------------------------
50     // std::exception sucks, and isn't entirely cross-platform reliable in its implementation,
51     // so I made a replacement. The internal messages are non-const, which means that a
52     // catch clause can optionally modify them and then re-throw to a top-level handler.
53     //
54     // Note, this class is "abstract" which means you shouldn't use it directly like, ever.
55     // Use Exception::RuntimeError instead for generic exceptions.
56     //
57     // Because exceptions are the (only!) really useful example of multiple inheritance,
58     // this class has only a trivial constructor, and must be manually initialized using
59     // InitBaseEx() or by individual member assignments. This is because C++ multiple inheritence
60     // is, by design, a lot of fail, especially when class initializers are mixed in.
61     //
62     // [TODO] : Add an InnerException component, and Clone() facility.
63     //
64     class BaseException
65     {
66     protected:
67     wxString m_message_diag; // (untranslated) a "detailed" message of what disastrous thing has occurred!
68     wxString m_message_user; // (translated) a "detailed" message of what disastrous thing has occurred!
69    
70     public:
71     virtual ~BaseException() throw()=0; // the =0; syntax forces this class into "abstract" mode.
72    
73     const wxString& DiagMsg() const { return m_message_diag; }
74     const wxString& UserMsg() const { return m_message_user; }
75    
76     wxString& DiagMsg() { return m_message_diag; }
77     wxString& UserMsg() { return m_message_user; }
78    
79 william 62 BaseException& SetBothMsgs( const wxChar* msg_diag );
80     BaseException& SetDiagMsg( const wxString& msg_diag );
81     BaseException& SetUserMsg( const wxString& msg_user );
82    
83 william 31 // Returns a message suitable for diagnostic / logging purposes.
84     // This message is always in English, and includes a full stack trace.
85     virtual wxString FormatDiagnosticMessage() const;
86    
87     // Returns a message suitable for end-user display.
88     // This message is usually meant for display in a user popup or such.
89 william 62 virtual wxString FormatDisplayMessage() const;
90 william 31
91     virtual void Rethrow() const=0;
92     virtual BaseException* Clone() const=0;
93     };
94    
95     // --------------------------------------------------------------------------------------
96     // Ps2Generic Exception
97     // --------------------------------------------------------------------------------------
98     // This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc).
99     //
100     // Implementation note: does not derive from BaseException, so that we can use different
101     // catch block hierarchies to handle them (if needed).
102     //
103     // Translation Note: Currently these exceptions are never translated. English/diagnostic
104     // format only. :)
105     //
106     class Ps2Generic
107     {
108     protected:
109     wxString m_message; // a "detailed" message of what disastrous thing has occurred!
110    
111     public:
112     virtual ~Ps2Generic() throw() {}
113    
114     virtual u32 GetPc() const=0;
115     virtual bool IsDelaySlot() const=0;
116     virtual wxString Message() const { return m_message; }
117 william 62
118     virtual void Rethrow() const=0;
119     virtual Ps2Generic* Clone() const=0;
120 william 31 };
121    
122     // Some helper macros for defining the standard constructors of internationalized constructors
123     // Parameters:
124     // classname - Yeah, the name of this class being defined. :)
125     //
126     // defmsg - default message (in english), which will be used for both english and i18n messages.
127     // The text string will be passed through the translator, so if it's int he gettext database
128     // it will be optionally translated.
129     //
130     // BUGZ?? I'd rather use 'classname' on the Clone() prototype, but for some reason it generates
131 william 62 // ambiguity errors on virtual inheritance (it really shouldn't!). So I have to force it to the
132 william 31 // BaseException base class. Not sure if this is Stupid Standard Tricks or Stupid MSVC Tricks. --air
133     //
134     // (update: web searches indicate it's MSVC specific -- happens in 2008, not sure about 2010).
135     //
136 william 62 #define DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
137     private: \
138     typedef parent _parent; \
139     public: \
140 william 31 virtual ~classname() throw() {} \
141     virtual void Rethrow() const { throw *this; } \
142     virtual classname* Clone() const { return new classname( *this ); }
143    
144 william 62 #define DEFINE_EXCEPTION_MESSAGES( classname ) \
145     public: \
146     classname& SetBothMsgs( const wxChar* msg_diag ) { BaseException::SetBothMsgs(msg_diag); return *this; } \
147     classname& SetDiagMsg( const wxString& msg_diag ) { m_message_diag = msg_diag; return *this; } \
148     classname& SetUserMsg( const wxString& msg_user ) { m_message_user = msg_user; return *this; }
149 william 31
150 william 62 #define DEFINE_RUNTIME_EXCEPTION( classname, parent, message ) \
151     DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
152     classname() { SetDiagMsg(message); } \
153     DEFINE_EXCEPTION_MESSAGES( classname )
154    
155    
156 william 31 // ---------------------------------------------------------------------------------------
157     // RuntimeError - Generalized Exceptions with Recoverable Traits!
158     // ---------------------------------------------------------------------------------------
159    
160 william 62 class RuntimeError : public BaseException
161 william 31 {
162 william 62 DEFINE_EXCEPTION_COPYTORS( RuntimeError, BaseException )
163     DEFINE_EXCEPTION_MESSAGES( RuntimeError )
164    
165 william 31 public:
166     bool IsSilent;
167    
168 william 62 RuntimeError() { IsSilent = false; }
169 william 31 RuntimeError( const std::runtime_error& ex, const wxString& prefix=wxEmptyString );
170     RuntimeError( const std::exception& ex, const wxString& prefix=wxEmptyString );
171     };
172    
173     // --------------------------------------------------------------------------------------
174     // CancelAppEvent - Exception for canceling an event in a non-verbose fashion
175     // --------------------------------------------------------------------------------------
176     // Typically the PCSX2 interface issues popup dialogs for runtime errors. This exception
177     // instead issues a "silent" cancelation that is handled by the app gracefully (generates
178     // log, and resumes messages queue processing).
179     //
180     // I chose to have this exception derive from RuntimeError, since if one is thrown from outside
181     // an App message loop we'll still want it to be handled in a reasonably graceful manner.
182 william 62 class CancelEvent : public RuntimeError
183 william 31 {
184 william 62 DEFINE_RUNTIME_EXCEPTION( CancelEvent, RuntimeError, wxLt("No reason given.") )
185    
186 william 31 public:
187 william 62 explicit CancelEvent( const wxString& logmsg )
188 william 31 {
189     m_message_diag = logmsg;
190     // overridden message formatters only use the diagnostic version...
191     }
192    
193     virtual wxString FormatDisplayMessage() const;
194     virtual wxString FormatDiagnosticMessage() const;
195     };
196    
197 william 62 // ---------------------------------------------------------------------------------------
198     // OutOfMemory
199     // ---------------------------------------------------------------------------------------
200     // This exception has a custom-formatted Diagnostic string. The parameter give when constructing
201     // the exception is a block/alloc name, which is used as a formatting parameter in the diagnostic
202     // output. The default diagnostic message is "Out of memory exception, while allocating the %s."
203     // where %s is filled in with the block name.
204     //
205     // The user string is not custom-formatted, and should contain *NO* %s tags.
206     //
207     class OutOfMemory : public RuntimeError
208 william 31 {
209 william 62 DEFINE_RUNTIME_EXCEPTION( OutOfMemory, RuntimeError, wxLt("Out of memory?!") )
210    
211 william 31 public:
212 william 62 wxString AllocDescription;
213 william 31
214 william 62 public:
215     OutOfMemory( const wxString& allocdesc );
216 william 31
217     virtual wxString FormatDisplayMessage() const;
218     virtual wxString FormatDiagnosticMessage() const;
219     };
220    
221     class ParseError : public RuntimeError
222     {
223 william 62 DEFINE_RUNTIME_EXCEPTION( ParseError, RuntimeError, wxLt("Parse error") );
224 william 31 };
225    
226     // ---------------------------------------------------------------------------------------
227     // Hardware/OS Exceptions:
228     // HardwareDeficiency / VirtualMemoryMapConflict
229     // ---------------------------------------------------------------------------------------
230    
231     // This exception is a specific type of OutOfMemory error that isn't "really" an out of
232     // memory error. More likely it's caused by a plugin or driver reserving a range of memory
233     // we'd really like to have access to.
234 william 62 class VirtualMemoryMapConflict : public OutOfMemory
235 william 31 {
236 william 62 DEFINE_RUNTIME_EXCEPTION( VirtualMemoryMapConflict, OutOfMemory, wxLt("Virtual memory map confict: Unable to claim specific required memory regions.") )
237 william 31 };
238    
239 william 62 class HardwareDeficiency : public RuntimeError
240 william 31 {
241     public:
242 william 62 DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, RuntimeError, wxLt("Your machine's hardware is incapable of running PCSX2. Sorry dood.") );
243 william 31 };
244    
245     // ---------------------------------------------------------------------------------------
246     // Streaming (file) Exceptions:
247     // Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
248     // ---------------------------------------------------------------------------------------
249    
250 william 62 #define DEFINE_STREAM_EXCEPTION_ACCESSORS( classname ) \
251     virtual classname& SetStreamName( const wxString& name ) { StreamName = name; return *this; } \
252     virtual classname& SetStreamName( const char* name ) { StreamName = fromUTF8(name); return *this; }
253 william 31
254 william 62 #define DEFINE_STREAM_EXCEPTION( classname, parent, message ) \
255     DEFINE_RUNTIME_EXCEPTION( classname, parent, message ) \
256     classname( const wxString& filename ) { \
257     StreamName = filename; \
258     SetBothMsgs(message); \
259     } \
260     DEFINE_STREAM_EXCEPTION_ACCESSORS( classname )
261    
262 william 31 // Generic stream error. Contains the name of the stream and a message.
263     // This exception is usually thrown via derived classes, except in the (rare) case of a
264     // generic / unknown error.
265     //
266 william 62 class Stream : public RuntimeError
267 william 31 {
268 william 62 DEFINE_STREAM_EXCEPTION( Stream, RuntimeError, wxLt("General file operation error.") )
269    
270 william 31 public:
271     wxString StreamName; // name of the stream (if applicable)
272    
273     virtual wxString FormatDiagnosticMessage() const;
274     virtual wxString FormatDisplayMessage() const;
275     };
276    
277     // A generic base error class for bad streams -- corrupted data, sudden closures, loss of
278     // connection, or anything else that would indicate a failure to read the data after the
279     // stream was successfully opened.
280     //
281 william 62 class BadStream : public Stream
282 william 31 {
283 william 62 DEFINE_STREAM_EXCEPTION( BadStream, Stream, wxLt("File data is corrupted or incomplete, or the stream connection closed unexpectedly.") )
284 william 31 };
285    
286     // A generic exception for odd-ball stream creation errors.
287     //
288 william 62 class CannotCreateStream : public Stream
289 william 31 {
290 william 62 DEFINE_STREAM_EXCEPTION( CannotCreateStream, Stream, wxLt("File could not be created or opened.") )
291 william 31 };
292    
293     // Exception thrown when an attempt to open a non-existent file is made.
294     // (this exception can also mean file permissions are invalid)
295     //
296 william 62 class FileNotFound : public CannotCreateStream
297 william 31 {
298     public:
299 william 62 DEFINE_STREAM_EXCEPTION( FileNotFound, CannotCreateStream, wxLt("File not found.") )
300 william 31 };
301    
302 william 62 class AccessDenied : public CannotCreateStream
303 william 31 {
304     public:
305 william 62 DEFINE_STREAM_EXCEPTION( AccessDenied, CannotCreateStream, wxLt("Permission denied to file.") )
306 william 31 };
307    
308     // EndOfStream can be used either as an error, or used just as a shortcut for manual
309     // feof checks.
310     //
311 william 62 class EndOfStream : public Stream
312 william 31 {
313     public:
314 william 62 DEFINE_STREAM_EXCEPTION( EndOfStream, Stream, wxLt("Unexpected end of file or stream.") );
315 william 31 };
316    
317     #ifdef __WXMSW__
318     // --------------------------------------------------------------------------------------
319     // Exception::WinApiError
320     // --------------------------------------------------------------------------------------
321     class WinApiError : public RuntimeError
322     {
323 william 62 DEFINE_EXCEPTION_COPYTORS( WinApiError, RuntimeError )
324     DEFINE_EXCEPTION_MESSAGES( WinApiError )
325    
326 william 31 public:
327     int ErrorId;
328    
329     public:
330 william 62 WinApiError();
331 william 31
332     wxString GetMsgFromWindows() const;
333     virtual wxString FormatDisplayMessage() const;
334     virtual wxString FormatDiagnosticMessage() const;
335     };
336     #endif
337     }
338    
339     using Exception::BaseException;

  ViewVC Help
Powered by ViewVC 1.1.22