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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 10 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 /* 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 BaseException& SetBothMsgs( const wxChar* msg_diag );
80 BaseException& SetDiagMsg( const wxString& msg_diag );
81 BaseException& SetUserMsg( const wxString& msg_user );
82
83 // 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 virtual wxString FormatDisplayMessage() const;
90
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
118 virtual void Rethrow() const=0;
119 virtual Ps2Generic* Clone() const=0;
120 };
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 // ambiguity errors on virtual inheritance (it really shouldn't!). So I have to force it to the
132 // 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 #define DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
137 private: \
138 typedef parent _parent; \
139 public: \
140 virtual ~classname() throw() {} \
141 virtual void Rethrow() const { throw *this; } \
142 virtual classname* Clone() const { return new classname( *this ); }
143
144 #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
150 #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 // ---------------------------------------------------------------------------------------
157 // RuntimeError - Generalized Exceptions with Recoverable Traits!
158 // ---------------------------------------------------------------------------------------
159
160 class RuntimeError : public BaseException
161 {
162 DEFINE_EXCEPTION_COPYTORS( RuntimeError, BaseException )
163 DEFINE_EXCEPTION_MESSAGES( RuntimeError )
164
165 public:
166 bool IsSilent;
167
168 RuntimeError() { IsSilent = false; }
169 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 class CancelEvent : public RuntimeError
183 {
184 DEFINE_RUNTIME_EXCEPTION( CancelEvent, RuntimeError, wxLt("No reason given.") )
185
186 public:
187 explicit CancelEvent( const wxString& logmsg )
188 {
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 // ---------------------------------------------------------------------------------------
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 {
209 DEFINE_RUNTIME_EXCEPTION( OutOfMemory, RuntimeError, wxLt("Out of memory?!") )
210
211 public:
212 wxString AllocDescription;
213
214 public:
215 OutOfMemory( const wxString& allocdesc );
216
217 virtual wxString FormatDisplayMessage() const;
218 virtual wxString FormatDiagnosticMessage() const;
219 };
220
221 class ParseError : public RuntimeError
222 {
223 DEFINE_RUNTIME_EXCEPTION( ParseError, RuntimeError, wxLt("Parse error") );
224 };
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 class VirtualMemoryMapConflict : public OutOfMemory
235 {
236 DEFINE_RUNTIME_EXCEPTION( VirtualMemoryMapConflict, OutOfMemory, wxLt("Virtual memory map confict: Unable to claim specific required memory regions.") )
237 };
238
239 class HardwareDeficiency : public RuntimeError
240 {
241 public:
242 DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, RuntimeError, wxLt("Your machine's hardware is incapable of running PCSX2. Sorry dood.") );
243 };
244
245 // ---------------------------------------------------------------------------------------
246 // Streaming (file) Exceptions:
247 // Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
248 // ---------------------------------------------------------------------------------------
249
250 #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
254 #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 // 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 class Stream : public RuntimeError
267 {
268 DEFINE_STREAM_EXCEPTION( Stream, RuntimeError, wxLt("General file operation error.") )
269
270 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 class BadStream : public Stream
282 {
283 DEFINE_STREAM_EXCEPTION( BadStream, Stream, wxLt("File data is corrupted or incomplete, or the stream connection closed unexpectedly.") )
284 };
285
286 // A generic exception for odd-ball stream creation errors.
287 //
288 class CannotCreateStream : public Stream
289 {
290 DEFINE_STREAM_EXCEPTION( CannotCreateStream, Stream, wxLt("File could not be created or opened.") )
291 };
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 class FileNotFound : public CannotCreateStream
297 {
298 public:
299 DEFINE_STREAM_EXCEPTION( FileNotFound, CannotCreateStream, wxLt("File not found.") )
300 };
301
302 class AccessDenied : public CannotCreateStream
303 {
304 public:
305 DEFINE_STREAM_EXCEPTION( AccessDenied, CannotCreateStream, wxLt("Permission denied to file.") )
306 };
307
308 // EndOfStream can be used either as an error, or used just as a shortcut for manual
309 // feof checks.
310 //
311 class EndOfStream : public Stream
312 {
313 public:
314 DEFINE_STREAM_EXCEPTION( EndOfStream, Stream, wxLt("Unexpected end of file or stream.") );
315 };
316
317 #ifdef __WXMSW__
318 // --------------------------------------------------------------------------------------
319 // Exception::WinApiError
320 // --------------------------------------------------------------------------------------
321 class WinApiError : public RuntimeError
322 {
323 DEFINE_EXCEPTION_COPYTORS( WinApiError, RuntimeError )
324 DEFINE_EXCEPTION_MESSAGES( WinApiError )
325
326 public:
327 int ErrorId;
328
329 public:
330 WinApiError();
331
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