变态的libDispatch结构分析-object结构

文件位置:libdispatch/src/object_internal.h

1. 不同结构体的类型type

enum {
	_DISPATCH_CONTINUATION_TYPE		=	 0x00000, // meta-type for continuations
	_DISPATCH_QUEUE_TYPE			=    0x10000, // meta-type for queues
	_DISPATCH_SOURCE_TYPE			=    0x20000, // meta-type for sources
	_DISPATCH_SEMAPHORE_TYPE		=    0x30000, // meta-type for semaphores
	_DISPATCH_ATTR_TYPE				= 0x10000000, // meta-type for attribute structures
	
	DISPATCH_CONTINUATION_TYPE		= _DISPATCH_CONTINUATION_TYPE,
	
	DISPATCH_QUEUE_ATTR_TYPE		= _DISPATCH_QUEUE_TYPE | _DISPATCH_ATTR_TYPE,

	DISPATCH_QUEUE_TYPE				= 1 | _DISPATCH_QUEUE_TYPE,
	DISPATCH_QUEUE_GLOBAL_TYPE		= 2 | _DISPATCH_QUEUE_TYPE,
	DISPATCH_QUEUE_MGR_TYPE			= 3 | _DISPATCH_QUEUE_TYPE,

	DISPATCH_SEMAPHORE_TYPE			= _DISPATCH_SEMAPHORE_TYPE,
	
	DISPATCH_SOURCE_ATTR_TYPE		= _DISPATCH_SOURCE_TYPE | _DISPATCH_ATTR_TYPE,
	
	DISPATCH_SOURCE_KEVENT_TYPE		= 1 | _DISPATCH_SOURCE_TYPE,
};
注解:
continuation_type:用于封装成dispatch_continuation_t,可以当作压入队列的一个block

queue_type:队列类型;

source_type:source类型,source只是一种资源的统称,queue或者function都可以当作一种source;

semaphore_type:信号类型,消费-生产者模式;

kevent_type:用于kevent通信。




2. vtable

#define DISPATCH_VTABLE_HEADER(x)    \
    unsigned long const do_type;    \
    const char *const do_kind; \
    size_t (*const do_debug)(struct x *, char *, size_t);    \
    struct dispatch_queue_s *(*const do_invoke)(struct x *);    \
    bool (*const do_probe)(struct x *); \
    void (*const do_dispose)(struct x *)

#define dx_type(x) (x)->do_vtable->do_type
#define dx_kind(x) (x)->do_vtable->do_kind
#define dx_debug(x, y, z) (x)->do_vtable->do_debug((x), (y), (z))
#define dx_dispose(x) (x)->do_vtable->do_dispose(x)
#define dx_invoke(x) (x)->do_vtable->do_invoke(x)
#define dx_probe(x) (x)->do_vtable->do_probe(x)

相当于C++的模版,通过DISPATCH_VTABLE_HEADER为x结构定义一个vtable;

因为c-object中,并没有操作一类的说法,面向过程的实现,我这里称之为方法;

注释:

do_type: 这就是前文所指的type:

do_kined: char* 起到说明作用;

do_debug: debug方法

do_invoke:唤醒队列的方法;

do_dispose:  dispose方法;

do_probe: probe方法,用于检测x中的一些变量是否满足条件。


不同type的结构会对应不同的vtable,vtable指示了处理的方法。


3. 头部信息

#define DISPATCH_STRUCT_HEADER(x, y)	\
	const struct y *do_vtable;	\
	struct x *volatile do_next;	\
	unsigned int do_ref_cnt;	\
	unsigned int do_xref_cnt;	\
	unsigned int do_suspend_cnt;	\
	struct dispatch_queue_s *do_targetq;	\
	void *do_ctxt; \
	dispatch_function_t do_finalizer

头部结构体宏:

do_vatable:第二节讲到的vtable;

do_next: 链表的next;

do_ref_cnt: 引用计数;

do_xref_cnt:外部引用计数;用途?

do_suspend_cnt:suspend计数,用作暂停标志,比如延时处理的任务,设置该引用计数之后;在任务到时后,计时器处理将会将该标志位修改,然后唤醒队列调度

dispatch_queue_s:目标队列,就是当前这个struct x在哪个队列运行;

do_ctext:上下文

4. 通用结构

struct dispatch_object_vtable_s {
    DISPATCH_VTABLE_HEADER(dispatch_object_s);
};

struct dispatch_object_s {
    DISPATCH_STRUCT_HEADER(dispatch_object_s, dispatch_object_vtable_s);
};


5. 方法解析

位于libdispatch/src/object.c


(1). debug

在Debug打印上,用了va_list,要想详细了解,请参看:

http://blog.csdn.net/wzwind/article/details/1666518

下面的msg只是提供打印的内容
void
dispatch_debug(dispatch_object_t obj, const char *msg, ...)
{
	va_list ap;

	va_start(ap, msg);

	dispatch_debugv(obj, msg, ap);

	va_end(ap);
}

void
dispatch_debugv(dispatch_object_t dou, const char *msg, va_list ap)
{
	char buf[4096];
	size_t offs;

	struct dispatch_object_s *obj = DO_CAST(dou);

	if (obj && obj->do_vtable->do_debug) {
		offs = dx_debug(obj, buf, sizeof(buf));
	} else {
		offs = snprintf(buf, sizeof(buf), "NULL vtable slot");
	}

	snprintf(buf + offs, sizeof(buf) - offs, ": %s", msg);

	_dispatch_logv(buf, ap);
}



(2). retain 与release对

获取与释放。目的: /?

#define DISPATCH_OBJECT_GLOBAL_REFCNT	(~0u)

void
dispatch_retain(dispatch_object_t dou)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	if (obj->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
		return; // global object
	}
	if ((dispatch_atomic_inc(&obj->do_xref_cnt) - 1) == 0) {
		DISPATCH_CLIENT_CRASH("Resurrection of an object");
	}
}

void
_dispatch_retain(dispatch_object_t dou)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	if (obj->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
		return; // global object
	}
	if ((dispatch_atomic_inc(&obj->do_ref_cnt) - 1) == 0) {
		DISPATCH_CLIENT_CRASH("Resurrection of an object");
	}
}
void
dispatch_release(dispatch_object_t dou)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	unsigned int oldval;

	if (obj->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
		return;
	}

	oldval = dispatch_atomic_dec(&obj->do_xref_cnt) + 1;
	
	if (fastpath(oldval > 1)) {
		return;
	}
	if (oldval == 1) {
		if ((uintptr_t)obj->do_vtable == (uintptr_t)&_dispatch_source_kevent_vtable) {
			return _dispatch_source_xref_release((dispatch_source_t)obj);
		}
		if (slowpath(DISPATCH_OBJECT_SUSPENDED(obj))) {
			// Arguments for and against this assert are within 6705399
			DISPATCH_CLIENT_CRASH("Release of a suspended object");
		}
		return _dispatch_release(obj);
	}
	DISPATCH_CLIENT_CRASH("Over-release of an object");
}
void
_dispatch_release(dispatch_object_t dou)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	unsigned int oldval;

	if (obj->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
		return; // global object
	}

	oldval = dispatch_atomic_dec(&obj->do_ref_cnt) + 1;
	
	if (fastpath(oldval > 1)) {
		return;
	}
	if (oldval == 1) {
		if (obj->do_next != DISPATCH_OBJECT_LISTLESS) {
			DISPATCH_CRASH("release while enqueued");
		}
		if (obj->do_xref_cnt) {
			DISPATCH_CRASH("release while external references exist");
		}

		return dx_dispose(obj);
	}
	DISPATCH_CRASH("over-release");
}










void
_dispatch_dispose(dispatch_object_t dou)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	dispatch_queue_t tq = obj->do_targetq;
	dispatch_function_t func = obj->do_finalizer;
	void *ctxt = obj->do_ctxt;

	obj->do_vtable = (struct dispatch_object_vtable_s *)0x200;

	free(obj);

	if (func && ctxt) {
		dispatch_async_f(tq, ctxt, func);
	}
	_dispatch_release(tq);
}


void *
dispatch_get_context(dispatch_object_t dou)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	return obj->do_ctxt;
}

void
dispatch_set_context(dispatch_object_t dou, void *context)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	if (obj->do_ref_cnt != DISPATCH_OBJECT_GLOBAL_REFCNT) {
		obj->do_ctxt = context;
	}
}

void
dispatch_set_finalizer_f(dispatch_object_t dou, dispatch_function_t finalizer)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	obj->do_finalizer = finalizer;
}

void
dispatch_suspend(dispatch_object_t dou)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	if (slowpath(obj->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
		return;
	}
	(void)dispatch_atomic_add(&obj->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_INTERVAL);
}

void
dispatch_resume(dispatch_object_t dou)
{
	struct dispatch_object_s *obj = DO_CAST(dou);

	// Global objects cannot be suspended or resumed. This also has the
	// side effect of saturating the suspend count of an object and
	// guarding against resuming due to overflow.
	if (slowpath(obj->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
		return;
	}

	// Switch on the previous value of the suspend count.  If the previous
	// value was a single suspend interval, the object should be resumed.
	// If the previous value was less than the suspend interval, the object
	// has been over-resumed.
	switch (dispatch_atomic_sub(&obj->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_INTERVAL) + DISPATCH_OBJECT_SUSPEND_INTERVAL) {
	case DISPATCH_OBJECT_SUSPEND_INTERVAL:
		_dispatch_wakeup(obj);
		break;
	case DISPATCH_OBJECT_SUSPEND_LOCK:
	case 0:
		DISPATCH_CLIENT_CRASH("Over-resume of an object");
		break;
	default:
		break;
	}
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值