- Notifications
You must be signed in to change notification settings - Fork5
A simple library to provide RAII in standard-compliant C99, using raii_with(resource, initializer, destructor) { ... }-syntax:
License
Qqwy/raii_with
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A simple library to provide RAII (or something very much like it) in standard-compliant C99, usingraii_with(resource, initializer, destructor) { ... }
-syntax:
#include"raii/raii.h"intmain() {raii_with(int*myint,safe_malloc(sizeof(int)),free){*myint=10;printf("myint is located at %p and contains: %d\n",myint,*myint);printf("%s\n",__func__); }intres=safe_return_example();printf("res: %d\n",res);printf("Test\n");}
Resource Acquisition Is Initialization (or, if you prefer, Resource Relinquishment is Destruction)is a pattern that C++ and some other languages use to ensure that a resource is automatically released once you are doneworking with it.
Theraii library for C99 tries to emulate this, by letting you writeraii_with
statementsthat are similar to thewith
-statements of e.g. Python.
The advantages over managing resources manually are:
- Manual management is error-prone:
- Checking for proper initialization or early-fail on error requires a linear amount of cleanup lines per nested resource if writing this using if-statements.
- The alternative, using
goto
s to labels at the end of the function, is prone to mistakes when new content is added to the function or the internal order of resources is swapped.
- Using an explicit lifetime-stack object means that you need to conceptually work with this lifetime-stack all the time.
Instead,raii:
- is built such that swapping the order of the resources will swap the order of the clean-up logic for you.
- Variables introduced using
raii_with
only exist in the block you provide. Referencing after the block will result in a compiler error, so that's a whole lot of bugs you don't need to worry about anymore! - creates a hidden lifetime 'stack' (which is implemented as a linked-list), which you don't have to care about, because all you have to care aboutis that you can just use
safe_return
to return early from within araii_with
-block. - Use
continue
orbreak
to jump to the end of the currentraii_with
-block.
raii uses a custom control structure macro to ensure you can pass any code block to theraii_with
-statement.
For more information, you are encouraged to read the inline documentation in theraii/raii.h
file.
For more information about writing Custom Control Structure Macro's, see my related libraryexceptional that introduces block-style exceptions to C99,and the there-linked further resources as well.
- Do not use
return
from withinraii_with
, but onlysafe_return
, because otherwise the destructors will not be run. - Do not perform pointer-swaps with
var_decl
; the destructor will still be run on the original structure, becauseraii
keeps its own reference to the resource.
I believe both of these things are very logical and easy to keep in mind. (resulting inraii being a near-leak-free abstraction). If you know of a way to further reduce these without introducing new ones, please share it!
I'd like to thank:
- Simon Tatham for hiswonderful guide to creating your own Custom Control Structure Macros
- tsoding/reximcut for the interesting approach to using lifetimes for resource managementyoutube video and subsequentreddit discussion.