Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -351,10 +351,24 @@ * @brief Returns whether the object is a proxy object. * * @return A boolean whether the object is a proxy object */ - (bool)isProxy; + +/*! + * @brief Returns whether the class allows weak references. + * + * @return Whether the class allows weak references + */ +- (bool)allowsWeakReference; + +/*! + * @brief Retain a weak reference to this object. + * + * @return Whether a weak reference to this object has been retained + */ +- (bool)retainWeakReference; @end /*! * @class OFObject OFObject.h ObjFW/OFObject.h * Index: src/runtime/arc.m ================================================================== --- src/runtime/arc.m +++ src/runtime/arc.m @@ -154,11 +154,12 @@ break; } } } - if (value != nil) { + if (value != nil && class_respondsToSelector(object_getClass(value), + @selector(allowsWeakReference)) && [value allowsWeakReference]) { struct weak_ref *ref = objc_hashtable_get(hashtable, value); if (ref == NULL) { if ((ref = calloc(1, sizeof(*ref))) == NULL) OBJC_ERROR("Not enough memory to allocate weak " @@ -171,11 +172,12 @@ (ref->count + 1) * sizeof(id*))) == NULL) OBJC_ERROR("Not enough memory to allocate weak " "reference!") ref->locations[ref->count++] = object; - } + } else + value = nil; *object = value; #ifdef OF_HAVE_THREADS if (!of_spinlock_unlock(&spinlock)) @@ -186,27 +188,31 @@ } id objc_loadWeakRetained(id *object) { - id ret = nil; + id value = nil; struct weak_ref *ref; #ifdef OF_HAVE_THREADS if (!of_spinlock_lock(&spinlock)) OBJC_ERROR("Failed to lock spinlock!") #endif if ((ref = objc_hashtable_get(hashtable, *object)) != NULL) - ret = *object; + value = *object; #ifdef OF_HAVE_THREADS if (!of_spinlock_unlock(&spinlock)) OBJC_ERROR("Failed to unlock spinlock!") #endif - return objc_retain(ret); + if (class_respondsToSelector(object_getClass(value), + @selector(retainWeakReference)) && [value retainWeakReference]) + return value; + + return nil; } id objc_initWeak(id *object, id value) {