PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/ActorKit.h

http://plactorkit.googlecode.com/
C Header | 415 lines | 32 code | 37 blank | 346 comment | 0 complexity | 6bc9cec44b61027b5a53065095eaf5fd MD5 | raw file
  1. /*
  2. * Author: Landon Fuller <landonf@plausiblelabs.com>
  3. * Copyright (c) 2008 Plausible Labs Cooperative, Inc.
  4. * All rights reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use,
  10. * copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following
  13. * conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be
  16. * included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  20. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  22. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  23. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  25. * OTHER DEALINGS IN THE SOFTWARE.
  26. */
  27. #import <Foundation/Foundation.h>
  28. #include <TargetConditionals.h>
  29. #include <pthread.h>
  30. #import <mach/mach.h>
  31. #import <mach/semaphore.h>
  32. /**
  33. * @defgroup functions Functions Reference
  34. */
  35. /**
  36. * @defgroup constants Constants Reference
  37. */
  38. /**
  39. * @defgroup types Types Reference
  40. * @ingroup constants
  41. */
  42. /**
  43. * @defgroup enums Enumerations
  44. * @ingroup constants
  45. */
  46. /**
  47. * @defgroup globals Global Variables
  48. * @ingroup constants
  49. */
  50. /**
  51. * @defgroup exceptions Exceptions
  52. * @ingroup constants
  53. */
  54. /* Exceptions */
  55. extern NSString *PLActorException;
  56. /* Error Domain and Codes */
  57. extern NSString *PLActorErrorDomain;
  58. /**
  59. * NSError codes in the Plausible Actor error domain.
  60. * @ingroup enums
  61. */
  62. typedef enum {
  63. /** An unknown error has occured. If this
  64. * code is received, it is a bug, and should be reported. */
  65. PLActorErrorUnknown = 0,
  66. } PLActorError;
  67. /**
  68. * Per-actor unique transaction ID. May be used
  69. * to differentiate RPC requests.
  70. *
  71. * @ingroup types
  72. */
  73. typedef uint32_t PLActorTxId;
  74. /**
  75. * Used to specify a time interval, in milliseconds.
  76. * @ingroup types
  77. */
  78. typedef uint32_t PLActorTimeInterval;
  79. /**
  80. * @defgroup constants_plactor_timewait PLActorTimeInterval Constants
  81. *
  82. * Time interval constants.
  83. *
  84. * @ingroup constants
  85. * @{
  86. */
  87. /**
  88. * Wait forever.
  89. */
  90. #define PLActorTimeWaitForever -1
  91. /**
  92. * Do not wait.
  93. */
  94. #define PLActorTimeWaitNone 0
  95. /**
  96. * @} constants_plactor_timewait
  97. */
  98. /* iPhone does not have NSPredicate */
  99. #if !TARGET_OS_IPHONE
  100. #define HAVE_NSPREDICATE 1
  101. #endif
  102. /* Functions */
  103. /**
  104. * @ingroup functions
  105. *
  106. * A selective receive filter function. Must return YES if the message
  107. * matches the filter, or NO otherwise.
  108. *
  109. * @param message Message to test.
  110. * @param context User-supplied context.
  111. */
  112. typedef BOOL (*plactor_receive_filter_t) (id message, void *context);
  113. /* Library Includes */
  114. #import "PLActorKit.h"
  115. #import "PLActorProcess.h"
  116. #import "PLActorMessage.h"
  117. #import "PLActorRPC.h"
  118. #import "PLActorRPCProxy.h"
  119. #import "PLRunloopRPCProxy.h"
  120. /* Private API */
  121. #ifdef ACTOR_PRIVATE_API
  122. #import "PLActorQueue.h"
  123. #import "PLActorSimpleQueue.h"
  124. #import "PLActorWriteLockQueue.h"
  125. #import "PLActorLocalProcess.h"
  126. #import "PLSimpleActorProcess.h"
  127. #import "PLThreadedActorProcess.h"
  128. #endif /* ACTOR_PRIVATE_API */
  129. /**
  130. * @mainpage Plausible ActorKit
  131. *
  132. * @section intro_sec Introduction
  133. *
  134. * ActorKit provides an Objective-C implementation of asynchronous inter-thread message passing.
  135. *
  136. * The purpose of ActorKit is to facilitate the implementation of concurrent software on both the desktop (Mac OS X)
  137. * and embedded devices (iPhone OS). On the iPhone, thread-based concurrency is a critical tool in
  138. * achieving high interface responsiveness while implementing long-running and potentially computationally expensive
  139. * background processing. On Mac OS X, thread-based concurrency opens the door to leveraging the power of
  140. * increasingly prevalent multi-core desktop computers.
  141. *
  142. * To this end, ActorKit endeavours to provide easily understandable invariants for concurrent software:
  143. *
  144. * - All threads are actors.
  145. * - Any actor may create additional actors.
  146. * - Any actor may asynchronously deliver a message to another actor.
  147. * - An actor may synchronously wait for message delivery from another actor.
  148. *
  149. * As an actor may only synchronously receive messages, no additional concurrency primitives are required, such as mutexes or
  150. * condition variables.
  151. *
  152. * Building on this base concurrency model, ActorKit provides facilities for proxying Objective-C method invocations
  153. * between threads, providing direct, transparent, synchronous and asynchronous execution of Objective-C methods
  154. * on actor threads.
  155. *
  156. * @section actor_basics Actor Creation and Simple Message Passing
  157. *
  158. * @subsection actor_basics_messages Messages
  159. *
  160. * The Actor model of concurrency is fundamentally based on communication between isolated actors through
  161. * asynchronous message passing. In ActorKit, any Objective-C object conforming to the NSObject protocol may
  162. * be used as an inter-actor message, but message objects should be immutable to ensure thread safety. ActorKit, being written
  163. * in Objective-C, can not enforce message immutablity or full isolation of Actor threads. It is entirely possible to
  164. * pass mutable messages, or access mutable global variables. Like many other libraries implementing Actor message passing
  165. * semantics, isolation is maintained purely through convention.
  166. *
  167. * While ActorKit supports messaging with any Objective-C object, the PLActorMessage class provides generally useful
  168. * facilities such as unique message transaction ids, automatically determining the message sender, and including
  169. * additional message payloads.
  170. *
  171. * @subsection actor_basics_processes Actor Proceses
  172. *
  173. * In ActorKit, all threads are fully functioning actors -- including the "main" Cocoa thread. Each actor
  174. * is represented by a PLActorProcess instance, which may be passed to any other running actors, and is
  175. * used to send messages asynchronously to the given process.
  176. *
  177. * ActorKit ensures that all message reception within a given actor occurs serially, and provides
  178. * strict guarantees on message ordering -- messages M1 and M2 sent from actor A1 will be delivered to
  179. * actor A2 in the same order. However, delivery of messages from actor A1 may be interspersed
  180. * with delivery of messages sent by other actors:
  181. *
  182. * @msc
  183. * Actor1,Actor3,Actor2;
  184. * Actor1=>Actor3 [label="msg=\"M1\""];
  185. * Actor2=>Actor3 [label="msg=\"M3\""];
  186. * Actor1=>Actor3 [label="msg=\"M2\""];
  187. * @endmsc
  188. *
  189. * In the future, ActorKit may be extended to leverage Apple's Grand Central [1] to provide hybrid event/thread M:N scheduling
  190. * of actor execution on available cores, an approach presented by Philipp Haller and Martin Odersky and implemented
  191. * in Scala's Actor library [2].
  192. *
  193. * @subsection actor_basics_example A Simple Echo Actor
  194. *
  195. * @code
  196. * - (void) echo {
  197. * NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  198. * PLActorMessage *message;
  199. *
  200. * // Loop forever, receiving messages
  201. * while ((message = [PLActorKit receive]) != nil) {
  202. * // Echo the same message back to the sender.
  203. * [[message sender] send: message];
  204. *
  205. * // Flush the autorelease pool through every loop iteration
  206. * [pool release];
  207. * pool = [[NSAutoreleasePool alloc] init];
  208. * }
  209. *
  210. * [pool release];
  211. * }
  212. *
  213. * - (void) run {
  214. * // Spawn a new actor thread. This will return a process instance which may be used
  215. * // to deliver messages the new actor.
  216. * id<PLActorProcess> proc = [PLActorKit spawnWithTarget: self selector: @selector(echo:)];
  217. *
  218. * // Send a simple message to the actor.
  219. * [proc send: [PLActorMessage messageWithObject: @"Hello"]];
  220. *
  221. * // Wait for the echo
  222. * PLActorMessage *message = [PLActorKit receive];
  223. * }
  224. *
  225. * @endcode
  226. *
  227. * @section actor_rpc Sending Synchronous Messages with Actors
  228. *
  229. * In an Actor system where all messages are sent asynchronously, synchronous messaging may be achieved
  230. * with the following steps:
  231. *
  232. * - Allocate a unique transaction id
  233. * - Send a message with that transaction id
  234. * - Wait for a reply with a matching transaction id.
  235. *
  236. * Message Sequence:
  237. * @msc
  238. * Actor1,Actor2;
  239. * Actor1=>Actor2 [label="msg=\"Hello A2\" sender=Actor1 txid=5"];
  240. * --- [label="Actor1 Waiting for response"];
  241. * Actor1<=Actor2 [label="msg=\"Hello A1\" sender=Actor2 txid=5"];
  242. * @endmsc
  243. *
  244. * ActorKit provides facilities for handling this common usage scenario. Unique transaction ids may be generated
  245. * via the PLActorKit::createTransactionId method, and every PLActorMessage generates and uses a new transactionId.
  246. *
  247. * The PLActorRPC class utilizes the PLActorMessage's transaction id to wait for a reply on your behalf.
  248. *
  249. * Send a message, and wait for the reply:
  250. * @code
  251. * id<PLActorProcess> helloActor = [PLActorKit spawnWithTarget: self selector: @selector(helloActor:)];
  252. * PLActorMessage *message = [PLActorMessage messageWithObject: @"Hello"];
  253. * PLActorMessage *reply = [PLActorRPC sendRPC: message toProcess: helloActor];
  254. * @endcode
  255. *
  256. * @section actor_rpc_objc Transparently Proxying Objective-C Messages with Actors
  257. *
  258. * ActorKit provides two NSProxy subclasses which provide \b transparent proxying of Objective-C synchronous
  259. * and asynchronous method invocations via actor messaging. PLActorRPCProxy spawns a new actor to execute Objective-C
  260. * methods for a given object instance, while PLRunloopRPCProxy executes Objective-C methods on a provided NSRunLoop.
  261. *
  262. * In combination, these classes allow for safely and transparenty executing methods on Objective-C
  263. * instances from any thread:
  264. *
  265. * @code
  266. * NSString *actorString = [PLActorRPCProxy proxyWithTarget: @"Hello"];
  267. * NSString *runloopString = [PLRunloopRPCProxy proxyWithTarget: @"Hello" runLoop: [NSRunLoop mainRunLoop]];
  268. *
  269. * // Executes synchronously, via a newly created actor thread.
  270. * [actorString description];
  271. *
  272. * // Executes synchronously, on the main runloop.
  273. * [runloopString description];
  274. *
  275. * @endcode
  276. *
  277. * By default, PLActorRPCProxy and PLRunloopRPCProxy will execute methods synchronously, waiting
  278. * for completion prior to returning. In order to execute a method asynchronously -- allowing a long
  279. * running method to execute without waiting for completion -- it is necessary to mark methods for
  280. * asynchronous execution.
  281. *
  282. * The Objective-C runtime provides a number of type qualifiers that were intended for use in
  283. * implementing a Distributed Object system. Of particular note is the 'oneway' qualifier, which allows
  284. * us to specify that a method should be invoked asynchronously.
  285. *
  286. * When a method is declared with a return value of 'oneway void', the proxy classes will introspect this return
  287. * value, and execute the method asynchronously, without waiting for a reply:
  288. *
  289. * @code
  290. * - (oneway void) asyncMethod {
  291. * // Execute, asynchronously
  292. * }
  293. * @endcode
  294. *
  295. * @msc
  296. * Actor1, PLActorRPCProxy, Actor2;
  297. *
  298. * Actor1 => PLActorRPCProxy [label="[Actor2 asyncMethod]"];
  299. * PLActorRPCProxy => Actor2 [label="[Actor2 asyncMethod]"];
  300. * @endmsc
  301. *
  302. * @code
  303. * - (NSString *) synchronousMethod {
  304. * // Execute, synchronously
  305. * return @"Hello";
  306. * }
  307. * @endcode
  308. *
  309. * @msc
  310. * Actor1, PLActorRPCProxy, Actor2;
  311. *
  312. * Actor1 => PLActorRPCProxy [label="[Actor2 synchronousMethod]"];
  313. * PLActorRPCProxy => Actor2 [label="[Actor2 synchronousMethod]"];
  314. * --- [label="Actor1 waiting for result, Actor2 executing"];
  315. * Actor2 >> PLActorRPCProxy [label="Result: <NSString>"];
  316. * PLActorRPCProxy >> Actor1 [label="Result: <NSString>"];
  317. * @endmsc
  318. *
  319. * @subsection actor_rpc_objc_example A Simple Echo Actor with PLActorRPCProxy
  320. *
  321. * The following actor returns a proxy from its init method, ensuring that all methods
  322. * called on the object instance will occur via the actor thread.
  323. *
  324. * @code
  325. *
  326. * // An actor that responds to Objective-C messages either synchronously or asynchronously.
  327. * @implementation EchoActor
  328. *
  329. * - (id) init {
  330. * if ((self = [super init]) == nil)
  331. * return nil;
  332. *
  333. * // Launch our actor
  334. * id proxy = [[PLActorRPCProxy alloc] initWithTarget: self];
  335. *
  336. * // Release ourself, as the proxy has retained our object,
  337. * // and return our proxy to the caller
  338. * [self release];
  339. * return proxy;
  340. * }
  341. *
  342. * // Method is called asynchronously
  343. * - (oneway void) asynchronousEcho: (NSString *) text listener: (EchoListener *) echoListener {
  344. * [echoListener receiveEcho: text];
  345. * }
  346. *
  347. * // Method is called synchronously
  348. * - (NSString *) synchronousEcho: (NSString *) text {
  349. * return text;
  350. * }
  351. *
  352. * @end
  353. *
  354. * @endcode
  355. *
  356. * @section services Integration & Development Services
  357. * ActorKit is provided free of charge under the MIT license, and may be freely integrated with any application.
  358. * We can provide assistance with integrating our code in your own iPhone or Mac application, as well as development of additional features under
  359. * a license of your choosing.
  360. *
  361. * Contact Plausible Labs for more information: http://www.plausiblelabs.com
  362. *
  363. * @section References
  364. *
  365. * [1] Grand Central (technology), Wikipedia contributors, Wikipedia, The Free Encyclopedia, November 19, 2008, 17:13 UTC. Available from
  366. * <a href="http://en.wikipedia.org/w/index.php?title=Grand_Central_(technology)&oldid=252808705">http://en.wikipedia.org/w/index.php?title=Grand_Central_(technology)&oldid=252808705</a>. Accessed November 19, 2008.
  367. *
  368. * [2] Actors that Unify Threads and Events, Philipp Haller and Martin Odersky, LAMP-REPORT-2007-001, EPFL, January 2007. Available from
  369. * <a href="http://lamp.epfl.ch/~phaller/actors.html">http://lamp.epfl.ch/~phaller/actors.html</a>.
  370. */
  371. /**
  372. * @page error_handling Error Handling Programming Guide
  373. *
  374. * All returned errors will be a member of one of the below defined domains, however, new domains and error codes may be added at any time.
  375. * If you do not wish to report on the error cause, many methods support a simple form that requires no NSError argument.
  376. *
  377. * @section Error Domains, Codes, and User Info
  378. */