Browse Source

closes #342: object caching

git-svn-id: svn://svn.lighttpd.net/xcache/trunk@1558 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
master
Xuefer 5 years ago
parent
commit
de6840d14b
16 changed files with 285 additions and 24 deletions
  1. +1
    -0
      ChangeLog
  2. +1
    -1
      Makefile.frag.deps
  3. +1
    -0
      NEWS
  4. +8
    -0
      mod_cacher/xc_cache.h
  5. +11
    -10
      mod_cacher/xc_cacher.c
  6. +15
    -0
      processor/class-helper.h
  7. +2
    -0
      processor/class-helper.m4
  8. +28
    -5
      processor/foot.m4
  9. +5
    -0
      processor/head.m4
  10. +1
    -0
      processor/process.m4
  11. +1
    -0
      processor/processor-t.h
  12. +122
    -7
      processor/processor.m4
  13. +10
    -0
      processor/var-helper-t.h
  14. +72
    -0
      processor/var-helper.h
  15. +3
    -0
      processor/var-helper.m4
  16. +4
    -1
      util/xc_vector.h

+ 1
- 0
ChangeLog View File

@@ -10,6 +10,7 @@ ChangeLog
* (WIP) defragment
* (WIP) cache to disk
* fixed #348: added class const support for __FILE__ __DIR__
* closes #342: added support for object caching. handle IS_RESTORCE as interger
* disassembler, decompiler:
* PHP_5_6 support
* misc:


+ 1
- 1
Makefile.frag.deps View File

@@ -18,7 +18,7 @@ xcache/xc_ini.lo $(builddir)/xcache/xc_ini.lo: $(srcdir)/xcache/xc_ini.h
xcache/xc_malloc.lo $(builddir)/xcache/xc_malloc.lo: $(srcdir)/util/xc_align.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h
xcache/xc_mutex.lo $(builddir)/xcache/xc_mutex.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h
xcache/xc_opcode_spec.lo $(builddir)/xcache/xc_opcode_spec.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_opcode_spec_def.h $(srcdir)/xcache/xc_shm.h
xcache/xc_processor.lo $(builddir)/xcache/xc_processor.lo: $(XCACHE_PROC_C) $(XCACHE_PROC_H) $(srcdir)/mod_cacher/xc_cache.h $(srcdir)/processor/debug.h $(srcdir)/processor/processor-t.h $(srcdir)/processor/string-helper-t.h $(srcdir)/processor/string-helper.h $(srcdir)/processor/types.h $(srcdir)/util/xc_align.h $(srcdir)/util/xc_trace.h $(srcdir)/util/xc_util.h $(srcdir)/util/xc_vector.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(srcdir)/xcache_globals.h
xcache/xc_processor.lo $(builddir)/xcache/xc_processor.lo: $(XCACHE_PROC_C) $(XCACHE_PROC_H) $(srcdir)/mod_cacher/xc_cache.h $(srcdir)/processor/class-helper.h $(srcdir)/processor/debug.h $(srcdir)/processor/processor-t.h $(srcdir)/processor/string-helper-t.h $(srcdir)/processor/string-helper.h $(srcdir)/processor/types.h $(srcdir)/processor/var-helper-t.h $(srcdir)/processor/var-helper.h $(srcdir)/util/xc_align.h $(srcdir)/util/xc_trace.h $(srcdir)/util/xc_util.h $(srcdir)/util/xc_vector.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(srcdir)/xcache_globals.h
xcache/xc_sandbox.lo $(builddir)/xcache/xc_sandbox.lo: $(srcdir)/util/xc_vector.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(srcdir)/xcache_globals.h
xcache/xc_shm.lo $(builddir)/xcache/xc_shm.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h
xcache/xc_shm_mmap.lo $(builddir)/xcache/xc_shm_mmap.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h


+ 1
- 0
NEWS View File

@@ -3,6 +3,7 @@
* api updates
* cache defragment, cache to disk
* added class const support for __FILE__ __DIR__
* adds support for object caching
* updated disassembler decompiler support

3.2.0 2014-09-18


+ 8
- 0
mod_cacher/xc_cache.h View File

@@ -184,6 +184,14 @@ typedef struct {
zend_uchar name_type;
#endif
zval *value;

#ifdef ZEND_ENGINE_2
zend_uint objects_count;
zend_object *objects;
#endif
zend_uint class_names_count;
xc_constant_string_t *class_names;

zend_bool have_references;
} xc_entry_var_t;
/* }}} */


+ 11
- 10
mod_cacher/xc_cacher.c View File

@@ -3342,7 +3342,7 @@ PHP_FUNCTION(xcache_get)
stored_entry_var = (xc_entry_var_t *) xc_entry_find_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) &entry_var TSRMLS_CC);
if (stored_entry_var) {
/* return */
xc_processor_restore_zval(return_value, stored_entry_var->value, stored_entry_var->have_references TSRMLS_CC);
xc_processor_restore_var(return_value, stored_entry_var TSRMLS_CC);
xc_cached_hit_unlocked(cache->cached TSRMLS_CC);
}
else {
@@ -3383,11 +3383,6 @@ PHP_FUNCTION(xcache_set)
return;
}

if (Z_TYPE_P(value) == IS_OBJECT) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Objects cannot be stored in the variable cache. Use serialize before xcache_set");
RETURN_NULL();
}

/* max ttl */
if (xc_var_maxttl && (!entry_var.entry.ttl || entry_var.entry.ttl > xc_var_maxttl)) {
entry_var.entry.ttl = xc_var_maxttl;
@@ -3615,10 +3610,16 @@ static inline void xc_var_inc_dec(int inc, INTERNAL_FUNCTION_PARAMETERS) /* {{{
}

TRACE("%s", "incdec: notlong");
xc_processor_restore_zval(&oldzval, stored_entry_var->value, stored_entry_var->have_references TSRMLS_CC);
convert_to_long(&oldzval);
value = Z_LVAL(oldzval);
zval_dtor(&oldzval);
if (stored_entry_var->objects_count) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot convert object to integer");
value = 0;
}
else {
xc_processor_restore_var(&oldzval, stored_entry_var TSRMLS_CC);
convert_to_long(&oldzval);
value = Z_LVAL(oldzval);
zval_dtor(&oldzval);
}
}
else {
TRACE("incdec: %s not found", entry_var.entry.name.str.val);


+ 15
- 0
processor/class-helper.h View File

@@ -0,0 +1,15 @@
static zend_class_entry *xc_lookup_class(const char *class_name, int class_name_len TSRMLS_DC) /* {{{ */
{
xc_cest_t *cest;
#ifdef ZEND_ENGINE_2
if (zend_lookup_class_ex(class_name, class_name_len, NULL, 0, &cest TSRMLS_CC) != SUCCESS) {
return NULL;
}
#else
if (zend_hash_find(EG(class_table), class_name, class_name_len, (void **) &cest) != SUCCESS) {
return NULL;
}
#endif
return CestToCePtr(*cest);
}
/* }}} */

+ 2
- 0
processor/class-helper.m4 View File

@@ -112,3 +112,5 @@ static void xc_fix_method(xc_processor_t *processor, zend_op_array *dst TSRMLS_D
}
/* }}} */
#endif

define(`xc_lookup_class', `IFRESTORE(``xc_lookup_class'($@)',``xc_lookup_class' can be use in restore only')')

+ 28
- 5
processor/foot.m4 View File

@@ -83,9 +83,9 @@ err_alloc:
}
dnl }}}
')
DEFINE_STORE_API(`xc_entry_var_t')
DEFINE_STORE_API(`xc_entry_php_t')
DEFINE_STORE_API(`xc_entry_data_php_t')
DEFINE_STORE_API(`xc_entry_var_t')
EXPORTED_FUNCTION(`xc_entry_php_t *xc_processor_restore_xc_entry_php_t(xc_entry_php_t *dst, const xc_entry_php_t *src TSRMLS_DC)') dnl {{{
{
xc_processor_t processor;
@@ -118,23 +118,46 @@ EXPORTED_FUNCTION(`xc_entry_data_php_t *xc_processor_restore_xc_entry_data_php_t
return dst;
}
dnl }}}
EXPORTED_FUNCTION(`zval *xc_processor_restore_zval(zval *dst, const zval *src, zend_bool have_references TSRMLS_DC)') dnl {{{
EXPORTED_FUNCTION(`zval *xc_processor_restore_var(zval *dst, const xc_entry_var_t *src TSRMLS_DC)') dnl {{{
{
xc_processor_t processor;
size_t i;

memset(&processor, 0, sizeof(processor));
processor.handle_reference = have_references;
processor.handle_reference = src->have_references;

if (processor.handle_reference) {
zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0);
dnl fprintf(stderr, "mark[%p] = %p\n", src, dst);
zend_hash_add(&processor.zvalptrs, (char *)src, sizeof(src), (void*)&dst, sizeof(dst), NULL);
zend_hash_add(&processor.zvalptrs, (char *)src->value, sizeof(src->value), (void *) &dst, sizeof(dst), NULL);
}
processor.entry_var_src = src;

#ifdef ZEND_ENGINE_2
if (src->objects_count) {
processor.object_handles = emalloc(sizeof(*processor.object_handles) * src->objects_count);
xc_vector_init(zend_object_handle, &processor.objects, 0);
for (i = 0; i < src->objects_count; ++i) {
zend_object *object = emalloc(sizeof(*object));
xc_restore_zend_object(&processor, object, &src->objects[i] TSRMLS_CC);
processor.object_handles[i] = zend_objects_store_put(object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
}
}
xc_restore_zval(&processor, dst, src TSRMLS_CC);
#endif
xc_restore_zval(&processor, dst, src->value TSRMLS_CC);
if (processor.handle_reference) {
zend_hash_destroy(&processor.zvalptrs);
}

#ifdef ZEND_ENGINE_2
if (src->objects_count) {
for (i = 0; i < src->objects_count; ++i) {
zend_objects_store_del_ref_by_handle_ex(processor.object_handles[i], NULL TSRMLS_CC);
}
efree(processor.object_handles);
}
#endif

return dst;
}
dnl }}}


+ 5
- 0
processor/head.m4 View File

@@ -54,4 +54,9 @@ static void xc_zend_extension_op_array_ctor_handler(zend_extension *extension, z

#include "processor/string-helper.h"
include(__dir__`/string-helper.m4')

#include "processor/class-helper.h"
include(__dir__`/class-helper.m4')

#include "processor/var-helper.h"
include(__dir__`/var-helper.m4')

+ 1
- 0
processor/process.m4 View File

@@ -69,6 +69,7 @@ define(`PROCESS', `dnl PROCESS(1:type, 2:elm)
, `$1', `xc_entry_type_t', `PROCESS_SCALAR(`$2', `d', `$1')'
, `$1', `xc_hash_value_t', `PROCESS_SCALAR(`$2', `lu', `$1')'
, `$1', `last_brk_cont_t', `PROCESS_SCALAR(`$2', `d', `$1')'
, `$1', `zend_object_handle',`PROCESS_SCALAR(`$2', `d', `$1')'

, `$1', `xc_ztstring', `PROCESS_xc_ztstring(`$2')'
, `$1', `xc_zval_type_t', `PROCESS_xc_zval_type_t(`$2')'


+ 1
- 0
processor/processor-t.h View File

@@ -24,6 +24,7 @@ typedef struct _xc_processor_t {
zend_bool readonly_protection; /* wheather it's present */

#include "processor/string-helper-t.h"
#include "processor/var-helper-t.h"

#ifdef HAVE_XCACHE_TEST
xc_vector_t allocsizes;


+ 122
- 7
processor/processor.m4 View File

@@ -118,6 +118,64 @@ DEF_STRUCT_P_FUNC(`zend_ast', , `dnl {{{
')
dnl }}}
#endif
DEF_STRUCT_P_FUNC(`zend_object', , `dnl {{{
dnl handle ce
dnl IFCALCSTORE(`
dnl pushdef(`SRC', `ifelse(`$1', `ce', `src->ce->name', `')')
dnl pushdef(`DST', `ifelse(`$1', `ce', `(*(char **)&dst->ce)', `')')
dnl PROC_STRING(`ce')
dnl popdef(`SRC')
dnl popdef(`DST')
dnl ', `IFRESTORE(`
dnl if (!(DST(`ce') = xc_lookup_class((const char *) SRC(`ce') TSRMLS_CC))) {
dnl DST(`ce') = zend_standard_class_def;
dnl php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s not found when restroing variable", (const char *) SRC(`ce'));
dnl }
dnl DONE(`ce')
dnl ', `
dnl PROCESS(zend_ulong, ce)
dnl ')')
IFCALC(`
xc_var_collect_class(processor, SRC(ce) TSRMLS_CC);
DONE(ce)
', `IFSTORE(`
DST(ce) = (zend_class_entry *) xc_var_ce_to_index(processor, DST(ce) TSRMLS_CC);
DONE(ce)
', `IFRESTORE(`
DST(ce) = xc_var_index_to_ec(processor, (size_t) DST(ce) TSRMLS_CC);
DONE(ce)
', `
PROCESS_SCALAR(ce, %lu, unsigned long)
')')')

STRUCT_P(HashTable, properties, HashTable_zval_ptr)
#ifdef ZEND_ENGINE_2_4
dnl TODO: how to rebuild properties_table
STRUCT_ARRAY(int, ce->default_properties_count, zval_ptr, properties_table)
#endif
#ifdef ZEND_ENGINE_2
COPYNULL(`guards')
#endif
')
dnl }}}
#ifdef ZEND_ENGINE_2
DEF_STRUCT_P_FUNC(`zend_object_value', , `dnl {{{
IFCALC(`
xc_var_collect_object(processor, SRC(handle) TSRMLS_CC);
DONE(handle)
', `IFSTORE(`
DST(handle) = (zend_object_handle) xc_var_store_handle(processor, DST(handle) TSRMLS_CC);
DONE(handle)
', `IFRESTORE(`
DST(handle) = xc_var_restore_handle(processor, (size_t) DST(handle) TSRMLS_CC);
DONE(handle)
', `
PROCESS(zend_object_handle, handle)
')')')
COPY(handlers)
')
dnl }}}
#endif
DEF_STRUCT_P_FUNC(`zval', , `dnl {{{
IFDASM(`do {
zval_dtor(DST());
@@ -141,7 +199,6 @@ dnl {{{ zvalue_value
DISABLECHECK(`
switch ((Z_TYPE_P(SRC()) & IS_CONSTANT_TYPE_MASK)) {
case IS_LONG:
case IS_RESOURCE:
case IS_BOOL:
PROCESS(long, value.lval)
break;
@@ -195,16 +252,18 @@ proc_unicode:
#endif

case IS_OBJECT:
IFNOTMEMCPY(`IFCOPY(`memcpy(DST(), SRC(), sizeof(SRC()[0]));')')
dnl STRUCT(value.obj)
#ifndef ZEND_ENGINE_2
STRUCT_P(zend_class_entry, value.obj.ce)
STRUCT_P(HashTable, value.obj.properties, HashTable_zval_ptr)
#ifdef ZEND_ENGINE_2
STRUCT(zend_object_value, value.obj)
#else
STRUCT(zend_object, value.obj)
#endif
break;

default:
assert(0);
/* IS_RESOURCE */
IFCOPY(`Z_TYPE_P(DST()) = IS_LONG;')
PROCESS(long, value.lval)
break;
}
')
dnl }}}
@@ -1339,6 +1398,9 @@ DEF_STRUCT_P_FUNC(`xc_entry_php_t', , `dnl {{{
')
dnl }}}
DEF_STRUCT_P_FUNC(`xc_entry_var_t', , `dnl {{{
IFCALCSTORE(`xc_entry_var_t *vsrc = /* const_cast */ (xc_entry_var_t *) src;')

dnl restore is done in foot.m4
STRUCT(xc_entry_t, entry)

#ifdef IS_UNICODE
@@ -1368,6 +1430,59 @@ DEF_STRUCT_P_FUNC(`xc_entry_var_t', , `dnl {{{

IFDPRINT(`INDENT()`'fprintf(stderr, "zval:value");')
STRUCT_P_EX(zval_ptr, DST(`value'), SRC(`value'), `value', `', `&')

#ifdef ZEND_ENGINE_2
IFCALC(`
dnl objects = collect_from(value);
pushdef(`src', `vsrc')
SRC(objects_count) = xc_vector_size(&processor->objects);
SRC(objects) = xc_vector_detach(zend_object, &processor->objects);
popdef(`src')
xc_vector_destroy(&processor->objects);
if (SRC(`objects_count')) {
xc_vector_init(xc_constant_string_t, &processor->class_names, 0);
zend_hash_init(&processor->class_name_to_index, 0, NULL, NULL, 0);
}
')
dnl must be after calc .value
PROCESS(zend_uint, objects_count)
STRUCT_ARRAY(zend_uint, objects_count, zend_object, objects)
IFSTORE(`{
/* no longer needed */
if (vsrc->objects_count) {
efree(vsrc->objects);
vsrc->objects_count = 0;
vsrc->objects = NULL;
zend_hash_destroy(&processor->handle_to_index);
}
}')
#endif

dnl classe_
IFCALC(`
dnl class_names = collect_from(objects);
pushdef(`src', `vsrc')
SRC(class_names_count) = xc_vector_size(&processor->class_names);
SRC(class_names) = xc_vector_detach(xc_constant_string_t, &processor->class_names);
popdef(`src')
xc_vector_destroy(&processor->class_names);
')
PROCESS(zend_uint, class_names_count)
STRUCT_ARRAY(zend_uint, class_names_count, xc_constant_string_t, class_names)
IFSTORE(`
/* no longer needed */
if (vsrc->class_names_count) {
dnl size_t i;
dnl for (i = 0; i < vsrc->class_names_count; ++i) {
dnl efree(vsrc->class_names[i]);
dnl }
efree(vsrc->class_names);
vsrc->class_names_count = 0;
vsrc->class_names = NULL;
zend_hash_destroy(&processor->class_name_to_index);
}
')

PROCESS(zend_bool, have_references)
DONE(value)
')


+ 10
- 0
processor/var-helper-t.h View File

@@ -0,0 +1,10 @@
/* {{{ var object helpers */
zend_bool have_objects;
xc_vector_t objects; /* in calc only */
HashTable handle_to_index; /* in calc/store only */
zend_object_handle *object_handles; /* in restore only */
const xc_entry_var_t *entry_var_src; /* in restore */

xc_vector_t class_names; /* in calc only */
HashTable class_name_to_index; /* in calc/store only */
/* }}} */

+ 72
- 0
processor/var-helper.h View File

@@ -0,0 +1,72 @@
#ifdef ZEND_ENGINE_2
static void xc_var_collect_object(xc_processor_t *processor, zend_object_handle handle TSRMLS_DC) /* {{{ */
{
size_t next_index = xc_vector_size(&processor->objects);

if (!xc_vector_initialized(&processor->objects)) {
xc_vector_init(zend_object, &processor->objects, 0);
zend_hash_init(&processor->handle_to_index, 0, NULL, NULL, 0);
}

if (_zend_hash_index_update_or_next_insert(&processor->handle_to_index, handle, (void *) &next_index, sizeof(next_index), NULL, HASH_ADD ZEND_FILE_LINE_CC) == SUCCESS) {
zend_object *object = zend_object_store_get_object_by_handle(handle TSRMLS_CC);
xc_vector_push_back(&processor->objects, object);
}
}
/* }}} */
static size_t xc_var_store_handle(xc_processor_t *processor, zend_object_handle handle TSRMLS_DC) /* {{{ */
{
size_t *index;

if (zend_hash_index_find(&processor->handle_to_index, handle, (void **) &index) != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Internal error: handle not found in objects");
return (size_t) -1;
}

return *index;
}
/* }}} */
static zend_object_handle xc_var_restore_handle(xc_processor_t *processor, size_t index TSRMLS_DC) /* {{{ */
{
zend_object_handle handle = processor->object_handles[index];
zend_objects_store_add_ref_by_handle(handle TSRMLS_CC);
return handle;
}
/* }}} */
#endif
static void xc_var_collect_class(xc_processor_t *processor, zend_class_entry *ce TSRMLS_DC) /* {{{ */
{
size_t next_index = xc_vector_size(&processor->class_names);

if (zend_hash_add(&processor->class_name_to_index, ce->name, ce->name_length, (void *) &next_index, sizeof(next_index), NULL) == SUCCESS) {
xc_constant_string_t class_name = { ce->name, ce->name_length };
xc_vector_push_back(&processor->class_names, &class_name);
}
}
/* }}} */
/* on store */
static size_t xc_var_ce_to_index(xc_processor_t *processor, zend_class_entry *ce TSRMLS_DC) /* {{{ */
{
size_t *index;

if (zend_hash_find(&processor->class_name_to_index, ce->name, ce->name_length, (void **) &index) != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Internal error: class name not found in class names");
return (size_t) -1;
}

return *index;
}
/* }}} */
/* on restore */
static zend_class_entry *xc_var_index_to_ec(xc_processor_t *processor, size_t index TSRMLS_DC) /* {{{ */
{
xc_constant_string_t *name = &processor->entry_var_src->class_names[index];
zend_class_entry *ce;

if (!(ce = xc_lookup_class(name->str, name->len+1 TSRMLS_CC))) {
ce = zend_standard_class_def;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s not found when restroing variable", name->str);
}
return ce;
}
/* }}} */

+ 3
- 0
processor/var-helper.m4 View File

@@ -0,0 +1,3 @@
define(`xc_collect_object', `IFCALC(``xc_collect_object'($@)',``xc_collect_object' can be use in calc only')')
define(`xc_var_store_handle', `IFSTORE(``xc_var_store_handle'($@)',``xc_var_store_handle' can be use in store only')')
define(`xc_var_restore_handle', `IFRESTORE(``xc_var_restore_handle'($@)',``xc_var_restore_handle' can be use in restore only')')

+ 4
- 1
util/xc_vector.h View File

@@ -38,16 +38,19 @@ typedef struct {

static inline void xc_vector_destroy_impl(xc_vector_t *vector TSRMLS_DC)
{
vector->size = 0;
if (vector->data) {
pefree(vector->data, vector->persistent);
vector->data = NULL;
}
vector->capacity = 0;
vector->size = 0;
vector->data_size = 0;
}

#define xc_vector_destroy(vector) xc_vector_destroy_impl(vector TSRMLS_CC)

#define xc_vector_size(vector) ((vector)->size)
#define xc_vector_initialized(vector) ((vector)->data_size != 0)
#define xc_vector_element_ptr_(vector, index) ( \
(void *) ( \
((char *) (vector)->data) + (index) * (vector)->data_size \


Loading…
Cancel
Save