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