Added uniquing support for deserialized strings.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@4335 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-06-02 09:32:16 +00:00
parent e0e4bd85b2
commit a7ba6ae51d
3 changed files with 161 additions and 0 deletions

View file

@ -1,3 +1,8 @@
Tue Jun 2 10:50:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSSerializer.m: Added uniquing for deserialized strings.
* Source/include/NSSerialization.h: likewise.
Tue Jun 2 5:45:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/TcpPort.m: Fixed to compile cleanly under cygwin.

View file

@ -80,4 +80,29 @@
@end
#ifndef NO_GNUSTEP
/*
* GNUstep extends deserialization by having the option to make the
* resulting data more compact by ensuring that repeated strings
* are only stored once. If the property-list has a lot of repeated
* strings in it, this will be more space efficient but it will be
* slower (though other parts of your code may speed up through more
* efficient equality testing of uniqued strings).
* The default is NOT to deserialize uniqued strings.
*
* The [+uniquing:] method turns uniquing on/off. Turning off uniquing
* destroys the NSCountedSet used for uniquing.
* The [+purge] method lets you remove some of the objects from the
* NSCountedSet used for uniquing. The count of each string in the
* set is decreased, so that strings that have only been deserialized
* once are removed.
*/
@interface NSDeserializer (GNUstep)
+ (void) _becomeThreaded: (id)notification; /* private */
+ (void) purge;
+ (void) uniquing: (BOOL)flag;
@end
#endif
#endif /* __NSSerialization_h_GNUSTEP_BASE_INCLUDE */

View file

@ -30,6 +30,10 @@
#include <Foundation/NSString.h>
#include <Foundation/NSException.h>
#include <Foundation/NSProxy.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSSet.h>
#include <Foundation/NSThread.h>
#include <Foundation/NSNotificationQueue.h>
#include <base/NSGArray.h>
#include <base/NSGCString.h>
@ -343,6 +347,12 @@ static BOOL shouldBeCompact = NO;
/*
* Class variables for uniquing incoming strings.
*/
static NSRecursiveLock *uniqueLock = nil;
static NSCountedSet *uniqueSet = nil;
/*
* Variables to cache class information.
*/
@ -425,6 +435,31 @@ deserializeFromInfo(_NSDeserializerInfo* info)
(*info->debImp)(info->data, debSel, b, size, info->cursor);
s = (NSGCString*)NSAllocateObject(CSCls, 0, NSDefaultMallocZone());
s = (*csInitImp)(s, csInitSel, b, size-1, NSDefaultMallocZone());
/*
* If we are supposed to be doing uniquing of strings, handle it.
*/
if (uniqueSet != nil)
{
id uniqued;
if (uniqueLock != nil)
[uniqueLock lock];
[uniqueSet addObject: s];
uniqued = [uniqueSet member: s];
if (uniqueLock != nil)
[uniqueLock unlock];
if (uniqued != s)
{
RELEASE(s);
s = RETAIN(uniqued);
}
}
/*
* If uniquing was done on serialisation, store the string for
* later reference.
*/
if (info->didUnique)
FastArrayAddItem(&info->array, (FastArrayItem)s);
return s;
@ -438,6 +473,31 @@ deserializeFromInfo(_NSDeserializerInfo* info)
(*info->debImp)(info->data, debSel, b, size*2, info->cursor);
s = (NSGString*)NSAllocateObject(USCls, 0, NSDefaultMallocZone());
s = (*usInitImp)(s, usInitSel, b, size, NSDefaultMallocZone());
/*
* If we are supposed to be doing uniquing of strings, handle it.
*/
if (uniqueSet != nil)
{
id uniqued;
if (uniqueLock != nil)
[uniqueLock lock];
[uniqueSet addObject: s];
uniqued = [uniqueSet member: s];
if (uniqueLock != nil)
[uniqueLock unlock];
if (uniqued != s)
{
RELEASE(s);
s = RETAIN(uniqued);
}
}
/*
* If uniquing was done on serialisation, store the string for
* later reference.
*/
if (info->didUnique)
FastArrayAddItem(&info->array, (FastArrayItem)s);
return s;
@ -632,6 +692,18 @@ deserializeFromInfo(_NSDeserializerInfo* info)
maInitImp = [MACls instanceMethodForSelector: maInitSel];
idInitImp = [IDCls instanceMethodForSelector: idInitSel];
mdInitImp = [MDCls instanceMethodForSelector: mdInitSel];
if ([NSThread isMultiThreaded])
{
[self _becomeThreaded: nil];
}
else
{
[NSNotificationCenter
addObserver: self
selector: @selector(_becomeThreaded:)
name: NSWillBecomeMultiThreadedNotification
object: nil];
}
}
}
@ -693,3 +765,62 @@ deserializeFromInfo(_NSDeserializerInfo* info)
}
@end
@implementation NSDeserializer (GNUstep)
/*
* If we are multi-threaded, we must guard access to the uniquing set.
*/
+ (void) _becomeThreaded: (id)notification
{
uniqueLock = [NSRecursiveLock new];
}
/*
* Remove one copy of each object in the uniquing set, or remove all
* objects if the flag is YES.
*/
+ (void) purge
{
if (uniqueSet)
{
NSArray *all;
id obj;
unsigned i;
if (uniqueLock != nil)
[uniqueLock lock];
all = [uniqueSet allObjects];
for (i = [all count]; i > 0; i--)
{
[uniqueSet removeObject: [all objectAtIndex: i-1]];
}
if (uniqueLock != nil)
[uniqueLock unlock];
}
}
/*
* Turn uniquing of deserialized strings on/off
*/
+ (void) uniquing: (BOOL)flag
{
if (uniqueLock != nil)
[uniqueLock lock];
if (flag)
{
if (uniqueSet == nil)
{
uniqueSet = [NSCountedSet new];
}
}
else
{
if (uniqueSet != nil)
{
DESTROY(uniqueSet);
}
}
if (uniqueLock != nil)
[uniqueLock unlock];
}
@end