Skip to content

Commit

Permalink
working with proxies
Browse files Browse the repository at this point in the history
  • Loading branch information
stevedekorte committed Sep 13, 2011
1 parent 155e24a commit 050bea1
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 193 deletions.
5 changes: 3 additions & 2 deletions ActorKit/ActorKit.h
Expand Up @@ -6,6 +6,7 @@
// Copyright 2011 Steve Dekorte. BSD licensed.
//

#import "Future.h"
#import "NSObject+Actor.h"
#import "ActorProxy.h"
#import "FutureProxy.h"
#import "NSThread+Actor.h"
#import "NSObject+Actor.h"
27 changes: 27 additions & 0 deletions ActorKit/ActorProxy.h
@@ -0,0 +1,27 @@
//
// NSObject+Actor.h
// ActorKit
//
// Created by Steve Dekorte on 20110831.
// Copyright 2011 Steve Dekorte. BSD licensed.
//

#import "FutureProxy.h"
#import "Mutex.h"
#import "NSThread+Actor.h"

@interface ActorProxy : NSProxy
{
id actorTarget;
Mutex *mutex;
FutureProxy *firstFuture;
NSThread *actorThread;
}

@property (retain, atomic) id actorTarget;
@property (retain, atomic) Mutex *mutex;
@property (retain, atomic) FutureProxy *firstFuture;
@property (retain, atomic) NSThread *actorThread;


@end
134 changes: 134 additions & 0 deletions ActorKit/ActorProxy.m
@@ -0,0 +1,134 @@
//
// NSObject+Actor.m
// ActorKit
//
// Created by Steve Dekorte on 20110831.
// Copyright 2011 Steve Dekorte. BSD licensed.
//

#import "ActorProxy.h"


@implementation ActorProxy

@synthesize actorTarget;
@synthesize mutex;
@synthesize firstFuture;
@synthesize actorThread;

- init
{
return self;
}

- (NSThread *)actorThreadCreateOrResumeIfNeeded
{
NSThread *thread = [self actorThread];

if(!thread)
{
[self setMutex:[[[Mutex alloc] init] autorelease]];
thread = [[[NSThread alloc] initWithTarget:self selector:@selector(actorRunLoop:) object:nil] autorelease];
[self setActorThread:thread];
[thread setName:[NSString stringWithFormat:@"%@", [actorTarget className]]];
[thread start];
}
else
{
[[self mutex] resumeThread];
}

return thread;
}

- (void)dealloc
{
// threads retain the Future's they are waiting on, which retains the actor
// so dealloc should only occur when it's safe of dependencies

if([self actorThread])
{
[[self actorThread] cancel];
}

[self setFirstFuture:nil];
[self setActorThread:nil];
[super dealloc];
}

- (FutureProxy *)futurePerformInvocation:(NSInvocation *)anInvocation
{
NSLock *lock = [[self actorThread] lock];
[lock lock];

FutureProxy *future = [[[FutureProxy alloc] init] autorelease];

[future setActor:self];
[future setFutureInvocation:anInvocation];
[anInvocation retainArguments];

if([self firstFuture])
{
[[self firstFuture] futureAppend:future];
}
else
{
[self setFirstFuture:future];
}

[self actorThreadCreateOrResumeIfNeeded];
[lock unlock];

return future;
}

- (void)actorRunLoop:sender
{
NSLock *lock = [[self actorThread] lock];

if([NSThread currentThread] != [self actorThread])
{
[NSException raise:@"Actor" format:@"attempt to start actor loop from another thread"];
}

while(![[NSThread currentThread] isCancelled])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool

while([self firstFuture])
{
FutureProxy *f = [self firstFuture];
[f futureSend]; // exceptions are caught within the send method
[lock lock];
[self setFirstFuture:[f nextFuture]];
[lock unlock];
}

[pool release];

[[self mutex] pauseThread];
}
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
return YES;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if([[anInvocation methodSignature] methodReturnType][0] != '@')
{
[NSException raise:@"ActorProxy" format:[NSString stringWithFormat:@"'%@' only methods that return objects are supported", NSStringFromSelector([anInvocation selector])]];
}

FutureProxy *f = [self futurePerformInvocation:anInvocation];
[anInvocation setReturnValue:(void *)&f];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [actorTarget methodSignatureForSelector:aSelector];
}

@end
28 changes: 10 additions & 18 deletions ActorKit/Future.h → ActorKit/FutureProxy.h
Expand Up @@ -7,43 +7,35 @@

#import "Mutex.h"

@interface Future : NSObject
@interface FutureProxy : NSProxy
{
id actor;
SEL selector;
id argument;
NSInvocation *futureInvocation;
id value;
id nextFuture;
BOOL done;
NSMutableSet *waitingThreads;
NSException *exception;
NSError *error;
Mutex *lock;
id delegate;
SEL action;
}

// private

@property (assign, nonatomic) Mutex *lock;
@property (assign, nonatomic) id actor;
@property (assign, nonatomic) SEL selector;
@property (retain, nonatomic) id argument;
@property (retain, nonatomic) Mutex *lock;
@property (retain, nonatomic) NSInvocation *futureInvocation;
@property (retain, nonatomic) id value;
@property (retain, nonatomic) id nextFuture;
@property (retain, nonatomic) NSMutableSet *waitingThreads;
@property (retain, nonatomic) NSError *error;
@property (assign, nonatomic) id delegate;

- (void)append:(Future *)aFuture;
- (void)send;
- (void)setResult:(id)anObject;

// public

@property (retain, nonatomic) NSException *exception;

- result;
// private

- (void)futureAppend:(FutureProxy *)aFuture;
- (void)futureSend;
- (void)setFutureResult:(id)anObject;
- futureResult;


@end
64 changes: 35 additions & 29 deletions ActorKit/Future.m → ActorKit/FutureProxy.m
Expand Up @@ -6,25 +6,23 @@
// Copyright 2011 Steve Dekorte. BSD licensed.
//

#import "Future.h"
#import "ActorProxy.h"
#import "FutureProxy.h"
#import "NSThread+Actor.h"

@implementation Future
@implementation FutureProxy

@synthesize lock;
@synthesize actor;
@synthesize selector;
@synthesize argument;
@synthesize futureInvocation;
@synthesize value;
@synthesize nextFuture;
@synthesize waitingThreads;
@synthesize exception;
@synthesize error;
@synthesize delegate;

- (id)init
{
self = [super init];
//self = [super init];

if (self)
{
Expand All @@ -39,47 +37,49 @@ - (id)init
- (void)dealloc
{
[self setActor:nil];
[self setArgument:nil];
[self setFutureInvocation:nil];
[self setValue:nil];
[self setNextFuture:nil];
[self setWaitingThreads:nil];
[self setException:nil];
[self setError:nil];
[self setDelegate:nil];
[self setLock:nil];
[super dealloc];
}

- (void)append:(Future *)aFuture
- (void)futureAppend:(FutureProxy *)aFuture
{
if(nextFuture)
{
[nextFuture append:aFuture];
[nextFuture futureAppend:aFuture];
}
else
{
[self setNextFuture:aFuture];
}
}

- (void)send
- (void)futureShowSend
{
NSLog(@"FutureProxy send [%@ %@]\n",
[[actor actorTarget] className],
NSStringFromSelector([futureInvocation selector]));
}

- (void)futureSend
{
@try
{
/*
printf("Future send [%s %s%s]\n",
[[actor className] UTF8String],
[NSStringFromSelector(selector) UTF8String],
[[argument className] UTF8String]);
*/
id r = [actor performSelector:selector withObject:argument];
[self setResult:r];
id r;
//[self futureShowSend];
[futureInvocation invokeWithTarget:[actor actorTarget]];
[futureInvocation getReturnValue:(void *)&r];
[self setFutureResult:r];
}
@catch (NSException *e)
{
printf("exception\n");
[self setException:e];
[self setResult:nil];
[self setFutureResult:nil];
}

for(NSThread *waitingThread in waitingThreads)
Expand All @@ -91,7 +91,7 @@ - (void)send
[lock resumeThread];
}

- (void)setResult:(id)anObject
- (void)setFutureResult:(id)anObject
{
if(done)
{
Expand All @@ -101,11 +101,6 @@ - (void)setResult:(id)anObject
done = YES;

[self setValue:anObject];

if (delegate && action)
{
[delagate performSelector:action withObject:self];
}
}

- (BOOL)isWaitingOnCurrentThread
Expand All @@ -123,7 +118,7 @@ - (BOOL)isWaitingOnCurrentThread
return NO;
}

- result
- futureResult
{
if(done)
{
Expand Down Expand Up @@ -152,4 +147,15 @@ - (BOOL)isWaitingOnCurrentThread
return value;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
id r = [self futureResult];
[anInvocation invokeWithTarget:r];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [[self futureResult] methodSignatureForSelector:aSelector];
}

@end
11 changes: 2 additions & 9 deletions ActorKit/NSObject+Actor.h
Expand Up @@ -6,17 +6,10 @@
// Copyright 2011 Steve Dekorte. BSD licensed.
//

#import "Future.h"
#import "ActorProxy.h"

@interface NSObject (NSObject_Actor)

// private

- (void)actorRunLoop:sender;

// public

- (void)asyncPerformSelector:(SEL)selector withObject:anObject;
- (Future *)futurePerformSelector:(SEL)selector withObject:anObject;
- (ActorProxy *)asActor;

@end

0 comments on commit 050bea1

Please sign in to comment.