Author: paullanders
Date: Fri Nov 11 19:19:32 2016
New Revision: 40217

URL: http://svn.gna.org/viewcvs/gnustep?rev=40217&view=rev
Log:
Merge NSObject changes from trunk instead of my previous commit. Fixes retain 
and release compatibility with libobjc2 in a platform safe way.

Modified:
    libs/base/branches/gnustep_testplant_branch/Source/NSObject.m

Modified: libs/base/branches/gnustep_testplant_branch/Source/NSObject.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/branches/gnustep_testplant_branch/Source/NSObject.m?rev=40217&r1=40216&r2=40217&view=diff
==============================================================================
--- libs/base/branches/gnustep_testplant_branch/Source/NSObject.m       
(original)
+++ libs/base/branches/gnustep_testplant_branch/Source/NSObject.m       Fri Nov 
11 19:19:32 2016
@@ -1,26 +1,20 @@
 /** Implementation of NSObject for GNUStep
    Copyright (C) 1994-2010 Free Software Foundation, Inc.
-
    Written by:  Andrew Kachites McCallum <mccal...@gnu.ai.mit.edu>
    Date: August 1994
-
    This file is part of the GNUstep Base Library.
-
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
-
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.
-
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02111 USA.
-
    <title>NSObject class reference</title>
    $Date$ $Revision$
    */
@@ -113,11 +107,10 @@
 - (id) initWithObject: (id)anObject;
 @end
 
-/*
- * allocationLock is needed when running multi-threaded for
- * protecting the map table of zombie information.
- */
-static NSLock *allocationLock;
+/* allocationLock is needed when for protecting the map table of zombie
+ * information and if atomic operations are not available.
+ */
+static NSLock *allocationLock = nil;
 
 BOOL   NSZombieEnabled = NO;
 BOOL   NSDeallocateZombies = NO;
@@ -187,15 +180,28 @@
 #endif
 
 
+/* Traditionally, GNUstep has been using a 32bit reference count in front
+ * of the object. The automatic reference counting implementation in
+ * libobjc2 uses an intptr_t instead, so NSObject will only be compatible
+ * with ARC if either of the following apply:
+ *
+ * a) sizeof(intptr_t) == sizeof(int32_t)
+ * b) we can provide atomic operations on pointer sized values, allowing
+ *    us to extend the refcount to intptr_t.
+ */
+#ifdef GS_ARC_COMPATIBLE
+#undef GS_ARC_COMPATIBLE
+#endif
 
 #if defined(__llvm__) || (defined(USE_ATOMIC_BUILTINS) && (__GNUC__ > 4 || 
(__GNUC__ == 4 && __GNUC_MINOR__ >= 1)))
 /* Use the GCC atomic operations with recent GCC versions */
 
-typedef int32_t volatile *gsatomic_t;
+typedef intptr_t volatile *gsatomic_t;
+typedef intptr_t gsrefcount_t;
 #define GSATOMICREAD(X) (*(X))
 #define GSAtomicIncrement(X)    __sync_add_and_fetch(X, 1)
 #define GSAtomicDecrement(X)    __sync_sub_and_fetch(X, 1)
-
+#define GS_ARC_COMPATIBLE 1
 
 #elif  defined(_WIN32)
 
@@ -203,7 +209,7 @@
  */
 
 typedef int32_t volatile *gsatomic_t;
-
+typedef int32_t gsrefcount_t;
 #ifndef _WIN64
 #undef InterlockedIncrement
 #undef InterlockedDecrement
@@ -221,6 +227,7 @@
  */
 
 typedef int32_t volatile *gsatomic_t;
+typedef int32_t gsrefcount_t;
 
 #define        GSATOMICREAD(X) (*(X))
 
@@ -254,6 +261,7 @@
 #elif defined(__PPC__) || defined(__POWERPC__)
 
 typedef int32_t volatile *gsatomic_t;
+typedef int32_t gsrefcount_t;
 
 #define        GSATOMICREAD(X) (*(X))
 
@@ -292,6 +300,7 @@
 #elif defined(__m68k__)
 
 typedef int32_t volatile *gsatomic_t;
+typedef int32_t gsrefcount_t;
 
 #define        GSATOMICREAD(X) (*(X))
 
@@ -316,6 +325,7 @@
 #elif defined(__mips__)
 
 typedef int32_t volatile *gsatomic_t;
+typedef int32_t gsrefcount_t;
 
 #define        GSATOMICREAD(X) (*(X))
 
@@ -356,8 +366,7 @@
 
 #if    !defined(GSATOMICREAD)
 
-/*
- * Having just one allocationLock for all leads to lock contention
+/* Having just one allocationLock for all leads to lock contention
  * if there are lots of threads doing lots of retain/release calls.
  * To alleviate this, instead of a single
  * allocationLock for all objects, we divide the object space into
@@ -382,6 +391,17 @@
 
 #endif
 
+#ifndef GS_ARC_COMPATIBLE
+/*
+ * If we haven't previously declared that we can work in fast-ARC mode,
+ * check whether a point is 32bit (4 bytes) wide, which also enables ARC
+ * integration.
+ */
+#  if __SIZEOF_POINTER__ == 4
+#    define GS_ARC_COMPATIBLE 1
+#  endif
+#endif
+
 #if defined(__GNUC__) && __GNUC__ < 4
 #define __builtin_offsetof(s, f) (uintptr_t)(&(((s*)0)->f))
 #endif
@@ -392,7 +412,7 @@
  *     (before the start) in each object.
  */
 typedef struct obj_layout_unpadded {
-  uintptr_t    retained;
+  gsrefcount_t retained;
 } unp;
 #define        UNP sizeof(unp)
 
@@ -412,7 +432,7 @@
 struct obj_layout {
   char padding[__BIGGEST_ALIGNMENT__ - ((UNP % __BIGGEST_ALIGNMENT__)
     ? (UNP % __BIGGEST_ALIGNMENT__) : __BIGGEST_ALIGNMENT__)];
-  uintptr_t    retained;
+  gsrefcount_t retained;
 };
 typedef        struct obj_layout *obj;
 
@@ -423,7 +443,7 @@
  * (and hence whether the extra reference count was decremented).<br />
  * This function is used by the [NSObject-release] method.
  */
-BOOL
+inline BOOL
 NSDecrementExtraRefCountWasZero(id anObject)
 {
   if (double_release_check_enabled)
@@ -435,58 +455,45 @@
         [NSException raise: NSGenericException
                    format: @"Release would release object too many times."];
     }
-  if (allocationLock != 0)
-    {
+  {
 #if    defined(GSATOMICREAD)
-      int32_t  result;
-
-      result = GSAtomicDecrement((gsatomic_t)&(((obj)anObject)[-1].retained));
-      if (result < 0)
-       {
-         if (result != -1)
-           {
-             [NSException raise: NSInternalInconsistencyException
-               format: @"NSDecrementExtraRefCount() decremented too far"];
-           }
-         /* The counter has become negative so it must have been zero.
-          * We reset it and return YES ... in a correctly operating
-          * process we know we can safely reset back to zero without
-          * worrying about atomicity, since there can be no other
-          * thread accessing the object (or its reference count would
-          * have been greater than zero)
-          */
-         (((obj)anObject)[-1].retained) = 0;
-         return YES;
-       }
+    gsrefcount_t       result;
+
+    result = GSAtomicDecrement((gsatomic_t)&(((obj)anObject)[-1].retained));
+    if (result < 0)
+      {
+        if (result != -1)
+          {
+            [NSException raise: NSInternalInconsistencyException
+              format: @"NSDecrementExtraRefCount() decremented too far"];
+          }
+        /* The counter has become negative so it must have been zero.
+         * We reset it and return YES ... in a correctly operating
+         * process we know we can safely reset back to zero without
+         * worrying about atomicity, since there can be no other
+         * thread accessing the object (or its reference count would
+         * have been greater than zero)
+         */
+        (((obj)anObject)[-1].retained) = 0;
+        return YES;
+      }
 #else  /* GSATOMICREAD */
-      NSLock *theLock = GSAllocationLockForObject(anObject);
-
-      [theLock lock];
-      if (((obj)anObject)[-1].retained == 0)
-       {
-         [theLock unlock];
-         return YES;
-       }
-      else
-       {
-         ((obj)anObject)[-1].retained--;
-         [theLock unlock];
-         return NO;
-       }
+    NSLock *theLock = GSAllocationLockForObject(anObject);
+
+    [theLock lock];
+    if (((obj)anObject)[-1].retained == 0)
+      {
+        [theLock unlock];
+        return YES;
+      }
+    else
+      {
+        ((obj)anObject)[-1].retained--;
+        [theLock unlock];
+        return NO;
+      }
 #endif /* GSATOMICREAD */
-    }
-  else
-    {
-      if (((obj)anObject)[-1].retained == 0)
-       {
-         return YES;
-       }
-      else
-       {
-         ((obj)anObject)[-1].retained--;
-         return NO;
-       }
-    }
+  }
   return NO;
 }
 
@@ -510,42 +517,30 @@
 inline void
 NSIncrementExtraRefCount(id anObject)
 {
-  if (allocationLock != 0)
-    {
 #if    defined(GSATOMICREAD)
-      /* I've seen comments saying that some platforms only support up to
-       * 24 bits in atomic locking, so raise an exception if we try to
-       * go beyond 0xfffffe.
-       */
-      if (GSAtomicIncrement((gsatomic_t)&(((obj)anObject)[-1].retained))
-        > 0xfffffe)
-       {
-         [NSException raise: NSInternalInconsistencyException
-           format: @"NSIncrementExtraRefCount() asked to increment too far"];
-       }
+  /* I've seen comments saying that some platforms only support up to
+   * 24 bits in atomic locking, so raise an exception if we try to
+   * go beyond 0xfffffe.
+   */
+  if (GSAtomicIncrement((gsatomic_t)&(((obj)anObject)[-1].retained))
+    > 0xfffffe)
+    {
+      [NSException raise: NSInternalInconsistencyException
+        format: @"NSIncrementExtraRefCount() asked to increment too far"];
+    }
 #else  /* GSATOMICREAD */
-      NSLock *theLock = GSAllocationLockForObject(anObject);
-
-      [theLock lock];
-      if (((obj)anObject)[-1].retained > 0xfffffe)
-       {
-         [theLock unlock];
-         [NSException raise: NSInternalInconsistencyException
-           format: @"NSIncrementExtraRefCount() asked to increment too far"];
-       }
-      ((obj)anObject)[-1].retained++;
+  NSLock *theLock = GSAllocationLockForObject(anObject);
+
+  [theLock lock];
+  if (((obj)anObject)[-1].retained > 0xfffffe)
+    {
       [theLock unlock];
+      [NSException raise: NSInternalInconsistencyException
+        format: @"NSIncrementExtraRefCount() asked to increment too far"];
+    }
+  ((obj)anObject)[-1].retained++;
+  [theLock unlock];
 #endif /* GSATOMICREAD */
-    }
-  else
-    {
-      if (((obj)anObject)[-1].retained > 0xfffffe)
-       {
-         [NSException raise: NSInternalInconsistencyException
-           format: @"NSIncrementExtraRefCount() asked to increment too far"];
-       }
-      ((obj)anObject)[-1].retained++;
-    }
 }
 
 #ifndef        NDEBUG
@@ -597,6 +592,8 @@
  *     the start of each object.
  */
 
+// FIXME rewrite object allocation to use class_createInstance when we
+// are using libobjc2.
 inline id
 NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
 {
@@ -735,23 +732,9 @@
  * </p>
  */
 @implementation NSObject
+#if  defined(GS_ARC_COMPATIBLE)
 - (void)_ARCCompliantRetainRelease {}
-
-+ (void) _becomeMultiThreaded: (NSNotification *)aNotification
-{
-  if (allocationLock == 0)
-    {
-#if !defined(GSATOMICREAD)
-      NSUInteger       i;
-
-      for (i = 0; i < LOCKCOUNT; i++)
-        {
-         allocationLocks[i] = [NSLock new];
-       }
-#endif
-      allocationLock = [NSLock new];
-    }
-}
+#endif
 
 /**
  * Semi-private function in libobjc2 that initialises the classes used for
@@ -849,6 +832,21 @@
 #  endif
 #endif
 
+      /* Create the lock for NSZombie and for allocation when atomic
+       * operations are not available.
+       */
+      allocationLock = [NSLock new];
+#if !defined(GSATOMICREAD)
+      {
+        NSUInteger     i;
+
+        for (i = 0; i < LOCKCOUNT; i++)
+          {
+            allocationLocks[i] = [NSLock new];
+          }
+      }
+#endif
+
       /* Create the global lock.
        * NB. Ths is one of the first things we do ... setting up a new lock
        * must not call any other Objective-C classes and must not involve
@@ -897,15 +895,6 @@
        * object, and that class hasn't been initialized yet ...
        */
       zombieClass = objc_lookUpClass("NSZombie");
-
-      /* Now that we have a working autorelease system and working string
-       * classes we are able to set up notifications.
-       */
-      [[NSNotificationCenter defaultCenter]
-       addObserver: self
-          selector: @selector(_becomeMultiThreaded:)
-              name: NSWillBecomeMultiThreadedNotification
-            object: nil];
     }
   return;
 }


_______________________________________________
Gnustep-cvs mailing list
Gnustep-cvs@gna.org
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to