Lumiera  0.pre.03
»edit your freedom«
error-state.c
Go to the documentation of this file.
1 /*
2  ERROR-STATE - Lumiera C error flag implementation
3 
4  Copyright (C)
5  2008, Christian Thaeter <ct@pipapo.org>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
14 
27 #include "lib/error.h"
28 
29 #include <pthread.h>
30 
31 
32 /*
33  predefined errors
34 */
35 LUMIERA_ERROR_DEFINE (ERRNO, "errno");
36 LUMIERA_ERROR_DEFINE (EERROR, "could not initialise error system");
37 LUMIERA_ERROR_DEFINE (UNKNOWN, "unknown error");
38 
39 
40 /* Thread local storage */
41 static pthread_key_t lumiera_error_tls;
42 static pthread_once_t lumiera_error_initialized = PTHREAD_ONCE_INIT;
43 
48 {
49  lumiera_err err;
50  char* extra;
51 };
52 
53 typedef struct lumiera_errorcontext_struct lumiera_errorcontext;
54 typedef lumiera_errorcontext* LumieraErrorcontext;
55 
56 
57 static void
58 lumiera_error_tls_delete (void* err)
59 {
60  if (err)
61  free (((LumieraErrorcontext)err)->extra);
62  free(err);
63 }
64 
65 static void
66 lumiera_error_tls_init (void)
67 {
68  if (!!pthread_key_create (&lumiera_error_tls, lumiera_error_tls_delete))
69  LUMIERA_DIE (EERROR);
70 }
71 
72 
73 LumieraErrorcontext
74 lumiera_error_get (void)
75 {
76  pthread_once (&lumiera_error_initialized, lumiera_error_tls_init);
77 
78  LumieraErrorcontext self = pthread_getspecific (lumiera_error_tls);
79  if (!self)
80  {
81  /* malloc() and not lumiera_malloc() here because nothing else might be initialised when calling this */
82  self = malloc (sizeof *self);
83  if (!self)
84  LUMIERA_DIE (EERROR);
85 
86  self->err = NULL;
87  self->extra = NULL;
88  pthread_setspecific (lumiera_error_tls, self);
89  }
90 
91  return self;
92 }
93 
94 
95 lumiera_err
96 lumiera_error_set (lumiera_err nerr, const char* extra)
97 {
98  LumieraErrorcontext self = lumiera_error_get ();
99 
100  if (!self->err)
101  {
102  self->err = nerr;
103  free (self->extra);
104  if (extra)
105  self->extra = strdup (extra);
106  else
107  self->extra = NULL;
108  }
109 
110  return self->err;
111 }
112 
113 
114 lumiera_err
116 {
117  LumieraErrorcontext self = lumiera_error_get ();
118  lumiera_err err = self->err;
119 
120  if (err)
121  self->err = NULL;
122  return err;
123 }
124 
125 const char*
127 {
128  return lumiera_error_get ()->extra;
129 }
130 
131 
132 lumiera_err
134 {
135  return lumiera_error_get ()->err;
136 }
137 
138 int
139 lumiera_error_expect (lumiera_err expected)
140 {
141  LumieraErrorcontext self = lumiera_error_get ();
142  lumiera_err err = self->err;
143 
144  if (err == expected)
145  {
146  if (err)
147  self->err = NULL;
148  return 1;
149  }
150  else
151  return 0;
152 }
lumiera_err lumiera_error_peek(void)
Check current error state without clearing it Please avoid this function and use lumiera_error() if p...
Definition: error-state.c:133
int lumiera_error_expect(lumiera_err expected)
Expect some error Check that the current error state matches some expectation, if true then the error...
Definition: error-state.c:139
Lumiera error handling (C interface).
Holding error and some context data.
Definition: error-state.c:47
#define LUMIERA_DIE(err)
Abort unconditionally with a &#39;Fatal Error!&#39; message.
Definition: error.h:54
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:115
lumiera_err lumiera_error_set(lumiera_err nerr, const char *extra)
Set error state for the current thread.
Definition: error-state.c:96
const char * lumiera_error_extra(void)
Query the extra context for the last error.
Definition: error-state.c:126
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition: error.h:71