struct objc_cache *cache;
struct objc_protocol_list *protocols;
};
-#define CLS_GETINFO(cls,infomask) ((cls)->info & infomask)
-#define CLS_SETINFO(cls,infomask) ((cls)->info |= infomask)
+#define CLS_GETINFO(cls,infomask) ((cls)->info & (infomask))
+#define CLS_SETINFO(cls,infomask) ((cls)->info |= (infomask))
#define CLS_CLASS 0x1L
#define CLS_META 0x2L
// the JavaBridge constructs classes with these markers
#define CLS_JAVA_HYBRID 0x200L
#define CLS_JAVA_CLASS 0x400L
+// thread-safe +initialize
+#define CLS_INITIALIZING 0x800
+
+/*
+ * (true as of 2001-9-24)
+ * Thread-safety note: changes to these flags are not atomic, so
+ * the only thing preventing lost updates is the timing of the changes.
+ *
+ * As long as the following are isolated from each other for any one class,
+ * nearly all flag updates will be safe:
+ * - compile-time
+ * - loading in one thread (not including +load) without messaging
+ * - initializing in one thread with messaging from that thread only
+ * - multi-threaded messaging with method caching
+ *
+ * The current code doesn't protect loading yet.
+ *
+ * Times when the flags may change:
+ * CLS_CLASS: compile-time, hand-built classes
+ * CLS_META: compile time, hand-built classes
+ * CLS_INITIALIZED: initialize
+ * CLS_POSING: unsafe, but posing has other thread-safety problems
+ * CLS_MAPPED: compile-time
+ * CLS_FLUSH_CACHE: messaging
+ * CLS_GROW_CACHE: messaging
+ * FLUSH_CACHE and GROW_CACHE are protected from each other by the
+ * cacheUpdateLock.
+ * CLS_NEED_BIND: load, initialize
+ * CLS_METHOD_ARRAY: load
+ * CLS_JAVA_HYBRID: hand-built classes
+ * CLS_JAVA_CLASS: hand-built classes, initialize
+ * CLS_INITIALIZING: initialize
+ *
+ * The only unsafe updates are:
+ * - posing (unsafe anyway)
+ * - hand-built classes (including JavaBridge classes)
+ * There is a short time between objc_addClass inserts the new class
+ * into the class_hash and the builder setting the right flags.
+ * A thread looking at the class_hash could send a message to the class
+ * and trigger initialization, and the changes to the initialization
+ * flags and the hand-adjusted flags could collide.
+ * Solution: don't do that.
+ */
+
+
/*
* Category Template
*/
struct objc_method_list *class_methods;
struct objc_protocol_list *protocols;
};
+
/*
* Instance Variable Template
*/
typedef struct objc_ivar *Ivar;
-struct objc_ivar_list {
- int ivar_count;
+struct objc_ivar {
+ char *ivar_name;
+ char *ivar_type;
+ int ivar_offset;
#ifdef __alpha__
int space;
#endif
- struct objc_ivar {
- char *ivar_name;
- char *ivar_type;
- int ivar_offset;
+};
+
+struct objc_ivar_list {
+ int ivar_count;
#ifdef __alpha__
- int space;
+ int space;
#endif
- } ivar_list[1]; /* variable length structure */
+ struct objc_ivar ivar_list[1]; /* variable length structure */
};
OBJC_EXPORT Ivar object_setInstanceVariable(id, const char *name, void *);
*/
typedef struct objc_method *Method;
+struct objc_method {
+ SEL method_name;
+ char *method_types;
+ IMP method_imp;
+};
+
struct objc_method_list {
struct objc_method_list *obsolete;
#ifdef __alpha__
int space;
#endif
- struct objc_method {
- SEL method_name;
- char *method_types;
- IMP method_imp;
- } method_list[1]; /* variable length structure */
+ struct objc_method method_list[1]; /* variable length structure */
};
/* Protocol support */
#define CACHE_BUCKET_NAME(B) ((B)->method_name)
#define CACHE_BUCKET_IMP(B) ((B)->method_imp)
#define CACHE_BUCKET_VALID(B) (B)
+#define CACHE_HASH(sel, mask) (((uarith_t)(sel)>>2) & (mask))
struct objc_cache {
unsigned int mask; /* total = mask + 1 */
unsigned int occupied;
OBJC_EXPORT unsigned method_getNumberOfArguments(Method);
OBJC_EXPORT unsigned method_getSizeOfArguments(Method);
OBJC_EXPORT unsigned method_getArgumentInfo(Method m, int arg, const char **type, int *offset);
-OBJC_EXPORT const char * NSModulePathForClass (Class aClass);
// usage for nextMethodList
//