1 /* GNU Objective C Runtime protocol related functions.
2 Copyright (C) 2010 Free Software Foundation, Inc.
3 Contributed by Nicola Pero
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 3, or (at your option) any later version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 #include "objc-private/common.h"
26 #include "objc/objc.h"
27 #include "objc/runtime.h"
28 #include "objc-private/module-abi-8.h" /* For runtime structures */
30 #include "objc-private/runtime.h" /* the kitchen sink */
31 #include "objc-private/hash.h" /* For the hash table of protocols. */
32 #include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */
34 /* This is a table that maps a name to a Protocol instance with that
35 name. Because there may be multiple Protocol instances with the
36 same name (no harm in that) the table records only one
38 static cache_ptr __protocols_hashtable;
40 /* A mutex protecting the protocol_hashtable. */
41 static objc_mutex_t __protocols_hashtable_lock = NULL;
43 /* Called at startup by init.c. */
45 __objc_protocols_init (void)
47 __protocols_hashtable_lock = objc_mutex_allocate ();
49 /* The keys in the table are strings, and the values are Protocol
51 __protocols_hashtable = objc_hash_new (64, (hash_func_type) objc_hash_string,
52 (compare_func_type) objc_compare_strings);
55 /* Add a protocol to the hashtable. */
57 __objc_protocols_add_protocol (const char *name, Protocol *object)
59 objc_mutex_lock (__protocols_hashtable_lock);
61 /* If we find a protocol with the same name already in the
62 hashtable, we do not need to add the new one, because it will be
63 identical to it. This in the reasonable assumption that two
64 protocols with the same name are identical, which is expected in
65 any sane program. If we are really paranoid, we would compare
66 the protocols and abort if they are not identical.
67 Unfortunately, this would slow down the startup of all
68 Objective-C programs while trying to catch a problem that has
69 never been seen in practice, so we don't do it. */
70 if (! objc_hash_is_key_in_hash (__protocols_hashtable, name))
72 objc_hash_add (&__protocols_hashtable, name, object);
75 objc_mutex_unlock (__protocols_hashtable_lock);
79 objc_getProtocol (const char *name)
86 objc_mutex_lock (__protocols_hashtable_lock);
87 protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name));
88 objc_mutex_unlock (__protocols_hashtable_lock);
94 objc_copyProtocolList (unsigned int *numberOfReturnedProtocols)
96 unsigned int count = 0;
97 Protocol **returnValue = NULL;
100 objc_mutex_lock (__protocols_hashtable_lock);
102 /* Count how many protocols we have. */
103 node = objc_hash_next (__protocols_hashtable, NULL);
107 node = objc_hash_next (__protocols_hashtable, node);
114 /* Allocate enough memory to hold them. */
115 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
117 /* Copy the protocols. */
118 node = objc_hash_next (__protocols_hashtable, NULL);
121 returnValue[i] = node->value;
123 node = objc_hash_next (__protocols_hashtable, node);
126 returnValue[i] = NULL;
128 objc_mutex_unlock (__protocols_hashtable_lock);
130 if (numberOfReturnedProtocols)
131 *numberOfReturnedProtocols = count;
137 class_addProtocol (Class class_, Protocol *protocol)
139 struct objc_protocol_list *protocols;
141 if (class_ == Nil || protocol == NULL)
144 if (class_conformsToProtocol (class_, protocol))
147 /* Check that it is a Protocol object before casting it to (struct
149 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
152 objc_mutex_lock (__objc_runtime_mutex);
154 /* Create the objc_protocol_list. */
155 protocols = malloc (sizeof (struct objc_protocol_list));
156 protocols->count = 1;
157 protocols->list[0] = protocol;
159 /* Attach it to the list of class protocols. */
160 protocols->next = class_->protocols;
161 class_->protocols = protocols;
163 objc_mutex_unlock (__objc_runtime_mutex);
169 class_conformsToProtocol (Class class_, Protocol *protocol)
171 struct objc_protocol_list* proto_list;
173 if (class_ == Nil || protocol == NULL)
176 /* Check that it is a Protocol object before casting it to (struct
178 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
181 /* Acquire the runtime lock because the list of protocols for a
182 class may be modified concurrently, for example if another thread
183 calls class_addProtocol(), or dynamically loads from a file a
184 category of the class. */
185 objc_mutex_lock (__objc_runtime_mutex);
186 proto_list = class_->protocols;
191 for (i = 0; i < proto_list->count; i++)
193 if (proto_list->list[i] == protocol
194 || protocol_conformsToProtocol (proto_list->list[i],
197 objc_mutex_unlock (__objc_runtime_mutex);
201 proto_list = proto_list->next;
204 objc_mutex_unlock (__objc_runtime_mutex);
209 class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
211 unsigned int count = 0;
212 Protocol **returnValue = NULL;
213 struct objc_protocol_list* proto_list;
215 /* Lock the runtime mutex because the class protocols may be
216 concurrently modified. */
217 objc_mutex_lock (__objc_runtime_mutex);
219 /* Count how many protocols we have. */
220 proto_list = class_->protocols;
224 count = count + proto_list->count;
225 proto_list = proto_list->next;
232 /* Allocate enough memory to hold them. */
233 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
235 /* Copy the protocols. */
236 proto_list = class_->protocols;
241 for (j = 0; j < proto_list->count; j++)
243 returnValue[i] = proto_list->list[j];
246 proto_list = proto_list->next;
249 returnValue[i] = NULL;
251 objc_mutex_unlock (__objc_runtime_mutex);
253 if (numberOfReturnedProtocols)
254 *numberOfReturnedProtocols = count;
260 protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol)
262 struct objc_protocol_list* proto_list;
264 if (protocol == NULL || anotherProtocol == NULL)
267 if (protocol == anotherProtocol)
270 /* Check that the objects are Protocol objects before casting them
271 to (struct objc_protocol *). */
272 if (protocol->class_pointer != anotherProtocol->class_pointer)
275 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
278 if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
279 ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
282 /* We do not acquire any lock because protocols are currently
283 immutable. We can freely iterate over a protocol structure. */
284 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
289 for (i = 0; i < proto_list->count; i++)
291 if (protocol_conformsToProtocol (proto_list->list[i], anotherProtocol))
294 proto_list = proto_list->next;
301 protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol)
303 if (protocol == anotherProtocol)
306 if (protocol == NULL || anotherProtocol == NULL)
309 /* Check that the objects are Protocol objects before casting them
310 to (struct objc_protocol *). */
311 if (protocol->class_pointer != anotherProtocol->class_pointer)
314 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
317 /* Equality between formal protocols is only formal (nothing to do
318 with actually checking the list of methods they have!). Two
319 formal Protocols are equal if and only if they have the same
322 Please note (for comparisons with other implementations) that
323 checking the names is equivalent to checking that Protocol A
324 conforms to Protocol B and Protocol B conforms to Protocol A,
325 because this happens iff they have the same name. If they have
326 different names, A conforms to B if and only if A includes B, but
327 the situation where A includes B and B includes A is a circular
328 dependency between Protocols which is forbidden by the compiler,
329 so A conforms to B and B conforms to A with A and B having
330 different names is an impossible case. */
331 if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
332 ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
339 protocol_getName (Protocol *protocol)
341 /* Check that it is a Protocol object before casting it to (struct
343 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
346 return ((struct objc_protocol *)protocol)->protocol_name;
349 struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
354 struct objc_method_description no_result = { NULL, NULL };
355 const char* selector_name;
356 struct objc_method_description_list *methods;
360 /* The current ABI does not have any information on optional protocol methods. */
361 if (! requiredMethod)
364 /* Check that it is a Protocol object before casting it to (struct
366 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
369 selector_name = sel_getName (selector);
372 methods = ((struct objc_protocol *)protocol)->instance_methods;
374 methods = ((struct objc_protocol *)protocol)->class_methods;
378 for (i = 0; i < methods->count; i++)
380 if (strcmp ((char*)(methods->list[i].name), selector_name) == 0)
381 return methods->list[i];
388 struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
391 unsigned int *numberOfReturnedMethods)
393 struct objc_method_description_list *methods;
394 unsigned int count = 0;
395 struct objc_method_description *returnValue = NULL;
398 /* The current ABI does not have any information on optional protocol methods. */
399 if (! requiredMethod)
401 if (numberOfReturnedMethods)
402 *numberOfReturnedMethods = 0;
407 /* Check that it is a Protocol object before casting it to (struct
409 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
411 if (numberOfReturnedMethods)
412 *numberOfReturnedMethods = 0;
417 /* We do not acquire any lock because protocols are currently
418 immutable. We can freely iterate over a protocol structure. */
421 methods = ((struct objc_protocol *)protocol)->instance_methods;
423 methods = ((struct objc_protocol *)protocol)->class_methods;
428 count = methods->count;
430 /* Allocate enough memory to hold them. */
431 returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1)));
434 for (i = 0; i < count; i++)
436 returnValue[i].name = methods->list[i].name;
437 returnValue[i].types = methods->list[i].types;
439 returnValue[i].name = NULL;
440 returnValue[i].types = NULL;
443 if (numberOfReturnedMethods)
444 *numberOfReturnedMethods = count;
449 Property protocol_getProperty (Protocol *protocol, const char *propertyName,
450 BOOL requiredProperty, BOOL instanceProperty)
452 if (protocol == NULL || propertyName == NULL)
455 if (!requiredProperty || !instanceProperty)
458 /* Check that it is a Protocol object before casting it to (struct
460 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
464 /* The current ABI does not have any information on protocol properties. */
468 Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties)
470 unsigned int count = 0;
471 Property *returnValue = NULL;
473 /* Check that it is a Protocol object before casting it to (struct
475 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
477 if (numberOfReturnedProperties)
478 *numberOfReturnedProperties = 0;
483 /* We do not acquire any lock because protocols are currently
484 immutable. We can freely iterate over a protocol structure. */
487 /* The current ABI does not have any information on protocol properties. */
488 if (numberOfReturnedProperties)
489 *numberOfReturnedProperties = count;
494 Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols)
496 unsigned int count = 0;
497 Protocol **returnValue = NULL;
498 struct objc_protocol_list* proto_list;
500 /* Check that it is a Protocol object before casting it to (struct
502 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
504 if (numberOfReturnedProtocols)
505 *numberOfReturnedProtocols = 0;
510 /* We do not acquire any lock because protocols are currently
511 immutable. We can freely iterate over a protocol structure. */
513 /* Count how many protocols we have. */
514 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
518 count = count + proto_list->count;
519 proto_list = proto_list->next;
526 /* Allocate enough memory to hold them. */
527 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
529 /* Copy the protocols. */
530 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
535 for (j = 0; j < proto_list->count; j++)
537 returnValue[i] = proto_list->list[j];
540 proto_list = proto_list->next;
543 returnValue[i] = NULL;
546 if (numberOfReturnedProtocols)
547 *numberOfReturnedProtocols = count;