]> git.saurik.com Git - apple/cf.git/blob - PlugIn.subproj/CFPlugIn_Factory.c
CF-299.32.tar.gz
[apple/cf.git] / PlugIn.subproj / CFPlugIn_Factory.c
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* CFPlugIn_Factory.c
26 Copyright 1999-2002, Apple, Inc. All rights reserved.
27 Responsibility: Doug Davidson
28 */
29
30 #include "CFBundle_Internal.h"
31 #include "CFInternal.h"
32
33 static CFSpinLock_t CFPlugInGlobalDataLock = 0;
34 static CFMutableDictionaryRef _factoriesByFactoryID = NULL; /* Value is _CFPFactory */
35 static CFMutableDictionaryRef _factoriesByTypeID = NULL; /* Value is array of _CFPFactory */
36
37 static void _CFPFactoryAddToTable(_CFPFactory *factory) {
38 __CFSpinLock(&CFPlugInGlobalDataLock);
39 if (_factoriesByFactoryID == NULL) {
40 CFDictionaryValueCallBacks _factoryDictValueCallbacks = {0, NULL, NULL, NULL, NULL};
41 // Use default allocator
42 _factoriesByFactoryID = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &_factoryDictValueCallbacks);
43 }
44 CFDictionarySetValue(_factoriesByFactoryID, factory->_uuid, factory);
45 __CFSpinUnlock(&CFPlugInGlobalDataLock);
46 }
47
48 static void _CFPFactoryRemoveFromTable(_CFPFactory *factory) {
49 __CFSpinLock(&CFPlugInGlobalDataLock);
50 if (_factoriesByFactoryID != NULL) {
51 CFDictionaryRemoveValue(_factoriesByFactoryID, factory->_uuid);
52 }
53 __CFSpinUnlock(&CFPlugInGlobalDataLock);
54 }
55
56 __private_extern__ _CFPFactory *_CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled) {
57 _CFPFactory *result = NULL;
58
59 __CFSpinLock(&CFPlugInGlobalDataLock);
60 if (_factoriesByFactoryID != NULL) {
61 result = (_CFPFactory *)CFDictionaryGetValue(_factoriesByFactoryID, factoryID);
62 if (result && result->_enabled != enabled) {
63 result = NULL;
64 }
65 }
66 __CFSpinUnlock(&CFPlugInGlobalDataLock);
67 return result;
68 }
69
70 static void _CFPFactoryDeallocate(_CFPFactory *factory) {
71 CFAllocatorRef allocator = factory->_allocator;
72 SInt32 c;
73
74 _CFPFactoryRemoveFromTable(factory);
75
76 if (factory->_plugIn) {
77 _CFPlugInRemoveFactory(factory->_plugIn, factory);
78 }
79
80 /* Remove all types for this factory. */
81 c = CFArrayGetCount(factory->_types);
82 while (c--) {
83 _CFPFactoryRemoveType(factory, CFArrayGetValueAtIndex(factory->_types, c));
84 }
85 CFRelease(factory->_types);
86
87 if (factory->_funcName) {
88 CFRelease(factory->_funcName);
89 }
90
91 if (factory->_uuid) {
92 CFRelease(factory->_uuid);
93 }
94
95 CFAllocatorDeallocate(allocator, factory);
96 CFRelease(allocator);
97 }
98
99 static _CFPFactory *_CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRef factoryID) {
100 _CFPFactory *factory;
101 UInt32 size;
102 size = sizeof(_CFPFactory);
103 allocator = ((NULL == allocator) ? CFRetain(__CFGetDefaultAllocator()) : CFRetain(allocator));
104 factory = CFAllocatorAllocate(allocator, size, 0);
105 if (NULL == factory) {
106 CFRelease(allocator);
107 return NULL;
108 }
109
110 factory->_allocator = allocator;
111
112 factory->_uuid = CFRetain(factoryID);
113 factory->_enabled = true;
114 factory->_instanceCount = 0;
115
116 _CFPFactoryAddToTable(factory);
117
118 factory->_types = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
119
120 return factory;
121 }
122
123 __private_extern__ _CFPFactory *_CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func) {
124 _CFPFactory *factory = _CFPFactoryCommonCreate(allocator, factoryID);
125
126 factory->_func = func;
127 factory->_plugIn = NULL;
128 factory->_funcName = NULL;
129
130 return factory;
131 }
132
133 __private_extern__ _CFPFactory *_CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName) {
134 _CFPFactory *factory = _CFPFactoryCommonCreate(allocator, factoryID);
135
136 factory->_func = NULL;
137 factory->_plugIn = plugIn;
138 if (plugIn) {
139 _CFPlugInAddFactory(plugIn, factory);
140 }
141 factory->_funcName = (funcName ? CFStringCreateCopy(allocator, funcName) : NULL);
142
143 return factory;
144 }
145
146 __private_extern__ CFUUIDRef _CFPFactoryGetFactoryID(_CFPFactory *factory) {
147 return factory->_uuid;
148 }
149
150 __private_extern__ CFPlugInRef _CFPFactoryGetPlugIn(_CFPFactory *factory) {
151 return factory->_plugIn;
152 }
153
154 __private_extern__ void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactory *factory, CFUUIDRef typeID) {
155 void *result = NULL;
156 if (factory->_enabled) {
157 if (factory->_func == NULL) {
158 factory->_func = CFBundleGetFunctionPointerForName(factory->_plugIn, factory->_funcName);
159 if (factory->_func == NULL) {
160 CFLog(__kCFLogPlugIn, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory->_funcName, factory->_uuid, factory->_plugIn);
161 }
162 #if defined(__MACH__) && defined(__ppc__)
163 else {
164 // return values from CFBundleGetFunctionPointerForName will always be dyld, but
165 // we must force-fault them because pointers to glue code do not fault correctly
166 factory->_func = (void *)((unsigned long)(factory->_func) | 0x1);
167 }
168 #endif
169 }
170 if (factory->_func) {
171 #if 1
172 // UPPGOOP
173 FAULT_CALLBACK((void **)&(factory->_func));
174 result = (void *)INVOKE_CALLBACK2(factory->_func, allocator, typeID);
175 #else
176 result = factory->_func(allocator, typeID);
177 #endif
178 }
179 } else {
180 CFLog(__kCFLogPlugIn, CFSTR("Factory %@ is disabled"), factory->_uuid);
181 }
182 return result;
183 }
184
185 __private_extern__ void _CFPFactoryDisable(_CFPFactory *factory) {
186 factory->_enabled = false;
187 if (factory->_instanceCount == 0) {
188 _CFPFactoryDeallocate(factory);
189 }
190 }
191
192 __private_extern__ Boolean _CFPFactoryIsEnabled(_CFPFactory *factory) {
193 return factory->_enabled;
194 }
195
196 __private_extern__ void _CFPFactoryFlushFunctionCache(_CFPFactory *factory) {
197 /* MF:!!! Assert that this factory belongs to a plugIn. */
198 /* This is called by the factory's plugIn when the plugIn unloads its code. */
199 factory->_func = NULL;
200 }
201
202 __private_extern__ void _CFPFactoryAddType(_CFPFactory *factory, CFUUIDRef typeID) {
203 CFMutableArrayRef array;
204
205 /* Add the type to the factory's type list */
206 CFArrayAppendValue(factory->_types, typeID);
207
208 /* Add the factory to the type's array of factories */
209 __CFSpinLock(&CFPlugInGlobalDataLock);
210 if (_factoriesByTypeID == NULL) {
211 // Create this from default allocator
212 _factoriesByTypeID = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
213 }
214 array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
215 if (array == NULL) {
216 CFArrayCallBacks _factoryArrayCallbacks = {0, NULL, NULL, NULL, NULL};
217 // Create this from default allocator
218 array = CFArrayCreateMutable(NULL, 0, &_factoryArrayCallbacks);
219 CFDictionarySetValue(_factoriesByTypeID, typeID, array);
220 CFRelease(array);
221 }
222 CFArrayAppendValue(array, factory);
223 __CFSpinUnlock(&CFPlugInGlobalDataLock);
224 }
225
226 __private_extern__ void _CFPFactoryRemoveType(_CFPFactory *factory, CFUUIDRef typeID) {
227 /* Remove it from the factory's type list */
228 SInt32 idx;
229
230 idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID);
231 if (idx >=0) {
232 CFArrayRemoveValueAtIndex(factory->_types, idx);
233 }
234
235 /* Remove the factory from the type's list of factories */
236 __CFSpinLock(&CFPlugInGlobalDataLock);
237 if (_factoriesByTypeID != NULL) {
238 CFMutableArrayRef array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
239 if (array != NULL) {
240 idx = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), factory);
241 if (idx >=0) {
242 CFArrayRemoveValueAtIndex(array, idx);
243 if (CFArrayGetCount(array) == 0) {
244 CFDictionaryRemoveValue(_factoriesByTypeID, typeID);
245 }
246 }
247 }
248 }
249 __CFSpinUnlock(&CFPlugInGlobalDataLock);
250 }
251
252 __private_extern__ Boolean _CFPFactorySupportsType(_CFPFactory *factory, CFUUIDRef typeID) {
253 SInt32 idx;
254
255 idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID);
256 return ((idx >= 0) ? true : false);
257 }
258
259 __private_extern__ CFArrayRef _CFPFactoryFindForType(CFUUIDRef typeID) {
260 CFArrayRef result = NULL;
261
262 __CFSpinLock(&CFPlugInGlobalDataLock);
263 if (_factoriesByTypeID != NULL) {
264 result = CFDictionaryGetValue(_factoriesByTypeID, typeID);
265 }
266 __CFSpinUnlock(&CFPlugInGlobalDataLock);
267
268 return result;
269 }
270
271 /* These methods are called by CFPlugInInstance when an instance is created or destroyed. If a factory's instance count goes to 0 and the factory has been disabled, the factory is destroyed. */
272 __private_extern__ void _CFPFactoryAddInstance(_CFPFactory *factory) {
273 /* MF:!!! Assert that factory is enabled. */
274 factory->_instanceCount++;
275 if (factory->_plugIn) {
276 _CFPlugInAddPlugInInstance(factory->_plugIn);
277 }
278 }
279
280 __private_extern__ void _CFPFactoryRemoveInstance(_CFPFactory *factory) {
281 /* MF:!!! Assert that _instanceCount > 0. */
282 factory->_instanceCount--;
283 if (factory->_plugIn) {
284 _CFPlugInRemovePlugInInstance(factory->_plugIn);
285 }
286 if ((factory->_instanceCount == 0) && (!factory->_enabled)) {
287 _CFPFactoryDeallocate(factory);
288 }
289 }