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/runtime.h"
27 #include "objc-private/module-abi-8.h" /* For runtime structures */
29 #include "objc-private/runtime.h" /* the kitchen sink */
30 #include "objc-private/hash.h" /* For the hash table of protocols. */
31 #include "objc-private/protocols.h" /* For __objc_protocols_init() and
32 __objc_protocols_add_protocol(). */
33 #include <stdlib.h> /* For malloc. */
35 /* This is a table that maps a name to a Protocol instance with that
36 name. Because there may be multiple Protocol instances with the
37 same name (no harm in that) the table records only one
39 static cache_ptr __protocols_hashtable
;
41 /* A mutex protecting the protocol_hashtable. */
42 static objc_mutex_t __protocols_hashtable_lock
= NULL
;
44 /* Called at startup by init.c. */
46 __objc_protocols_init (void)
48 __protocols_hashtable_lock
= objc_mutex_allocate ();
50 /* The keys in the table are strings, and the values are Protocol
52 __protocols_hashtable
= objc_hash_new (64, (hash_func_type
) objc_hash_string
,
53 (compare_func_type
) objc_compare_strings
);
56 /* Add a protocol to the hashtable. */
58 __objc_protocols_add_protocol (const char *name
, Protocol
*object
)
60 objc_mutex_lock (__protocols_hashtable_lock
);
62 /* If we find a protocol with the same name already in the
63 hashtable, we do not need to add the new one, because it will be
64 identical to it. This in the reasonable assumption that two
65 protocols with the same name are identical, which is expected in
66 any sane program. If we are really paranoid, we would compare
67 the protocols and abort if they are not identical.
68 Unfortunately, this would slow down the startup of all
69 Objective-C programs while trying to catch a problem that has
70 never been seen in practice, so we don't do it. */
71 if (! objc_hash_is_key_in_hash (__protocols_hashtable
, name
))
73 objc_hash_add (&__protocols_hashtable
, name
, object
);
76 objc_mutex_unlock (__protocols_hashtable_lock
);
80 objc_getProtocol (const char *name
)
87 objc_mutex_lock (__protocols_hashtable_lock
);
88 protocol
= (Protocol
*)(objc_hash_value_for_key (__protocols_hashtable
, name
));
89 objc_mutex_unlock (__protocols_hashtable_lock
);
95 objc_copyProtocolList (unsigned int *numberOfReturnedProtocols
)
97 unsigned int count
= 0;
98 Protocol
**returnValue
= NULL
;
101 objc_mutex_lock (__protocols_hashtable_lock
);
103 /* Count how many protocols we have. */
104 node
= objc_hash_next (__protocols_hashtable
, NULL
);
108 node
= objc_hash_next (__protocols_hashtable
, node
);
115 /* Allocate enough memory to hold them. */
116 returnValue
= (Protocol
**)(malloc (sizeof (Protocol
*) * (count
+ 1)));
118 /* Copy the protocols. */
119 node
= objc_hash_next (__protocols_hashtable
, NULL
);
122 returnValue
[i
] = node
->value
;
124 node
= objc_hash_next (__protocols_hashtable
, node
);
127 returnValue
[i
] = NULL
;
129 objc_mutex_unlock (__protocols_hashtable_lock
);
131 if (numberOfReturnedProtocols
)
132 *numberOfReturnedProtocols
= count
;
138 class_addProtocol (Class class_
, Protocol
*protocol
)
140 struct objc_protocol_list
*protocols
;
142 if (class_
== Nil
|| protocol
== NULL
)
145 if (class_conformsToProtocol (class_
, protocol
))
148 /* Check that it is a Protocol object before casting it to (struct
150 if (protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
153 objc_mutex_lock (__objc_runtime_mutex
);
155 /* Create the objc_protocol_list. */
156 protocols
= malloc (sizeof (struct objc_protocol_list
));
157 protocols
->count
= 1;
158 protocols
->list
[0] = protocol
;
160 /* Attach it to the list of class protocols. */
161 protocols
->next
= class_
->protocols
;
162 class_
->protocols
= protocols
;
164 objc_mutex_unlock (__objc_runtime_mutex
);
170 class_conformsToProtocol (Class class_
, Protocol
*protocol
)
172 struct objc_protocol_list
* proto_list
;
174 if (class_
== Nil
|| protocol
== NULL
)
177 /* Check that it is a Protocol object before casting it to (struct
179 if (protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
182 /* Acquire the runtime lock because the list of protocols for a
183 class may be modified concurrently, for example if another thread
184 calls class_addProtocol(), or dynamically loads from a file a
185 category of the class. */
186 objc_mutex_lock (__objc_runtime_mutex
);
187 proto_list
= class_
->protocols
;
192 for (i
= 0; i
< proto_list
->count
; i
++)
194 if (proto_list
->list
[i
] == protocol
195 || protocol_conformsToProtocol (proto_list
->list
[i
],
198 objc_mutex_unlock (__objc_runtime_mutex
);
202 proto_list
= proto_list
->next
;
205 objc_mutex_unlock (__objc_runtime_mutex
);
210 class_copyProtocolList (Class class_
, unsigned int *numberOfReturnedProtocols
)
212 unsigned int count
= 0;
213 Protocol
**returnValue
= NULL
;
214 struct objc_protocol_list
* proto_list
;
218 if (numberOfReturnedProtocols
)
219 *numberOfReturnedProtocols
= 0;
223 /* Lock the runtime mutex because the class protocols may be
224 concurrently modified. */
225 objc_mutex_lock (__objc_runtime_mutex
);
227 /* Count how many protocols we have. */
228 proto_list
= class_
->protocols
;
232 count
= count
+ proto_list
->count
;
233 proto_list
= proto_list
->next
;
240 /* Allocate enough memory to hold them. */
241 returnValue
= (Protocol
**)(malloc (sizeof (Protocol
*) * (count
+ 1)));
243 /* Copy the protocols. */
244 proto_list
= class_
->protocols
;
249 for (j
= 0; j
< proto_list
->count
; j
++)
251 returnValue
[i
] = proto_list
->list
[j
];
254 proto_list
= proto_list
->next
;
257 returnValue
[i
] = NULL
;
259 objc_mutex_unlock (__objc_runtime_mutex
);
261 if (numberOfReturnedProtocols
)
262 *numberOfReturnedProtocols
= count
;
268 protocol_conformsToProtocol (Protocol
*protocol
, Protocol
*anotherProtocol
)
270 struct objc_protocol_list
* proto_list
;
272 if (protocol
== NULL
|| anotherProtocol
== NULL
)
275 if (protocol
== anotherProtocol
)
278 /* Check that the objects are Protocol objects before casting them
279 to (struct objc_protocol *). */
280 if (protocol
->class_pointer
!= anotherProtocol
->class_pointer
)
283 if (protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
286 if (strcmp (((struct objc_protocol
*)protocol
)->protocol_name
,
287 ((struct objc_protocol
*)anotherProtocol
)->protocol_name
) == 0)
290 /* We do not acquire any lock because protocols are currently
291 immutable. We can freely iterate over a protocol structure. */
292 proto_list
= ((struct objc_protocol
*)protocol
)->protocol_list
;
297 for (i
= 0; i
< proto_list
->count
; i
++)
299 if (protocol_conformsToProtocol (proto_list
->list
[i
], anotherProtocol
))
302 proto_list
= proto_list
->next
;
309 protocol_isEqual (Protocol
*protocol
, Protocol
*anotherProtocol
)
311 if (protocol
== anotherProtocol
)
314 if (protocol
== NULL
|| anotherProtocol
== NULL
)
317 /* Check that the objects are Protocol objects before casting them
318 to (struct objc_protocol *). */
319 if (protocol
->class_pointer
!= anotherProtocol
->class_pointer
)
322 if (protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
325 /* Equality between formal protocols is only formal (nothing to do
326 with actually checking the list of methods they have!). Two
327 formal Protocols are equal if and only if they have the same
330 Please note (for comparisons with other implementations) that
331 checking the names is equivalent to checking that Protocol A
332 conforms to Protocol B and Protocol B conforms to Protocol A,
333 because this happens iff they have the same name. If they have
334 different names, A conforms to B if and only if A includes B, but
335 the situation where A includes B and B includes A is a circular
336 dependency between Protocols which is forbidden by the compiler,
337 so A conforms to B and B conforms to A with A and B having
338 different names is an impossible case. */
339 if (strcmp (((struct objc_protocol
*)protocol
)->protocol_name
,
340 ((struct objc_protocol
*)anotherProtocol
)->protocol_name
) == 0)
347 protocol_getName (Protocol
*protocol
)
349 /* Check that it is a Protocol object before casting it to (struct
351 if (protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
354 return ((struct objc_protocol
*)protocol
)->protocol_name
;
357 struct objc_method_description
protocol_getMethodDescription (Protocol
*protocol
,
362 struct objc_method_description no_result
= { NULL
, NULL
};
363 struct objc_method_description_list
*methods
;
367 /* The current ABI does not have any information on optional protocol methods. */
368 if (! requiredMethod
)
371 /* Check that it is a Protocol object before casting it to (struct
373 if (protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
377 methods
= ((struct objc_protocol
*)protocol
)->instance_methods
;
379 methods
= ((struct objc_protocol
*)protocol
)->class_methods
;
383 for (i
= 0; i
< methods
->count
; i
++)
385 if (sel_isEqual (methods
->list
[i
].name
, selector
))
386 return methods
->list
[i
];
388 if (strcmp (sel_getName (methods->list[i].name), selector_name) == 0)
389 return methods->list[i];
397 struct objc_method_description
*protocol_copyMethodDescriptionList (Protocol
*protocol
,
400 unsigned int *numberOfReturnedMethods
)
402 struct objc_method_description_list
*methods
;
403 unsigned int count
= 0;
404 struct objc_method_description
*returnValue
= NULL
;
407 /* The current ABI does not have any information on optional protocol methods. */
408 if (! requiredMethod
)
410 if (numberOfReturnedMethods
)
411 *numberOfReturnedMethods
= 0;
416 /* Check that it is a Protocol object before casting it to (struct
418 if (protocol
== NULL
|| protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
420 if (numberOfReturnedMethods
)
421 *numberOfReturnedMethods
= 0;
426 /* We do not acquire any lock because protocols are currently
427 immutable. We can freely iterate over a protocol structure. */
430 methods
= ((struct objc_protocol
*)protocol
)->instance_methods
;
432 methods
= ((struct objc_protocol
*)protocol
)->class_methods
;
437 count
= methods
->count
;
439 /* Allocate enough memory to hold them. */
440 returnValue
= (struct objc_method_description
*)(malloc (sizeof (struct objc_method_description
) * (count
+ 1)));
443 for (i
= 0; i
< count
; i
++)
445 returnValue
[i
].name
= methods
->list
[i
].name
;
446 returnValue
[i
].types
= methods
->list
[i
].types
;
448 returnValue
[i
].name
= NULL
;
449 returnValue
[i
].types
= NULL
;
452 if (numberOfReturnedMethods
)
453 *numberOfReturnedMethods
= count
;
458 Property
protocol_getProperty (Protocol
*protocol
, const char *propertyName
,
459 BOOL requiredProperty
, BOOL instanceProperty
)
461 if (protocol
== NULL
|| propertyName
== NULL
)
464 if (!requiredProperty
|| !instanceProperty
)
467 /* Check that it is a Protocol object before casting it to (struct
469 if (protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
473 /* The current ABI does not have any information on protocol properties. */
477 Property
*protocol_copyPropertyList (Protocol
*protocol
, unsigned int *numberOfReturnedProperties
)
479 unsigned int count
= 0;
480 Property
*returnValue
= NULL
;
482 /* Check that it is a Protocol object before casting it to (struct
484 if (protocol
== NULL
|| protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
486 if (numberOfReturnedProperties
)
487 *numberOfReturnedProperties
= 0;
492 /* We do not acquire any lock because protocols are currently
493 immutable. We can freely iterate over a protocol structure. */
496 /* The current ABI does not have any information on protocol properties. */
497 if (numberOfReturnedProperties
)
498 *numberOfReturnedProperties
= count
;
503 Protocol
**protocol_copyProtocolList (Protocol
*protocol
, unsigned int *numberOfReturnedProtocols
)
505 unsigned int count
= 0;
506 Protocol
**returnValue
= NULL
;
507 struct objc_protocol_list
* proto_list
;
509 /* Check that it is a Protocol object before casting it to (struct
511 if (protocol
== NULL
|| protocol
->class_pointer
!= objc_lookupClass ("Protocol"))
513 if (numberOfReturnedProtocols
)
514 *numberOfReturnedProtocols
= 0;
519 /* We do not acquire any lock because protocols are currently
520 immutable. We can freely iterate over a protocol structure. */
522 /* Count how many protocols we have. */
523 proto_list
= ((struct objc_protocol
*)protocol
)->protocol_list
;
527 count
= count
+ proto_list
->count
;
528 proto_list
= proto_list
->next
;
535 /* Allocate enough memory to hold them. */
536 returnValue
= (Protocol
**)(malloc (sizeof (Protocol
*) * (count
+ 1)));
538 /* Copy the protocols. */
539 proto_list
= ((struct objc_protocol
*)protocol
)->protocol_list
;
544 for (j
= 0; j
< proto_list
->count
; j
++)
546 returnValue
[i
] = proto_list
->list
[j
];
549 proto_list
= proto_list
->next
;
552 returnValue
[i
] = NULL
;
555 if (numberOfReturnedProtocols
)
556 *numberOfReturnedProtocols
= count
;