]> git.saurik.com Git - apple/libdispatch.git/blob - src/data.m
libdispatch-339.92.1.tar.gz
[apple/libdispatch.git] / src / data.m
1 /*
2 * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
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
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
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.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21 #include "internal.h"
22
23 #if USE_OBJC
24
25 #if !__OBJC2__
26 #error "Cannot build with legacy ObjC runtime"
27 #endif
28 #if _OS_OBJECT_OBJC_ARC
29 #error "Cannot build with ARC"
30 #endif
31
32 #include <Foundation/NSString.h>
33
34 @interface DISPATCH_CLASS(data) ()
35 - (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
36 freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm;
37 - (BOOL)_bytesAreVM;
38 @end
39
40 @interface DISPATCH_CLASS(data_empty) : DISPATCH_CLASS(data)
41 @end
42
43 @implementation DISPATCH_CLASS(data)
44
45 + (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
46 return _dispatch_objc_alloc(self, sizeof(struct dispatch_data_s));
47 }
48
49 - (id)init {
50 return [self initWithBytes:NULL length:0 copy:NO freeWhenDone:NO
51 bytesAreVM:NO];
52 }
53
54 - (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
55 freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm {
56 dispatch_block_t destructor;
57 if (copy) {
58 destructor = DISPATCH_DATA_DESTRUCTOR_DEFAULT;
59 } else if (freeBytes) {
60 if (vm) {
61 destructor = DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
62 } else {
63 destructor = DISPATCH_DATA_DESTRUCTOR_FREE;
64 }
65 } else {
66 destructor = DISPATCH_DATA_DESTRUCTOR_NONE;
67 }
68 dispatch_data_init(self, bytes, length, destructor);
69 return self;
70 }
71
72 #define _dispatch_data_objc_dispose(selector) \
73 struct dispatch_data_s *dd = (void*)self; \
74 _dispatch_data_dispose(self); \
75 dispatch_queue_t tq = dd->do_targetq; \
76 dispatch_function_t func = dd->finalizer; \
77 void *ctxt = dd->ctxt; \
78 [super selector]; \
79 if (func && ctxt) { \
80 if (!tq) { \
81 tq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);\
82 } \
83 dispatch_async_f(tq, ctxt, func); \
84 } \
85 if (tq) { \
86 _dispatch_release(tq); \
87 }
88
89 - (void)dealloc {
90 _dispatch_data_objc_dispose(dealloc);
91 }
92
93 - (void)finalize {
94 _dispatch_data_objc_dispose(finalize);
95 }
96
97 - (BOOL)_bytesAreVM {
98 struct dispatch_data_s *dd = (void*)self;
99 return dd->destructor == DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
100 }
101
102 - (void)_setContext:(void*)context {
103 struct dispatch_data_s *dd = (void*)self;
104 dd->ctxt = context;
105 }
106
107 - (void*)_getContext {
108 struct dispatch_data_s *dd = (void*)self;
109 return dd->ctxt;
110 }
111
112 - (void)_setFinalizer:(dispatch_function_t)finalizer {
113 struct dispatch_data_s *dd = (void*)self;
114 dd->finalizer = finalizer;
115 }
116
117 - (void)_setTargetQueue:(dispatch_queue_t)queue {
118 struct dispatch_data_s *dd = (void*)self;
119 _dispatch_retain(queue);
120 dispatch_queue_t prev;
121 prev = dispatch_atomic_xchg2o(dd, do_targetq, queue, release);
122 if (prev) _dispatch_release(prev);
123 }
124
125 - (NSString *)debugDescription {
126 Class nsstring = objc_lookUpClass("NSString");
127 if (!nsstring) return nil;
128 char buf[2048];
129 _dispatch_data_debug(self, buf, sizeof(buf));
130 return [nsstring stringWithFormat:
131 [nsstring stringWithUTF8String:"<%s: %s>"],
132 class_getName([self class]), buf];
133 }
134
135 @end
136
137 @implementation DISPATCH_CLASS(data_empty)
138
139 // Force non-lazy class realization rdar://10640168
140 + (void)load {
141 }
142
143 - (id)retain {
144 return (id)self;
145 }
146
147 - (oneway void)release {
148 }
149
150 - (id)autorelease {
151 return (id)self;
152 }
153
154 - (NSUInteger)retainCount {
155 return ULONG_MAX;
156 }
157
158 + (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
159 return (id)&_dispatch_data_empty;
160 }
161
162 - (void)_setContext:(void*) DISPATCH_UNUSED context {
163 }
164
165 - (void*)_getContext {
166 return NULL;
167 }
168
169 - (void)_setFinalizer:(dispatch_function_t) DISPATCH_UNUSED finalizer {
170 }
171
172 - (void)_setTargetQueue:(dispatch_queue_t) DISPATCH_UNUSED queue {
173 }
174
175 @end
176
177 #endif // USE_OBJC