Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

working with proxies

  • Loading branch information...
commit 050bea1c1aaa1c5c10c30f66236d386eef512356 1 parent 155e24a
@stevedekorte authored
View
5 ActorKit/ActorKit.h
@@ -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
27 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
View
134 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
View
28 ActorKit/Future.h → ActorKit/FutureProxy.h
@@ -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
View
64 ActorKit/Future.m → ActorKit/FutureProxy.m
@@ -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,22 +37,20 @@ - (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
{
@@ -62,24 +58,28 @@ - (void)append:(Future *)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
View
11 ActorKit/NSObject+Actor.h
@@ -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
View
140 ActorKit/NSObject+Actor.m
@@ -7,146 +7,16 @@
//
#import "NSObject+Actor.h"
-#import "NSThread+Actor.h"
-#import <objc/runtime.h>
+//#import <objc/runtime.h>
@implementation NSObject (NSObject_Actor)
-- (void)setMutex:(Mutex *)aMutex
+- (ActorProxy *)asActor
{
- objc_setAssociatedObject(self, "mutex", aMutex, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ ActorProxy *ap = [[[ActorProxy alloc] init] autorelease];
+ [ap setActorTarget:self];
+ return ap;
}
-- (Mutex *)mutex
-{
- return (Mutex *)objc_getAssociatedObject(self, "mutex");
-}
-
-
-- (void)setFirstFuture:(Future *)aFuture
-{
- objc_setAssociatedObject(self, "firstFuture", aFuture, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-}
-
-- (Future *)firstFuture
-{
- return (Future *)objc_getAssociatedObject(self, "firstFuture");
-}
-
-
-- (void)setActorThread:(NSThread *)aThread
-{
- objc_setAssociatedObject(self, "actorThread", aThread, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-}
-
-- (NSThread *)actorThread
-{
- return (NSThread *)objc_getAssociatedObject(self, "actorThread");;
-}
-
-- (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:@"%@", [self className]]];
- [thread start];
- }
- else
- {
- [[self mutex] resumeThread];
- }
-
- return thread;
-}
-
-// still need to implement dealloc
-
-/*
-- (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];
-}
-*/
-
-- (Future *)newFuture
-{
- Future *future = [[[Future alloc] init] autorelease];
-
-
- return future;
-}
-
-- (void)asyncPerformSelector:(SEL)selector withObject:anObject
-{
- [self futurePerformSelector:selector withObject:anObject];
-}
-
-- (Future *)futurePerformSelector:(SEL)selector withObject:anObject
-{
- NSLock *lock = [[self actorThread] lock];
- [lock lock];
-
- Future *future = [self newFuture];
-
- [future setActor:self];
- [future setSelector:selector];
- [future setArgument:anObject];
-
- if([self firstFuture])
- {
- [[self firstFuture] append: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])
- {
- Future *f = [self firstFuture];
- [f send]; // exceptions are caught within the send method
- [lock lock];
- [self setFirstFuture:[f nextFuture]];
- [lock unlock];
- }
-
- [pool release];
-
- [[self mutex] pauseThread];
- }
-}
@end
Please sign in to comment.
Something went wrong with that request. Please try again.