Created
February 14, 2013 06:35
-
-
Save mikelikespie/4950998 to your computer and use it in GitHub Desktop.
Zero-Copy bridging between dispatch_data_t and NSData
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSData+PIOAdditions.h | |
// PonyExpress | |
// | |
// Created by Michael Lewis on 2/13/13. | |
// | |
// | |
#import <Foundation/Foundation.h> | |
#import <dispatch/data.h> | |
@interface NSData (PIOAdditions) | |
+ (instancetype)dataWithDispatchData:(dispatch_data_t)data; | |
// returns a dispatch_data_t representation of this object. | |
// This does not copy the internal bytes | |
- (dispatch_data_t)copyDispatchData DISPATCH_RETURNS_RETAINED; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSData+PIOAdditions.m | |
// PonyExpress | |
// | |
// Created by Michael Lewis on 2/13/13. | |
// | |
// | |
#import "Common.h" | |
#import "NSData+PIOAdditions.h" | |
// A way to do copyless dispatch data if the dispatch_data_t has just one segment. | |
@interface _PIOMappedDispatchData : NSData | |
- (instancetype)initWithData:(dispatch_data_t)data; | |
@end | |
@implementation NSData (PIOAdditions) | |
+ (instancetype)dataWithDispatchData:(dispatch_data_t)data; | |
{ | |
return [[_PIOMappedDispatchData alloc] initWithData:data]; | |
} | |
- (dispatch_data_t)copyDispatchData; | |
{ | |
// just incase we are mutable; | |
CFDataRef immutableSelf = CFBridgingRetain([self copy]); | |
return dispatch_data_create(self.bytes, self.length, dispatch_get_main_queue(), ^{ | |
CFRelease(immutableSelf); | |
}); | |
} | |
@end | |
@implementation _PIOMappedDispatchData { | |
dispatch_data_t _data; | |
NSUInteger _length; | |
const void *_bytes; | |
} | |
- (instancetype)initWithData:(dispatch_data_t)data; | |
{ | |
const void *buffer; | |
size_t size = 0; | |
data = dispatch_data_create_map(data, &buffer, &size); | |
self = [super init]; | |
if (self != nil) { | |
_bytes = buffer; | |
_length = size; | |
_data = data; | |
} else { | |
sr_dispatch_release(data); | |
} | |
return self; | |
} | |
- (NSUInteger)length; | |
{ | |
return _length; | |
} | |
- (const void *)bytes; | |
{ | |
return _bytes; | |
} | |
- (dispatch_data_t)copyDispatchData; | |
{ | |
sr_dispatch_retain(_data); | |
return _data; | |
} | |
- (void)dealloc | |
{ | |
if (_data != NULL) { | |
sr_dispatch_release(_data); | |
} | |
} | |
- (id)copy; | |
{ | |
return [[_PIOMappedDispatchData alloc] initWithData:_data]; | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSDataTest.m | |
// PonyExpress | |
// | |
// Created by Michael Lewis on 2/13/13. | |
// | |
// | |
#import <SenTestingKit/SenTestingKit.h> | |
#import "NSData+PIOAdditions.h" | |
#import "Common.h" | |
@interface NSDataTest : SenTestCase | |
@end | |
@implementation NSDataTest | |
- (void)testEfficientForOneSegment; | |
{ | |
dispatch_data_t data = dispatch_data_create("hello", 5, dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_DEFAULT); | |
NSData *d1 = [NSData dataWithDispatchData:data]; | |
dispatch_data_t newData = [d1 copyDispatchData]; | |
STAssertEquals(newData, data, @"Should not have created a new data object since it was one segment"); | |
sr_dispatch_release(data); | |
sr_dispatch_release(newData); | |
} | |
- (void)testEfficientForDataCopy; | |
{ | |
NSData *data = [[NSData alloc] initWithBytes:"hello" length:5]; | |
dispatch_data_t newData = [data copyDispatchData]; | |
NSData *data2 = [NSData dataWithDispatchData:newData]; | |
STAssertEquals(data.bytes, data2.bytes, @"Should all ahve the same buffer"); | |
sr_dispatch_release(newData); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
dispatch_data_t
is already toll-free-bridged toNSData
, so is this code necessary at all? The two methods here don't seem to do anything you can't do with a simple C typecast.