Author: thebeing
Date: Wed Jul 27 09:02:42 2016
New Revision: 40038

URL: http://svn.gna.org/viewcvs/gnustep?rev=40038&view=rev
Log:
Avoid reallocating objects post-hoc based on the initializer used.

Modified:
    libs/base/trunk/ChangeLog
    libs/base/trunk/Headers/Foundation/NSData.h
    libs/base/trunk/Source/NSData.m

Modified: libs/base/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/ChangeLog?rev=40038&r1=40037&r2=40038&view=diff
==============================================================================
--- libs/base/trunk/ChangeLog   (original)
+++ libs/base/trunk/ChangeLog   Wed Jul 27 09:02:42 2016
@@ -1,3 +1,12 @@
+2016-07-27  Niels Grewe <[email protected]>
+
+       * Header/Foundation/NSData.h
+       * Source/NSData.m:
+       Make the deallocator block a direct ivar of NSDataMalloc
+       (or NSMutableDataMalloc respectively). Breaks binary 
+       compatibility but avoids reallocating objects based on 
+       the initializer used.
+
 2016-07-26  Niels Grewe <[email protected]>
 
        * Source/NSDictionary.m

Modified: libs/base/trunk/Headers/Foundation/NSData.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Headers/Foundation/NSData.h?rev=40038&r1=40037&r2=40038&view=diff
==============================================================================
--- libs/base/trunk/Headers/Foundation/NSData.h (original)
+++ libs/base/trunk/Headers/Foundation/NSData.h Wed Jul 27 09:02:42 2016
@@ -102,11 +102,12 @@
  * <override-subclass/>
  * Initialize the receiver to hold memory pointed to by bytes without copying.
  * When the receiver is deallocated, the memory will be freed using the user
- * supplied deallocator block.
+ * supplied deallocBlock. Note that passing a block that (either directly or
+ * indirectly) holds a strong reference the receiver will cause a retain 
cycle. 
  */
 - (instancetype) initWithBytesNoCopy: (void*)bytes
                               length: (NSUInteger)length
-                         deallocator: (GSDataDeallocatorBlock)deallocator;
+                         deallocator: (GSDataDeallocatorBlock)deallocBlock;
 #endif
 - (id) initWithBytes: (const void*)aBuffer
              length: (NSUInteger)bufferSize;

Modified: libs/base/trunk/Source/NSData.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSData.m?rev=40038&r1=40037&r2=40038&view=diff
==============================================================================
--- libs/base/trunk/Source/NSData.m     (original)
+++ libs/base/trunk/Source/NSData.m     Wed Jul 27 09:02:42 2016
@@ -385,6 +385,7 @@
 {
   NSUInteger   length;
   __strong void        *bytes;
+  GSDataDeallocatorBlock deallocator;
 }
 @end
 
@@ -395,16 +396,13 @@
 @end
 
 @interface NSDataWithDeallocatorBlock : NSDataMalloc
-{
-  @private
-  GSDataDeallocatorBlock _deallocator;
-}
 @end
 
 @interface     NSMutableDataMalloc : NSMutableData
 {
   NSUInteger   length;
   __strong void        *bytes;
+  GSDataDeallocatorBlock deallocator;
   NSZone       *zone;
   NSUInteger   capacity;
   NSUInteger   growth;
@@ -414,10 +412,6 @@
 @end
 
 @interface NSMutableDataWithDeallocatorBlock : NSMutableDataMalloc
-{
-  @private
-  GSDataDeallocatorBlock _deallocator;
-}
 @end
 
 #ifdef HAVE_MMAP
@@ -3330,7 +3324,7 @@
 
 - (instancetype) initWithBytesNoCopy: (void*)buf
                               length: (NSUInteger)len
-                         deallocator: (GSDataDeallocatorBlock)deallocator
+                         deallocator: (GSDataDeallocatorBlock)deallocBlock
 {
   if (buf == NULL && len > 0)
     {
@@ -3339,7 +3333,7 @@
         format: @"[%@-initWithBytesNoCopy:length:deallocator:] called with "
           @"length but NULL bytes", NSStringFromClass([self class])];
     }
-  else if (NULL == deallocator)
+  else if (NULL == deallocBlock)
     {
       // For a nil deallocator we can just swizzle into a static data object
       GSClassSwizzle(self, dataStatic);
@@ -3348,15 +3342,9 @@
       return self;
     }
 
-  /* This is a bit unfortunate: Our implementation has no space to hold the
-   * deallocator block ivar in NSDataMalloc, so if we are invoked via this
-   * initialiser, we have to undo the previous allocation and reallocate
-   * ourselves as NSDataWithDeallocatorBlock.
-   */
-  [self release];
-  return [[dataBlock alloc] initWithBytesNoCopy: buf
-                                         length: len
-                                    deallocator: deallocator];
+  GSClassSwizzle(self, dataBlock);
+  ASSIGN(deallocator, deallocBlock);
+  return self;
 }
 
 - (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
@@ -3375,7 +3363,7 @@
 @implementation NSDataWithDeallocatorBlock
 - (instancetype) initWithBytesNoCopy: (void*)buf
                               length: (NSUInteger)len
-                         deallocator: (GSDataDeallocatorBlock)deallocator
+                         deallocator: (GSDataDeallocatorBlock)deallocBlock
 {
   if (buf == NULL && len > 0)
     {
@@ -3387,16 +3375,16 @@
 
   bytes = buf;
   length = len;
-  ASSIGN(_deallocator, deallocator);
+  ASSIGN(deallocator, deallocBlock);
   return self;
 }
 
 - (void) dealloc
 {
-  if (_deallocator != NULL)
-    {
-      CALL_BLOCK(_deallocator, bytes, length);
-      DESTROY(_deallocator);
+  if (deallocator != NULL)
+    {
+      CALL_BLOCK(deallocator, bytes, length);
+      DESTROY(deallocator);
     }
   // Clear out the ivars so that super doesn't double free.
   bytes = NULL;
@@ -3703,7 +3691,7 @@
 
 - (instancetype) initWithBytesNoCopy: (void*)buf
                               length: (NSUInteger)len
-                         deallocator: (GSDataDeallocatorBlock)deallocator
+                         deallocator: (GSDataDeallocatorBlock)deallocBlock;
 {
   if (buf == NULL && len > 0)
     {
@@ -3712,7 +3700,7 @@
         format: @"[%@-initWithBytesNoCopy:length:deallocator:] called with "
           @"length but NULL bytes", NSStringFromClass([self class])];
     }
-  else if (NULL == deallocator)
+  else if (NULL == deallocBlock)
     {
       // Can reuse this class.
       return [self initWithBytesNoCopy: buf
@@ -3721,13 +3709,17 @@
     }
 
   /*
-   * Custom deallocator. Need to re-allocate as an instance of
-   * NSMutableDataWithDeallocatorBlock
+   * Custom deallocator. swizzle to NSMutableDataWithDeallocatorBlock
    */
-  [self release];
-  return [[mutableDataBlock alloc] initWithBytesNoCopy: buf
-                                                length: len
-                                           deallocator: deallocator];
+  GSClassSwizzle(self, mutableDataBlock);
+  if (nil == (self = [self initWithBytesNoCopy: buf
+                                         length: len
+                                   freeWhenDone: NO]))
+    {
+      return nil;
+    }
+  ASSIGN(deallocator, deallocBlock);
+  return self;
 }
 
 // THIS IS THE DESIGNATED INITIALISER
@@ -4238,7 +4230,7 @@
 
 - (instancetype) initWithBytesNoCopy: (void*)buf
                               length: (NSUInteger)len
-                         deallocator: (GSDataDeallocatorBlock)deallocator
+                         deallocator: (GSDataDeallocatorBlock)deallocBlock
 {
   if (buf == NULL && len > 0)
     {
@@ -4258,19 +4250,19 @@
     {
       return nil;
     }
-  ASSIGN(_deallocator, deallocator);
+  ASSIGN(deallocator, deallocBlock);
   return self;
 }
 
 - (void) dealloc
 {
-  if (_deallocator != NULL)
-    {
-      CALL_BLOCK(_deallocator, bytes, capacity);
+  if (deallocator != NULL)
+    {
+      CALL_BLOCK(deallocator, bytes, capacity);
       // Clear out the ivars so that super doesn't double free.
       bytes = NULL;
       length = 0;
-      DESTROY(_deallocator);
+      DESTROY(deallocator);
     }
 
   [super dealloc];
@@ -4294,10 +4286,10 @@
       if (bytes)
        {
          memcpy(tmp, bytes, capacity < size ? capacity : size);
-         if (_deallocator != NULL)
-           {
-          CALL_BLOCK(_deallocator, bytes, capacity);
-          DESTROY(_deallocator);
+         if (deallocator != NULL)
+           {
+          CALL_BLOCK(deallocator, bytes, capacity);
+          DESTROY(deallocator);
              zone = NSDefaultMallocZone();
            }
          else
@@ -4305,10 +4297,10 @@
              NSZoneFree(zone, bytes);
            }
        }
-      else if (_deallocator != NULL)
-       {
-      CALL_BLOCK(_deallocator, bytes, capacity);
-      DESTROY(_deallocator);
+      else if (deallocator != NULL)
+       {
+      CALL_BLOCK(deallocator, bytes, capacity);
+      DESTROY(deallocator);
          zone = NSDefaultMallocZone();
        }
       bytes = tmp;


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to