zend_object源码-handle的作用

说到zend的类和对象不得不说两个数据结构,一个是 zend_class_entry, 一个是_zend_object。

struct _zend_object {
    zend_refcounted_h gc;
    uint32_t          handle; // TODO: may be removed ???
    zend_class_entry *ce;
    const zend_object_handlers *handlers;
    HashTable        *properties;
    zval              properties_table[1];
};

问题点: _zend_object 结构体中的handle的作用?

看源码的时候一直很纳闷这个handle是用来干嘛的呢? 就一个数值,对一个object有什么用呢, 后来在看swoole的源码的时候发现swoole用这个handle在作为全局对象存储 swoole_objects.array 的数组下标 。 swoole_objects的定义在 php_swoole.h中,存入swoole_objects是通过 swoole_set_object(zval *object, void *ptr) 函数处理的

通过上面的现象,猜测,这个handle可能是zend引擎对于当前程序一共有多少个object的一个计数,同时用这个计数用做array的索引,方便定位查找之类的。如果是这样的话handle的值可能就是 1,2,3....1000 这样的数值 , 体现的应该是zend引擎对于对象的管理逻辑

求解

涉及到的对象操作的文件

  1. zend_objects.h
  2. zend_objects.c
  3. zend_objects_API.h
  4. zend_objects_API.c

对象操作的方法

ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce);
ZEND_API void zend_object_std_dtor(zend_object *object);
ZEND_API zend_object *zend_objects_new(zend_class_entry *ce);
ZEND_API void zend_objects_destroy_object(zend_object *object);
ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *old_object);
ZEND_API zend_object *zend_objects_clone_obj(zval *object);

我们就从 zend_object_std_init 新建object 来看

ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce)
{
    zval *p, *end;

    GC_REFCOUNT(object) = 1;
    GC_TYPE_INFO(object) = IS_OBJECT;
    object->ce = ce;
    object->properties = NULL;
    zend_objects_store_put(object);  //handle的处理
    p = object->properties_table;
    if (EXPECTED(ce->default_properties_count != 0)) {
        end = p + ce->default_properties_count;
        do {
            ZVAL_UNDEF(p);
            p++;
        } while (p != end);
    }
    if (UNEXPECTED(ce->ce_flags & ZEND_ACC_USE_GUARDS)) {
        GC_FLAGS(object) |= IS_OBJ_USE_GUARDS;
        ZVAL_UNDEF(p);
    }
}

init函数中有这么一句 zend_objects_store_put(object); , 这个函数里对handle做了处理, 这里面涉及到一个全局变量 EG(objects_store) , 这个全局变量中就存储了所有的objects

ZEND_API void zend_objects_store_put(zend_object *object)
{
    int handle;

    if (EG(objects_store).free_list_head != -1) {
        handle = EG(objects_store).free_list_head;
        EG(objects_store).free_list_head = GET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[handle]);
    } else {
        if (EG(objects_store).top == EG(objects_store).size) {
            EG(objects_store).size <<= 1;
            EG(objects_store).object_buckets = (zend_object **) erealloc(EG(objects_store).object_buckets, EG(objects_store).size * sizeof(zend_object*));
        }
        handle = EG(objects_store).top++;
    }
    object->handle = handle;
    EG(objects_store).object_buckets[handle] = object;
}

通过上面的跟踪也就大概明白了这个handle的作用, 其实就是用来作为 EG(objects_store).object_buckets数组的下标

你可能感兴趣的:(zend_object源码-handle的作用)