/[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 283 - (show 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 /* 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 "Assertions.h"
19 #include "ScopedPtr.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 BaseException* FromErrno( const wxString& streamname, int errcode );
47
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 BaseException& SetBothMsgs( const wxChar* msg_diag );
81 BaseException& SetDiagMsg( const wxString& msg_diag );
82 BaseException& SetUserMsg( const wxString& msg_user );
83
84 // 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 virtual wxString FormatDisplayMessage() const;
91
92 virtual void Rethrow() const=0;
93 virtual BaseException* Clone() const=0;
94 };
95
96 typedef ScopedPtr<BaseException> ScopedExcept;
97
98 // --------------------------------------------------------------------------------------
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
121 virtual void Rethrow() const=0;
122 virtual Ps2Generic* Clone() const=0;
123 };
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 // ambiguity errors on virtual inheritance (it really shouldn't!). So I have to force it to the
135 // 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 #define DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
140 private: \
141 typedef parent _parent; \
142 public: \
143 virtual ~classname() throw() {} \
144 virtual void Rethrow() const { throw *this; } \
145 virtual classname* Clone() const { return new classname( *this ); }
146
147 #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
153 #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 // ---------------------------------------------------------------------------------------
160 // RuntimeError - Generalized Exceptions with Recoverable Traits!
161 // ---------------------------------------------------------------------------------------
162
163 class RuntimeError : public BaseException
164 {
165 DEFINE_EXCEPTION_COPYTORS( RuntimeError, BaseException )
166 DEFINE_EXCEPTION_MESSAGES( RuntimeError )
167
168 public:
169 bool IsSilent;
170
171 RuntimeError() { IsSilent = false; }
172 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 class CancelEvent : public RuntimeError
186 {
187 DEFINE_RUNTIME_EXCEPTION( CancelEvent, RuntimeError, pxLt("No reason given.") )
188
189 public:
190 explicit CancelEvent( const wxString& logmsg )
191 {
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 // ---------------------------------------------------------------------------------------
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 {
212 DEFINE_RUNTIME_EXCEPTION( OutOfMemory, RuntimeError, wxEmptyString )
213
214 public:
215 wxString AllocDescription;
216
217 public:
218 OutOfMemory( const wxString& allocdesc );
219
220 virtual wxString FormatDisplayMessage() const;
221 virtual wxString FormatDiagnosticMessage() const;
222 };
223
224 class ParseError : public RuntimeError
225 {
226 DEFINE_RUNTIME_EXCEPTION( ParseError, RuntimeError, pxL("Parse error") );
227 };
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 class VirtualMemoryMapConflict : public OutOfMemory
238 {
239 DEFINE_RUNTIME_EXCEPTION( VirtualMemoryMapConflict, OutOfMemory, wxEmptyString )
240
241 VirtualMemoryMapConflict( const wxString& allocdesc );
242
243 virtual wxString FormatDisplayMessage() const;
244 virtual wxString FormatDiagnosticMessage() const;
245 };
246
247 class HardwareDeficiency : public RuntimeError
248 {
249 public:
250 DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, RuntimeError, pxL("Your machine's hardware is incapable of running PCSX2. Sorry dood.") );
251 };
252
253 // ---------------------------------------------------------------------------------------
254 // Streaming (file) Exceptions:
255 // Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
256 // ---------------------------------------------------------------------------------------
257
258 #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
262 #define DEFINE_STREAM_EXCEPTION( classname, parent ) \
263 DEFINE_RUNTIME_EXCEPTION( classname, parent, wxEmptyString ) \
264 classname( const wxString& filename ) { \
265 StreamName = filename; \
266 } \
267 DEFINE_STREAM_EXCEPTION_ACCESSORS( classname )
268
269 // 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 //
273 class BadStream : public RuntimeError
274 {
275 DEFINE_STREAM_EXCEPTION( BadStream, RuntimeError )
276
277 public:
278 wxString StreamName; // name of the stream (if applicable)
279
280 virtual wxString FormatDiagnosticMessage() const;
281 virtual wxString FormatDisplayMessage() const;
282
283 protected:
284 void _formatDiagMsg( FastFormatUnicode& dest ) const;
285 void _formatUserMsg( FastFormatUnicode& dest ) const;
286 };
287
288 // A generic exception for odd-ball stream creation errors.
289 //
290 class CannotCreateStream : public BadStream
291 {
292 DEFINE_STREAM_EXCEPTION( CannotCreateStream, BadStream )
293
294 virtual wxString FormatDiagnosticMessage() const;
295 virtual wxString FormatDisplayMessage() const;
296 };
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 class FileNotFound : public CannotCreateStream
302 {
303 public:
304 DEFINE_STREAM_EXCEPTION( FileNotFound, CannotCreateStream )
305
306 virtual wxString FormatDiagnosticMessage() const;
307 virtual wxString FormatDisplayMessage() const;
308 };
309
310 class AccessDenied : public CannotCreateStream
311 {
312 public:
313 DEFINE_STREAM_EXCEPTION( AccessDenied, CannotCreateStream )
314
315 virtual wxString FormatDiagnosticMessage() const;
316 virtual wxString FormatDisplayMessage() const;
317 };
318
319 // EndOfStream can be used either as an error, or used just as a shortcut for manual
320 // feof checks.
321 //
322 class EndOfStream : public BadStream
323 {
324 public:
325 DEFINE_STREAM_EXCEPTION( EndOfStream, BadStream )
326
327 virtual wxString FormatDiagnosticMessage() const;
328 virtual wxString FormatDisplayMessage() const;
329 };
330
331 #ifdef __WXMSW__
332 // --------------------------------------------------------------------------------------
333 // Exception::WinApiError
334 // --------------------------------------------------------------------------------------
335 class WinApiError : public RuntimeError
336 {
337 DEFINE_EXCEPTION_COPYTORS( WinApiError, RuntimeError )
338 DEFINE_EXCEPTION_MESSAGES( WinApiError )
339
340 public:
341 int ErrorId;
342
343 public:
344 WinApiError();
345
346 wxString GetMsgFromWindows() const;
347 virtual wxString FormatDisplayMessage() const;
348 virtual wxString FormatDiagnosticMessage() const;
349 };
350 #endif
351 }
352
353 using Exception::BaseException;
354 using Exception::ScopedExcept;

  ViewVC Help
Powered by ViewVC 1.1.22