git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@4973 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-10-05 10:04:12 +00:00
parent 127c08ae4f
commit d72ea5bdbe
4 changed files with 83 additions and 31 deletions

View file

@ -1,3 +1,8 @@
Tue Sep 5 11:21:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSUserDefaults.m: Fix for crash when reading corrupt file.
Also -added code to create ~/GNUstep directory if needed.
Mon Sep 4 11:06:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Tools/gdomap.c: better debug output (hopefully)

View file

@ -176,7 +176,11 @@ Normally, memory is allocated in zones. Most memory is allocated from a
default area (returned by the NSDefaultMallocZone()) function. In some cases
where you want to ensure that a group of objects are all located in roughly the
same area of memory (for performance reasons) you might create a special zone
and allocate the objects fromn that area.
large enough to accomodate the objects you wish to create, and allocate the
objects from that area. This will minimise the paging that your application
needs to do in accessing those objects frequently. With the low price of RAM
in modern systems, paging is likely to be much less of a problem nowadays, and
the need for zoning memory is much lower than it used to be.
At a low-level, memory allocation is performed by two functions -
NSAllocateObject() and NSDeallocateObject(), but you need never normally deal
@ -189,16 +193,33 @@ some functionality of that class (such as caching of frequently used objects).
Generally, objects are created using the methods +alloc, -copy, -mutableCopy
and are destroyed using -dealloc. The allocation methods are covers for the
more versatile +allocWithZone:, -copyWithZone: and -mutableCopyWithZone:
methods. NSObject also provides +new, which is simply a cover for the
methods (which specify the zone from which the memory is to be allocated,
rather than forcing you to use the default zone).
NSObject also provides +new, which is simply a cover for the
combination of a +alloc and a -init.
The -dealloc method returns the memory occupied by the object to the zone from
which it was originally allocated, it can use the -zone method to determine
which zone this is.
Explicit memory allocation and deallocation is efficient - but when you pass
objects around inside a program (and especially from/to libraries etc) it
quickly becomes difficult and/or inefficient to keep track of who owns an
object and should be responsible for calling it's deallocation method.
To take this problem away, some mechanism is needed. The OpenStep specification
provides a reference counting mechanism along with a set of conventions that
make memory management easy. In addition to this, the GNU Objective-C compiler
and the GNUstep system provide a memory sweeping garbage collection mechanism
(using the Boehm conservative garbage collection library).
@node Reference Counting, Memory Allocation, Garbage Collection, Memory Management
@section Reference Counting
The reference counting scheme for object allocation/deallocation is quite
simple. Objects are normally created with a reference count of 1. An objects
reference count may be increased by callsing -retain, and decreased by calling
-release. If a -releae would make the reference count become zero, the
-release. If a -release would make the reference count become zero, the
-dealloc method is automatically called to destroy the object - freeing its
memory.

View file

@ -116,8 +116,8 @@ extern NSString* const NSDateTimeOrdering;
NSMutableArray *_changedDomains; /* ..after first time that persistent
user defaults are changed */
NSDictionary *_dictionaryRep; // Cached dictionary representation
NSMutableString *_defaultsDatabase;
NSMutableString *_defaultsDatabaseLockName;
NSString *_defaultsDatabase;
NSString *_defaultsDatabaseLockName;
NSDistributedLock *_defaultsDatabaseLock;
NSDate *_lastSync;
NSTimer *_tickingTimer; // for synchronization

View file

@ -59,8 +59,9 @@ static SEL nextObjectSel = @selector(nextObject);
static SEL objectForKeySel = @selector(objectForKey:);
/* User's Defaults database */
static NSString* GNU_UserDefaultsDatabase = @"GNUstep/.GNUstepDefaults";
static NSString* GNU_UserDefaultsDatabaseLock = @"GNUstep/.GNUstepUDLock";
static NSString *GNU_UserDefaultsPrefix = @"GNUstep";
static NSString *GNU_UserDefaultsDatabase = @".GNUstepDefaults";
static NSString *GNU_UserDefaultsDatabaseLock = @".GNUstepUDLock";
static Class NSArrayClass;
static Class NSDataClass;
@ -295,21 +296,48 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
return [self initWithUser: NSUserName()];
}
static NSString *pathForUser(NSString *user)
{
NSFileManager *mgr = [NSFileManager defaultManager];
NSString *home;
NSString *path;
BOOL isDir;
home = NSHomeDirectoryForUser(user);
if (home == nil)
{
return nil;
}
path = [home stringByAppendingPathComponent: GNU_UserDefaultsPrefix];
if ([mgr fileExistsAtPath: path isDirectory: &isDir] == NO)
{
NSLog(@"Directory '%'@ does not exist - creating it", path);
if ([mgr createDirectoryAtPath: path attributes: nil] == NO)
{
NSLog(@"Unable to create user GNUstep directory '%@'", path);
return nil;
}
}
if (isDir == NO)
{
NSLog(@"ERROR - '%@' is not a directory!", path);
return nil;
}
path = [path stringByAppendingPathComponent: GNU_UserDefaultsDatabase];
return path;
}
/* Initializes defaults for the specified user calling initWithFile: . */
- (id) initWithUser: (NSString*)userName
{
NSString *userHome = NSHomeDirectoryForUser(userName);
NSString *filename;
NSString *path = pathForUser(userName);
// Either userName is empty or it's wrong
if (!userHome)
if (path == nil)
{
RELEASE(self);
return nil;
}
filename = [NSStringClass stringWithFormat: @"%@/%@",
userHome, GNU_UserDefaultsDatabase];
return [self initWithContentsOfFile: filename];
return [self initWithContentsOfFile: path];
}
- (id) initWithContentsOfFile: (NSString*)path
@ -319,31 +347,29 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
[super init];
// Find the user's home folder and build the paths (executed only once)
if (!_defaultsDatabase)
if (_defaultsDatabase == nil)
{
if (path != nil && [path isEqual: @""] == NO)
_defaultsDatabase = (NSMutableString*)[path mutableCopy];
{
_defaultsDatabase = [path copy];
}
else
{
_defaultsDatabase = (NSMutableString*)
[NSMutableString stringWithFormat: @"%@/%@",
NSHomeDirectoryForUser(NSUserName()),
GNU_UserDefaultsDatabase];
IF_NO_GC([_defaultsDatabase retain]);
_defaultsDatabase = [pathForUser(NSUserName()) copy];
}
if ([[_defaultsDatabase lastPathComponent] isEqual:
[GNU_UserDefaultsDatabase lastPathComponent]] == YES)
_defaultsDatabaseLockName = (NSMutableString*)
[NSMutableString stringWithFormat: @"%@/%@",
[_defaultsDatabase stringByDeletingLastPathComponent],
[GNU_UserDefaultsDatabaseLock lastPathComponent]];
GNU_UserDefaultsDatabase] == YES)
{
path = [_defaultsDatabase stringByDeletingLastPathComponent];
}
else
_defaultsDatabaseLockName = (NSMutableString*)
[NSMutableString stringWithFormat: @"%@/%@",
NSHomeDirectoryForUser(NSUserName()),
GNU_UserDefaultsDatabaseLock];
IF_NO_GC([_defaultsDatabaseLockName retain]);
{
path = [pathForUser(NSUserName()) stringByDeletingLastPathComponent];
}
path = [path stringByAppendingPathComponent:
GNU_UserDefaultsDatabaseLock];
_defaultsDatabaseLockName = [path copy];
_defaultsDatabaseLock =
RETAIN([NSDistributedLock lockWithPath: _defaultsDatabaseLockName]);
}