Permalink
Browse files

working with proxies

  • Loading branch information...
1 parent 155e24a commit 050bea1c1aaa1c5c10c30f66236d386eef512356 @stevedekorte committed Sep 13, 2011
View
@@ -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"
View
@@ -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
View
@@ -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
@@ -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
@@ -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)
{
@@ -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)
@@ -91,7 +91,7 @@ - (void)send
[lock resumeThread];
}
-- (void)setResult:(id)anObject
+- (void)setFutureResult:(id)anObject
{
if(done)
{
@@ -101,11 +101,6 @@ - (void)setResult:(id)anObject
done = YES;
[self setValue:anObject];
-
- if (delegate && action)
- {
- [delagate performSelector:action withObject:self];
- }
}
- (BOOL)isWaitingOnCurrentThread
@@ -123,7 +118,7 @@ - (BOOL)isWaitingOnCurrentThread
return NO;
}
-- result
+- futureResult
{
if(done)
{
@@ -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
@@ -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
Oops, something went wrong.

0 comments on commit 050bea1

Please sign in to comment.