C言語でもdeferを使いたい #2
c言語でdeferを実装してみよう。
まず、前回示したようにdeferを実装する構造体は次のようになる。
#include <stddef.h>
typedef struct defer_item{
void (*deleter)(void* context);
void *context;
}defer_item_t;
typedef struct defer_impl{
size_t len,cap;
defer_item_t *items;
}defer_impl_t;
そして、初期化・解消処理は次のように書ける。
#include <stdlib.h>
#include <assert.h>
// コンパイルオプション(gccなら-DDEFER_DEFAULT_CAP=XX)で
// 変更できるようにマクロを定義する。
#ifndef DEFER_DEFAULT_CAP
#define DEFER_DEFAULT_CAP 16
#endif/*DEFER_DEFAULT_CAP*/
defer_handle defer_open(){
defer_impl_t*const impl = malloc(sizeof(defer_impl_t));
defer_item_t*const items = malloc(DEFER_DEFAULT_CAP*sizeof(defer_item_t));
if (!impl||!items){
//early returnですぐに制御を戻す
free(impl);
free(items);
return NULL;
}
// implに設定を書き込みんでいく
impl->cap=DEFER_DEFAULT_CAP;
impl->len=0;
impl->items=items;//move ownership into impl
return impl;
}
void defer_close(defer_handle d){
assert(d);//d==NULLは明らかなコーディングミスなので落とす
defer_item_t *const rbegin=&d->items[d->len-1];
defer_item_t *const rend=&d->items[-1];
for (defer_item_t* iter=rbegin;iter!=rend;iter--){
iter->deleter(iter->context);
}
free(d->items);
free(d);
}
次に開放処理を登録する関数を示す。