mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
* 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:
parent
b462208383
commit
86f35c472c
11 changed files with 471 additions and 25 deletions
26
ChangeLog
26
ChangeLog
|
@ -1,3 +1,29 @@
|
|||
2003-10-30 David Ayers <d.ayers@inode.at>
|
||||
|
||||
* 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.
|
||||
|
||||
2003-10-28 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* configure.ac: Simplify and clarify ffi errors.
|
||||
|
|
|
@ -162,12 +162,9 @@ typedef enum _NSGNUstepStringEncoding
|
|||
} NSGNUstepStringEncoding;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Variables
|
||||
*/
|
||||
|
||||
GS_EXPORT NSRecursiveLock *gnustep_global_lock;
|
||||
|
||||
/* Taken from base/Headers/Foundation/NSLock.h */
|
||||
#define GS_INITIALIZED_LOCK(IDENT,CLASSNAME) \
|
||||
(IDENT != nil ? IDENT : [CLASSNAME newLockAt: &IDENT])
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Class/Method Extensions
|
||||
|
@ -279,6 +276,14 @@ GS_EXPORT NSRecursiveLock *gnustep_global_lock;
|
|||
- (NSMutableSet *) debugSet;
|
||||
@end
|
||||
|
||||
@interface NSLock (GSCategories)
|
||||
+ (id)newLockAt:(NSLock **)location;
|
||||
@end
|
||||
|
||||
@interface NSRecursiveLock (GSCategories)
|
||||
+ (id)newLockAt:(NSLock **)location;
|
||||
@end
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Functions
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include <Foundation/NSLock.h>
|
||||
|
||||
@class NSNotification;
|
||||
|
||||
@interface GSLazyLock : NSLock
|
||||
{
|
||||
int locked;
|
||||
|
|
|
@ -128,4 +128,42 @@
|
|||
|
||||
@end
|
||||
|
||||
#ifndef NO_GNUSTEP
|
||||
|
||||
/**
|
||||
* Returns IDENT which will be initialized
|
||||
* to an instance of a CLASSNAME in a thread safe manner.
|
||||
* If IDENT has been previoulsy initilized
|
||||
* this macro merely returns IDENT.
|
||||
* IDENT is considered uninitialzed, if it contains nil.
|
||||
* CLASSNAME must be either NSLock, NSRecursiveLock or one
|
||||
* of thier subclasses.
|
||||
* See [NSLock+newLockAt:] for details.
|
||||
* This macro is intended for code that cannot insure
|
||||
* that a lock can be initialized in thread safe manner otherwise.
|
||||
* <example>
|
||||
* NSLock *my_lock = nil;
|
||||
*
|
||||
* void function (void)
|
||||
* {
|
||||
* [GS_INITIALIZED_LOCK(my_lock, NSLock) lock];
|
||||
* do_work ();
|
||||
* [my_lock unlock];
|
||||
* }
|
||||
*
|
||||
* </example>
|
||||
*/
|
||||
#define GS_INITIALIZED_LOCK(IDENT,CLASSNAME) \
|
||||
(IDENT != nil ? IDENT : [CLASSNAME newLockAt: &IDENT])
|
||||
|
||||
@interface NSLock (GSCategories)
|
||||
+ (id)newLockAt:(id *)location;
|
||||
@end
|
||||
|
||||
@interface NSRecursiveLock (GSCategories)
|
||||
+ (id)newLockAt:(id *)location;
|
||||
@end
|
||||
|
||||
#endif /* NO_GNUSTEP */
|
||||
|
||||
#endif /* _GNUstep_H_NSLock*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -36,6 +36,7 @@ CHECKABLE_TOOLS = \
|
|||
call \
|
||||
containers \
|
||||
fref \
|
||||
gslock \
|
||||
nsarchiver \
|
||||
nsarray \
|
||||
nsattributedstring \
|
||||
|
@ -74,7 +75,8 @@ ADDITIONAL_TOOLS = \
|
|||
nsconnection_client \
|
||||
nsconnection_server \
|
||||
|
||||
// TEST_TOOL_NAME += nsconnection_client nsconnection_server
|
||||
# TEST_TOOL_NAME += nsconnection_client nsconnection_server
|
||||
TEST_TOOL_NAME += nsconnection_client nsconnection_server $(ADDITIONAL_TOOLS)
|
||||
|
||||
# The tool Objective-C source files to be compiled
|
||||
awake_OBJC_FILES = awake.m
|
||||
|
@ -84,6 +86,7 @@ call_OBJC_FILES = call.m
|
|||
containers_OBJC_FILES = containers.m
|
||||
diningPhilosophers_OBJC_FILES = diningPhilosophers.m
|
||||
fref_OBJC_FILES = fref.m
|
||||
gslock_OBJC_FILES = gslock.m
|
||||
gstcpport-client_OBJC_FILES = gstcpport-client.m
|
||||
gstcpport-server_OBJC_FILES = gstcpport-server.m
|
||||
nsarchiver_OBJC_FILES = nsarchiver.m
|
||||
|
|
227
Testing/gslock.m
Normal file
227
Testing/gslock.m
Normal file
|
@ -0,0 +1,227 @@
|
|||
/** gslock - Program to test GSLazyLocks.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
Written by: David Ayers <d.ayers@inode.at>
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSFileHandle.h>
|
||||
#include <Foundation/NSThread.h>
|
||||
|
||||
#include <GNUstepBase/GSLock.h>
|
||||
|
||||
NSLock *lock = nil;
|
||||
|
||||
NSLock *gLock1 = nil;
|
||||
GSLazyRecursiveLock *gLock2 = nil;
|
||||
|
||||
NSConditionLock *cLock = nil;
|
||||
|
||||
volatile int counter = 0;
|
||||
volatile int threadExitCounter;
|
||||
|
||||
void
|
||||
wait_a_while()
|
||||
{
|
||||
volatile int i;
|
||||
for (i = 0; i < 5; i++)
|
||||
i = ((i + 1) + (i - 1) / 2);
|
||||
}
|
||||
|
||||
#define NUM_ITERATIONS 10000
|
||||
|
||||
@interface Tester : NSObject
|
||||
- (void)runTest:(NSString *)ident;
|
||||
- (void)dummy:(id)none;
|
||||
- (void)createNewLockAt:(id)none;
|
||||
@end
|
||||
@implementation Tester
|
||||
- (void)dummy:(id)none
|
||||
{
|
||||
NSLog(@"Multithreaded:%@",[NSThread currentThread]);
|
||||
}
|
||||
- (void)runTest:(NSString *)ident
|
||||
{
|
||||
NSDate *start;
|
||||
NSDate *end;
|
||||
int i,j;
|
||||
NSTimeInterval time = 0;
|
||||
NSAutoreleasePool *pool;
|
||||
BOOL makeMulti;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
makeMulti = ([ident isEqualToString: @"Make Multithreaded GS"]);
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
start = [NSDate date];
|
||||
for (j = 0; j < NUM_ITERATIONS; j++)
|
||||
{
|
||||
volatile int temp;
|
||||
|
||||
[lock lock];
|
||||
|
||||
temp = counter;
|
||||
wait_a_while();
|
||||
|
||||
if (makeMulti && i == 49 )
|
||||
{
|
||||
[NSThread detachNewThreadSelector: @selector(dummy:)
|
||||
toTarget: self
|
||||
withObject: nil];
|
||||
makeMulti = NO;
|
||||
}
|
||||
|
||||
|
||||
counter = temp + 1;
|
||||
wait_a_while();
|
||||
|
||||
[lock unlock];
|
||||
}
|
||||
end = [NSDate date];
|
||||
time += [end timeIntervalSinceDate: start];
|
||||
}
|
||||
NSLog(@"End (%@/%@/%@):%f ",
|
||||
[NSThread currentThread], ident, lock, time / 100 );
|
||||
|
||||
threadExitCounter++;
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
-(void)createNewLockAt:(id)none
|
||||
{
|
||||
[cLock lock];
|
||||
|
||||
GS_INITIALIZED_LOCK(gLock1,NSLock);
|
||||
GS_INITIALIZED_LOCK(gLock2,GSLazyRecursiveLock);
|
||||
|
||||
NSLog(@"Created locks: %@ %@", gLock1, gLock2);
|
||||
|
||||
[cLock unlockWithCondition: YES];
|
||||
}
|
||||
@end
|
||||
|
||||
void
|
||||
test_lazyLocks()
|
||||
{
|
||||
Tester *tester;
|
||||
int i;
|
||||
|
||||
tester = [Tester new];
|
||||
|
||||
[tester runTest:@"empty"];
|
||||
|
||||
lock = [GSLazyLock new];
|
||||
[tester runTest:@"single GS"];
|
||||
|
||||
lock = [GSLazyRecursiveLock new];
|
||||
[tester runTest:@"single (r) GS"];
|
||||
|
||||
lock = [NSLock new];
|
||||
[tester runTest:@"single NS"];
|
||||
|
||||
lock = [NSRecursiveLock new];
|
||||
[tester runTest:@"single (r) NS"];
|
||||
|
||||
lock = [GSLazyLock new];
|
||||
[tester runTest:@"Make Multithreaded GS"];
|
||||
|
||||
/* We are now multithreaded. */
|
||||
NSCAssert1 ([lock class] == [NSLock class],
|
||||
@"Class didn't morph:%@", lock);
|
||||
|
||||
lock = [GSLazyLock new];
|
||||
NSCAssert1 ([lock class] == [NSLock class],
|
||||
@"Returned wrong lock:%@", lock);
|
||||
/* These tests actually only test NS*Lock locking, but... */
|
||||
[tester runTest:@"multi simple GS"];
|
||||
|
||||
lock = [GSLazyRecursiveLock new];
|
||||
NSCAssert1 ([lock class] == [NSRecursiveLock class],
|
||||
@"Returned wrong lock:%@", lock);
|
||||
[tester runTest:@"multi simple (r) GS"];
|
||||
|
||||
lock = [NSLock new];
|
||||
[tester runTest:@"multi simple NS"];
|
||||
|
||||
lock = [NSRecursiveLock new];
|
||||
[tester runTest:@"multi simple NS"];
|
||||
|
||||
/* Let's test locking anyway while we're at it. */
|
||||
for (threadExitCounter = 0, i = 0; i < 3; i++)
|
||||
{
|
||||
NSString *ident;
|
||||
ident = [NSString stringWithFormat: @"multi complex (%d)", i];
|
||||
[NSThread detachNewThreadSelector: @selector(runTest:)
|
||||
toTarget: tester
|
||||
withObject: ident];
|
||||
}
|
||||
|
||||
while (threadExitCounter < 3)
|
||||
[NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 10.0]];
|
||||
|
||||
NSCAssert1 (counter == NUM_ITERATIONS * 1300,
|
||||
@"Locks broken! %d", counter );
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_newLockAt(void)
|
||||
{
|
||||
Tester *t = [Tester new];
|
||||
|
||||
cLock = [[NSConditionLock alloc] initWithCondition: NO];
|
||||
|
||||
[NSThread detachNewThreadSelector: @selector(createNewLockAt:)
|
||||
toTarget: t
|
||||
withObject: nil];
|
||||
|
||||
[cLock lockWhenCondition: YES
|
||||
beforeDate: [NSDate dateWithTimeIntervalSinceNow: 10.0]];
|
||||
[cLock unlock];
|
||||
|
||||
NSCAssert1([gLock1 isKindOfClass: [NSLock class]],
|
||||
@"-[NSLock newLockAt:] returned %@", gLock1);
|
||||
NSCAssert1([gLock2 isKindOfClass: [NSRecursiveLock class]],
|
||||
@"-[GSLazyRecursiveLock newLockAt:] returned %@", gLock1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
[NSAutoreleasePool enableDoubleReleaseCheck:YES];
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
test_lazyLocks();
|
||||
test_newLockAt();
|
||||
|
||||
[pool release];
|
||||
|
||||
exit(0);
|
||||
}
|
Loading…
Reference in a new issue