Merge branch 'master' of github.com:gnustep/libs-base

This commit is contained in:
Gregory John Casamento 2019-10-29 00:32:21 -04:00
commit ab7f39d833
14 changed files with 930 additions and 1039 deletions

View file

@ -70,13 +70,21 @@
* Release an dispatch object.
*/
#define GS_DISPATCH_RELEASE(x) dispatch_release(x)
/**
* Allows an arbitrary block to be submitted to the queue. Since dispatch blocks
* return nothing and take no arguments, the caller can use the before and after
* arguments to set up and tear down the block as required.
* Allows an arbitrary block to be submitted to the queue (if available) or run
* in place. Since dispatch blocks return nothing and take no arguments, the
* caller can use the before and after arguments to guard calling the block as
* required.
*/
#define GS_DISPATCH_SUBMIT_BLOCK(group, queue, before, after, block, args, ...) \
dispatch_group_async(group, queue, ^(void){before; block(args, ## __VA_ARGS__); after;})
if (queue != NULL) {\
dispatch_group_async(group, queue, ^(void){before block(args, ## __VA_ARGS__); after});\
} else {\
before\
block(args, ## __VA_ARGS__);\
after\
}
/**
* Submits a block without special provisions.
@ -85,32 +93,30 @@
/**
* Convenience macro to create serial or concurrent dispatch queues for the
* various -enumerateUsingBlock: methods.
* Convenience macro to create concurrent dispatch queues for the various
* -enumerateUsingBlock: methods. Non-concurrent will be run in place.
*/
#define GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(queue, opts)\
dispatch_queue_t queue;\
dispatch_group_t queue ## Group;\
dispatch_queue_t queue = NULL;\
dispatch_group_t queue ## Group = NULL;\
if (opts & NSEnumerationConcurrent)\
{\
queue = GS_DISPATCH_GET_DEFAULT_CONCURRENT_QUEUE();\
}\
else\
{\
queue = GS_DISPATCH_QUEUE_CREATE(DISPATCH_QUEUE_SERIAL);\
}\
queue ## Group = GS_DISPATCH_GROUP_CREATE();
queue ## Group = GS_DISPATCH_GROUP_CREATE();\
}
/**
* Convenience macro to destroy serial or concurrent dispatch queues for the
* various -enumerateUsingBlock: methods.
* Convenience macro to destroy concurrent dispatch queues for the various
* -enumerateUsingBlock: methods.
*/
#define GS_DISPATCH_TEARDOWN_QUEUE_AND_GROUP_FOR_ENUMERATION(queue, opts)\
GS_DISPATCH_GROUP_FINISH(queue ## Group);\
GS_DISPATCH_RELEASE(enumQueueGroup);\
if (NO == (opts & NSEnumerationConcurrent))\
{\
GS_DISPATCH_RELEASE(enumQueue);\
if (queue != NULL) { \
GS_DISPATCH_GROUP_FINISH(queue ## Group);\
GS_DISPATCH_RELEASE(queue ## Group);\
if (NO == (opts & NSEnumerationConcurrent))\
{\
GS_DISPATCH_RELEASE(queue);\
}\
}

View file

@ -1584,14 +1584,26 @@ setNonBlocking(SOCKET fd)
*/
if (_handler != nil && [_handler handshake] == YES)
{
id hdl = _handler;
id del = _delegate;
BOOL val = _delegateValid;
_delegate = _handler;
/* Retain self to prevent a dangling pointer the handler closes and
* releases this socket. Also, do not restore the old delegate if it
* was changed directly or indirectly by the handler.
* FIXME We leave the socket an inconsistent state if any exception
* is raised in _sendEvent:.
*/
RETAIN(self);
_delegate = hdl;
_delegateValid = YES;
[super _sendEvent: event];
_delegate = del;
_delegateValid = val;
if (_delegate == hdl)
{
_delegate = del;
_delegateValid = val;
}
RELEASE(self);
}
else
{

View file

@ -1790,7 +1790,7 @@ compare(id elem1, id elem2, void* context)
{
GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts)
FOR_IN (id, obj, enumerator)
GS_DISPATCH_SUBMIT_BLOCK(enumQueueGroup, enumQueue, if (YES == shouldStop) {return;}, return, aBlock, obj, count, &shouldStop);
GS_DISPATCH_SUBMIT_BLOCK(enumQueueGroup, enumQueue, if (shouldStop == NO) {, }, aBlock, obj, count, &shouldStop);
if (isReverse)
{
count--;
@ -1841,30 +1841,32 @@ compare(id elem1, id elem2, void* context)
GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts)
FOR_IN (id, obj, enumerator)
# if __has_feature(blocks) && (GS_USE_LIBDISPATCH == 1)
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
if (enumQueue != NULL)
{
return;
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
{
return;
}
if (predicate(obj, count, &shouldStop))
{
[setLock lock];
[set addIndex: count];
[setLock unlock];
}
});
}
if (predicate(obj, count, &shouldStop))
{
[setLock lock];
[set addIndex: count];
[setLock unlock];
}
});
# else
else // call block directly
# endif
if (CALL_BLOCK(predicate, obj, count, &shouldStop))
{
/* TODO: It would be more efficient to collect an NSRange and only
* pass it to the index set when CALL_BLOCK returned NO. */
[set addIndex: count];
/* TODO: It would be more efficient to collect an NSRange and only
* pass it to the index set when CALL_BLOCK returned NO. */
[set addIndex: count];
}
# endif
if (shouldStop)
{
break;
break;
}
count++;
END_FOR_IN(enumerator)
@ -1936,33 +1938,35 @@ compare(id elem1, id elem2, void* context)
GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts)
FOR_IN (id, obj, enumerator)
# if __has_feature(blocks) && (GS_USE_LIBDISPATCH == 1)
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
if (enumQueue != NULL)
{
return;
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
{
return;
}
if (predicate(obj, count, &shouldStop))
{
// FIXME: atomic operation on the shouldStop variable would be nicer,
// but we don't expose the GSAtomic* primitives anywhere.
[indexLock lock];
index = count;
// Cancel all other predicate evaluations:
shouldStop = YES;
[indexLock unlock];
}
});
}
if (predicate(obj, count, &shouldStop))
{
// FIXME: atomic operation on the shouldStop variable would be nicer,
// but we don't expose the GSAtomic* primitives anywhere.
[indexLock lock];
index = count;
// Cancel all other predicate evaluations:
shouldStop = YES;
[indexLock unlock];
}
});
# else
else // call block directly
# endif
if (CALL_BLOCK(predicate, obj, count, &shouldStop))
{
index = count;
shouldStop = YES;
index = count;
shouldStop = YES;
}
# endif
if (shouldStop)
{
break;
break;
}
count++;
END_FOR_IN(enumerator)

View file

@ -159,7 +159,7 @@ otherTime(NSDate* other)
return NSAllocateObject(self, 0, z);
}
+ (id) date
+ (instancetype) date
{
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
initWithTimeIntervalSinceReferenceDate: GSPrivateTimeNow()]);
@ -171,14 +171,14 @@ otherTime(NSDate* other)
* specified by the preferences in the user defaults database, allowing
* phrases like 'last tuesday'
*/
+ (id) dateWithNaturalLanguageString: (NSString*)string
+ (instancetype) dateWithNaturalLanguageString: (NSString*)string
{
return [self dateWithNaturalLanguageString: string
locale: nil];
}
+ (id) dateWithNaturalLanguageString: (NSString*)string
locale: (NSDictionary*)locale
+ (instancetype) dateWithNaturalLanguageString: (NSString*)string
locale: (NSDictionary*)locale
{
NSCharacterSet *ws;
NSCharacterSet *digits;
@ -885,35 +885,36 @@ otherTime(NSDate* other)
}
}
+ (id) dateWithString: (NSString*)description
+ (instancetype) dateWithString: (NSString*)description
{
return AUTORELEASE([[self alloc] initWithString: description]);
}
+ (id) dateWithTimeInterval: (NSTimeInterval)seconds sinceDate: (NSDate*)date
+ (instancetype) dateWithTimeInterval: (NSTimeInterval)seconds
sinceDate: (NSDate*)date
{
return AUTORELEASE([[self alloc] initWithTimeInterval: seconds
sinceDate: date]);
}
+ (id) dateWithTimeIntervalSince1970: (NSTimeInterval)seconds
+ (instancetype) dateWithTimeIntervalSince1970: (NSTimeInterval)seconds
{
return AUTORELEASE([[self alloc] initWithTimeIntervalSinceReferenceDate:
seconds - NSTimeIntervalSince1970]);
}
+ (id) dateWithTimeIntervalSinceNow: (NSTimeInterval)seconds
+ (instancetype) dateWithTimeIntervalSinceNow: (NSTimeInterval)seconds
{
return AUTORELEASE([[self alloc] initWithTimeIntervalSinceNow: seconds]);
}
+ (id) dateWithTimeIntervalSinceReferenceDate: (NSTimeInterval)seconds
+ (instancetype) dateWithTimeIntervalSinceReferenceDate: (NSTimeInterval)seconds
{
return AUTORELEASE([[self alloc] initWithTimeIntervalSinceReferenceDate:
seconds]);
}
+ (id) distantPast
+ (instancetype) distantPast
{
if (_distantPast == nil)
{
@ -922,7 +923,7 @@ otherTime(NSDate* other)
return _distantPast;
}
+ (id) distantFuture
+ (instancetype) distantFuture
{
if (_distantFuture == nil)
{
@ -940,7 +941,7 @@ otherTime(NSDate* other)
return GSPrivateTimeNow();
}
- (id) addTimeInterval: (NSTimeInterval)seconds
- (instancetype) addTimeInterval: (NSTimeInterval)seconds
{
return [self dateByAddingTimeInterval: seconds];
}
@ -976,7 +977,7 @@ otherTime(NSDate* other)
return abstractClass;
}
- (id) dateByAddingTimeInterval: (NSTimeInterval)ti
- (instancetype) dateByAddingTimeInterval: (NSTimeInterval)ti
{
return [[self class] dateWithTimeIntervalSinceReferenceDate:
otherTime(self) + ti];
@ -1069,7 +1070,7 @@ otherTime(NSDate* other)
return (NSUInteger)[self timeIntervalSinceReferenceDate];
}
- (id) initWithCoder: (NSCoder*)coder
- (instancetype) initWithCoder: (NSCoder*)coder
{
NSTimeInterval interval;
id o;
@ -1099,12 +1100,12 @@ otherTime(NSDate* other)
return o;
}
- (id) init
- (instancetype) init
{
return [self initWithTimeIntervalSinceReferenceDate: GSPrivateTimeNow()];
}
- (id) initWithString: (NSString*)description
- (instancetype) initWithString: (NSString*)description
{
// Easiest to just have NSCalendarDate do the work for us
NSCalendarDate *d = [calendarClass alloc];
@ -1123,8 +1124,8 @@ otherTime(NSDate* other)
}
}
- (id) initWithTimeInterval: (NSTimeInterval)secsToBeAdded
sinceDate: (NSDate*)anotherDate
- (instancetype) initWithTimeInterval: (NSTimeInterval)secsToBeAdded
sinceDate: (NSDate*)anotherDate
{
if (anotherDate == nil)
{
@ -1137,20 +1138,20 @@ otherTime(NSDate* other)
otherTime(anotherDate) + secsToBeAdded];
}
- (id) initWithTimeIntervalSince1970: (NSTimeInterval)seconds
- (instancetype) initWithTimeIntervalSince1970: (NSTimeInterval)seconds
{
return [self initWithTimeIntervalSinceReferenceDate:
seconds - NSTimeIntervalSince1970];
}
- (id) initWithTimeIntervalSinceNow: (NSTimeInterval)secsToBeAdded
- (instancetype) initWithTimeIntervalSinceNow: (NSTimeInterval)secsToBeAdded
{
// Get the current time, add the secs and init thyself
return [self initWithTimeIntervalSinceReferenceDate:
GSPrivateTimeNow() + secsToBeAdded];
}
- (id) initWithTimeIntervalSinceReferenceDate: (NSTimeInterval)secs
- (instancetype) initWithTimeIntervalSinceReferenceDate: (NSTimeInterval)secs
{
[self subclassResponsibility: _cmd];
return self;

View file

@ -178,7 +178,7 @@ static SEL appSel;
FOR_IN(id, key, enumerator)
obj = (*objectForKey)(self, objectForKeySelector, key);
GS_DISPATCH_SUBMIT_BLOCK(enumQueueGroup, enumQueue,
if (shouldStop){return;};, return;, aBlock, key, obj, &shouldStop);
if (shouldStop == NO) {, }, aBlock, key, obj, &shouldStop);
if (YES == shouldStop)
{
break;
@ -1054,28 +1054,30 @@ compareIt(id o1, id o2, void* context)
FOR_IN(id, key, enumerator)
obj = (*objectForKey)(self, objectForKeySelector, key);
#if (__has_feature(blocks) && (GS_USE_LIBDISPATCH == 1))
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
{
return;
}
if (aPredicate(key, obj, &shouldStop))
{
[setLock lock];
addObject(buildSet, addObjectSelector, key);
[setLock unlock];
}
});
#else
if (enumQueue != NULL)
{
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
{
return;
}
if (aPredicate(key, obj, &shouldStop))
{
[setLock lock];
addObject(buildSet, addObjectSelector, key);
[setLock unlock];
}
});
}
else // call block directly
#endif
if (CALL_BLOCK(aPredicate, key, obj, &shouldStop))
{
addObject(buildSet, addObjectSelector, key);
}
#endif
if (YES == shouldStop)
if (shouldStop)
{
break;
break;
}
END_FOR_IN(enumerator)
GS_DISPATCH_TEARDOWN_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts)

View file

@ -917,7 +917,7 @@ static NSUInteger posForIndex(GSIArray array, NSUInteger index)
if ((innerI <= lastInRange) && (innerI >= range.location))
{
GS_DISPATCH_SUBMIT_BLOCK(enumQueueGroup, enumQueue,
if (shouldStop) {return;}, return;,
if (shouldStop == NO) {, },
aBlock, innerI, &shouldStop);
}
if (shouldStop)

View file

@ -657,7 +657,7 @@ static SEL remSel;
{
GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts)
FOR_IN (id, obj, enumerator)
GS_DISPATCH_SUBMIT_BLOCK(enumQueueGroup, enumQueue, if (YES == shouldStop) {return;}, return, aBlock, obj, count, &shouldStop);
GS_DISPATCH_SUBMIT_BLOCK(enumQueueGroup, enumQueue, if (shouldStop == NO) {, }, aBlock, obj, count, &shouldStop);
if (isReverse)
{
count--;
@ -865,33 +865,35 @@ static SEL remSel;
GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts)
FOR_IN (id, obj, enumerator)
# if __has_feature(blocks) && (GS_USE_LIBDISPATCH == 1)
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
if (enumQueue != NULL)
{
return;
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
{
return;
}
if (predicate(obj, count, &shouldStop))
{
// FIXME: atomic operation on the shouldStop variable would be nicer,
// but we don't expose the GSAtomic* primitives anywhere.
[indexLock lock];
index = count;
// Cancel all other predicate evaluations:
shouldStop = YES;
[indexLock unlock];
}
});
}
if (predicate(obj, count, &shouldStop))
{
// FIXME: atomic operation on the shouldStop variable would be nicer,
// but we don't expose the GSAtomic* primitives anywhere.
[indexLock lock];
index = count;
// Cancel all other predicate evaluations:
shouldStop = YES;
[indexLock unlock];
}
});
# else
else // call block directly
# endif
if (CALL_BLOCK(predicate, obj, count, &shouldStop))
{
index = count;
shouldStop = YES;
index = count;
shouldStop = YES;
}
# endif
if (shouldStop)
{
break;
break;
}
count++;
END_FOR_IN(enumerator)
@ -940,30 +942,32 @@ static SEL remSel;
GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts)
FOR_IN (id, obj, enumerator)
# if __has_feature(blocks) && (GS_USE_LIBDISPATCH == 1)
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
if (enumQueue != NULL)
{
return;
dispatch_group_async(enumQueueGroup, enumQueue, ^(void){
if (shouldStop)
{
return;
}
if (predicate(obj, count, &shouldStop))
{
[setLock lock];
[set addIndex: count];
[setLock unlock];
}
});
}
if (predicate(obj, count, &shouldStop))
{
[setLock lock];
[set addIndex: count];
[setLock unlock];
}
});
# else
else // call block directly
# endif
if (CALL_BLOCK(predicate, obj, count, &shouldStop))
{
/* TODO: It would be more efficient to collect an NSRange and only
* pass it to the index set when CALL_BLOCK returned NO. */
[set addIndex: count];
/* TODO: It would be more efficient to collect an NSRange and only
* pass it to the index set when CALL_BLOCK returned NO. */
[set addIndex: count];
}
# endif
if (shouldStop)
{
break;
break;
}
count++;
END_FOR_IN(enumerator)

View file

@ -907,7 +907,7 @@ static Class NSMutableSet_concrete_class;
GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(enumQueue, opts)
FOR_IN (id, obj, enumerator)
{
GS_DISPATCH_SUBMIT_BLOCK(enumQueueGroup,enumQueue, if (shouldStop) {return;}, return;, aBlock, obj, &shouldStop);
GS_DISPATCH_SUBMIT_BLOCK(enumQueueGroup,enumQueue, if (shouldStop == NO) {, }, aBlock, obj, &shouldStop);
if (shouldStop)
{
break;

File diff suppressed because it is too large Load diff