--- ex.pod 2002/01/26 22:43:54 1.7
+++ ex.pod 2002/01/29 11:05:21 1.8
@@ -258,22 +258,13 @@
=head2 Exception Context
In order to maintain the exception catching stack and for passing the
-exception between the throw point and the catch point, B<OSSP ex> uses
-a global exception context macro B<__ex_ctx> holding a pointer to a
-structure of type B<ex_ctx_t>. This is a private data structure and
-should be treated as opaque by the user.
-
-By default (define C<__EX_CTX_USE_GLOBAL__> or as long as
-C<__EX_CTX_USE_CUSTOM__> is not defined) this references a global
-variable C<__ex_ctx_global>. This variable is either defined by the user
-by placing the directive "C<EX_CTX_GLOBAL>" macro somewhere outside of
-any functions in the application or alternatively link the F<libex>
-library to the application.
-
-Alternatively one can define C<__EX_CTX_USE_STATIC__> to get a static
-declaration directly inside the header file (for small environments
-where F<ex.h> is included once only) or define C<__EX_CTX_USE_CUSTOM__>
-and provide an own macro definition for B<__ex_ctx>.
+exception between the throw and the catch point, B<OSSP ex> uses a
+global exception context, returned on-the-fly by the callback "ex_ctx_t
+*(*B<__ex_ctx>)(void)".
+
+The default B<__ex_ctx> (as provided by F<libex>) returns a pointer to
+a static B<ex_ctx_t> context. For use in multi-threading environments,
+this should be overwritten with a per-thread context structure.
To initialize an exception context structure there are two macros
defined: B<EX_CTX_INITIALIZER> for static initialization and
@@ -281,20 +272,17 @@
=head2 Termination Handler
-In case there is an exception thrown which is not caught by
-any B<ex_try>/B<ex_catch> clauses, B<OSSP ex> calls the macro
-B<__ex_terminate>(C<ex_t *>). It receives a pointer to the exception
+In case there is an exception thrown which is not caught by any
+B<ex_try>/B<ex_catch> clauses, B<OSSP ex> calls the callback "void
+(*B<__ex_terminate>)(C<ex_t *>)". It receives a pointer to the exception
object which should have been thrown.
-By default (define C<__EX_TERMINATE_USE_ABORT__> or as long as
-C<__EX_TERMINATE_USE_CUSTOM__> is not defined) this prints a message of
-the form "C<**EX: UNCAUGHT EXCEPTION: class=0xXXXXXXXX object=0xXXXXXXXX
-value=0xXXXXXXX [file:123:func]>" to F<stderr> and then calls abort(3)
-in order to terminate the application.
-
-Alternatively one can define C<__EX_TERMINATE_USE_NOOP__> to ignore the
-exception or or define C<__EX_TERMINATE_USE_CUSTOM__> and provide an own
-macro definition for B<__ex_terminate>.
+The default B<__ex_terminate> (as provided by F<libex>) this prints
+a message of the form "C<**EX: UNCAUGHT EXCEPTION: class=0xXXXXXXXX
+object=0xXXXXXXXX value=0xXXXXXXX [file:123:func]>" to F<stderr> and
+then calls abort(3) in order to terminate the application. For use in
+multi-threading environments, this should be overwritten with a callback
+function which terminates only the current thread.
=head2 Namespace Mapping
@@ -307,10 +295,10 @@
For this B<OSSP ex> optionally provides the ability to provide
additional namespace mappings for those API macros. By default (define
-C<__EX_NS_USE_CXX__> o or as long as C<__EX_CTX_USE_CUSTOM__> and
-C<__cplusplus> is not defined) you can additional C++ style macros named
-B<catch>, B<throw>, B<rethrow> and B<shield>. As an alternative you
-can define C<__EX_NS_USE_UCCXX__> to get the same but with an (more
+C<__EX_NS_USE_CXX__> or as long as C<__EX_NS_USE_CUSTOM__> and
+C<__cplusplus> is not defined) you can additional C++ style macros
+named B<catch>, B<throw>, B<rethrow> and B<shield>. As an alternative
+you can define C<__EX_NS_USE_UCCXX__> to get the same but with an (more
namespace safe) upper case first letter.
=head1 MULTITHREADING ENVIRONMENTS
@@ -337,83 +325,98 @@
#ifndef __PTH_EX_H__
#define __PTH_EX_H__
-
- /* include GNU pth API */
+
#include "pth.h"
- /* configure and include OSSP ex API */
- #define __EX_CTX_USE_CUSTOM__
- #define __ex_ctx \
- (ex_ctx_t *)pth_getkey(ex_ctx_key)
- #define __ex_terminate(e) \
- pth_exit(e->ex_value)
- #include "ex.h"
-
- int pth_init_ex(void);
- pth_t pth_spawn_ex(pth_attr_t attr, void *(*entry)(void *), void *arg);
-
- #ifndef PTH_EX_C
+ int pth_init_ex (void);
+ pth_t pth_spawn_ex (pth_attr_t attr, void *(*entry)(void *), void *arg);
+
+ #ifndef PTH_EX_INTERNAL
#define pth_init pth_ex_init
#define pth_spawn pth_ex_spawn
#endif
-
+
#endif /* __PTH_EX_H__ */
=item F<pth_ex.c>
- #define PTH_EX_C
+ #include <stdlib.h>
+
+ #define PTH_EX_INTERNAL
#include "pth_ex.h"
-
+ #include "pth.h"
+ #include "ex.h"
+
/* context storage key */
- static pth_key_t ex_ctx_key;
-
+ static pth_key_t pth_ex_ctx_key;
+
/* context destructor */
- void ex_ctx_destroy(void *data)
+ static void pth_ex_ctx_destroy(void *data)
{
if (data != NULL)
free(data);
return;
}
-
+
+ /* callback: context fetching */
+ static ex_ctx_t *pth_ex_ctx(void)
+ {
+ return (ex_ctx_t *)pth_key_getdata(pth_ex_ctx_key);
+ }
+
+ /* callback: termination */
+ static void pth_ex_terminate(ex_t *e)
+ {
+ pth_exit(e->ex_value);
+ }
+
/* pth_init() wrapper */
int pth_init_ex(void)
{
int rc;
-
+
+ /* perform original operation */
rc = pth_init();
- pth_key_create(&ex_ctx_key, ex_ctx_destroy);
+
+ /* additionally create thread data key and override OSSP ex callbacks */
+ pth_key_create(&pth_ex_ctx_key, pth_ex_ctx_destroy);
+ __ex_ctx = pth_ex_ctx;
+ __ex_terminate = pth_ex_terminate;
+
return rc;
}
-
+
/* internal thread entry wrapper information */
typedef struct {
void *(*entry)(void *);
void *arg;
} pth_spawn_ex_t;
-
+
/* internal thread entry wrapper */
static void *pth_spawn_wrapper(void *arg)
{
pth_spawn_ex_t *wrapper;
ex_ctx_t *ex_ctx;
-
+
+ /* create per-thread exception context */
wrapper = (pth_spawn_ex_t *)arg;
ex_ctx = (ex_ctx_t *)malloc(sizeof(ex_ctx_t));
EX_CTX_INITIALIZE(ex_ctx);
- pth_key_setdata(ex_ctx_key, ex_ctx);
- return wrapper.entry(wrapper.arg);
+ pth_key_setdata(pth_ex_ctx_key, ex_ctx);
+
+ /* perform original operation */
+ return wrapper->entry(wrapper->arg);
}
-
+
/* pth_spawn() wrapper */
pth_t pth_spawn_ex(pth_attr_t attr, void *(*entry)(void *), void *arg)
{
- pth_t tid;
pth_spawn_ex_t wrapper;
-
+
+ /* spawn thread but execute start function through wrapper */
wrapper.entry = entry;
wrapper.arg = arg;
- tid = pth_spawn(attr, pth_spawn_wrapper, &wrapper);
- return tid;
+ return pth_spawn(attr, pth_spawn_wrapper, &wrapper);
}
=back
|