X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=ucw%2Ftrans.h;h=e5e328482f1fc8d165fd2410c3c7138f3bbea2d6;hb=05ffab94be8da943cffb8fb30d7073ab78aef94c;hp=7ba8e6ff53827df4cf4439402aac964d840e798b;hpb=d8c423da72506f8688a609c2a3bd9caf5f5bd93a;p=libucw.git diff --git a/ucw/trans.h b/ucw/trans.h index 7ba8e6ff..e5e32848 100644 --- a/ucw/trans.h +++ b/ucw/trans.h @@ -1,7 +1,7 @@ /* * The UCW Library -- Transactions * - * (c) 2008 Martin Mares + * (c) 2008--2011 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -10,66 +10,73 @@ #ifndef _UCW_TRANS_H #define _UCW_TRANS_H -#include "ucw/clists.h" -#include "ucw/mempool.h" +#include -#include +#include -/* Resource pools */ - -struct respool { - clist resources; - struct mempool *mp; // If set, resources are allocated from the mempool, otherwise by xmalloc() -}; - -struct resource { - cnode n; - struct res_class *rclass; - void *priv; // Private to the class +/** A structure describing a transaction. All fields are for internal use only. **/ +struct trans { + struct trans *prev_trans; + struct mempool_state *trans_pool_state; + struct respool *rpool; + struct respool *prev_rpool; + struct exception *thrown_exc; + jmp_buf jmp; }; -struct res_class { - const char *name; - void (*undo)(struct res *t); - void (*dump)(struct res *t); +void trans_init(void); /** Initializes the transaction system for the current thread. Called automatically as needed. **/ +void trans_cleanup(void); /** Frees memory occupied by the transaction system pools for the current thread. **/ + +struct trans *trans_open(void); /** Creates a new transaction. Used inside `TRANS_TRY`. **/ +struct trans *trans_get_current(void); /** Get a pointer to the currently running transaction, or NULL if there is none. **/ +void trans_commit(void); /** Commits the current transaction. **/ +void trans_rollback(void); /** Rolls back the current transaction. **/ +void trans_fold(void); /** Folds the current transaction to its parent. **/ +void trans_dump(void); /** Prints out a debugging dump of the transaction stack to stdout. **/ + +struct mempool *trans_get_pool(void); + +/** + * Data associated with an exception. Usually, this structure is created + * by calling @trans_throw(), but if you want to pass more data, you can + * create your own exception and throw it using @trans_throw_exc(). + **/ +struct exception { + const char *id; // Hierarchical identifier of the exception + const char *msg; // Error message to present to the user + void *object; // Object on which the exception happened + // More data specific for the particular `id' can follow }; -struct respool *rp_new(void); -void rp_delete(struct respool *rp); -void rp_dump(struct respool *rp); +/** Creates an exception and throws it. The error message can contain `printf`-like formatting. **/ +void trans_throw(const char *id, void *object, const char *fmt, ...) FORMAT_CHECK(printf,3,4) NONRET; -struct resource *res_alloc(struct respool *rp); -void res_fix(struct resource *r); -void res_undo(struct resource *r); -void res_dump(struct resource *r); +/** A `va_list` variant of @trans_throw(). **/ +void trans_vthrow(const char *id, void *object, const char *fmt, va_list args) NONRET; -static inline struct resource * -res_new(struct respool *rp, struct res_class *rc, void *priv) -{ - struct resource *r = res_alloc(rp); - r->rclass = rc; - r->priv = priv; - return r; -} +/** Throw an already constructed exception (or re-throw an exception you have caught). **/ +void trans_throw_exc(struct exception *x) NONRET; -/* Transactions */ +/** Declare the current exception caught and roll back the current transaction. Called from `TRANS_END`. **/ +void trans_caught(void); -struct trans { - struct trans *prev; - struct mempool_state trans_pool_state; - struct respool res_pool; - jmp_buf jmp; -}; +struct exception *trans_current_exc(void); /** Return the exception in flight, or NULL if there is none. **/ -void trans_init(void); // Called automatically on trans_open() if needed -void trans_cleanup(void); // Free memory occupied by the transaction system pools +#define TRANS_TRY do { \ + struct trans *_t = trans_open(); \ + if (!setjmp(_t->jmp)) \ + { -struct trans *trans_open(void); -struct trans *trans_get_current(void); -void trans_commit(void); -void trans_rollback(void); -void trans_dump(void); +#define TRANS_CATCH(x) \ + trans_commit(); \ + } \ + else \ + { \ + struct exception *x UNUSED = trans_current_exc(); -/* Exceptions */ +#define TRANS_END \ + trans_caught(); \ + } \ + } while(0) #endif