summaryrefslogtreecommitdiff
path: root/TAO/tao/try_macros.h
blob: e2cca533c162ca43e2824c5991802111487e1457 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// This may look like C, but it's really -*- C++ -*-
// $Id$

// ============================================================================
//
// = LIBRARY
//    TAO
//
// = FILENAME
//    try_macros.h
//
// = DESCRIPTION
//   Writing code that is portable between platforms with a without
//   native C++ exceptions is hard.  The following macros offer some
//   help on this task, mostly oriented to making the ORB code and the
//   IDL generated code portable.
//
// = AUTHOR
//     Copyright by Douglas C. Schmidt.
//
// ============================================================================

#ifndef TAO_TRY_MACROS_H
#define TAO_TRY_MACROS_H

#include "tao/orbconf.h"

// Define a local enviroment variable...
#define TAO_IN_ENV  _env
#define TAO_TRY_ENV _tao_try_environment

// These macros can be used to write "portable" code between platforms
// supporting CORBA exceptions natively (using the C++ exceptions) or
// through the Enviroment parameter.  Their use requires some
// discipline, but they certainly help...

#if defined (TAO_HAS_EXCEPTIONS)

// The first "do" scope is for the TAO_TRY_ENV.
// The second "do" scope is for the TAO_CHECK_ENV continues.
// These are all on one line so the keywords don't confuse compilers.
#define TAO_TRY do { CORBA_Environment TAO_TRY_ENV; try {
#define TAO_TRY_VAR(X) do { CORBA_Environment &TAO_TRY_ENV = X; \
                            ACE_UNUSED_ARG (TAO_TRY_ENV); try {

#define TAO_TRY_EX(LABEL) do { CORBA_Environment TAO_TRY_ENV; try {
#define TAO_TRY_VAR_EX(X,LABEL) do { CORBA_Environment &TAO_TRY_ENV = X; \
                                ACE_UNUSED_ARG (TAO_TRY_ENV); try {

#define TAO_CATCH(TYPE,VAR) } catch (TYPE & VAR) { ACE_UNUSED_ARG (VAR);

// @@ @@ @@ This conditional compilation is meant to be catch abnormal
//          exceptions so the debugger can catch the exception for us.
#if defined (TAO_DONT_CATCH_DOT_DOT_DOT)
#define TAO_CATCHALL TAO_CATCH (TAO_DONT_CATCH, ex)
#else
#define TAO_CATCHALL } catch (...) {
#endif /* TAO_DONT_CATCH_DOT_DOT_DOT */

#define TAO_ENDTRY }} while (0)

// Use this macro if there's a return statement following TAO_ENDTRY
// and the statement is the last statement in the function.
#define TAO_ENDTRY_RETURN(X) TAO_ENDTRY; ACE_NOTREACHED (return X)

// No need to do checking, exception handling does it for us.
#define TAO_CHECK_ENV
#define TAO_CHECK_ENV_EX(LABEL)
#define TAO_CHECK_ENV_RETURN(X, Y)
#define TAO_CHECK_ENV_RETURN_VOID(X)

#define TAO_TRY_THROW(EXCEPTION) throw EXCEPTION
#define TAO_TRY_THROW_EX(EXCEPTION,LABEL) throw EXCEPTION

#define TAO_THROW(EXCEPTION) throw EXCEPTION
#define TAO_THROW_ENV(EXCEPTION, ENV) throw EXCEPTION
#define TAO_RETHROW throw

#define TAO_GOTO(LABEL) goto LABEL
#define TAO_LABEL(LABEL) LABEL:

#if defined (ACE_WIN32)

// MSVC++ gives a warning if there is no return after the throw
// expression, it is possible that other compilers have the same
// problem.
#define TAO_THROW_ENV_RETURN(EXCEPTION, ENV, RETURN) do { \
  throw EXCEPTION; \
  return RETURN; } while (0)
#define TAO_RETHROW_RETURN(RETURN) throw; \
  return RETURN
#define TAO_RETHROW_RETURN_VOID throw; \
  return

#else

#define TAO_THROW_ENV_RETURN(EXCEPTION, ENV, RETURN) throw EXCEPTION
#define TAO_RETHROW_RETURN(RETURN) throw
#define TAO_RETHROW_RETURN_VOID throw

#endif /* ACE_WIN32 */

#define TAO_THROW_RETURN(EXCEPTION,RETURN) TAO_THROW_ENV_RETURN(EXCEPTION,TAO_IN_ENV,RETURN)

#define TAO_RETHROW_SAME_ENV_RETURN(RETURN) TAO_RETHROW_RETURN (RETURN)
#define TAO_RETHROW_SAME_ENV_RETURN_VOID TAO_RETHROW_RETURN_VOID

// #define TAO_THROW_SPEC(X) ACE_THROW_SPEC(X)
#define TAO_THROW_SPEC(X)
// The IDL compiler is not generating throw specs, so putting them in
// the servant implementation only results in compilation
// errors. Further the spec does not say that we should generate them
// and I'm concerned that putting a throw spec can result in an
// "unexpected" exception, which *could* be translated into a
// CORBA::UNKNOWN, but I'm not sure.

#define TAO_RAISE(EXCEPTION) throw EXCEPTION
// This is used in the implementation of the _raise methods

#else /* ACE_HAS_EXCEPTIONS && TAO_IDL_COMPILES_HAS_EXCEPTIONS */

#define TAO_TRY_VAR(X) \
do { CORBA_Environment &TAO_TRY_ENV = X; \
int TAO_TRY_FLAG = 1; \
TAO_TRY_LABEL: \
if (TAO_TRY_FLAG) \
do {

// The first "do" scope is for the TAO_TRY_ENV.
// The second "do" scope is for the TAO_CHECK_ENV continues.
#define TAO_TRY \
do { CORBA_Environment TAO_TRY_ENV; \
int TAO_TRY_FLAG = 1; \
TAO_TRY_LABEL: \
if (TAO_TRY_FLAG) \
do {

// This serves a similar purpose as the macro above,
// The second "do" scope is for the TAO_CHECK_ENV continues.
#define TAO_TRY_EX(LABEL) \
do { \
CORBA_Environment TAO_TRY_ENV; \
int TAO_TRY_FLAG = 1; \
TAO_TRY_LABEL ## LABEL: \
if (TAO_TRY_FLAG) \
do {

#define TAO_TRY_VAR_EX(X,LABEL) \
do { \
CORBA_Environment &TAO_TRY_ENV = X; \
int TAO_TRY_FLAG = 1; \
TAO_TRY_LABEL ## LABEL: \
if (TAO_TRY_FLAG) \
do {

// Throwing an exception within a try block must be treated differently
// on platforms that don't support native exception because the exception
// won't get caught by the catch clauses automatically.
#define TAO_TRY_THROW(EXCEPTION) \
{\
  TAO_TRY_ENV.exception (new EXCEPTION); \
  TAO_TRY_FLAG = 0; \
  goto TAO_TRY_LABEL; \
}

#define TAO_TRY_THROW_EX (EXCEPTION,LABEL) \
{\
  TAO_TRY_ENV.exception (new EXCEPTION); \
  TAO_TRY_FLAG = 0; \
  goto TAO_TRY_LABEL ## LABEL; \
}

// Each CATCH statement ends the previous scope and starts a new one.
// Since all CATCH statements can end the TAO_TRY macro, they must all
// start a new scope for the next potential TAO_CATCH.  The TAO_ENDTRY
// will finish them all.  Cool, eh?
#define TAO_CATCH(TYPE,VAR) \
} while (0); \
do \
if (TAO_TRY_ENV.exception () != 0 && \
    TYPE::_narrow(TAO_TRY_ENV.exception ()) != 0) { \
  TYPE &VAR = *TYPE::_narrow (TAO_TRY_ENV.exception ()); \
  ACE_UNUSED_ARG (VAR);

#define TAO_CATCHALL TAO_CATCH(CORBA_Exception, ex)

// The first "while" closes the local scope.  The second "while"
// closes the TAO_TRY_ENV scope.
#define TAO_ENDTRY \
} while (0); \
} while (0)

// Use this macro if there's a return statement following TAO_ENDTRY
// and the statement is the last statement in the function.
#define TAO_ENDTRY_RETURN(X) TAO_ENDTRY; return X

// If continue is called, control will skip to the next TAO_CATCH
// statement.
#define TAO_CHECK_ENV \
{\
if (TAO_TRY_ENV.exception () != 0) \
  { \
    TAO_TRY_FLAG = 0; \
    goto TAO_TRY_LABEL; \
  } \
}

// Same as above but for TAO_TRY_EX
#define TAO_CHECK_ENV_EX(LABEL) \
{\
if (TAO_TRY_ENV.exception () != 0) \
  { \
    TAO_TRY_FLAG = 0; \
    goto TAO_TRY_LABEL ## LABEL; \
  } \
}

#define TAO_CHECK_ENV_RETURN(X, Y) \
 if ( X . exception () != 0) return Y

#define TAO_CHECK_ENV_RETURN_VOID(X) \
 if ( X . exception () != 0) return

#define TAO_THROW(EXCEPTION) \
do {\
 TAO_IN_ENV.exception (new EXCEPTION); \
  return; } while (0)

#define TAO_THROW_ENV(EXCEPTION, ENV) \
do {\
  ENV.exception (new EXCEPTION); \
  return; } while (0)

#define TAO_THROW_RETURN(EXCEPTION, RETURN) \
do {\
 TAO_IN_ENV.exception (new EXCEPTION); \
 return RETURN; } while (0)

#define TAO_THROW_ENV_RETURN(EXCEPTION, ENV, RETURN) \
do {\
 ENV.exception (new EXCEPTION); \
 return RETURN; } while (0)

#define TAO_RETHROW \
TAO_IN_ENV.exception (TAO_TRY_ENV.exception ()); \
return

#define TAO_GOTO(LABEL) goto LABEL
#define TAO_LABEL(LABEL) LABEL:

#define TAO_RETHROW_RETURN(RETURN) \
TAO_IN_ENV.exception (TAO_TRY_ENV.exception ()); \
return RETURN

#define TAO_RETHROW_RETURN_VOID \
TAO_IN_ENV.exception (TAO_TRY_ENV.exception ()); \
return

#define TAO_RETHROW_SAME_ENV_RETURN(RETURN) return RETURN
#define TAO_RETHROW_SAME_ENV_RETURN_VOID return

#define TAO_THROW_SPEC(X)

#define TAO_RAISE(EXCEPTION)

#endif /* TAO_HAS_EXCEPTIONS */

#define TAO_CATCHANY TAO_CATCH(CORBA_Exception, ex)

#define TAO_CHECK_RETURN(Y) TAO_CHECK_ENV_RETURN (TAO_IN_ENV, Y)
#define TAO_CHECK_RETURN_VOID TAO_CHECK_ENV_RETURN_VOID (TAO_IN_ENV)

// This macros can be used even outside the TAO_TRY blocks, in fact
// some are designed for that purpose.

#define TAO_CHECK_ENV_PRINT_RETURN(ENV, PRINT_STRING, RETURN) \
 if (ENV . exception () != 0) \
    { \
        ENV.print_exception (PRINT_STRING); \
        return RETURN; \
    }

#define TAO_CHECK_ENV_PRINT_RETURN_VOID(ENV, PRINT_STRING) \
 if (ENV . exception () != 0) \
    { \
        ENV.print_exception (PRINT_STRING); \
        return; \
    }

// This macros are used to grab a lock using a Guard, test that the
// lock was correctly grabbed and throw an exception on failure.
// If you do not wish to throw an exception, but just to return a
// value please use the ACE macros.
#define TAO_GUARD_THROW(MUTEX,OBJ,LOCK,ENV,EXCEPTION) \
  ACE_Guard<MUTEX> OBJ (LOCK); \
  if (OBJ.locked () == 0) \
      TAO_THROW_ENV (EXCEPTION,ENV)

#define TAO_GUARD_THROW_RETURN(MUTEX,OBJ,LOCK,RETURN,ENV,EXCEPTION) \
  ACE_Guard<MUTEX> OBJ (LOCK); \
  if (OBJ.locked () == 0) \
      TAO_THROW_ENV_RETURN (EXCEPTION,ENV,RETURN)

#define TAO_READ_GUARD_THROW(MUTEX,OBJ,LOCK,ENV,EXCEPTION) \
  ACE_Read_Guard<MUTEX> OBJ (LOCK); \
  if (OBJ.locked () == 0) \
      TAO_THROW_ENV (EXCEPTION,ENV)

#define TAO_READ_GUARD_THROW_RETURN(MUTEX,OBJ,LOCK,RETURN,ENV,EXCEPTION) \
  ACE_Read_Guard<MUTEX> OBJ (LOCK); \
  if (OBJ.locked () == 0) \
      TAO_THROW_ENV_RETURN (EXCEPTION,ENV,RETURN)

#define TAO_WRITE_GUARD_THROW(MUTEX,OBJ,LOCK,ENV,EXCEPTION) \
  ACE_Write_Guard<MUTEX> OBJ (LOCK); \
  if (OBJ.locked () == 0) \
      TAO_THROW_ENV (EXCEPTION,ENV)

#define TAO_WRITE_GUARD_THROW_RETURN(MUTEX,OBJ,LOCK,RETURN,ENV,EXCEPTION) \
  ACE_Write_Guard<MUTEX> OBJ (LOCK); \
  if (OBJ.locked () == 0) \
      TAO_THROW_ENV_RETURN (EXCEPTION,ENV,RETURN)

#endif /* TAO_TRY_MACROS_H */