OSSP CVS Repository

ossp - Check-in [1700]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 1700
Date: 2002-Jan-30 13:17:58 (local)
2002-Jan-30 12:17:58 (UTC)
User:rse
Branch:
Comment: replace MT stuff
Tickets:
Inspections:
Files:
ossp-pkg/ex/ex.pod      1.12 -> 1.13     109 inserted, 104 deleted

ossp-pkg/ex/ex.pod 1.12 -> 1.13

--- ex.pod       2002/01/30 11:55:52     1.12
+++ ex.pod       2002/01/30 12:17:58     1.13
@@ -328,117 +328,122 @@
 
 =head2 GNU pth
 
-Using B<OSSP ex> with B<GNU pth> is straight-forward. One just have to
-wrap pth_init() and pth_spawn() to tie the exception facility to the
-threading facility.
+Using B<OSSP ex> with B<GNU pth> is straight-forward, because B<GNU pth>
+already has support for B<OSSP ex> built-in. All which is needed is that
+B<GNU pth> is configured with the Autoconf option C<--with-ex>. Then
+each thread has its own B<OSSP ex> exception context.
+
+=head2 POSIX pthreads
+
+Using B<OSSP ex> inside a standard B<POSIX pthreads> environment is
+also straight-forward, although it requires additional coding. What
+you basically have to do is to make sure that the B<__ex_ctx> becomes
+a per-thread context and that B<__ex_terminate> terminates only the
+current thread. To get an impression, a small utility library for this
+follows:
 
 =over 4
 
-=item F<pth_ex.h>
+=item F<pthread_ex.h>
 
- #ifndef __PTH_EX_H__
- #define __PTH_EX_H__
- 
- #include "pth.h"
- 
- 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>
-
- #include <stdlib.h>
- 
- #define PTH_EX_INTERNAL
- #include "pth_ex.h"
- #include "pth.h"
- #include "ex.h"
- 
- /* context storage key */
- static pth_key_t pth_ex_ctx_key;
- 
- /* context destructor */
- 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();
- 
-     /* 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(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_spawn_ex_t wrapper;
- 
-     /* spawn thread but execute start function through wrapper */
-     wrapper.entry = entry;
-     wrapper.arg   = arg;
-     return pth_spawn(attr, pth_spawn_wrapper, &wrapper);
- }
+#ifndef __PTHREAD_EX_H__
+#define __PTHREAD_EX_H__
 
-=back
+#include <pthread.h>
 
-=head2 POSIX pthreads
+int pthread_init_ex   (void);
+int pthread_create_ex (pthread_t *thread, const pthread_attr_t *attr, void *(*entry)(void *), void *arg);
+
+#ifndef PTHREAD_EX_INTERNAL
+#define pthread_init   pthread_init_ex
+#define pthread_create pthread_create_ex
+#endif
+
+#endif /* __PTHREAD_EX_H__ */
+
+=item F<pthread_ex.c>
+
+#include <stdlib.h>
+#include <pthread.h>
+
+#define PTHREAD_EX_INTERNAL
+#include "pthread_ex.h"
+#include "ex.h"
+
+/* context storage key */
+static pthread_key_t pthread_ex_ctx_key;
+
+/* context destructor */
+static void pthread_ex_ctx_destroy(void *data)
+{
+    if (data != NULL)
+        free(data);
+    return;
+}
+
+/* callback: context fetching */
+static ex_ctx_t *pthread_ex_ctx(void)
+{
+    return (ex_ctx_t *)pthread_getspecific(pthread_ex_ctx_key);
+}
+
+/* callback: termination */
+static void pthread_ex_terminate(ex_t *e)
+{
+    pthread_exit(e->ex_value);
+}
+
+/* pthread init */
+int pthread_init_ex(void)
+{
+    int rc;
+
+    /* additionally create thread data key and override OSSP ex callbacks */
+    pthread_key_create(&pthread_ex_ctx_key, pthread_ex_ctx_destroy);
+    __ex_ctx       = pthread_ex_ctx;
+    __ex_terminate = pthread_ex_terminate;
+
+    return rc;
+}
+
+/* internal thread entry wrapper information */
+typedef struct {
+    void *(*entry)(void *);
+    void *arg;
+} pthread_create_ex_t;
+
+/* internal thread entry wrapper */
+static void *pthread_create_wrapper(void *arg)
+{
+    pthread_create_ex_t *wrapper;
+    ex_ctx_t *ex_ctx;
+
+    /* create per-thread exception context */
+    wrapper = (pthread_create_ex_t *)arg;
+    ex_ctx = (ex_ctx_t *)malloc(sizeof(ex_ctx_t));
+    EX_CTX_INITIALIZE(ex_ctx);
+    pthread_setspecific(pthread_ex_ctx_key, ex_ctx);
+
+    /* perform original operation */
+    return wrapper->entry(wrapper->arg);
+}
+
+/* pthread_create() wrapper */
+int pthread_create_ex(pthread_t *thread, const pthread_attr_t *attr, void *(*entry)(void *), void *arg)
+{
+    pthread_create_ex_t wrapper;
+
+    /* spawn thread but execute start function through wrapper */
+    wrapper.entry = entry;
+    wrapper.arg   = arg;
+    return pthread_create(thread, attr, pthread_create_wrapper, &wrapper);
+}
+
+=back
 
-Using B<OSSP ex> inside a B<POSIX pthreads> environment is identical to
-using it inside B<GNU pth>. You can use the same solution as above by
-just replacing all B<pth_> prefixes with B<pthread_> prefixes.
+Now all which is required is that you include F<pthread_ex.h> after
+the standard F<pthread.h> header and to call B<pthread_init>() once at
+startup of your program.
 
 =head1 EXAMPLES
 

CVSTrac 2.0.1