* kclib1のページ#6 -(by [[K]], 2019.04.16) ** (10) KAutoreleasePool -仕事でObjective-Cを使った時に、autoreleasePoolの仕組みが便利だなと感じたので、似たようなものを作ってみました(本家よりもかなりシンプルですが)。 -Objective-Cを知らない人向けに言うと、「使わなくなったオブジェクトを自動でfreeしてくれる便利な仕組み」って感じです。 ---- -KAutoreleasePool *KAutoreleasePool_open() --自動解放プールをオープンします。以後は自動的にこのプールがデフォルトになります。 -void KAutoreleasePool_add(KAutoreleasePool *w, int s, void *p) --自動解放プールに、サイズとポインタを登録します。wに0を指定した場合はデフォルトのプールへの登録になります。 -int KAutoreleasePool_remove(KAutoreleasePool *w, void *p) --自動解放プールに登録されているポインタを削除します。戻り値は登録されていたサイズです。 --これのあとにaddを使うことで、登録されたポインタを別のプールに付け替えることもできます。 -void *KAutoreleasePool_alloc(KAutoreleasePool *w, int s) --sを使ってKMallocして、取得したポインタを直ちに自動解放プールに登録して、それでそれを返します。 -void KAutoreleasePool_close(KAutoreleasePool *w) --自動解放プールを閉じます。つまりこの時点でプール内のすべてのポインタがfreeされることになります。 ---- -[内部実装] typedef struct KAutoreleaseNode_ { void *p; int s; void *n; } KAutoreleaseNode; typedef struct KAutoreleasePool_ { void *prv; KAutoreleaseNode *n; } KAutoreleasePool; ---- -[内部実装] #include "kclib1.h" KAutoreleasePool *KAutoreleasePool_top; static KPtrPool *nodePool; KAutoreleasePool *KAutoreleasePool_open() { KAutoreleasePool *w; if (KMalloc_work->p == 0) KMalloc_init(); if (nodePool == 0) nodePool = KMalloc_work->p + KMalloc_index(sizeof (KAutoreleaseNode)); w = KMalloc_alloc(sizeof (KAutoreleasePool)); w->prv = KAutoreleasePool_top; KAutoreleasePool_top = w; w->n = 0; return w; } void KAutoreleasePool_add(KAutoreleasePool *w, int s, void *p) { KAutoreleaseNode *n; if (w == 0) w = KAutoreleasePool_top; n = KPtrPool_alloc(nodePool); n->n = w->n; n->p = p; n->s = s; w->n = n; } int KAutoreleasePool_remove(KAutoreleasePool *w, void *p) { KAutoreleaseNode *n, *m = 0; if (w == 0) w = KAutoreleasePool_top; n = w->n; while (n != 0) { if (n->p == p) { int s = n->s; if (m != 0) m->n = n->n; else w->n = n->n; KPtrPool_free(nodePool, n); return s; } m = n; n = n->n; } kerrorExit("KAutoreleasePool_remove: not found: p=%08x", p); return -1; // dummy. } void *KAutoreleasePool_alloc(KAutoreleasePool *w, int s) { void *p = KMalloc_alloc(s); KAutoreleasePool_add(w, s, p); return p; } void KAutoreleasePool_close(KAutoreleasePool *w) { KAutoreleaseNode *n, *nn; if (w != KAutoreleasePool_top) kerrorExit("KAutoreleasePool_close: nesting error"); for (n = w->n; n != 0; ) { nn = n->n; KMalloc_free(n->s, n->p); KPtrPool_free(nodePool, n); n = nn; } KAutoreleasePool_top = w->prv; KMalloc_free(sizeof (KAutoreleasePool), w); } * こめんと欄 #comment