summaryrefslogtreecommitdiff
path: root/TAO/tao/try_macros.h
blob: 79485c0c26f2a1a09913b17653fa2044855579ae (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
// 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.
//
// ============================================================================

#if !defined (TAO_TRY_MACROS_H)
#define TAO_TRY_MACROS_H

#include "tao/orbconf.h"

// 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_USE_EXCEPTIONS)

#define TAO_TRY_ENV __env
// The first "do" scope is for the env.
// The second "do" scope is for the TAO_CHECK_ENV continues.
#define TAO_TRY \
do { \
CORBA_Environment TAO_TRY_ENV; \
try {

#define TAO_TRY_EX(LABEL) \
do { \
CORBA_Environment TAO_TRY_ENV; \
try {

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

#define TAO_CATCHANY \
} catch (...) {
#define TAO_ENDTRY }} while (0)

// 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_THROW(EXCEPTION) throw EXCEPTION
#define TAO_THROW_ENV(EXCEPTION, ENV) throw EXCEPTION
#define TAO_RETHROW throw

#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_RETURN(EXCEPTION, RETURN) do {\
  throw EXCEPTION; \
  return RETURN; } while (0)
#define TAO_THROW_ENV_RETURN(EXCEPTION, ENV, RETURN) do { \
  throw EXCEPTION; \
  return RETURN; } while (0)
#define TAO_RETHROW_RETURN(RETURN) throw; \
  return RETURN

#else

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

#endif /* ACE_WIN32 */

// #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 a local enviroment variable...
#define TAO_TRY_ENV __env

// I would like to experiment with this idea in the future....
#if 0
#define TAO_TRY_VAR(X) \
do { CORBA_Environment &_env = CORBA_Environment::default_environment ()= X; \
int TAO_TRY_FLAG = 1; \
TAO_TRY_LABEL: \
if (TAO_TRY_FLAG) \
do {
#endif /* 0 */

// The first "do" scope is for the 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 {

// 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_CATCHANY \
} while (0); \
do { \
if (TAO_TRY_ENV.exception () != 0)

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

// If continue is called, control will skip to the next TAO_CATCHANY
// 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) \
do {\
if (TAO_TRY_ENV.exception () != 0) \
  { \
    TAO_TRY_FLAG = 0; \
    goto TAO_TRY_LABEL ## LABEL; \
  } \
} while (0)

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

#define TAO_THROW(EXCEPTION) \
do {\
  _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 {\
 _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 \
_env.exception (TAO_TRY_ENV.exception ()); \
return

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

#define TAO_THROW_SPEC(X)

#define TAO_RAISE(EXCEPTION)

#endif /* TAO_USE_EXCEPTIONS */

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

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

#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; \
    }

// Throwing an exception from within a TAO_TRY block has slightly
// different semantics, we need to check that in the near future.
# define TAO_TRY_THROW(EXCEPTION) TAO_THROW(EXCEPTION)

// 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 */