2 * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
25 dispatch_debug(dispatch_object_t dou
, const char *msg
, ...)
31 dispatch_debugv(dou
._do
, msg
, ap
);
37 dispatch_debugv(dispatch_object_t dou
, const char *msg
, va_list ap
)
42 if (dou
._do
&& dou
._do
->do_vtable
->do_debug
) {
43 offs
= dx_debug(dou
._do
, buf
, sizeof(buf
));
45 offs
= snprintf(buf
, sizeof(buf
), "NULL vtable slot");
48 snprintf(buf
+ offs
, sizeof(buf
) - offs
, ": %s", msg
);
50 _dispatch_logv(buf
, ap
);
54 dispatch_retain(dispatch_object_t dou
)
56 if (dou
._do
->do_xref_cnt
== DISPATCH_OBJECT_GLOBAL_REFCNT
) {
57 return; // global object
59 if ((dispatch_atomic_inc(&dou
._do
->do_xref_cnt
) - 1) == 0) {
60 DISPATCH_CLIENT_CRASH("Resurrection of an object");
65 _dispatch_retain(dispatch_object_t dou
)
67 if (dou
._do
->do_ref_cnt
== DISPATCH_OBJECT_GLOBAL_REFCNT
) {
68 return; // global object
70 if ((dispatch_atomic_inc(&dou
._do
->do_ref_cnt
) - 1) == 0) {
71 DISPATCH_CLIENT_CRASH("Resurrection of an object");
76 dispatch_release(dispatch_object_t dou
)
78 typeof(dou
._do
->do_xref_cnt
) oldval
;
80 if (dou
._do
->do_xref_cnt
== DISPATCH_OBJECT_GLOBAL_REFCNT
) {
84 oldval
= dispatch_atomic_dec(&dou
._do
->do_xref_cnt
) + 1;
86 if (fastpath(oldval
> 1)) {
90 #ifndef DISPATCH_NO_LEGACY
91 if (dou
._do
->do_vtable
== (void*)&_dispatch_source_kevent_vtable
) {
92 return _dispatch_source_legacy_xref_release(dou
._ds
);
95 if (slowpath(DISPATCH_OBJECT_SUSPENDED(dou
._do
))) {
96 // Arguments for and against this assert are within 6705399
97 DISPATCH_CLIENT_CRASH("Release of a suspended object");
99 return _dispatch_release(dou
._do
);
101 DISPATCH_CLIENT_CRASH("Over-release of an object");
105 _dispatch_dispose(dispatch_object_t dou
)
107 dispatch_queue_t tq
= dou
._do
->do_targetq
;
108 dispatch_function_t func
= dou
._do
->do_finalizer
;
109 void *ctxt
= dou
._do
->do_ctxt
;
111 dou
._do
->do_vtable
= (void *)0x200;
116 dispatch_async_f(tq
, ctxt
, func
);
118 _dispatch_release(tq
);
122 _dispatch_release(dispatch_object_t dou
)
124 typeof(dou
._do
->do_ref_cnt
) oldval
;
126 if (dou
._do
->do_ref_cnt
== DISPATCH_OBJECT_GLOBAL_REFCNT
) {
127 return; // global object
130 oldval
= dispatch_atomic_dec(&dou
._do
->do_ref_cnt
) + 1;
132 if (fastpath(oldval
> 1)) {
136 if (dou
._do
->do_next
!= DISPATCH_OBJECT_LISTLESS
) {
137 DISPATCH_CRASH("release while enqueued");
139 if (dou
._do
->do_xref_cnt
) {
140 DISPATCH_CRASH("release while external references exist");
143 return dx_dispose(dou
._do
);
145 DISPATCH_CRASH("over-release");
149 dispatch_get_context(dispatch_object_t dou
)
151 return dou
._do
->do_ctxt
;
155 dispatch_set_context(dispatch_object_t dou
, void *context
)
157 if (dou
._do
->do_ref_cnt
!= DISPATCH_OBJECT_GLOBAL_REFCNT
) {
158 dou
._do
->do_ctxt
= context
;
163 dispatch_set_finalizer_f(dispatch_object_t dou
, dispatch_function_t finalizer
)
165 dou
._do
->do_finalizer
= finalizer
;
169 dispatch_suspend(dispatch_object_t dou
)
171 if (slowpath(dou
._do
->do_ref_cnt
== DISPATCH_OBJECT_GLOBAL_REFCNT
)) {
174 dispatch_atomic_add(&dou
._do
->do_suspend_cnt
, DISPATCH_OBJECT_SUSPEND_INTERVAL
);
178 dispatch_resume(dispatch_object_t dou
)
180 if (slowpath(dou
._do
->do_ref_cnt
== DISPATCH_OBJECT_GLOBAL_REFCNT
)) {
183 switch (dispatch_atomic_sub(&dou
._do
->do_suspend_cnt
, DISPATCH_OBJECT_SUSPEND_INTERVAL
) + DISPATCH_OBJECT_SUSPEND_INTERVAL
) {
184 case DISPATCH_OBJECT_SUSPEND_INTERVAL
:
185 _dispatch_wakeup(dou
._do
);
188 DISPATCH_CLIENT_CRASH("Over-resume of an object");
196 dispatch_object_debug_attr(dispatch_object_t dou
, char* buf
, size_t bufsiz
)
198 return snprintf(buf
, bufsiz
, "refcnt = 0x%x, suspend_cnt = 0x%x, ",
199 dou
._do
->do_ref_cnt
, dou
._do
->do_suspend_cnt
);