Commits

Tuukka Norri committed 64cf999

Fixed memory-related issues
- Wrote an NSNotification subclass that doesn't retain its object. It is needed for sending a certain notification on object deallocation.
- Fixed various bugs in BXEntityDescription. Properties were compared in global containers even after their entities had been deallocated.
- Couldn't come up with any reason why relationships should be in a weak container, so changed it to an NSMutableDictionary.

Comments (0)

Files changed (4)

BaseTen.xcodeproj/project.pbxproj

 		5395E7270E2F77DF006E8441 /* BXPGEntityImporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5395E7250E2F77DF006E8441 /* BXPGEntityImporter.m */; };
 		539758520E1E86200042120A /* BXDataModelCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 539758500E1E86200042120A /* BXDataModelCompiler.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		539758530E1E86200042120A /* BXDataModelCompiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 539758510E1E86200042120A /* BXDataModelCompiler.m */; };
+		53A59B250E34EB570026D7E1 /* BXWeakNotification.h in Headers */ = {isa = PBXBuildFile; fileRef = 53A59B230E34EB570026D7E1 /* BXWeakNotification.h */; };
+		53A59B260E34EB570026D7E1 /* BXWeakNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 53A59B240E34EB570026D7E1 /* BXWeakNotification.m */; };
 		53B24CF40E223A14007AED76 /* BXPGDatabaseDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 53B24CF20E223A14007AED76 /* BXPGDatabaseDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		53B24CF50E223A14007AED76 /* BXPGDatabaseDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 53B24CF30E223A14007AED76 /* BXPGDatabaseDescription.m */; };
 		53B24CFA0E223C8C007AED76 /* BXPGTableDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 53B24CF80E223C8C007AED76 /* BXPGTableDescription.h */; };
 		539EDD740C46218B00B6E5EC /* BXAttributeDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXAttributeDescription.m; path = Sources/BXAttributeDescription.m; sourceTree = "<group>"; };
 		539EDD800C46243100B6E5EC /* BXAttributeDescriptionPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXAttributeDescriptionPrivate.h; path = Sources/BXAttributeDescriptionPrivate.h; sourceTree = "<group>"; };
 		539EE9F10B4A7E85005DDDA5 /* BXEntityDescriptionPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BXEntityDescriptionPrivate.h; path = Sources/BXEntityDescriptionPrivate.h; sourceTree = "<group>"; };
+		53A59B230E34EB570026D7E1 /* BXWeakNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BXWeakNotification.h; sourceTree = "<group>"; };
+		53A59B240E34EB570026D7E1 /* BXWeakNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BXWeakNotification.m; sourceTree = "<group>"; };
 		53A75FEE0B032ECF0032A99C /* BXDatabaseContextPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BXDatabaseContextPrivate.h; path = Sources/BXDatabaseContextPrivate.h; sourceTree = "<group>"; };
 		53AE2C990B1721A4000E6EF1 /* BaseTen.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = BaseTen.icns; sourceTree = "<group>"; };
 		53B24CF20E223A14007AED76 /* BXPGDatabaseDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXPGDatabaseDescription.h; path = Sources/BXPGDatabaseDescription.h; sourceTree = "<group>"; };
 				53666CC20E1CD8D20028DBEA /* PGTSHOM.h */,
 				53666CC30E1CD8D20028DBEA /* PGTSHOM.m */,
 				53666CD20E1CD8D20028DBEA /* PGTSScannedMemoryAllocator.h */,
+				53A59B230E34EB570026D7E1 /* BXWeakNotification.h */,
+				53A59B240E34EB570026D7E1 /* BXWeakNotification.m */,
 			);
 			name = Utility;
 			sourceTree = "<group>";
 		53666D2E0E1CDDA70028DBEA /* Metadata */ = {
 			isa = PBXGroup;
 			children = (
-				53666C990E1CD8D20028DBEA /* PGTSTypeDescription.m */,
 				53666C9C0E1CD8D20028DBEA /* PGTSAbstractClassDescription.h */,
 				53666C9D0E1CD8D20028DBEA /* PGTSAbstractClassDescription.m */,
 				53666C9E0E1CD8D20028DBEA /* PGTSAbstractDescription.h */,
 				53666CD50E1CD8D20028DBEA /* PGTSTableDescription.h */,
 				53666CD60E1CD8D20028DBEA /* PGTSTableDescription.m */,
 				53666CD70E1CD8D20028DBEA /* PGTSTypeDescription.h */,
+				53666C990E1CD8D20028DBEA /* PGTSTypeDescription.m */,
 			);
 			name = Metadata;
 			sourceTree = "<group>";
 				53877EEB0E2773E30097C35F /* NSRelationshipDescription+BXPGAdditions.h in Headers */,
 				53D9DDED0E2B4F310009D370 /* BXPGEntityConverter.h in Headers */,
 				5395E7260E2F77DF006E8441 /* BXPGEntityImporter.h in Headers */,
+				53A59B250E34EB570026D7E1 /* BXWeakNotification.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				53877EEC0E2773E30097C35F /* NSRelationshipDescription+BXPGAdditions.m in Sources */,
 				53D9DDEC0E2B4F300009D370 /* BXPGEntityConverter.m in Sources */,
 				5395E7270E2F77DF006E8441 /* BXPGEntityImporter.m in Sources */,
+				53A59B260E34EB570026D7E1 /* BXWeakNotification.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Sources/BXEntityDescription.m

 #import "BXConstantsPrivate.h"
 #import "BXLogger.h"
 #import "PGTSHOM.h"
+#import "BXWeakNotification.h"
 
 #import "MKCCollections.h"
 
 	{
 		[gEntities removeObjectForKey: [self entityKey]];
 	}
+	
+	@synchronized (mAttributes)
+	{
+		TSEnumerate (currentAttribute, e, [mAttributes objectEnumerator])
+		{
+			[currentAttribute setEntity: nil];
+			[[currentAttribute class] unregisterProperty: currentAttribute entity: self];
+		}
+	}
     
     @synchronized (mRelationships)
     {
         {
             [currentRel setEntity: nil];
             [[currentRel inverseRelationship] setDestinationEntity: nil];
+			[[currentRel class] unregisterProperty: currentRel entity: self];
         }
     }
     
     NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
-    [nc postNotificationName: kBXEntityDescriptionWillDeallocNotification
-                      object: self];
+	NSNotification* n = [BXWeakNotification notificationWithName: 
+						 kBXEntityDescriptionWillDeallocNotification object: self];
+	[nc postNotification: n];
     
 	[self dealloc2];
 	[super dealloc];
 {
 	if (! [self hasCapability: kBXEntityCapabilityRelationships])
 		[NSException raise: NSInvalidArgumentException format: @"Entity %@ can't access its relationships.", self];
-	return [mRelationships dictionaryRepresentation];
+	return [[mRelationships copy] autorelease];
 }
 
 - (BOOL) hasCapability: (enum BXEntityCapability) aCapability
         mDatabaseObjectClass = [BXDatabaseObject class];
         mDatabaseURI = [anURI copy];
         mSchemaName = [sName copy];
-		mRelationships = [MKCDictionary copyDictionaryWithKeyType: kMKCCollectionTypeObject
-														valueType: kMKCCollectionTypeWeakObject];
+		mRelationships = [[NSMutableDictionary alloc] init];
+		
 		mObjectIDs = [[MKCHashTable alloc] init];
         mSuperEntities = [[MKCHashTable alloc] init];
         mSubEntities = [[MKCHashTable alloc] init];
+		
 		mValidationLock = [[NSLock alloc] init];
     }
     return self;
 			[[currentRel class] unregisterProperty: currentRel entity: self];
 
 		[mRelationships removeAllObjects];
-		
-		//mRelationships is a map table.
-		TSEnumerate (currentRelName, e, [aDict keyEnumerator])
-			[mRelationships setObject: [aDict objectForKey: currentRelName] forKey: currentRelName];
+		[mRelationships addEntriesFromDictionary: aDict];
     }
 }
 

Sources/BXWeakNotification.h

+//
+// BXWeakNotification.h
+// BaseTen
+//
+// Copyright (C) 2006-2008 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://basetenframework.org/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface BXWeakNotification : NSNotification
+{
+	id mName;
+	id mObject; //Weak
+	id mUserInfo;
+}
++ (id) notificationWithName: (NSString *) aName object: (id) anObject;
+@end

Sources/BXWeakNotification.m

+//
+// BXWeakNotification.m
+// BaseTen
+//
+// Copyright (C) 2006-2008 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://basetenframework.org/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import "BXWeakNotification.h"
+
+
+@implementation BXWeakNotification
+- (id) init
+{
+	//Don't call super's implementation, see NSNotification's documentation on subclassing.
+	return self;
+}
+
+- (void) setObject: (id) anObject
+{
+	mObject = anObject;
+}
+
+- (void) setName: (NSString *) aName
+{
+	if (mName != aName)
+	{
+		[mName release];
+		mName = [aName retain];
+	}
+}
+
+- (NSString *) name
+{
+	return mName;
+}
+
+- (NSDictionary *) userInfo
+{
+	return mUserInfo;
+}
+
+- (id) object
+{
+	return mObject;
+}
+
+- (void) dealloc
+{
+	[mName release];
+	[mUserInfo release];
+	[super dealloc];
+}
+
++ (id) notificationWithName: (NSString *) aName object: (id) anObject
+{
+	id retval = [[[self alloc] init] autorelease];
+	[retval setName: aName];
+	[retval setObject: anObject];
+	return retval;
+}
+@end