Browse files

asActor now always returns the same actor for a given instance

  • Loading branch information...
1 parent a848ec9 commit c46d1d4be9f1e3db8aaafb53ace7d6bb57bc3e9c @stevedekorte committed Sep 14, 2011
BIN .DS_Store
Binary file not shown.
Oops, something went wrong.
@@ -20,10 +20,11 @@
NSThread *actorThread;
+// all private
@property (retain, atomic) id actorTarget;
@property (retain, atomic) Mutex *actorMutex;
@property (retain, atomic) FutureProxy *firstFuture;
@property (retain, atomic) NSThread *actorThread;
@@ -18,18 +18,18 @@
BOOL done;
NSMutableSet *futureWaitingThreads;
NSException *futureException;
- Mutex *futureLock;
+ Mutex *futureLock; // used to pause any threads accessing future before it is done
// these are all private
-@property (assign, nonatomic) id futureActor;
-@property (retain, nonatomic) NSInvocation *futureInvocation;
-@property (retain, nonatomic) id futureValue;
-@property (retain, nonatomic) id nextFuture;
-@property (retain, nonatomic) NSMutableSet *futureWaitingThreads;
-@property (retain, nonatomic) NSException *futureException;
-@property (retain, nonatomic) Mutex *futureLock;
+@property (assign, atomic) id futureActor;
+@property (retain, atomic) NSInvocation *futureInvocation;
+@property (retain, atomic) id futureValue;
+@property (retain, atomic) id nextFuture;
+@property (retain, atomic) NSMutableSet *futureWaitingThreads;
+@property (retain, atomic) NSException *futureException;
+@property (retain, atomic) Mutex *futureLock;
- (void)futureAppend:(FutureProxy *)aFuture;
- (void)futureSend;
@@ -140,7 +140,6 @@ - (void)futureRaiseExceptionIfDeadlock
[NSException raise:@"Future" format:@"waiting for result on this coroutine would cause a deadlock"];
- futureResult
@@ -7,15 +7,24 @@
#import "NSObject+Actor.h"
-//#import <objc/runtime.h>
+#import <objc/runtime.h>
@implementation NSObject (NSObject_Actor)
+static char *actorKey = "actor";
- (ActorProxy *)asActor
- ActorProxy *ap = [[[ActorProxy alloc] init] autorelease];
- [ap setActorTarget:self];
- return ap;
+ ActorProxy *actor = objc_getAssociatedObject(self, actorKey);
+ if(!actor)
+ {
+ actor = [[[ActorProxy alloc] init] autorelease];
+ [actor setActorTarget:self];
+ objc_setAssociatedObject(self, actorKey, actor, OBJC_ASSOCIATION_ASSIGN);
+ }
+ return actor;
@@ -48,7 +48,7 @@ - (Mutex *)lock
Mutex *lock = [[self threadDictionary] objectForKey:@"lock"];
- if (!lock)
+ if (lock == nil)
lock = [[[NSLock alloc] init] autorelease];
[self setLock:lock];
@@ -1,27 +1,36 @@
- ActorKit allows any object to become an actor.
+ ActorKit is a framework supporting multithreaded actors with transparent futures in Objective-C.
- Each actor has an os thread and a queue of incoming messages which it processes in
- first-in-first-out order.
+ Sending an "asActor" message to any object returns an actor proxy for the object.
- Any message to an actor returns a "future" object which is a proxy for the result
- and only blocks when it is accessed if the result isn't ready.
+ Each actor spawns an os thread to process it's queue of messages.
+ Sending messages to the actor will queue them to be processed in first-in-first-out order
+ by the actor's thread and immediately returns a "future" object.
- Futures detect and raise an exception in situations that would cause a deadlock.
+ A future is a proxy for the result. If it is accessed before the result is ready, it
+ pauses any calling threads until it is ready. After it is ready, it acts as a transparent
+ proxy for the result, passing messages to the result as if the future were the same object.
+ Futures detect and raise an exception in situations where pausing the calling thread
+ would cause a deadlock.
// these spawn threads for each actor to and return immediately
NSData *future1 = [(NSURL *)[[NSURL URLWithString:@""] asActor] fetch];
NSData *future2 = [(NSURL *)[[NSURL URLWithString:@""] asActor] fetch];
+ // ... do stuff that doesn't need to wait on the results ...
// now when we try to access the values, they block if the values aren't ready
NSLog(@"request 1 returned %i bytes", (int)[future1 length]);
NSLog(@"request 2 returned %i bytes", (int)[future2 length]);
@@ -51,11 +60,14 @@ Notes:
When an actor finishes processing it's message queue, it's thread
is paused until a new message is added to the queue.
+ Objects store their actor proxies as an associated object so the same
+ actor is returned for multiple calls of asActor on the same instance.
- Thanks to Mark Papadakis for help with figuring out how to properly use mutex conditions.
+ Thanks to Mark Papadakis for help me figure out how to properly use mutex conditions.

0 comments on commit c46d1d4

Please sign in to comment.