* Headers/Additions/GNUstepBase/GSLock.h: Added missing

forward declaration.
	* Headers/Additions/GNUstepBase/GSCategories.h: Remove
	declaraion of gnustep_global_lock.
	(GS_INITIALIZED_LOCK): New macro.
	(+[NSLock newLockAt:]): New method.
	(+[NSRecursiveLock newLockAt:]): Ditto.
	* Headers/Foundation/NSLock.h: Ditto.
	* Source/Additions/GSCategories.m: Replace global lock with
	local lock.
	(_GSLockInitializer): New class to initialize local lock
	safely.
	(newLockAt): New static function shared by +newLockAt:
	implementations to safely intialize lock variables.
	(+[NSLock newLockAt:]): Implemented and documented.
	(+[NSRecursiveLock newLockAt:]): Ditto.
	* Source/Additions/GSCompatibility.m: Remove
	gnustep_global_lock.
	* Source/Additions/GSObjCRuntime.m: Remove superfluous
	locking.
	* Source/Additions/Unicode.m: Use new GS_INITIALIZED_LOCK
	macro and replace global lock with local lock.
	* Source/NSLock.m
	(-[NSConditionLock lockWhenCondition:beforeDate:]):
	Implemented.
	* Testing/gslock.m: New test case.
	* Testing/GNUmakefile: Add new test case.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@18010 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
ayers 2003-10-30 13:44:55 +00:00
parent b462208383
commit 86f35c472c
11 changed files with 471 additions and 25 deletions

View file

@ -25,6 +25,7 @@
#include <string.h>
#include <Foundation/Foundation.h>
#include "GNUstepBase/GSCategories.h"
#include "GNUstepBase/GSLock.h"
/**
* Extension methods for the NSCalendarDate class
@ -874,3 +875,120 @@ static void MD5Transform (unsigned long buf[4], unsigned long const in[16])
}
@end
/**
* GNUstep specific (non-standard) additions to the NSLock class.
*/
static NSRecursiveLock *local_lock = nil;
/*
This class only exists to provide
a thread safe mechanism to initialize local_lock
as +initialize is called under a lock in ObjC runtimes.
User code should resort to GS_INITIALIZED_LOCK(),
which uses the +newLockAt: extension.
*/
@interface _GSLockInitializer : NSObject
@end
@implementation _GSLockInitializer
+ (void)initialize
{
if (!local_lock)
{
local_lock = [GSLazyRecursiveLock new];
}
}
@end
GS_STATIC_INLINE id
newLockAt(Class self, SEL _cmd, id *location)
{
if (location == 0)
{
[NSException raise: NSInvalidArgumentException
format: @"'%@' called with nil location",
NSStringFromSelector(_cmd)];
}
if (*location == nil)
{
if (local_lock == nil)
{
[_GSLockInitializer class];
}
[local_lock lock];
if (*location == nil)
{
*location = [[self alloc] init];
}
[local_lock unlock];
}
return *location;
}
@implementation NSLock (GSCategories)
/**
* Initializes the id pointed to by location
* with a new instance of the receiver's class
* in a thread safe manner, unless
* it has been previously initialized.
* Returns the contents pointed to by location.
* The location is considered unintialized if it contains nil.
* <br/>
* This method is used in the GS_INITIALIZED_LOCK macro
* to initialize lock variables when it cannot be insured
* that they can be initialized in a thread safe environment.
* <example>
* NSLock *my_lock = nil;
*
* void function (void)
* {
* [GS_INITIALIZED_LOCK(my_lock, NSLock) lock];
* do_work ();
* [my_lock unlock];
* }
*
* </example>
*/
+ (id)newLockAt:(id *)location
{
return newLockAt(self, _cmd, location);
}
@end
@implementation NSRecursiveLock (GSCategories)
/**
* Initializes the id pointed to by location
* with a new instance of the receiver's class
* in a thread safe manner, unless
* it has been previously initialized.
* Returns the contents pointed to by location.
* The location is considered unintialized if it contains nil.
* <br/>
* This method is used in the GS_INITIALIZED_LOCK macro
* to initialize lock variables when it cannot be insured
* that they can be initialized in a thread safe environment.
* <example>
* NSLock *my_lock = nil;
*
* void function (void)
* {
* [GS_INITIALIZED_LOCK(my_lock, NSRecursiveLock) lock];
* do_work ();
* [my_lock unlock];
* }
*
* </example>
*/
+ (id)newLockAt:(id *)location
{
return newLockAt(self, _cmd, location);
}
@end

View file

@ -27,9 +27,6 @@
#include "GNUstepBase/GSCategories.h"
#include "GNUstepBase/GCObject.h"
/* FIXME: Need to initialize this */
NSRecursiveLock *gnustep_global_lock = NULL;
NSString *GetEncodingName(NSStringEncoding availableEncodingValue)
{
// Deprecated

View file

@ -1563,13 +1563,8 @@ GSPrintf (FILE *fptr, NSString* format, ...)
if (stringClass == 0)
{
[gnustep_global_lock lock];
if (stringClass == 0)
{
stringClass = [NSString class];
enc = [stringClass defaultCStringEncoding];
}
[gnustep_global_lock unlock];
stringClass = [NSString class];
enc = [stringClass defaultCStringEncoding];
}
message = [stringClass allocWithZone: NSDefaultMallocZone()];
va_start (ap, format);

View file

@ -39,6 +39,7 @@
#else
#include <Foundation/Foundation.h>
#endif
#include "GNUstepBase/GSLock.h"
#include "GNUstepBase/GSCategories.h"
#include "GNUstepBase/Unicode.h"
#include <stdio.h>
@ -82,6 +83,8 @@ typedef struct {unichar from; unsigned char to;} _ucc_;
#define UNICODE_ENC ((unicode_enc) ? unicode_enc : internal_unicode_enc())
static NSRecursiveLock *local_lock = nil;
static const char *unicode_enc = NULL;
/* Check to see what type of internal unicode format the library supports */
@ -207,7 +210,7 @@ static void GSSetupEncodingTable(void)
{
if (encodingTable == 0)
{
[gnustep_global_lock lock];
[GS_INITIALIZED_LOCK(local_lock, GSLazyRecursiveLock) lock];
if (encodingTable == 0)
{
static struct _strenc_ **encTable = 0;
@ -257,7 +260,7 @@ static void GSSetupEncodingTable(void)
}
encodingTable = encTable;
}
[gnustep_global_lock unlock];
[local_lock unlock];
}
}
@ -325,7 +328,7 @@ GetAvailableEncodings()
{
if (_availableEncodings == 0)
{
[gnustep_global_lock lock];
[GS_INITIALIZED_LOCK(local_lock, GSLazyRecursiveLock) lock];
if (_availableEncodings == 0)
{
NSStringEncoding *encodings;
@ -352,7 +355,7 @@ GetAvailableEncodings()
encodings[pos] = 0;
_availableEncodings = encodings;
}
[gnustep_global_lock unlock];
[local_lock unlock];
}
return _availableEncodings;
}
@ -559,10 +562,10 @@ GetDefEncoding()
char *encoding;
unsigned int count;
[gnustep_global_lock lock];
[GS_INITIALIZED_LOCK(local_lock, GSLazyRecursiveLock) lock];
if (defEnc != GSUndefinedEncoding)
{
[gnustep_global_lock unlock];
[local_lock unlock];
return defEnc;
}
@ -604,7 +607,7 @@ GetDefEncoding()
" NSISOLatin1StringEncoding set as default.\n");
defEnc = NSISOLatin1StringEncoding;
}
[gnustep_global_lock unlock];
[local_lock unlock];
}
return defEnc;
}

View file

@ -447,8 +447,40 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
beforeDate: (NSDate*)limitDate
{
#ifndef HAVE_OBJC_CONDITION_TIMEDWAIT
[self notImplemented: _cmd];
GSSleepInfo ctxt;
CHECK_RECURSIVE_CONDITION_LOCK(_mutex);
GSSleepInit(limitDate, &ctxt);
do
{
if (_condition_value == condition_to_meet)
{
while (objc_mutex_trylock(_mutex) == -1)
{
if (GSSleepOrFail(&ctxt) == NO)
{
return NO;
}
}
if (_condition_value == condition_to_meet)
{
return YES;
}
if (objc_mutex_unlock(_mutex) == -1)
{
[NSException raise: NSConditionLockException
format: @"%s failed to unlock mutex",
GSNameFromSelector(_cmd)];
/* NOT REACHED */
}
}
}
while (GSSleepOrFail(&ctxt) == YES);
return NO;
#else
NSTimeInterval atimeinterval;
struct timespec endtime;