mirror of
https://github.com/gnustep/libs-back.git
synced 2025-05-31 01:11:00 +00:00
Optimisation for reading large properties: avoid memory reallocation and copying data.
This commit is contained in:
parent
f6707b897a
commit
e66906ef38
1 changed files with 41 additions and 29 deletions
70
Tools/xpbs.m
70
Tools/xpbs.m
|
@ -958,12 +958,14 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
[self setOwnedByOpenStep: NO];
|
[self setOwnedByOpenStep: NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableData*) getSelectionData: (XSelectionEvent*)xEvent
|
- (long) getSelectionData: (XSelectionEvent*)xEvent
|
||||||
type: (Atom*)type
|
type: (Atom*)type
|
||||||
size: (long)max
|
size: (long)max
|
||||||
|
into: (NSMutableData*)md
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
long bytes_added = 0L;
|
||||||
long long_offset = 0L;
|
long long_offset = 0L;
|
||||||
long long_length = FULL_LENGTH;
|
long long_length = FULL_LENGTH;
|
||||||
Atom req_type = AnyPropertyType;
|
Atom req_type = AnyPropertyType;
|
||||||
|
@ -971,7 +973,7 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
int actual_format;
|
int actual_format;
|
||||||
unsigned long bytes_remaining;
|
unsigned long bytes_remaining;
|
||||||
unsigned long number_items;
|
unsigned long number_items;
|
||||||
NSMutableData *md = nil;
|
BOOL initial = YES;
|
||||||
|
|
||||||
if (max > long_length) long_length = max;
|
if (max > long_length) long_length = max;
|
||||||
/*
|
/*
|
||||||
|
@ -1016,12 +1018,20 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
count = number_items * actual_format / 8;
|
count = number_items * actual_format / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (md == nil)
|
if (initial)
|
||||||
{
|
{
|
||||||
|
NSUInteger capacity = [md capacity];
|
||||||
|
int space = capacity - [md length];
|
||||||
|
int need = count + bytes_remaining;
|
||||||
|
|
||||||
/* data buffer needs to be big enough for the whole property
|
/* data buffer needs to be big enough for the whole property
|
||||||
*/
|
*/
|
||||||
md = [[NSMutableData alloc]
|
initial = NO;
|
||||||
initWithCapacity: count + bytes_remaining];
|
if (space < need)
|
||||||
|
{
|
||||||
|
capacity += need - space;
|
||||||
|
[md setCapacity: capacity];
|
||||||
|
}
|
||||||
req_type = actual_type;
|
req_type = actual_type;
|
||||||
}
|
}
|
||||||
else if (req_type != actual_type)
|
else if (req_type != actual_type)
|
||||||
|
@ -1033,15 +1043,14 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
req_name, act_name);
|
req_name, act_name);
|
||||||
XFree(req_name);
|
XFree(req_name);
|
||||||
XFree(act_name);
|
XFree(act_name);
|
||||||
RELEASE(md);
|
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
XFree(data);
|
XFree(data);
|
||||||
}
|
}
|
||||||
return nil;
|
return 0;
|
||||||
}
|
}
|
||||||
[md appendBytes: (void *)data length: count];
|
[md appendBytes: (void *)data length: count];
|
||||||
|
bytes_added += count;
|
||||||
long_offset += count / 4;
|
long_offset += count / 4;
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
|
@ -1054,19 +1063,18 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
if (status == Success)
|
if (status == Success)
|
||||||
{
|
{
|
||||||
*type = actual_type;
|
*type = actual_type;
|
||||||
return AUTORELEASE(md);
|
return bytes_added;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RELEASE(md);
|
return 0;
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) xSelectionNotify: (XSelectionEvent*)xEvent
|
- (void) xSelectionNotify: (XSelectionEvent*)xEvent
|
||||||
{
|
{
|
||||||
Atom actual_type;
|
Atom actual_type;
|
||||||
NSMutableData *md = nil;
|
NSMutableData *md;
|
||||||
|
|
||||||
if (xEvent->property == (Atom)None)
|
if (xEvent->property == (Atom)None)
|
||||||
{
|
{
|
||||||
|
@ -1083,9 +1091,8 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
}
|
}
|
||||||
[self setWaitingForSelection: 0];
|
[self setWaitingForSelection: 0];
|
||||||
|
|
||||||
md = [self getSelectionData: xEvent type: &actual_type size: 0];
|
md = [NSMutableData dataWithCapacity: FULL_LENGTH];
|
||||||
|
if ([self getSelectionData: xEvent type: &actual_type size: 0 into: md] > 0)
|
||||||
if (md != nil)
|
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
||||||
|
@ -1102,6 +1109,15 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
NSDebugMLLog(@"INCR",
|
NSDebugMLLog(@"INCR",
|
||||||
@"Size for INCR chunks is %u bytes.", (unsigned)size);
|
@"Size for INCR chunks is %u bytes.", (unsigned)size);
|
||||||
[md setLength: 0];
|
[md setLength: 0];
|
||||||
|
|
||||||
|
/* We expect to read multiple chunks, so to avoid excessive
|
||||||
|
* reallocation of memory we grow the buffer to be big enough
|
||||||
|
* to hold ten of them.
|
||||||
|
*/
|
||||||
|
if (size * 10 > [md capacity])
|
||||||
|
{
|
||||||
|
[md setCapacity: size * 10];
|
||||||
|
}
|
||||||
while (wait)
|
while (wait)
|
||||||
{
|
{
|
||||||
XNextEvent(xDisplay, &event);
|
XNextEvent(xDisplay, &event);
|
||||||
|
@ -1109,34 +1125,30 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
if (event.type == PropertyNotify
|
if (event.type == PropertyNotify
|
||||||
&& event.xproperty.state == PropertyNewValue)
|
&& event.xproperty.state == PropertyNewValue)
|
||||||
{
|
{
|
||||||
ENTER_POOL
|
long length;
|
||||||
NSMutableData *imd;
|
|
||||||
|
|
||||||
imd = [self getSelectionData: xEvent
|
|
||||||
type: &actual_type
|
|
||||||
size: size];
|
|
||||||
/* Getting the property data also deletes the property,
|
/* Getting the property data also deletes the property,
|
||||||
* telling the other end to send the next chunk.
|
* telling the other end to send the next chunk.
|
||||||
* An empty chunk indicates end of transfer.
|
* An empty chunk indicates end of transfer.
|
||||||
*/
|
*/
|
||||||
if ([imd length] > 0)
|
if ((length = [self getSelectionData: xEvent
|
||||||
|
type: &actual_type
|
||||||
|
size: size
|
||||||
|
into: md]) > 0)
|
||||||
{
|
{
|
||||||
if (GSDebugSet(@"INCR"))
|
if (GSDebugSet(@"INCR"))
|
||||||
{
|
{
|
||||||
char *name = XGetAtomName(xDisplay, actual_type);
|
char *name = XGetAtomName(xDisplay, actual_type);
|
||||||
NSLog(@"Retrieved %lu bytes type '%s'"
|
NSLog(@"Retrieved %ld bytes type '%s'"
|
||||||
@" from X selection.",
|
@" from X selection.", length, name);
|
||||||
(unsigned long)[imd length], name);
|
|
||||||
XFree(name);
|
XFree(name);
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
[md appendData: imd];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wait = NO;
|
wait = NO;
|
||||||
}
|
}
|
||||||
LEAVE_POOL
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ([md length] == 0)
|
if ([md length] == 0)
|
||||||
|
@ -1164,7 +1176,7 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (md != nil)
|
if ([md length] > 0)
|
||||||
{
|
{
|
||||||
// Convert data to text string.
|
// Convert data to text string.
|
||||||
if (actual_type == XG_UTF8_STRING)
|
if (actual_type == XG_UTF8_STRING)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue