blob: fd39a701d9ed05ea3335f67ed1037bb1a5d091af [file] [log] [blame]
/* mongo_except.h */
/* Copyright 2009 10gen Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file is based loosely on cexcept (http://www.nicemice.net/cexcept/). I
* have modified it to work better with mongo's API.
*
* The MONGO_TRY, MONGO_CATCH, and MONGO_TROW macros assume that a pointer to
* the current connection is available as 'conn'. If you would like to use a
* different name, use the _GENERIC version of these macros.
*
* WARNING: do not return or otherwise jump (excluding MONGO_TRHOW()) out of a
* MONGO_TRY block as the nessesary clean-up code will not be called. Jumping
* out of the MONGO_CATCH block is OK.
*/
#ifdef MONGO_CODE_EXAMPLE
mongo_connection conn[1]; /* makes conn a ptr to the connection */
MONGO_TRY{
mongo_find_one(...);
MONGO_THROW(conn, MONGO_EXCEPT_NETWORK);
}MONGO_CATCH{
switch(conn->exception->type){
case MONGO_EXCEPT_NETWORK:
do_something();
case MONGO_EXCEPT_FIND_ERR:
do_something();
default:
MONGO_RETHROW();
}
}
#endif
/* ORIGINAL CEXEPT COPYRIGHT:
cexcept: README 2.0.1 (2008-Jul-23-Wed)
http://www.nicemice.net/cexcept/
Adam M. Costello
http://www.nicemice.net/amc/
The package is both free-as-in-speech and free-as-in-beer:
Copyright (c) 2000-2008 Adam M. Costello and Cosmin Truta.
This package may be modified only if its author and version
information is updated accurately, and may be redistributed
only if accompanied by this unaltered notice. Subject to those
restrictions, permission is granted to anyone to do anything with
this package. The copyright holders make no guarantees regarding
this package, and are not responsible for any damage resulting from
its use.
*/
#ifndef _MONGO_EXCEPT_H_
#define _MONGO_EXCEPT_H_
#include <setjmp.h>
/* always non-zero */
typedef enum{
MONGO_EXCEPT_NETWORK=1,
MONGO_EXCEPT_FIND_ERR
}mongo_exception_type;
typedef struct {
jmp_buf base_handler;
jmp_buf *penv;
int caught;
volatile mongo_exception_type type;
}mongo_exception_context;
#define MONGO_TRY MONGO_TRY_GENERIC(conn)
#define MONGO_CATCH MONGO_CATCH_GENERIC(conn)
#define MONGO_THROW(e) MONGO_THROW_GENERIC(conn, e)
#define MONGO_RETHROW() MONGO_RETHROW_GENERIC(conn)
/* the rest of this file is implementation details */
/* this is done in mongo_connect */
#define MONGO_INIT_EXCEPTION(exception_ptr) \
do{ \
mongo_exception_type t; /* exception_ptr won't be available */\
(exception_ptr)->penv = &(exception_ptr)->base_handler; \
if ((t = setjmp((exception_ptr)->base_handler))) { /* yes, '=' is correct */ \
switch(t){ \
case MONGO_EXCEPT_NETWORK: bson_fatal_msg(0, "network error"); \
case MONGO_EXCEPT_FIND_ERR: bson_fatal_msg(0, "error in find"); \
default: bson_fatal_msg(0, "unknown exception"); \
} \
} \
}while(0)
#define MONGO_TRY_GENERIC(connection) \
{ \
jmp_buf *exception__prev, exception__env; \
exception__prev = (connection)->exception.penv; \
(connection)->exception.penv = &exception__env; \
if (setjmp(exception__env) == 0) { \
do
#define MONGO_CATCH_GENERIC(connection) \
while ((connection)->exception.caught = 0, \
(connection)->exception.caught); \
} \
else { \
(connection)->exception.caught = 1; \
} \
(connection)->exception.penv = exception__prev; \
} \
if (!(connection)->exception.caught ) { } \
else
/* Try ends with do, and Catch begins with while(0) and ends with */
/* else, to ensure that Try/Catch syntax is similar to if/else */
/* syntax. */
/* */
/* The 0 in while(0) is expressed as x=0,x in order to appease */
/* compilers that warn about constant expressions inside while(). */
/* Most compilers should still recognize that the condition is always */
/* false and avoid generating code for it. */
#define MONGO_THROW_GENERIC(connection, type_in) \
for (;; longjmp(*(connection)->exception.penv, type_in)) \
(connection)->exception.type = type_in
#define MONGO_RETHROW_GENERIC(connection) \
MONGO_THROW_GENERIC(connection, (connection)->exception.type)
#endif