Operation queue convenience methods

This commit is contained in:
rfm 2025-01-07 13:05:55 +00:00
parent 6b04eaa35c
commit 4c9c691626
4 changed files with 121 additions and 3 deletions

View file

@ -36,6 +36,14 @@ extern "C" {
@interface NSOperationQueue (GNUstepBase)
/** Wraps a nil terminated list of objects in key/value pairs in a
* dictionary and adds an operation to send a message to aTarget to
* perform aSelector (which takes the map as its single argument).
*/
- (void) addOperationWithTarget: (id<NSObject>)aTarget
performSelector: (SEL)aSelector
withMap: (id)firstkey, ...;
- (void) addOperationWithTarget: (id<NSObject>)aTarget
performSelector: (SEL)aSelector
withObject: (id<NSObject>)object1

View file

@ -22,9 +22,12 @@
*/
#import "../common.h"
#import "Foundation/NSDictionary.h"
#import "Foundation/NSException.h"
#import "Foundation/NSMapTable.h"
#import "Foundation/NSObject.h"
#import "Foundation/NSOperation.h"
#import "GNUstepBase/GSObjCRuntime.h"
#import "GNUstepBase/NSOperationQueue+GNUstepBase.h"
@ -72,6 +75,23 @@
*/
@implementation NSOperationQueue (GNUstepBase)
- (void) addOperationWithTarget: (id<NSObject>)aTarget
performSelector: (SEL)aSelector
withMap: (id)firstKey, ...
{
GSTargetOperation *top;
NSDictionary *map;
map = [NSDictionary alloc];
GS_USEIDPAIRLIST(firstKey,
map = [map initWithObjects: __pairs forKeys: __objects count: __count/2]);
top = [GSTargetOperation operationWithTarget: aTarget
performSelector: aSelector
withObject: AUTORELEASE(map)];
[self addOperation: top];
}
- (void) addOperationWithTarget: (id<NSObject>)aTarget
performSelector: (SEL)aSelector
withObject: (id<NSObject>)object1

View file

@ -105,6 +105,10 @@ int main()
NSOperationQueue *q;
int i;
NSMutableArray *a;
NSTimeInterval s;
NSTimeInterval f;
NSUInteger ran;
NSUInteger want;
# if __has_feature(blocks)
__block BOOL blockDidRun = NO;
#endif
@ -128,23 +132,32 @@ int main()
[obj release];
// multiple concurrent operations
s = [NSDate timeIntervalSinceReferenceDate];
[q setMaxConcurrentOperationCount: 10];
a = [NSMutableArray array];
for (i = 0; i < 5; ++i)
want = 200;
ran = 0;
for (i = 0; i < want; ++i)
{
obj = [[MyOperation alloc] initWithValue: i];
[a addObject: obj];
[q addOperation: obj];
}
[q waitUntilAllOperationsAreFinished];
f = [NSDate timeIntervalSinceReferenceDate];
PASS(([obj isFinished] == YES), "operation ran");
PASS(([obj isExecuting] == NO), "operation is not executing");
for (i = 0; i < 5; ++i)
for (i = 0; i < want; ++i)
{
obj = [a objectAtIndex: i];
PASS(([obj getCalculation] == (2*i)), "operation was performed");
if ([obj getCalculation] == (2*i))
{
ran++;
}
}
PASS((ran == want), "many operations, all were performed")
PASS((f - s) < 0.1, "many operations, duration was reasonably small")
// multiple concurrent operations
[q setMaxConcurrentOperationCount: 5];

View file

@ -0,0 +1,77 @@
#import <Foundation/Foundation.h>
#import <GNUstepBase/NSOperationQueue+GNUstepBase.h>
#import "ObjectTesting.h"
@interface MyClass : NSObject
{
unsigned counter;
}
- (void) count: (NSMapTable*)map;
- (unsigned) counter;
- (void) increment;
- (void) reset;
@end
@implementation MyClass
- (void) count: (NSDictionary*)map
{
unsigned c = [map count];
// NSLog(@"Count %u for %@", c, map);
counter += c;
}
- (unsigned) counter
{
return counter;
}
- (void) increment
{
counter = counter + 1;
}
- (void) reset
{
counter = 0;
}
@end
int main()
{
ENTER_POOL
NSOperationQueue *q;
NSUInteger i;
NSUInteger ran;
NSUInteger want;
NSTimeInterval s;
NSTimeInterval f;
MyClass *o = AUTORELEASE([[MyClass alloc] init]);
q = AUTORELEASE([[NSOperationQueue alloc] init]);
[q setMaxConcurrentOperationCount: 1];
ran = 0;
want = 200;
s = [NSDate timeIntervalSinceReferenceDate];
for (i = 0; i < want; i++)
{
[q addOperationWithTarget: o
performSelector: @selector(increment)];
}
[q waitUntilAllOperationsAreFinished];
f = [NSDate timeIntervalSinceReferenceDate];
PASS([o counter] == want, "expected number of operations")
PASS((f - s) < 0.1, "duration was reasonable")
[o reset];
[q addOperationWithTarget: o
performSelector: @selector(count:)
withMap:
@"Key1", @"Val1",
@"Key2", @"Val2",
@"Key3", @"Val3",
nil];
[q waitUntilAllOperationsAreFinished];
PASS([o counter] == 3, "map had three keys")
LEAVE_POOL
return 0;
}