andersch.dev

<2025-04-15 Tue>

Defer (Statement)

Defer statements are control flow mechanisms used in some programming languages to schedule code execution to the end of the current scope or function.

Deferred code blocks execute in reverse order (LIFO - last in, first out).

They are useful when working with files, locks, network connections, and other resources that require explicit cleanup.

Languages that include a defer statement are Golang (function-based), Odin, Jai, Zig (scope-based).

defer in C using GCC

#define __DEFER__(F, V)              \
  auto void F(int*);                 \
  __attribute__((cleanup(F))) int V; \
  auto void F(int*)

// version using C23 [[attribute]] syntax
//#define __DEFER__(F, V)      \
//  auto void F(int*);         \
//  [[gnu::cleanup(F)]] int V; \
//  auto void F(int*)

#define __DEFER(N) __DEFER_(N)
#define __DEFER_(N) __DEFER__(__DEFER_FUNCTION_ ## N, __DEFER_VARIABLE_ ## N)
#define defer __DEFER(__COUNTER__)

#include <stdio.h>
void mtx_unlock(int i) { printf("mtx: %i\n", i); }
int main ()
{
    defer {
        printf("rl");
        printf("d\n");
    }
    defer { printf("Wo"); };

    int a = 0;
    switch (a) {
        case 0: {
            printf("before defer\n");
            defer { printf("deferred in switch\n"); }
            printf("after defer\n");
        } break;
    }

    defer { printf("Hello\n"); }
    for (int i = 0; i < 12; ++i) {
        defer { mtx_unlock(i); }

        if (i == 2) {
            return 1; // works with early returns
        }
    }

    return 0;
}
#define hc_id(x, y)  _hc_id(x, y)
#define _hc_id(x, y) x ## y
#define hc_unique(x) hc_id(x, __COUNTER__)
#define _hc_defer(_d, _v, ...)                   \
  void _d(int *) { __VA_ARGS__; }                \
  int _v __attribute__ ((__cleanup__(_d)))

#define hc_defer(...) \
  _hc_defer(hc_unique(defer_d), hc_unique(defer_v), __VA_ARGS__)

#include <assert.h>

int foo = 0;
{
  hc_defer(assert(foo++ == 1));
  hc_defer(assert(foo++ == 0));
}

assert(foo == 2);

defer in C++

See A Defer Statement For C++11

template <typename F>
struct privDefer {
    F f;
    privDefer(F f) : f(f) {}
    ~privDefer() { f(); }
};

template <typename F>
privDefer<F> defer_func(F f) {
    return privDefer<F>(f);
}

#define DEFER_1(x, y) x##y
#define DEFER_2(x, y) DEFER_1(x, y)
#define DEFER_3(x)    DEFER_2(x, __COUNTER__)
#define defer(code)   auto DEFER_3(_defer_) = defer_func([&](){code;})