Author: rfm
Date: Sat Apr 26 11:26:59 2014
New Revision: 37812
URL: http://svn.gna.org/viewcvs/gnustep?rev=37812&view=rev
Log:
add GSUniqued
Added:
libs/performance/trunk/GSUniqued.h
libs/performance/trunk/GSUniqued.m
Modified:
libs/performance/trunk/ChangeLog
libs/performance/trunk/GNUmakefile
libs/performance/trunk/Performance.h
Modified: libs/performance/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/ChangeLog?rev=37812&r1=37811&r2=37812&view=diff
==============================================================================
--- libs/performance/trunk/ChangeLog (original)
+++ libs/performance/trunk/ChangeLog Sat Apr 26 11:26:59 2014
@@ -1,3 +1,12 @@
+2014-04-26 Richard Frith-Macdonald <[email protected]>
+
+ * GSUniqued.h:
+ * GSUniqued.m:
+ * Performance.h:
+ * GNUmakefile:
+ New code to implement uniqued copies of objects for lowered memory
+ footprint and faster collection lookups.
+
2013-11-05 Niels Grewe <[email protected]>
* GSFIFO.m: Fix calculation of the timeout for cooperating
Modified: libs/performance/trunk/GNUmakefile
URL:
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GNUmakefile?rev=37812&r1=37811&r2=37812&view=diff
==============================================================================
--- libs/performance/trunk/GNUmakefile (original)
+++ libs/performance/trunk/GNUmakefile Sat Apr 26 11:26:59 2014
@@ -43,6 +43,7 @@
GSTicker.m \
GSIndexedSkipList.m \
GSSkipMutableArray.m \
+ GSUniqued.m \
Performance_HEADER_FILES += \
@@ -54,6 +55,7 @@
GSThroughput.h \
GSTicker.h \
GSSkipMutableArray.h \
+ GSUniqued.h \
Performance_AGSDOC_FILES += \
@@ -64,7 +66,8 @@
GSThreadPool.h \
GSThroughput.h \
GSTicker.h \
- GSSkipMutableArray.h
+ GSSkipMutableArray.h \
+ GSUniqued.h \
# Optional Java wrappers for the library
Added: libs/performance/trunk/GSUniqued.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GSUniqued.h?rev=37812&view=auto
==============================================================================
--- libs/performance/trunk/GSUniqued.h (added)
+++ libs/performance/trunk/GSUniqued.h Sat Apr 26 11:26:59 2014
@@ -0,0 +1,80 @@
+#if !defined(INCLUDED_GSUNIQUED)
+#define INCLUDED_GSUNIQUED 1
+/**
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ Written by: Richard Frith-Macdonald <[email protected]>
+ Date: April 2014
+
+ This file is part of the Performance Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+ */
+#import <Foundation/NSObject.h>
+
+/** Class used to unique other objects.<br />
+ * <p>The point of this class is to lower the memory footprint and speed
+ * up comparisons (pointer equality) in cases where an application
+ * stores multiple copies of the same object in various maps.<br />
+ * Since uniquing is performed by storing an immutable copy of the
+ * original object in a map until there are no further references
+ * to that object, it's pointless to use this uniquing unless the
+ * application would be storing at least two copies of the object.<br />
+ * Also, since this is thread-safe there is a lock management
+ * overhead wherever a uniqued object is released, so performance
+ * gains are to be expected only if the uniqued object has a
+ * relatively long lifetime and is tested for equality with other
+ * instances frequently.<br />
+ * In short, use with care; while uniquing can have a big performance
+ * advantage for some programs, this is actually quite rare.
+ * </p>
+ * <p>The internal implementation of the uniquing works by taking
+ * immutable copies of the objects to be uniqued, storing those copies
+ * in a hash table, and swizzling their class pointers to a sub-class
+ * which will automatically remove the instance from the hash table
+ * before it is deallocated.<br />
+ * Access to the hash table is protected by locks so that uniqued
+ * objects may be used freely in multiple threads.<br />
+ * The name of the subclass used is the name of the original class
+ * with 'GSUniqued' added as a prefix.
+ * </p>
+ */
+@interface GSUniqued : NSObject
+
+/** This method returns a copy of its argument, uniqued so that other
+ * such copies of equal objects will be the same instance.<br />
+ * The argument must respond to -copyWithZone: by returning an instance
+ * of class of immutable objects (ie where the -hash and -isEqual:
+ * methods are stable for that instance).
+ */
++ (id) copyUniqued: (id<NSObject,NSCopying>)anObject;
+
+@end
+
+/** Category for uniquing any copyable object.<br />
+ * NB. This must only be used by classes for which -copyWithZone:
+ * produces an instance of an immutable class.
+ */
+@interface NSObject (GSUniqued)
+
+/** This method returns a copy of the receiver uniqued so that other
+ * such copies of equal objects content will be the same instance.
+ */
+- (id) copyUniqued;
+
+@end
+
+#endif
+
Added: libs/performance/trunk/GSUniqued.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GSUniqued.m?rev=37812&view=auto
==============================================================================
--- libs/performance/trunk/GSUniqued.m (added)
+++ libs/performance/trunk/GSUniqued.m Sat Apr 26 11:26:59 2014
@@ -0,0 +1,176 @@
+/**
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ Written by: Richard Frith-Macdonald <[email protected]>
+ Date: April 2014
+
+ This file is part of the Performance Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+ */
+
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSException.h>
+#import <Foundation/NSHashTable.h>
+#import <Foundation/NSLock.h>
+#import <Foundation/NSObjCRuntime.h>
+#import <Foundation/NSSet.h>
+#import <GNUstepBase/GSObjCRuntime.h>
+#import "GSUniqued.h"
+
+
+static Class GSUniquedClass = Nil;
+static NSLock *uniquedObjectsLock;
+static IMP iLock;
+static IMP iUnlock;
+static NSHashTable *uniquedObjects;
+static NSLock *classLock;
+static NSMutableDictionary *classMap;
+
+/* Deallocate a uniqued object ... we must remove it from the uniqued
+ * objects table and then call the real -dealloc method.
+ */
+static void
+uDealloc(id self, SEL _cmd)
+{
+ Class c;
+ IMP i;
+
+ NSHashRemove(uniquedObjects, self);
+ c = object_getClass(self);
+ c = class_getSuperclass(c);
+ i = class_getMethodImplementation(c, _cmd);
+ (*i)(self, _cmd);
+}
+
+/* Release a uniqued object ... we must obtain a lock in case the uniqued
+ * objects table has to be modified by removal of this instance on
+ * deallocation.
+ */
+static void
+uRelease(id self, SEL _cmd)
+{
+ Class c;
+ IMP i;
+
+ c = object_getClass(self);
+ c = class_getSuperclass(c);
+ i = class_getMethodImplementation(c, _cmd);
+ (*iLock)(uniquedObjectsLock, @selector(lock));
+ (*i)(self, _cmd);
+ (*iUnlock)(uniquedObjectsLock, @selector(unlock));
+}
+
+@implementation GSUniqued
+
++ (void) initialize
+{
+ if (Nil == GSUniquedClass)
+ {
+ classLock = [NSLock new];
+ classMap = [NSMutableDictionary new];
+ uniquedObjectsLock = [NSLock new];
+ iLock = [uniquedObjectsLock methodForSelector: @selector(lock)];
+ iUnlock = [uniquedObjectsLock methodForSelector: @selector(unlock)];
+ uniquedObjects = NSCreateHashTable(
+ NSNonRetainedObjectHashCallBacks, 10000);
+ GSUniquedClass = [GSUniqued class];
+ }
+}
+
++ (id) allocWithZone: (NSZone*)z
+{
+ [NSException raise: NSInvalidArgumentException
+ format: @"Attempt to allocate instance of GSUniqued"];
+ return nil;
+}
+
++ (id) copyUniqued: (id<NSObject,NSCopying>)anObject
+{
+ NSObject *found;
+
+ NSAssert(nil != anObject, NSInvalidArgumentException);
+ (*iLock)(uniquedObjectsLock, @selector(lock));
+ found = [(NSObject*)NSHashGet(uniquedObjects, anObject) retain];
+ (*iUnlock)(uniquedObjectsLock, @selector(unlock));
+
+ if (nil == found)
+ {
+ NSObject *aCopy;
+ Class c;
+ Class u;
+
+ aCopy = [anObject copyWithZone: NSDefaultMallocZone()];
+ c = object_getClass(aCopy);
+
+ [classLock lock];
+ u = [classMap objectForKey: c];
+ if (Nil == u)
+ {
+ const char *cn = class_getName(c);
+ char name[strlen(cn) + 20];
+ Method method;
+
+ sprintf(name, "GSUniqued%s", cn);
+ u = objc_allocateClassPair(c, name, 0);
+
+ method = class_getInstanceMethod([NSObject class],
+ @selector(dealloc));
+ class_addMethod(u, @selector(dealloc),
+ (IMP)uDealloc, method_getTypeEncoding(method));
+
+ method = class_getInstanceMethod([NSObject class],
+ @selector(release));
+ class_addMethod(u, @selector(release),
+ (IMP)uRelease, method_getTypeEncoding(method));
+
+ objc_registerClassPair(u);
+ [classMap setObject: u forKey: c];
+ }
+ [classLock unlock];
+
+ (*iLock)(uniquedObjectsLock, @selector(lock));
+ found = [(NSObject*)NSHashGet(uniquedObjects, anObject) retain];
+ if (nil == found)
+ {
+ found = aCopy;
+#if defined(GNUSTEP)
+ GSClassSwizzle(found, u);
+#else
+ object_setClass(found, u);
+#endif
+ NSHashInsert(uniquedObjects, found);
+ }
+ else
+ {
+ [aCopy release]; // Already uniqued by another thread
+ }
+ (*iUnlock)(uniquedObjectsLock, @selector(unlock));
+ }
+ return found;
+}
+
+@end
+
+@implementation NSObject (GSUniqued)
+
+- (id) copyUniqued
+{
+ if (Nil == GSUniquedClass) [GSUniqued class];
+ return [GSUniquedClass copyUniqued: (id<NSObject,NSCopying>)self];
+}
+
+@end
+
Modified: libs/performance/trunk/Performance.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/Performance.h?rev=37812&r1=37811&r2=37812&view=diff
==============================================================================
--- libs/performance/trunk/Performance.h (original)
+++ libs/performance/trunk/Performance.h Sat Apr 26 11:26:59 2014
@@ -32,4 +32,5 @@
#import "GSThroughput.h"
#import "GSTicker.h"
#import "GSSkipMutableArray.h"
+#import "GSUniqued.h"
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs