1#ifndef XXL_H 2#define XXL_H 3 4#ifndef WIN32 5/* BEGIN: autoconf substitutions */ 6#undef HAVE_SETJMP_H 7#undef HAVE_PTHREAD_H 8#undef HAVE_SYS_TYPES_H 9#undef STDC_HEADERS 10#undef XXL_WITHOUT_THREADS 11#undef const 12/* END: autoconf substitutions */ 13#define XXL_API 14#else 15#ifdef XXL_EXPORTS 16#define XXL_API __declspec(dllexport) 17#else 18#define XXL_API __declspec(dllimport) 19#endif 20#endif 21 22#if !defined(XXL_WITHOUT_THREADS) && !defined(WIN32) && !defined(HAVE_PTHREAD_H) 23#define XXL_WITHOUT_THREADS 24#endif 25 26#ifdef WIN32 27#include <windows.h> 28#include <winsock.h> 29#endif 30#include <stdio.h> 31#if defined(HAVE_SYS_TYPES_H) 32#include <sys/types.h> 33#endif 34#if defined(HAVE_SETJMP_H) || defined(WIN32) 35#include <setjmp.h> 36#endif 37#if !defined(WIN32) && defined(STDC_HEADERS) 38#include <errno.h> 39#endif 40#if !defined(XXL_WITHOUT_THREADS) && defined(HAVE_PTHREAD_H) 41#include <pthread.h> 42#endif 43 44#define XXL_ERROR_THREAD_CANCELLED 0xFFFFFFFF 45#define XXL_ERROR_RETRY_EXCEPTION 0xFFFFFFFE 46 47#ifdef __cplusplus 48extern "C" { 49#endif 50 51typedef enum _xxl_assettype_t 52{ 53 XXL_ASSET_PERMANENT, 54 XXL_ASSET_PROMOTE, 55 XXL_ASSET_TEMPORARY, 56 XXL_ASSET_AUTO, 57 XXL_ASSET_DEMOTE 58} xxl_assettype_t; 59 60typedef void (*xxl_assetfreefn_t)(void *, void *); 61 62typedef struct _xxl_asset_t xxl_asset_t; 63typedef struct _xxl_context_t xxl_context_t; 64typedef struct _xxl_exception_t xxl_exception_t; 65typedef struct _xxl_tsd_t xxl_tsd_t; 66 67struct _xxl_asset_t 68{ 69 void *ptr; 70 xxl_assetfreefn_t freefn; 71 void *arg; 72 xxl_assettype_t type; 73 xxl_asset_t *next; 74}; 75 76struct _xxl_exception_t 77{ 78 int code; 79 void *data; 80 const char *file; 81 unsigned int line; 82}; 83 84struct _xxl_context_t 85{ 86 jmp_buf *context; 87 unsigned int state; 88 xxl_exception_t exception; 89 xxl_exception_t pending; 90#if !defined(WIN32) && !defined(XXL_WITHOUT_THREADS) 91 int cancel_type; 92#endif 93 xxl_asset_t *assets; 94 xxl_context_t *next; 95}; 96 97struct _xxl_tsd_t 98{ 99 xxl_context_t *contexts; 100#if !defined(WIN32) || defined(XXL_WITHOUT_THREADS) 101 xxl_context_t *free_contexts; 102 xxl_asset_t *free_assets; 103#endif 104}; 105 106#define XXL_ASSET_ALL 0 107#define XXL_ASSET_CURRENT 1 108#define XXL_ASSET_FIRST 2 109 110/* These are only used internally */ 111#define XXL_SETJMP_TRY 0x00 112#define XXL_SETJMP_ERROR 0x01 113#define XXL_SETJMP_RETRY 0x02 114#define XXL_SETJMP_PROMOTE 0x03 115#define XXL_SETJMP_LEAVE 0x04 116#define XXL_SETJMP_PENDING 0x05 117#define XXL_SETJMP_MASK 0xFF 118 119#define XXL_STATE_HANDLED 0x00000100 120#define XXL_STATE_FINALLY 0x00000200 121#define XXL_STATE_PENDING 0x00000400 122#define XXL_STATE_THROWN 0x00000800 123#define XXL_STATE_MASK 0x0000FF00 124 125/* Public Macros */ 126#define XXL_ASSET_BLOCK_BEGIN \ 127 do \ 128 { \ 129 xxl_push_context(NULL); \ 130 { 131 132#define XXL_ASSET_BLOCK_END \ 133 } \ 134 xxl_pop_context(); \ 135 } while (0) 136 137#define XXL_ASSET_SAVE(asset, callback, arg, type) \ 138 xxl_push_asset((asset), (xxl_assetfreefn_t)(callback), (arg), (type)) 139#define XXL_ASSET_UPDATE(old_asset, new_asset) \ 140 xxl_update_asset((old_asset), (new_asset)) 141#define XXL_ASSET_RELEASE(asset, mode) \ 142 xxl_release_asset((asset), (mode)) 143 144#define XXL_THROW_ERROR(code, data) \ 145 xxl_throw_error((code), (data), __FILE__, __LINE__) 146#define XXL_RETHROW_ERROR() \ 147 xxl_leave_handler(XXL_SETJMP_PROMOTE) 148#define XXL_LEAVE() \ 149 xxl_leave_handler(XXL_SETJMP_LEAVE) 150#define XXL_RETRY() \ 151 xxl_leave_handler(XXL_SETJMP_RETRY) 152 153#define XXL_EXCEPTION_CODE() xxl_current_error_code() 154#define XXL_EXCEPTION_DATA() xxl_current_error_data() 155#define XXL_EXCEPTION_FILE() xxl_current_error_file() 156#define XXL_EXCEPTION_LINE() xxl_current_error_line() 157 158#define XXL_TRY_BEGIN \ 159 for (;;) \ 160 { \ 161 int __xxl_setjmp; \ 162 jmp_buf __xxl_jmpbuf; \ 163 volatile xxl_context_t *__xxl_context; \ 164 \ 165 __xxl_context = xxl_push_context(&__xxl_jmpbuf); \ 166 __xxl_setjmp = setjmp(__xxl_jmpbuf); \ 167 __xxl_context->state = (__xxl_context->state & XXL_STATE_MASK) | \ 168 (__xxl_setjmp & XXL_SETJMP_MASK); \ 169 __xxl_context->state &= ~(XXL_STATE_HANDLED | XXL_STATE_FINALLY); \ 170 \ 171 if ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_TRY || \ 172 (__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_RETRY) \ 173 { \ 174 { 175 176#define XXL_CATCH(code) \ 177 } \ 178 } \ 179 if ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_ERROR && \ 180 !(__xxl_context->state & XXL_STATE_HANDLED) && \ 181 (int)(code) == xxl_current_error_code()) \ 182 { \ 183 __xxl_context->state |= XXL_STATE_HANDLED; \ 184 { 185 186#define XXL_EXCEPT \ 187 } \ 188 } \ 189 if ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_ERROR && \ 190 !(__xxl_context->state & XXL_STATE_HANDLED)) \ 191 { \ 192 __xxl_context->state |= XXL_STATE_HANDLED; \ 193 { 194 195#define XXL_FINALLY \ 196 } \ 197 } \ 198 __xxl_context->state |= XXL_STATE_FINALLY; \ 199 { \ 200 { 201 202#define XXL_TRY_END \ 203 } \ 204 } \ 205 __xxl_context->state &= ~XXL_STATE_FINALLY; \ 206 if ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_PENDING || \ 207 (__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_PROMOTE || \ 208 ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_ERROR && \ 209 !(__xxl_context->state & XXL_STATE_HANDLED))) \ 210 { \ 211 xxl_leave_handler(XXL_SETJMP_ERROR); \ 212 } \ 213 xxl_pop_contexts(); \ 214 break; \ 215 } \ 216 do {} while (0) 217 218/* These are private functions. Do not call them directly. Use the macros 219 * defined above instead. 220 */ 221extern XXL_API xxl_context_t * xxl_push_context(jmp_buf *); 222extern XXL_API void xxl_pop_context(void); 223extern XXL_API void xxl_pop_contexts(void); 224extern XXL_API void xxl_leave_handler(int); 225extern XXL_API void xxl_throw_error(int, void *, const char *, unsigned int); 226extern XXL_API int xxl_current_error_code(void); 227extern XXL_API void * xxl_current_error_data(void); 228extern XXL_API const char * xxl_current_error_file(void); 229extern XXL_API unsigned int xxl_current_error_line(void); 230extern XXL_API void xxl_push_asset(void *, xxl_assetfreefn_t, void *, xxl_assettype_t); 231extern XXL_API void xxl_update_asset(void *, void *); 232extern XXL_API void xxl_release_asset(void *, int); 233 234/* These are public "convenience" functions. They are essentially wrappers around 235 * common functions that yield assets. Included among these functions are cleanup 236 * callbacks. 237 */ 238extern XXL_API void *xxl_malloc(size_t, xxl_assettype_t); 239extern XXL_API void *xxl_realloc(void *, size_t); 240extern XXL_API void xxl_free(void *); 241extern XXL_API void xxl_cleanup_ptr(void *, void *); 242 243extern XXL_API FILE *xxl_fopen(const char *, const char *, xxl_assettype_t); 244extern XXL_API int xxl_fclose(FILE *); 245extern XXL_API void xxl_cleanup_FILE(void *, void *); 246 247#ifndef WIN32 248extern XXL_API int xxl_open(const char *, int, mode_t, xxl_assettype_t); 249#else 250extern XXL_API int xxl_open(const char *, int, int, xxl_assettype_t); 251#endif 252extern XXL_API int xxl_close(int); 253extern XXL_API void xxl_cleanup_fd(void *, void *); 254 255#ifndef WIN32 256extern XXL_API int xxl_socket(int, int, int, xxl_assettype_t); 257extern XXL_API int xxl_shutdown(int, int); 258extern XXL_API int xxl_closesocket(int); 259#else 260extern XXL_API SOCKET xxl_socket(int, int, int, xxl_assettype_t); 261extern XXL_API int xxl_shutdown(SOCKET, int); 262extern XXL_API int xxl_closesocket(SOCKET); 263#endif 264extern XXL_API void xxl_cleanup_socket(void *, void *); 265 266#ifndef XXL_WITHOUT_THREADS 267#ifdef WIN32 268extern XXL_API BOOL xxl_lock(HANDLE, xxl_assettype_t); 269extern XXL_API BOOL xxl_unlock(HANDLE); 270#else 271extern XXL_API int xxl_lock(pthread_mutex_t *, xxl_assettype_t); 272extern XXL_API int xxl_unlock(pthread_mutex_t *); 273#endif 274extern XXL_API void xxl_cleanup_lock(void *, void *); 275#endif 276 277#ifdef WIN32 278extern XXL_API HGLOBAL xxl_GlobalAlloc(UINT, DWORD, xxl_assettype_t); 279extern XXL_API HGLOBAL xxl_GlobalReAlloc(HGLOBAL, DWORD, UINT); 280extern XXL_API HGLOBAL xxl_GlobalFree(HGLOBAL); 281extern XXL_API void xxl_cleanup_HGLOBAL(void *, void *); 282 283extern XXL_API void *xxl_HeapAlloc(HANDLE, DWORD, DWORD, xxl_assettype_t); 284extern XXL_API void *xxl_HeapReAlloc(HANDLE, DWORD, void *, DWORD); 285extern XXL_API void *xxl_HeapFree(HANDLE, void *); 286extern XXL_API void xxl_cleanup_HeapPtr(void *, void *); 287 288extern XXL_API HLOCAL xxl_LocalAlloc(UINT, UINT, xxl_assettype_t); 289extern XXL_API HLOCAL xxl_LocalReAlloc(HLOCAL, UINT, UINT); 290extern XXL_API HLOCAL xxl_LocalFree(HLOCAL); 291extern XXL_API void xxl_cleanup_HLOCAL(void *, void *); 292 293extern XXL_API void xxl_cleanup_HANDLE(void *, void *); 294#endif 295 296/* Macros for memory allocation. They're different for different platforms so that 297 * the most appropriate memory allocation routines will be used. 298 */ 299#ifndef WIN32 300#define XXL_MALLOC(nbytes, type) xxl_malloc((nbytes), (type)) 301#define XXL_REALLOC(ptr, nbytes) xxl_realloc((void *)(ptr), (nbytes)) 302#define XXL_FREE(ptr) xxl_free((void *)(ptr)) 303#else 304#if defined(XXL_USE_GLOBALHEAP) 305#define XXL_MALLOC(nbytes, type) xxl_GlobalAlloc(GMEM_FIXED, (nbytes), (type)) 306#define XXL_REALLOC(ptr, nbytes) xxl_GlobalReAlloc((HGLOBAL)(ptr), (nbytes), 0) 307#define XXL_FREE(ptr) xxl_GlobalFree((HGLOBAL)(ptr)) 308#elif defined(XXL_USE_LOCALHEAP) 309#define XXL_MALLOC(nbytes, type) xxl_LocalAlloc(LMEM_FIXED, (nbytes), (type)) 310#define XXL_REALLOC(ptr, nbytes) xxl_LocalReAlloc((HLOCAL)(ptr), (nbytes), 0) 311#define XXL_FREE(ptr) xxl_LocalFree((HLOCAL)(ptr)) 312#else 313#define XXL_MALLOC(nbytes, type) xxl_HeapAlloc(NULL, 0, (nbytes), (type)) 314#define XXL_REALLOC(ptr, nbytes) xxl_HeapReAlloc(NULL, 0, (ptr), (nbytes)) 315#define XXL_FREE(ptr) xxl_HeapFree(NULL, (ptr)) 316#endif 317#endif 318 319 320/* Convenience macros that totally trash the namespace if they're used. Have 321 * them included because people are lazy as hell, but allow them to be disabled 322 * in the event of a namespace collision. #define XXL_ENFORCE_PREFIX to 323 * disable the lazy man's API. 324 */ 325#ifndef XXL_ENFORCE_PREFIX 326#define TRY XXL_TRY_BEGIN 327#define CATCH(code) XXL_CATCH(code) 328#define EXCEPT XXL_EXCEPT 329#define FINALLY XXL_FINALLY 330#define END_TRY XXL_TRY_END 331#define THROW(code, data) XXL_THROW_ERROR(code, data) 332#define RETHROW() XXL_RETHROW_ERROR() 333#define EXCEPTION_CODE() XXL_EXCEPTION_CODE() 334#define EXCEPTION_INFO() XXL_EXCEPTION_INFO() 335#define EXCEPTION_FILE() XXL_EXCEPTION_FILE() 336#define EXCEPTION_LINE() XXL_EXCEPTION_LINE() 337#endif 338 339#ifdef __cplusplus 340} 341#endif 342 343#endif /* XXL_H */ 344