/* xxl.h.  Generated by configure.  */
#ifndef XXL_H
#define XXL_H

#ifndef WIN32
/* BEGIN:   autoconf substitutions */
#define HAVE_SETJMP_H 1
#define HAVE_PTHREAD_H 1
/* #undef HAVE_SYS_TYPES_H */
/* #undef STDC_HEADERS */
/* #undef XXL_WITHOUT_THREADS */
/* #undef const */
/* END:     autoconf substitutions */
#define XXL_API
#else
#ifdef XXL_EXPORTS
#define XXL_API __declspec(dllexport)
#else
#define XXL_API __declspec(dllimport)
#endif
#endif

#if !defined(XXL_WITHOUT_THREADS) && !defined(WIN32) && !defined(HAVE_PTHREAD_H)
#define XXL_WITHOUT_THREADS
#endif

#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#endif
#include <stdio.h>
#if defined(HAVE_SYS_TYPES_H)
#include <sys/types.h>
#endif
#if defined(HAVE_SETJMP_H) || defined(WIN32)
#include <setjmp.h>
#endif
#if !defined(WIN32) && defined(STDC_HEADERS)
#include <errno.h>
#endif
#if !defined(XXL_WITHOUT_THREADS) && defined(HAVE_PTHREAD_H)
#include <pthread.h>
#endif

#define XXL_ERROR_THREAD_CANCELLED      0xFFFFFFFF
#define XXL_ERROR_RETRY_EXCEPTION       0xFFFFFFFE

#ifdef __cplusplus
extern "C" {
#endif

typedef enum _xxl_assettype_t
{
    XXL_ASSET_PERMANENT,
    XXL_ASSET_PROMOTE,
    XXL_ASSET_TEMPORARY,
    XXL_ASSET_AUTO,
    XXL_ASSET_DEMOTE
} xxl_assettype_t;

typedef void (*xxl_assetfreefn_t)(void *, void *);

typedef struct _xxl_asset_t     xxl_asset_t;
typedef struct _xxl_context_t   xxl_context_t;
typedef struct _xxl_exception_t xxl_exception_t;
typedef struct _xxl_tsd_t       xxl_tsd_t;

struct _xxl_asset_t
{
    void                *ptr;
    xxl_assetfreefn_t   freefn;
    void                *arg;
    xxl_assettype_t     type;
    xxl_asset_t         *next;
};

struct _xxl_exception_t
{
    int                 code;
    void                *data;
    const char          *file;
    unsigned int        line;
};

struct _xxl_context_t
{
    jmp_buf             *context;
    unsigned int        state;
    xxl_exception_t     exception;
    xxl_exception_t     pending;
#if !defined(WIN32) && !defined(XXL_WITHOUT_THREADS)
    int                 cancel_type;
#endif
    xxl_asset_t         *assets;
    xxl_context_t       *next;
};

struct _xxl_tsd_t
{
    xxl_context_t       *contexts;
#if !defined(WIN32) || defined(XXL_WITHOUT_THREADS)
    xxl_context_t       *free_contexts;
    xxl_asset_t         *free_assets;
#endif
};

#define XXL_ASSET_ALL       0
#define XXL_ASSET_CURRENT   1
#define XXL_ASSET_FIRST     2

/* These are only used internally */
#define XXL_SETJMP_TRY      0x00
#define XXL_SETJMP_ERROR    0x01
#define XXL_SETJMP_RETRY    0x02
#define XXL_SETJMP_PROMOTE  0x03
#define XXL_SETJMP_LEAVE    0x04
#define XXL_SETJMP_PENDING  0x05
#define XXL_SETJMP_MASK     0xFF

#define XXL_STATE_HANDLED   0x00000100
#define XXL_STATE_FINALLY   0x00000200
#define XXL_STATE_PENDING   0x00000400
#define XXL_STATE_THROWN    0x00000800
#define XXL_STATE_MASK      0x0000FF00

/* Public Macros */
#define XXL_ASSET_BLOCK_BEGIN                                               \
    do                                                                      \
    {                                                                       \
        xxl_push_context(NULL);                                             \
        {

#define XXL_ASSET_BLOCK_END                                                 \
        }                                                                   \
        xxl_pop_context();                                                  \
    } while (0)

#define XXL_ASSET_SAVE(asset, callback, arg, type)                          \
    xxl_push_asset((asset), (xxl_assetfreefn_t)(callback), (arg), (type))
#define XXL_ASSET_UPDATE(old_asset, new_asset)                              \
    xxl_update_asset((old_asset), (new_asset))
#define XXL_ASSET_RELEASE(asset, mode)                                      \
    xxl_release_asset((asset), (mode))

#define XXL_THROW_ERROR(code, data)                                         \
    xxl_throw_error((code), (data), __FILE__, __LINE__)
#define XXL_RETHROW_ERROR()                                                 \
    xxl_leave_handler(XXL_SETJMP_PROMOTE)
#define XXL_LEAVE()                                                         \
    xxl_leave_handler(XXL_SETJMP_LEAVE)
#define XXL_RETRY()                                                         \
    xxl_leave_handler(XXL_SETJMP_RETRY)

#define XXL_EXCEPTION_CODE()    xxl_current_error_code()
#define XXL_EXCEPTION_DATA()    xxl_current_error_data()
#define XXL_EXCEPTION_FILE()    xxl_current_error_file()
#define XXL_EXCEPTION_LINE()    xxl_current_error_line()

#define XXL_TRY_BEGIN                                                           \
    for (;;)                                                                    \
    {                                                                           \
        int                     __xxl_setjmp;                                   \
        jmp_buf                 __xxl_jmpbuf;                                   \
        volatile xxl_context_t  *__xxl_context;                                 \
                                                                                \
        __xxl_context = xxl_push_context(&__xxl_jmpbuf);                        \
        __xxl_setjmp  = setjmp(__xxl_jmpbuf);                                   \
        __xxl_context->state  = (__xxl_context->state & XXL_STATE_MASK) |       \
                                (__xxl_setjmp & XXL_SETJMP_MASK);               \
        __xxl_context->state &= ~(XXL_STATE_HANDLED | XXL_STATE_FINALLY);       \
                                                                                \
        if ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_TRY ||       \
            (__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_RETRY)       \
        {                                                                       \
            {

#define XXL_CATCH(code)                                                         \
            }                                                                   \
        }                                                                       \
        if ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_ERROR &&     \
            !(__xxl_context->state & XXL_STATE_HANDLED) &&                      \
            (int)(code) == xxl_current_error_code())                            \
        {                                                                       \
            __xxl_context->state |= XXL_STATE_HANDLED;                          \
            {

#define XXL_EXCEPT                                                              \
            }                                                                   \
        }                                                                       \
        if ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_ERROR &&     \
            !(__xxl_context->state & XXL_STATE_HANDLED))                        \
        {                                                                       \
            __xxl_context->state |= XXL_STATE_HANDLED;                          \
            {

#define XXL_FINALLY                                                             \
            }                                                                   \
        }                                                                       \
        __xxl_context->state |= XXL_STATE_FINALLY;                              \
        {                                                                       \
            {

#define XXL_TRY_END                                                             \
            }                                                                   \
        }                                                                       \
        __xxl_context->state &= ~XXL_STATE_FINALLY;                             \
        if ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_PENDING ||   \
            (__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_PROMOTE ||   \
            ((__xxl_context->state & XXL_SETJMP_MASK) == XXL_SETJMP_ERROR &&    \
             !(__xxl_context->state & XXL_STATE_HANDLED)))                      \
        {                                                                       \
            xxl_leave_handler(XXL_SETJMP_ERROR);                                \
        }                                                                       \
        xxl_pop_contexts();                                                     \
        break;                                                                  \
    }                                                                           \
    do {} while (0)

/* These are private functions.  Do not call them directly.  Use the macros
 * defined above instead.
 */
extern XXL_API xxl_context_t *  xxl_push_context(jmp_buf *);
extern XXL_API void             xxl_pop_context(void);
extern XXL_API void             xxl_pop_contexts(void);
extern XXL_API void             xxl_leave_handler(int);
extern XXL_API void             xxl_throw_error(int, void *, const char *, unsigned int);
extern XXL_API int              xxl_current_error_code(void);
extern XXL_API void *           xxl_current_error_data(void);
extern XXL_API const char *     xxl_current_error_file(void);
extern XXL_API unsigned int     xxl_current_error_line(void);
extern XXL_API void             xxl_push_asset(void *, xxl_assetfreefn_t, void *, xxl_assettype_t);
extern XXL_API void             xxl_update_asset(void *, void *);
extern XXL_API void             xxl_release_asset(void *, int);

/* These are public "convenience" functions.  They are essentially wrappers around
 * common functions that yield assets.  Included among these functions are cleanup
 * callbacks.
 */
extern XXL_API void *xxl_malloc(size_t, xxl_assettype_t);
extern XXL_API void *xxl_realloc(void *, size_t);
extern XXL_API void xxl_free(void *);
extern XXL_API void xxl_cleanup_ptr(void *, void *);

extern XXL_API FILE *xxl_fopen(const char *, const char *, xxl_assettype_t);
extern XXL_API int  xxl_fclose(FILE *);
extern XXL_API void xxl_cleanup_FILE(void *, void *);

#ifndef WIN32
extern XXL_API int  xxl_open(const char *, int, mode_t, xxl_assettype_t);
#else
extern XXL_API int  xxl_open(const char *, int, int, xxl_assettype_t);
#endif
extern XXL_API int  xxl_close(int);
extern XXL_API void xxl_cleanup_fd(void *, void *);

#ifndef WIN32
extern XXL_API int  xxl_socket(int, int, int, xxl_assettype_t);
extern XXL_API int  xxl_shutdown(int, int);
extern XXL_API int  xxl_closesocket(int);
#else
extern XXL_API SOCKET xxl_socket(int, int, int, xxl_assettype_t);
extern XXL_API int    xxl_shutdown(SOCKET, int);
extern XXL_API int    xxl_closesocket(SOCKET);
#endif
extern XXL_API void   xxl_cleanup_socket(void *, void *);

#ifndef XXL_WITHOUT_THREADS
#ifdef WIN32
extern XXL_API BOOL xxl_lock(HANDLE, xxl_assettype_t);
extern XXL_API BOOL xxl_unlock(HANDLE);
#else
extern XXL_API int xxl_lock(pthread_mutex_t *, xxl_assettype_t);
extern XXL_API int xxl_unlock(pthread_mutex_t *);
#endif
extern XXL_API void xxl_cleanup_lock(void *, void *);
#endif

#ifdef WIN32
extern XXL_API HGLOBAL xxl_GlobalAlloc(UINT, DWORD, xxl_assettype_t);
extern XXL_API HGLOBAL xxl_GlobalReAlloc(HGLOBAL, DWORD, UINT);
extern XXL_API HGLOBAL xxl_GlobalFree(HGLOBAL);
extern XXL_API void    xxl_cleanup_HGLOBAL(void *, void *);

extern XXL_API void    *xxl_HeapAlloc(HANDLE, DWORD, DWORD, xxl_assettype_t);
extern XXL_API void    *xxl_HeapReAlloc(HANDLE, DWORD, void *, DWORD);
extern XXL_API void    *xxl_HeapFree(HANDLE, void *);
extern XXL_API void    xxl_cleanup_HeapPtr(void *, void *);

extern XXL_API HLOCAL  xxl_LocalAlloc(UINT, UINT, xxl_assettype_t);
extern XXL_API HLOCAL  xxl_LocalReAlloc(HLOCAL, UINT, UINT);
extern XXL_API HLOCAL  xxl_LocalFree(HLOCAL);
extern XXL_API void    xxl_cleanup_HLOCAL(void *, void *);

extern XXL_API void    xxl_cleanup_HANDLE(void *, void *);
#endif

/* Macros for memory allocation.  They're different for different platforms so that
 * the most appropriate memory allocation routines will be used.
 */
#ifndef WIN32
#define XXL_MALLOC(nbytes, type)    xxl_malloc((nbytes), (type))
#define XXL_REALLOC(ptr, nbytes)    xxl_realloc((void *)(ptr), (nbytes))
#define XXL_FREE(ptr)               xxl_free((void *)(ptr))
#else
#if defined(XXL_USE_GLOBALHEAP)
#define XXL_MALLOC(nbytes, type)    xxl_GlobalAlloc(GMEM_FIXED, (nbytes), (type))
#define XXL_REALLOC(ptr, nbytes)    xxl_GlobalReAlloc((HGLOBAL)(ptr), (nbytes), 0)
#define XXL_FREE(ptr)               xxl_GlobalFree((HGLOBAL)(ptr))
#elif defined(XXL_USE_LOCALHEAP)
#define XXL_MALLOC(nbytes, type)    xxl_LocalAlloc(LMEM_FIXED, (nbytes), (type))
#define XXL_REALLOC(ptr, nbytes)    xxl_LocalReAlloc((HLOCAL)(ptr), (nbytes), 0)
#define XXL_FREE(ptr)               xxl_LocalFree((HLOCAL)(ptr))
#else
#define XXL_MALLOC(nbytes, type)    xxl_HeapAlloc(NULL, 0, (nbytes), (type))
#define XXL_REALLOC(ptr, nbytes)    xxl_HeapReAlloc(NULL, 0, (ptr), (nbytes))
#define XXL_FREE(ptr)               xxl_HeapFree(NULL, (ptr))
#endif
#endif


/* Convenience macros that totally trash the namespace if they're used.  Have
 * them included because people are lazy as hell, but allow them to be disabled
 * in the event of a namespace collision.  #define XXL_ENFORCE_PREFIX to
 * disable the lazy man's API.
 */
#ifndef XXL_ENFORCE_PREFIX
#define TRY                 XXL_TRY_BEGIN
#define CATCH(code)         XXL_CATCH(code)
#define EXCEPT              XXL_EXCEPT
#define FINALLY             XXL_FINALLY
#define END_TRY             XXL_TRY_END
#define THROW(code, data)   XXL_THROW_ERROR(code, data)
#define RETHROW()           XXL_RETHROW_ERROR()
#define EXCEPTION_CODE()    XXL_EXCEPTION_CODE()
#define EXCEPTION_INFO()    XXL_EXCEPTION_INFO()
#define EXCEPTION_FILE()    XXL_EXCEPTION_FILE()
#define EXCEPTION_LINE()    XXL_EXCEPTION_LINE()
#endif

#ifdef __cplusplus
}
#endif

#endif  /* XXL_H */


syntax highlighted by Code2HTML, v. 0.9.1