/*	$OpenBSD: rf_freelist.h,v 1.2 1999/02/16 00:02:47 niklas Exp $	*/
/*	$NetBSD: rf_freelist.h,v 1.3 1999/02/05 00:06:11 oster Exp $	*/
/*
 * rf_freelist.h
 */
/*
 * Copyright (c) 1995 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Jim Zelenka
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

/*
 * rf_freelist.h -- code to manage counted freelists
 *
 * Keep an arena of fixed-size objects. When a new object is needed,
 * allocate it as necessary. When an object is freed, either put it
 * in the arena, or really free it, depending on the maximum arena
 * size.
 */

#ifndef _RF__RF_FREELIST_H_
#define _RF__RF_FREELIST_H_

#include "rf_types.h"
#include "rf_debugMem.h"
#include "rf_general.h"
#include "rf_threadstuff.h"

#define RF_FREELIST_STATS 0

#if RF_FREELIST_STATS > 0
typedef struct RF_FreeListStats_s {
	char   *file;
	int     line;
	int     allocations;
	int     frees;
	int     max_free;
	int     grows;
	int     outstanding;
	int     max_outstanding;
}       RF_FreeListStats_t;
#define RF_FREELIST_STAT_INIT(_fl_) { \
	bzero((char *)&((_fl_)->stats), sizeof(RF_FreeListStats_t)); \
	(_fl_)->stats.file = __FILE__; \
	(_fl_)->stats.line = __LINE__; \
}

#define RF_FREELIST_STAT_ALLOC(_fl_) { \
	(_fl_)->stats.allocations++; \
	(_fl_)->stats.outstanding++; \
	if ((_fl_)->stats.outstanding > (_fl_)->stats.max_outstanding) \
		(_fl_)->stats.max_outstanding = (_fl_)->stats.outstanding; \
}

#define RF_FREELIST_STAT_FREE_UPDATE(_fl_) { \
	if ((_fl_)->free_cnt > (_fl_)->stats.max_free) \
		(_fl_)->stats.max_free = (_fl_)->free_cnt; \
}

#define RF_FREELIST_STAT_FREE(_fl_) { \
	(_fl_)->stats.frees++; \
	(_fl_)->stats.outstanding--; \
	RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
}

#define RF_FREELIST_STAT_GROW(_fl_) { \
	(_fl_)->stats.grows++; \
	RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
}

#define RF_FREELIST_STAT_REPORT(_fl_) { \
	printf("Freelist at %s %d (%s)\n", (_fl_)->stats.file, (_fl_)->stats.line, RF_STRING(_fl_)); \
	printf("  %d allocations, %d frees\n", (_fl_)->stats.allocations, (_fl_)->stats.frees); \
	printf("  %d grows\n", (_fl_)->stats.grows); \
	printf("  %d outstanding\n", (_fl_)->stats.outstanding); \
	printf("  %d free (max)\n", (_fl_)->stats.max_free); \
	printf("  %d outstanding (max)\n", (_fl_)->stats.max_outstanding); \
}

#else				/* RF_FREELIST_STATS > 0 */

#define RF_FREELIST_STAT_INIT(_fl_)
#define RF_FREELIST_STAT_ALLOC(_fl_)
#define RF_FREELIST_STAT_FREE_UPDATE(_fl_)
#define RF_FREELIST_STAT_FREE(_fl_)
#define RF_FREELIST_STAT_GROW(_fl_)
#define RF_FREELIST_STAT_REPORT(_fl_)

#endif				/* RF_FREELIST_STATS > 0 */

struct RF_FreeList_s {
	void   *objlist;	/* list of free obj */
	int     free_cnt;	/* how many free obj */
	int     max_free_cnt;	/* max free arena size */
	int     obj_inc;	/* how many to allocate at a time */
	int     obj_size;	/* size of objects */
	        RF_DECLARE_MUTEX(lock)
#if RF_FREELIST_STATS > 0
	RF_FreeListStats_t stats;	/* statistics */
#endif				/* RF_FREELIST_STATS > 0 */
};
/*
 * fl     = freelist
 * maxcnt = max number of items in arena
 * inc    = how many to allocate at a time
 * size   = size of object
 */
#define RF_FREELIST_CREATE(_fl_,_maxcnt_,_inc_,_size_) { \
	int rc; \
	RF_ASSERT((_inc_) > 0); \
	RF_Malloc(_fl_, sizeof(RF_FreeList_t), (RF_FreeList_t *)); \
	(_fl_)->objlist = NULL; \
	(_fl_)->free_cnt = 0; \
	(_fl_)->max_free_cnt = _maxcnt_; \
	(_fl_)->obj_inc = _inc_; \
	(_fl_)->obj_size = _size_; \
	rc = rf_mutex_init(&(_fl_)->lock); \
	if (rc) { \
		RF_Free(_fl_, sizeof(RF_FreeList_t)); \
		_fl_ = NULL; \
	} \
	RF_FREELIST_STAT_INIT(_fl_); \
}

/*
 * fl    = freelist
 * cnt   = number to prime with
 * nextp = name of "next" pointer in obj
 * cast  = object cast
 */
#define RF_FREELIST_PRIME(_fl_,_cnt_,_nextp_,_cast_) { \
	void *_p; \
	int _i; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	for(_i=0;_i<(_cnt_);_i++) { \
		RF_Calloc(_p,1,(_fl_)->obj_size,(void *)); \
		if (_p) { \
			(_cast_(_p))->_nextp_ = (_fl_)->objlist; \
			(_fl_)->objlist = _p; \
			(_fl_)->free_cnt++; \
		} \
		else { \
			break; \
		} \
	} \
	RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

#define RF_FREELIST_MUTEX_OF(_fl_) ((_fl_)->lock)

#define RF_FREELIST_DO_UNLOCK(_fl_) { \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

#define RF_FREELIST_DO_LOCK(_fl_) { \
	RF_LOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * cnt   = number to prime with
 * nextp = name of "next" pointer in obj
 * cast  = object cast
 * init  = func to call to init obj
 */
#define RF_FREELIST_PRIME_INIT(_fl_,_cnt_,_nextp_,_cast_,_init_) { \
	void *_p; \
	int _i; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	for(_i=0;_i<(_cnt_);_i++) { \
		RF_Calloc(_p,1,(_fl_)->obj_size,(void *)); \
		if (_init_ (_cast_ _p)) { \
			RF_Free(_p,(_fl_)->obj_size); \
			_p = NULL; \
		} \
		if (_p) { \
			(_cast_(_p))->_nextp_ = (_fl_)->objlist; \
			(_fl_)->objlist = _p; \
			(_fl_)->free_cnt++; \
		} \
		else { \
			break; \
		} \
	} \
	RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * cnt   = number to prime with
 * nextp = name of "next" pointer in obj
 * cast  = object cast
 * init  = func to call to init obj
 * arg   = arg to init obj func
 */
#define RF_FREELIST_PRIME_INIT_ARG(_fl_,_cnt_,_nextp_,_cast_,_init_,_arg_) { \
	void *_p; \
	int _i; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	for(_i=0;_i<(_cnt_);_i++) { \
		RF_Calloc(_p,1,(_fl_)->obj_size,(void *)); \
		if (_init_ (_cast_ _p,_arg_)) { \
			RF_Free(_p,(_fl_)->obj_size); \
			_p = NULL; \
		} \
		if (_p) { \
			(_cast_(_p))->_nextp_ = (_fl_)->objlist; \
			(_fl_)->objlist = _p; \
			(_fl_)->free_cnt++; \
		} \
		else { \
			break; \
		} \
	} \
	RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * obj   = object to allocate
 * nextp = name of "next" pointer in obj
 * cast  = cast of obj assignment
 * init  = init obj func
 */
#define RF_FREELIST_GET_INIT(_fl_,_obj_,_nextp_,_cast_,_init_) { \
	void *_p; \
	int _i; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	RF_ASSERT(sizeof(*(_obj_))==((_fl_)->obj_size)); \
	if (_fl_->objlist) { \
		_obj_ = _cast_((_fl_)->objlist); \
		(_fl_)->objlist = (void *)((_obj_)->_nextp_); \
		(_fl_)->free_cnt--; \
	} \
	else { \
		/* \
		 * Allocate one at a time so we can free \
		 * one at a time without cleverness when arena \
		 * is full. \
		 */ \
		RF_Calloc(_obj_,1,(_fl_)->obj_size,_cast_); \
		if (_obj_) { \
			if (_init_ (_obj_)) { \
				RF_Free(_obj_,(_fl_)->obj_size); \
				_obj_ = NULL; \
			} \
			else { \
				for(_i=1;_i<(_fl_)->obj_inc;_i++) { \
					RF_Calloc(_p,1,(_fl_)->obj_size,(void *)); \
					if (_p) { \
						if (_init_ (_p)) { \
							RF_Free(_p,(_fl_)->obj_size); \
							_p = NULL; \
							break; \
						} \
						(_cast_(_p))->_nextp_ = (_fl_)->objlist; \
						(_fl_)->objlist = _p; \
					} \
					else { \
						break; \
					} \
				} \
			} \
		} \
		RF_FREELIST_STAT_GROW(_fl_); \
	} \
	RF_FREELIST_STAT_ALLOC(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * obj   = object to allocate
 * nextp = name of "next" pointer in obj
 * cast  = cast of obj assignment
 * init  = init obj func
 * arg   = arg to init obj func
 */
#define RF_FREELIST_GET_INIT_ARG(_fl_,_obj_,_nextp_,_cast_,_init_,_arg_) { \
	void *_p; \
	int _i; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	RF_ASSERT(sizeof(*(_obj_))==((_fl_)->obj_size)); \
	if (_fl_->objlist) { \
		_obj_ = _cast_((_fl_)->objlist); \
		(_fl_)->objlist = (void *)((_obj_)->_nextp_); \
		(_fl_)->free_cnt--; \
	} \
	else { \
		/* \
		 * Allocate one at a time so we can free \
		 * one at a time without cleverness when arena \
		 * is full. \
		 */ \
		RF_Calloc(_obj_,1,(_fl_)->obj_size,_cast_); \
		if (_obj_) { \
			if (_init_ (_obj_,_arg_)) { \
				RF_Free(_obj_,(_fl_)->obj_size); \
				_obj_ = NULL; \
			} \
			else { \
				for(_i=1;_i<(_fl_)->obj_inc;_i++) { \
					RF_Calloc(_p,1,(_fl_)->obj_size,(void *)); \
					if (_p) { \
						if (_init_ (_p,_arg_)) { \
							RF_Free(_p,(_fl_)->obj_size); \
							_p = NULL; \
							break; \
						} \
						(_cast_(_p))->_nextp_ = (_fl_)->objlist; \
						(_fl_)->objlist = _p; \
					} \
					else { \
						break; \
					} \
				} \
			} \
		} \
		RF_FREELIST_STAT_GROW(_fl_); \
	} \
	RF_FREELIST_STAT_ALLOC(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * obj   = object to allocate
 * nextp = name of "next" pointer in obj
 * cast  = cast of obj assignment
 * init  = init obj func
 */
#define RF_FREELIST_GET_INIT_NOUNLOCK(_fl_,_obj_,_nextp_,_cast_,_init_) { \
	void *_p; \
	int _i; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	RF_ASSERT(sizeof(*(_obj_))==((_fl_)->obj_size)); \
	if (_fl_->objlist) { \
		_obj_ = _cast_((_fl_)->objlist); \
		(_fl_)->objlist = (void *)((_obj_)->_nextp_); \
		(_fl_)->free_cnt--; \
	} \
	else { \
		/* \
		 * Allocate one at a time so we can free \
		 * one at a time without cleverness when arena \
		 * is full. \
		 */ \
		RF_Calloc(_obj_,1,(_fl_)->obj_size,_cast_); \
		if (_obj_) { \
			if (_init_ (_obj_)) { \
				RF_Free(_obj_,(_fl_)->obj_size); \
				_obj_ = NULL; \
			} \
			else { \
				for(_i=1;_i<(_fl_)->obj_inc;_i++) { \
					RF_Calloc(_p,1,(_fl_)->obj_size,(void *)); \
					if (_p) { \
						if (_init_ (_p)) { \
							RF_Free(_p,(_fl_)->obj_size); \
							_p = NULL; \
							break; \
						} \
						(_cast_(_p))->_nextp_ = (_fl_)->objlist; \
						(_fl_)->objlist = _p; \
					} \
					else { \
						break; \
					} \
				} \
			} \
		} \
		RF_FREELIST_STAT_GROW(_fl_); \
	} \
	RF_FREELIST_STAT_ALLOC(_fl_); \
}

/*
 * fl    = freelist
 * obj   = object to allocate
 * nextp = name of "next" pointer in obj
 * cast  = cast of obj assignment
 */
#define RF_FREELIST_GET(_fl_,_obj_,_nextp_,_cast_) { \
	void *_p; \
	int _i; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	RF_ASSERT(sizeof(*(_obj_))==((_fl_)->obj_size)); \
	if (_fl_->objlist) { \
		_obj_ = _cast_((_fl_)->objlist); \
		(_fl_)->objlist = (void *)((_obj_)->_nextp_); \
		(_fl_)->free_cnt--; \
	} \
	else { \
		/* \
		 * Allocate one at a time so we can free \
		 * one at a time without cleverness when arena \
		 * is full. \
		 */ \
		RF_Calloc(_obj_,1,(_fl_)->obj_size,_cast_); \
		if (_obj_) { \
			for(_i=1;_i<(_fl_)->obj_inc;_i++) { \
				RF_Calloc(_p,1,(_fl_)->obj_size,(void *)); \
				if (_p) { \
					(_cast_(_p))->_nextp_ = (_fl_)->objlist; \
					(_fl_)->objlist = _p; \
				} \
				else { \
					break; \
				} \
			} \
		} \
		RF_FREELIST_STAT_GROW(_fl_); \
	} \
	RF_FREELIST_STAT_ALLOC(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * obj   = object to allocate
 * nextp = name of "next" pointer in obj
 * cast  = cast of obj assignment
 * num   = num objs to return
 */
#define RF_FREELIST_GET_N(_fl_,_obj_,_nextp_,_cast_,_num_) { \
	void *_p, *_l, *_f; \
	int _i, _n; \
	_l = _f = NULL; \
	_n = 0; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	RF_ASSERT(sizeof(*(_obj_))==((_fl_)->obj_size)); \
	for(_n=0;_n<_num_;_n++) { \
		if (_fl_->objlist) { \
			_obj_ = _cast_((_fl_)->objlist); \
			(_fl_)->objlist = (void *)((_obj_)->_nextp_); \
			(_fl_)->free_cnt--; \
		} \
		else { \
			/* \
			 * Allocate one at a time so we can free \
			 * one at a time without cleverness when arena \
			 * is full. \
			 */ \
			RF_Calloc(_obj_,1,(_fl_)->obj_size,_cast_); \
			if (_obj_) { \
				for(_i=1;_i<(_fl_)->obj_inc;_i++) { \
					RF_Calloc(_p,1,(_fl_)->obj_size,(void *)); \
					if (_p) { \
						(_cast_(_p))->_nextp_ = (_fl_)->objlist; \
						(_fl_)->objlist = _p; \
					} \
					else { \
						break; \
					} \
				} \
			} \
			RF_FREELIST_STAT_GROW(_fl_); \
		} \
		if (_f == NULL) \
			_f = _obj_; \
		if (_obj_) { \
			(_cast_(_obj_))->_nextp_ = _l; \
			_l = _obj_; \
			RF_FREELIST_STAT_ALLOC(_fl_); \
		} \
		else { \
			(_cast_(_f))->_nextp_ = (_fl_)->objlist; \
			(_fl_)->objlist = _l; \
			_n = _num_; \
		} \
	} \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl = freelist
 * obj   = object to free
 * nextp = name of "next" pointer in obj
 */
#define RF_FREELIST_FREE(_fl_,_obj_,_nextp_) { \
	RF_LOCK_MUTEX((_fl_)->lock); \
	if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
		RF_Free(_obj_,(_fl_)->obj_size); \
	} \
	else { \
		RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
		(_obj_)->_nextp_ = (_fl_)->objlist; \
		(_fl_)->objlist = (void *)(_obj_); \
		(_fl_)->free_cnt++; \
	} \
	RF_FREELIST_STAT_FREE(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * obj   = object to free
 * nextp = name of "next" pointer in obj
 * num   = num to free (debugging)
 */
#define RF_FREELIST_FREE_N(_fl_,_obj_,_nextp_,_cast_,_num_) { \
	void *_no; \
	int _n; \
	_n = 0; \
	RF_LOCK_MUTEX((_fl_)->lock); \
	while(_obj_) { \
		_no = (_cast_(_obj_))->_nextp_; \
		if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
			RF_Free(_obj_,(_fl_)->obj_size); \
		} \
		else { \
			RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
			(_obj_)->_nextp_ = (_fl_)->objlist; \
			(_fl_)->objlist = (void *)(_obj_); \
			(_fl_)->free_cnt++; \
		} \
		_n++; \
		_obj_ = _no; \
		RF_FREELIST_STAT_FREE(_fl_); \
	} \
	RF_ASSERT(_n==(_num_)); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * obj   = object to free
 * nextp = name of "next" pointer in obj
 * clean = undo for init
 */
#define RF_FREELIST_FREE_CLEAN(_fl_,_obj_,_nextp_,_clean_) { \
	RF_LOCK_MUTEX((_fl_)->lock); \
	if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
		_clean_ (_obj_); \
		RF_Free(_obj_,(_fl_)->obj_size); \
	} \
	else { \
		RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
		(_obj_)->_nextp_ = (_fl_)->objlist; \
		(_fl_)->objlist = (void *)(_obj_); \
		(_fl_)->free_cnt++; \
	} \
	RF_FREELIST_STAT_FREE(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * obj   = object to free
 * nextp = name of "next" pointer in obj
 * clean = undo for init
 * arg   = arg for undo func
 */
#define RF_FREELIST_FREE_CLEAN_ARG(_fl_,_obj_,_nextp_,_clean_,_arg_) { \
	RF_LOCK_MUTEX((_fl_)->lock); \
	if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
		_clean_ (_obj_,_arg_); \
		RF_Free(_obj_,(_fl_)->obj_size); \
	} \
	else { \
		RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
		(_obj_)->_nextp_ = (_fl_)->objlist; \
		(_fl_)->objlist = (void *)(_obj_); \
		(_fl_)->free_cnt++; \
	} \
	RF_FREELIST_STAT_FREE(_fl_); \
	RF_UNLOCK_MUTEX((_fl_)->lock); \
}

/*
 * fl    = freelist
 * obj   = object to free
 * nextp = name of "next" pointer in obj
 * clean = undo for init
 */
#define RF_FREELIST_FREE_CLEAN_NOUNLOCK(_fl_,_obj_,_nextp_,_clean_) { \
	RF_LOCK_MUTEX((_fl_)->lock); \
	if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
		_clean_ (_obj_); \
		RF_Free(_obj_,(_fl_)->obj_size); \
	} \
	else { \
		RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
		(_obj_)->_nextp_ = (_fl_)->objlist; \
		(_fl_)->objlist = (void *)(_obj_); \
		(_fl_)->free_cnt++; \
	} \
	RF_FREELIST_STAT_FREE(_fl_); \
}

/*
 * fl     = freelist
 * nextp = name of "next" pointer in obj
 * cast  = cast to object type
 */
#define RF_FREELIST_DESTROY(_fl_,_nextp_,_cast_) { \
	void *_cur, *_next; \
	RF_FREELIST_STAT_REPORT(_fl_); \
	rf_mutex_destroy(&((_fl_)->lock)); \
	for(_cur=(_fl_)->objlist;_cur;_cur=_next) { \
		_next = (_cast_ _cur)->_nextp_; \
		RF_Free(_cur,(_fl_)->obj_size); \
	} \
	RF_Free(_fl_,sizeof(RF_FreeList_t)); \
}

/*
 * fl    = freelist
 * nextp = name of "next" pointer in obj
 * cast  = cast to object type
 * clean = func to undo obj init
 */
#define RF_FREELIST_DESTROY_CLEAN(_fl_,_nextp_,_cast_,_clean_) { \
	void *_cur, *_next; \
	RF_FREELIST_STAT_REPORT(_fl_); \
	rf_mutex_destroy(&((_fl_)->lock)); \
	for(_cur=(_fl_)->objlist;_cur;_cur=_next) { \
		_next = (_cast_ _cur)->_nextp_; \
		_clean_ (_cur); \
		RF_Free(_cur,(_fl_)->obj_size); \
	} \
	RF_Free(_fl_,sizeof(RF_FreeList_t)); \
}

/*
 * fl    = freelist
 * nextp = name of "next" pointer in obj
 * cast  = cast to object type
 * clean = func to undo obj init
 * arg   = arg for undo func
 */
#define RF_FREELIST_DESTROY_CLEAN_ARG(_fl_,_nextp_,_cast_,_clean_,_arg_) { \
	void *_cur, *_next; \
	RF_FREELIST_STAT_REPORT(_fl_); \
	rf_mutex_destroy(&((_fl_)->lock)); \
	for(_cur=(_fl_)->objlist;_cur;_cur=_next) { \
		_next = (_cast_ _cur)->_nextp_; \
		_clean_ (_cur,_arg_); \
		RF_Free(_cur,(_fl_)->obj_size); \
	} \
	RF_Free(_fl_,sizeof(RF_FreeList_t)); \
}

#endif				/* !_RF__RF_FREELIST_H_ */