/[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 283 - (hide annotations) (download)
Thu Dec 23 12:39:52 2010 UTC (9 years, 7 months ago) by william
File MIME type: text/plain
File size: 13812 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4132 local: v0.9.7.282-latest) 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 william 273 #include "Assertions.h"
19     #include "ScopedPtr.h"
20 william 31
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 william 273 BaseException* FromErrno( const wxString& streamname, int errcode );
47 william 31
48     // --------------------------------------------------------------------------------------
49     // BaseException
50     // --------------------------------------------------------------------------------------
51     // std::exception sucks, and isn't entirely cross-platform reliable in its implementation,
52     // so I made a replacement. The internal messages are non-const, which means that a
53     // catch clause can optionally modify them and then re-throw to a top-level handler.
54     //
55     // Note, this class is "abstract" which means you shouldn't use it directly like, ever.
56     // Use Exception::RuntimeError instead for generic exceptions.
57     //
58     // Because exceptions are the (only!) really useful example of multiple inheritance,
59     // this class has only a trivial constructor, and must be manually initialized using
60     // InitBaseEx() or by individual member assignments. This is because C++ multiple inheritence
61     // is, by design, a lot of fail, especially when class initializers are mixed in.
62     //
63     // [TODO] : Add an InnerException component, and Clone() facility.
64     //
65     class BaseException
66     {
67     protected:
68     wxString m_message_diag; // (untranslated) a "detailed" message of what disastrous thing has occurred!
69     wxString m_message_user; // (translated) a "detailed" message of what disastrous thing has occurred!
70    
71     public:
72     virtual ~BaseException() throw()=0; // the =0; syntax forces this class into "abstract" mode.
73    
74     const wxString& DiagMsg() const { return m_message_diag; }
75     const wxString& UserMsg() const { return m_message_user; }
76    
77     wxString& DiagMsg() { return m_message_diag; }
78     wxString& UserMsg() { return m_message_user; }
79    
80 william 62 BaseException& SetBothMsgs( const wxChar* msg_diag );
81     BaseException& SetDiagMsg( const wxString& msg_diag );
82     BaseException& SetUserMsg( const wxString& msg_user );
83    
84 william 31 // Returns a message suitable for diagnostic / logging purposes.
85     // This message is always in English, and includes a full stack trace.
86     virtual wxString FormatDiagnosticMessage() const;
87    
88     // Returns a message suitable for end-user display.
89     // This message is usually meant for display in a user popup or such.
90 william 62 virtual wxString FormatDisplayMessage() const;
91 william 31
92     virtual void Rethrow() const=0;
93     virtual BaseException* Clone() const=0;
94     };
95    
96 william 273 typedef ScopedPtr<BaseException> ScopedExcept;
97    
98 william 31 // --------------------------------------------------------------------------------------
99     // Ps2Generic Exception
100     // --------------------------------------------------------------------------------------
101     // This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc).
102     //
103     // Implementation note: does not derive from BaseException, so that we can use different
104     // catch block hierarchies to handle them (if needed).
105     //
106     // Translation Note: Currently these exceptions are never translated. English/diagnostic
107     // format only. :)
108     //
109     class Ps2Generic
110     {
111     protected:
112     wxString m_message; // a "detailed" message of what disastrous thing has occurred!
113    
114     public:
115     virtual ~Ps2Generic() throw() {}
116    
117     virtual u32 GetPc() const=0;
118     virtual bool IsDelaySlot() const=0;
119     virtual wxString Message() const { return m_message; }
120 william 62
121     virtual void Rethrow() const=0;
122     virtual Ps2Generic* Clone() const=0;
123 william 31 };
124    
125     // Some helper macros for defining the standard constructors of internationalized constructors
126     // Parameters:
127     // classname - Yeah, the name of this class being defined. :)
128     //
129     // defmsg - default message (in english), which will be used for both english and i18n messages.
130     // The text string will be passed through the translator, so if it's int he gettext database
131     // it will be optionally translated.
132     //
133     // BUGZ?? I'd rather use 'classname' on the Clone() prototype, but for some reason it generates
134 william 62 // ambiguity errors on virtual inheritance (it really shouldn't!). So I have to force it to the
135 william 31 // BaseException base class. Not sure if this is Stupid Standard Tricks or Stupid MSVC Tricks. --air
136     //
137     // (update: web searches indicate it's MSVC specific -- happens in 2008, not sure about 2010).
138     //
139 william 62 #define DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
140     private: \
141     typedef parent _parent; \
142     public: \
143 william 31 virtual ~classname() throw() {} \
144     virtual void Rethrow() const { throw *this; } \
145     virtual classname* Clone() const { return new classname( *this ); }
146    
147 william 62 #define DEFINE_EXCEPTION_MESSAGES( classname ) \
148     public: \
149     classname& SetBothMsgs( const wxChar* msg_diag ) { BaseException::SetBothMsgs(msg_diag); return *this; } \
150     classname& SetDiagMsg( const wxString& msg_diag ) { m_message_diag = msg_diag; return *this; } \
151     classname& SetUserMsg( const wxString& msg_user ) { m_message_user = msg_user; return *this; }
152 william 31
153 william 62 #define DEFINE_RUNTIME_EXCEPTION( classname, parent, message ) \
154     DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
155     classname() { SetDiagMsg(message); } \
156     DEFINE_EXCEPTION_MESSAGES( classname )
157    
158    
159 william 31 // ---------------------------------------------------------------------------------------
160     // RuntimeError - Generalized Exceptions with Recoverable Traits!
161     // ---------------------------------------------------------------------------------------
162    
163 william 62 class RuntimeError : public BaseException
164 william 31 {
165 william 62 DEFINE_EXCEPTION_COPYTORS( RuntimeError, BaseException )
166     DEFINE_EXCEPTION_MESSAGES( RuntimeError )
167    
168 william 31 public:
169     bool IsSilent;
170    
171 william 62 RuntimeError() { IsSilent = false; }
172 william 31 RuntimeError( const std::runtime_error& ex, const wxString& prefix=wxEmptyString );
173     RuntimeError( const std::exception& ex, const wxString& prefix=wxEmptyString );
174     };
175    
176     // --------------------------------------------------------------------------------------
177     // CancelAppEvent - Exception for canceling an event in a non-verbose fashion
178     // --------------------------------------------------------------------------------------
179     // Typically the PCSX2 interface issues popup dialogs for runtime errors. This exception
180     // instead issues a "silent" cancelation that is handled by the app gracefully (generates
181     // log, and resumes messages queue processing).
182     //
183     // I chose to have this exception derive from RuntimeError, since if one is thrown from outside
184     // an App message loop we'll still want it to be handled in a reasonably graceful manner.
185 william 62 class CancelEvent : public RuntimeError
186 william 31 {
187 william 283 DEFINE_RUNTIME_EXCEPTION( CancelEvent, RuntimeError, pxLt("No reason given.") )
188 william 62
189 william 31 public:
190 william 62 explicit CancelEvent( const wxString& logmsg )
191 william 31 {
192     m_message_diag = logmsg;
193     // overridden message formatters only use the diagnostic version...
194     }
195    
196     virtual wxString FormatDisplayMessage() const;
197     virtual wxString FormatDiagnosticMessage() const;
198     };
199    
200 william 62 // ---------------------------------------------------------------------------------------
201     // OutOfMemory
202     // ---------------------------------------------------------------------------------------
203     // This exception has a custom-formatted Diagnostic string. The parameter give when constructing
204     // the exception is a block/alloc name, which is used as a formatting parameter in the diagnostic
205     // output. The default diagnostic message is "Out of memory exception, while allocating the %s."
206     // where %s is filled in with the block name.
207     //
208     // The user string is not custom-formatted, and should contain *NO* %s tags.
209     //
210     class OutOfMemory : public RuntimeError
211 william 31 {
212 william 280 DEFINE_RUNTIME_EXCEPTION( OutOfMemory, RuntimeError, wxEmptyString )
213 william 62
214 william 31 public:
215 william 62 wxString AllocDescription;
216 william 31
217 william 62 public:
218     OutOfMemory( const wxString& allocdesc );
219 william 31
220     virtual wxString FormatDisplayMessage() const;
221     virtual wxString FormatDiagnosticMessage() const;
222     };
223    
224     class ParseError : public RuntimeError
225     {
226 william 283 DEFINE_RUNTIME_EXCEPTION( ParseError, RuntimeError, pxL("Parse error") );
227 william 31 };
228    
229     // ---------------------------------------------------------------------------------------
230     // Hardware/OS Exceptions:
231     // HardwareDeficiency / VirtualMemoryMapConflict
232     // ---------------------------------------------------------------------------------------
233    
234     // This exception is a specific type of OutOfMemory error that isn't "really" an out of
235     // memory error. More likely it's caused by a plugin or driver reserving a range of memory
236     // we'd really like to have access to.
237 william 62 class VirtualMemoryMapConflict : public OutOfMemory
238 william 31 {
239 william 280 DEFINE_RUNTIME_EXCEPTION( VirtualMemoryMapConflict, OutOfMemory, wxEmptyString )
240    
241     VirtualMemoryMapConflict( const wxString& allocdesc );
242    
243     virtual wxString FormatDisplayMessage() const;
244     virtual wxString FormatDiagnosticMessage() const;
245 william 31 };
246    
247 william 62 class HardwareDeficiency : public RuntimeError
248 william 31 {
249     public:
250 william 283 DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, RuntimeError, pxL("Your machine's hardware is incapable of running PCSX2. Sorry dood.") );
251 william 31 };
252    
253     // ---------------------------------------------------------------------------------------
254     // Streaming (file) Exceptions:
255     // Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
256     // ---------------------------------------------------------------------------------------
257    
258 william 62 #define DEFINE_STREAM_EXCEPTION_ACCESSORS( classname ) \
259     virtual classname& SetStreamName( const wxString& name ) { StreamName = name; return *this; } \
260     virtual classname& SetStreamName( const char* name ) { StreamName = fromUTF8(name); return *this; }
261 william 31
262 william 280 #define DEFINE_STREAM_EXCEPTION( classname, parent ) \
263     DEFINE_RUNTIME_EXCEPTION( classname, parent, wxEmptyString ) \
264 william 62 classname( const wxString& filename ) { \
265     StreamName = filename; \
266     } \
267     DEFINE_STREAM_EXCEPTION_ACCESSORS( classname )
268    
269 william 280 // A generic base error class for bad streams -- corrupted data, sudden closures, loss of
270     // connection, or anything else that would indicate a failure to open a stream or read the
271     // data after the stream was successfully opened.
272 william 31 //
273 william 280 class BadStream : public RuntimeError
274 william 31 {
275 william 280 DEFINE_STREAM_EXCEPTION( BadStream, RuntimeError )
276 william 62
277 william 31 public:
278     wxString StreamName; // name of the stream (if applicable)
279    
280     virtual wxString FormatDiagnosticMessage() const;
281     virtual wxString FormatDisplayMessage() const;
282    
283 william 280 protected:
284     void _formatDiagMsg( FastFormatUnicode& dest ) const;
285     void _formatUserMsg( FastFormatUnicode& dest ) const;
286 william 31 };
287    
288     // A generic exception for odd-ball stream creation errors.
289     //
290 william 280 class CannotCreateStream : public BadStream
291 william 31 {
292 william 280 DEFINE_STREAM_EXCEPTION( CannotCreateStream, BadStream )
293    
294     virtual wxString FormatDiagnosticMessage() const;
295     virtual wxString FormatDisplayMessage() const;
296 william 31 };
297    
298     // Exception thrown when an attempt to open a non-existent file is made.
299     // (this exception can also mean file permissions are invalid)
300     //
301 william 62 class FileNotFound : public CannotCreateStream
302 william 31 {
303     public:
304 william 280 DEFINE_STREAM_EXCEPTION( FileNotFound, CannotCreateStream )
305    
306     virtual wxString FormatDiagnosticMessage() const;
307     virtual wxString FormatDisplayMessage() const;
308 william 31 };
309    
310 william 62 class AccessDenied : public CannotCreateStream
311 william 31 {
312     public:
313 william 280 DEFINE_STREAM_EXCEPTION( AccessDenied, CannotCreateStream )
314    
315     virtual wxString FormatDiagnosticMessage() const;
316     virtual wxString FormatDisplayMessage() const;
317 william 31 };
318    
319     // EndOfStream can be used either as an error, or used just as a shortcut for manual
320     // feof checks.
321     //
322 william 280 class EndOfStream : public BadStream
323 william 31 {
324     public:
325 william 280 DEFINE_STREAM_EXCEPTION( EndOfStream, BadStream )
326    
327     virtual wxString FormatDiagnosticMessage() const;
328     virtual wxString FormatDisplayMessage() const;
329 william 31 };
330    
331     #ifdef __WXMSW__
332     // --------------------------------------------------------------------------------------
333     // Exception::WinApiError
334     // --------------------------------------------------------------------------------------
335     class WinApiError : public RuntimeError
336     {
337 william 62 DEFINE_EXCEPTION_COPYTORS( WinApiError, RuntimeError )
338     DEFINE_EXCEPTION_MESSAGES( WinApiError )
339    
340 william 31 public:
341     int ErrorId;
342    
343     public:
344 william 62 WinApiError();
345 william 31
346     wxString GetMsgFromWindows() const;
347     virtual wxString FormatDisplayMessage() const;
348     virtual wxString FormatDiagnosticMessage() const;
349     };
350     #endif
351     }
352    
353     using Exception::BaseException;
354 william 273 using Exception::ScopedExcept;

  ViewVC Help
Powered by ViewVC 1.1.22