Index: trunk/mod_cacher/xc_cacher.c
===================================================================
--- trunk/mod_cacher/xc_cacher.c	(revision 1132)
+++ trunk/mod_cacher/xc_cacher.c	(revision 1135)
@@ -100,5 +100,5 @@
 	struct _xc_lock_t  *lck;
 	struct _xc_shm_t   *shm; /* which shm contains us */
-	struct _xc_mem_t   *mem; /* which mem contains us */
+	xc_allocator_t *allocator;
 
 	xc_hash_t  *hentry; /* hash settings to entry */
@@ -125,4 +125,7 @@
 static zend_ulong xc_var_gc_interval = 0;
 
+static char *xc_php_allocator = NULL;
+static char *xc_var_allocator = NULL;
+
 /* total size */
 static zend_ulong xc_php_size  = 0;
@@ -163,5 +166,5 @@
 	php->hits     = 0;
 	php->refcount = 0;
-	stored_php = xc_processor_store_xc_entry_data_php_t(cache->shm, cache->mem, php TSRMLS_CC);
+	stored_php = xc_processor_store_xc_entry_data_php_t(cache->shm, cache->allocator, php TSRMLS_CC);
 	if (stored_php) {
 		xc_php_add_unlocked(cache->cached, stored_php);
@@ -188,5 +191,5 @@
 static void xc_php_free_unlocked(xc_cache_t *cache, xc_entry_data_php_t *php) /* {{{ */
 {
-	cache->mem->handlers->free(cache->mem, (xc_entry_data_php_t *)php);
+	cache->allocator->vtable->free(cache->allocator, (xc_entry_data_php_t *)php);
 }
 /* }}} */
@@ -310,6 +313,6 @@
 	entry->atime = XG(request_time);
 	stored_entry = type == XC_TYPE_PHP
-		? (xc_entry_t *) xc_processor_store_xc_entry_php_t(cache->shm, cache->mem, (xc_entry_php_t *) entry TSRMLS_CC)
-		: (xc_entry_t *) xc_processor_store_xc_entry_var_t(cache->shm, cache->mem, (xc_entry_var_t *) entry TSRMLS_CC);
+		? (xc_entry_t *) xc_processor_store_xc_entry_php_t(cache->shm, cache->allocator, (xc_entry_php_t *) entry TSRMLS_CC)
+		: (xc_entry_t *) xc_processor_store_xc_entry_var_t(cache->shm, cache->allocator, (xc_entry_var_t *) entry TSRMLS_CC);
 	if (stored_entry) {
 		xc_entry_add_unlocked(cache->cached, entryslotid, stored_entry);
@@ -338,5 +341,5 @@
 		xc_php_release_unlocked(cache, ((xc_entry_php_t *) entry)->php);
 	}
-	cache->mem->handlers->free(cache->mem, (xc_entry_t *)entry);
+	cache->allocator->vtable->free(cache->allocator, (xc_entry_t *)entry);
 }
 /* }}} */
@@ -604,10 +607,10 @@
 	zval *blocks, *hits;
 	size_t i;
-	const xc_block_t *b;
+	const xc_allocator_block_t *b;
 #ifndef NDEBUG
 	xc_memsize_t avail = 0;
 #endif
-	const xc_mem_t *mem = cache->mem;
-	const xc_mem_handlers_t *handlers = mem->handlers;
+	const xc_allocator_t *allocator = cache->allocator;
+	const xc_allocator_vtable_t *vtable = allocator->vtable;
 	zend_ulong interval;
 	const xc_cached_t *cached = cache->cached;
@@ -657,9 +660,9 @@
 	array_init(blocks);
 
-	add_assoc_long_ex(return_value, ZEND_STRS("size"),  handlers->size(mem));
-	add_assoc_long_ex(return_value, ZEND_STRS("avail"), handlers->avail(mem));
+	add_assoc_long_ex(return_value, ZEND_STRS("size"),  vtable->size(allocator));
+	add_assoc_long_ex(return_value, ZEND_STRS("avail"), vtable->avail(allocator));
 	add_assoc_bool_ex(return_value, ZEND_STRS("can_readonly"), xc_readonly_protection);
 
-	for (b = handlers->freeblock_first(mem); b; b = handlers->freeblock_next(b)) {
+	for (b = vtable->freeblock_first(allocator); b; b = vtable->freeblock_next(b)) {
 		zval *bi;
 
@@ -667,14 +670,14 @@
 		array_init(bi);
 
-		add_assoc_long_ex(bi, ZEND_STRS("size"),   handlers->block_size(b));
-		add_assoc_long_ex(bi, ZEND_STRS("offset"), handlers->block_offset(mem, b));
+		add_assoc_long_ex(bi, ZEND_STRS("size"),   vtable->block_size(b));
+		add_assoc_long_ex(bi, ZEND_STRS("offset"), vtable->block_offset(allocator, b));
 		add_next_index_zval(blocks, bi);
 #ifndef NDEBUG
-		avail += handlers->block_size(b);
+		avail += vtable->block_size(b);
 #endif
 	}
 	add_assoc_zval_ex(return_value, ZEND_STRS("free_blocks"), blocks);
 #ifndef NDEBUG
-	assert(avail == handlers->avail(mem));
+	assert(avail == vtable->avail(allocator));
 #endif
 }
@@ -2311,5 +2314,5 @@
 			/* do NOT touch cached data */
 			shm = cache->shm;
-			cache->shm->handlers->memdestroy(cache->mem);
+			cache->shm->handlers->memdestroy(cache->allocator);
 		}
 	}
@@ -2318,8 +2321,8 @@
 }
 /* }}} */
-static xc_cache_t *xc_cache_init(xc_shm_t *shm, xc_hash_t *hcache, xc_hash_t *hentry, xc_hash_t *hphp, xc_shmsize_t shmsize) /* {{{ */
+static xc_cache_t *xc_cache_init(xc_shm_t *shm, const char *allocator_name, xc_hash_t *hcache, xc_hash_t *hentry, xc_hash_t *hphp, xc_shmsize_t shmsize) /* {{{ */
 {
 	xc_cache_t *caches = NULL;
-	xc_mem_t *mem;
+	xc_allocator_t *allocator;
 	time_t now = time(NULL);
 	size_t i;
@@ -2343,9 +2346,14 @@
 	for (i = 0; i < hcache->size; i ++) {
 		xc_cache_t *cache = &caches[i];
-		CHECK(mem                     = shm->handlers->meminit(shm, memsize), "Failed init memory allocator");
-		CHECK(cache->cached           = mem->handlers->calloc(mem, 1, sizeof(xc_cached_t)), "cache OOM");
-		CHECK(cache->cached->entries  = mem->handlers->calloc(mem, hentry->size, sizeof(xc_entry_t*)), "entries OOM");
+		CHECK(allocator = shm->handlers->meminit(shm, memsize), "Failed init shm");
+		if (!(allocator->vtable = xc_allocator_find(allocator_name))) {
+			zend_error(E_ERROR, "Allocator %s not found", allocator_name);
+			goto err;
+		}
+		CHECK(allocator->vtable->init(shm, allocator, memsize), "Failed init allocator");
+		CHECK(cache->cached           = allocator->vtable->calloc(allocator, 1, sizeof(xc_cached_t)), "cache OOM");
+		CHECK(cache->cached->entries  = allocator->vtable->calloc(allocator, hentry->size, sizeof(xc_entry_t*)), "entries OOM");
 		if (hphp) {
-			CHECK(cache->cached->phps = mem->handlers->calloc(mem, hphp->size, sizeof(xc_entry_data_php_t*)), "phps OOM");
+			CHECK(cache->cached->phps = allocator->vtable->calloc(allocator, hphp->size, sizeof(xc_entry_data_php_t*)), "phps OOM");
 		}
 		CHECK(cache->lck              = xc_lock_init(NULL), "can't create lock");
@@ -2355,5 +2363,5 @@
 		cache->hphp    = hphp;
 		cache->shm     = shm;
-		cache->mem     = mem;
+		cache->allocator = allocator;
 		cache->cacheid = i;
 		cache->cached->last_gc_deletes = now;
@@ -2413,9 +2421,9 @@
 
 		if (xc_php_size) {
-			CHECK(xc_php_caches = xc_cache_init(shm, &xc_php_hcache, &xc_php_hentry, &xc_php_hentry, xc_php_size), "failed init opcode cache");
+			CHECK(xc_php_caches = xc_cache_init(shm, xc_php_allocator, &xc_php_hcache, &xc_php_hentry, &xc_php_hentry, xc_php_size), "failed init opcode cache");
 		}
 
 		if (xc_var_size) {
-			CHECK(xc_var_caches = xc_cache_init(shm, &xc_var_hcache, &xc_var_hentry, NULL, xc_var_size), "failed init variable cache");
+			CHECK(xc_var_caches = xc_cache_init(shm, xc_var_allocator, &xc_var_hcache, &xc_var_hentry, NULL, xc_var_size), "failed init variable cache");
 		}
 	}
@@ -3184,4 +3192,5 @@
 	PHP_INI_ENTRY1     ("xcache.count",                  "1", PHP_INI_SYSTEM, xcache_OnUpdateDummy,    NULL)
 	PHP_INI_ENTRY1     ("xcache.slots",                 "8K", PHP_INI_SYSTEM, xcache_OnUpdateDummy,    NULL)
+	PHP_INI_ENTRY1     ("xcache.allocator",        "bestfit", PHP_INI_SYSTEM, xcache_OnUpdateString,   &xc_php_allocator)
 	PHP_INI_ENTRY1     ("xcache.ttl",                    "0", PHP_INI_SYSTEM, xcache_OnUpdateULong,    &xc_php_ttl)
 	PHP_INI_ENTRY1     ("xcache.gc_interval",            "0", PHP_INI_SYSTEM, xcache_OnUpdateULong,    &xc_php_gc_interval)
@@ -3194,4 +3203,5 @@
 	PHP_INI_ENTRY1     ("xcache.var_maxttl",             "0", PHP_INI_SYSTEM, xcache_OnUpdateULong,    &xc_var_maxttl)
 	PHP_INI_ENTRY1     ("xcache.var_gc_interval",      "120", PHP_INI_SYSTEM, xcache_OnUpdateULong,    &xc_var_gc_interval)
+	PHP_INI_ENTRY1     ("xcache.var_allocator",    "bestfit", PHP_INI_SYSTEM, xcache_OnUpdateString,   &xc_var_allocator)
 	STD_PHP_INI_ENTRY  ("xcache.var_ttl",                "0", PHP_INI_ALL,    OnUpdateLong, var_ttl,   zend_xcache_globals, xcache_globals)
 PHP_INI_END()
@@ -3360,4 +3370,12 @@
 		pefree(xc_shm_scheme, 1);
 		xc_shm_scheme = NULL;
+	}
+	if (xc_php_allocator) {
+		pefree(xc_php_allocator, 1);
+		xc_php_allocator = NULL;
+	}
+	if (xc_var_allocator) {
+		pefree(xc_var_allocator, 1);
+		xc_var_allocator = NULL;
 	}
 
