Giter Club home page Giter Club logo

actorkit's Introduction

ActorKit

Version License Platform CI Status

A lightweight actor framework in Objective-C.

Features

  • Actors
  • Actor Pools
  • Synchronous and asynchronous invocations
  • Promises
  • Notification subscription and publication
  • Supervision
  • Linking

Requirements

  • iOS 8.0
  • watchOS 2.0
  • tvOS 9.0
  • OS X 10.10

Installation

ActorKit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'ActorKit'

Usage

Any object derived from NSObject can be turned into an actor by importing <ActorKit/ActorKit.h>.

`#import <ActorKit/ActorKit.h>`
Worker *worker = [[Worker alloc] initWithName:@"Bee"];
NSMutableArray *array = [NSMutableArray new];

As soon as you start sending messages to them as described below they will behave like actors automatically. There is nothing else you have to do.

Sending Messages to Actors

To send a synchronous message to the actor precede the call with sync:

BOOL success = [worker.sync doSomething];

Send an asynchronous message to the actor use async:

[array.async removeAllObjects];

Publishing notifications to other actors

Publish a notification with a payload:

[self publish:@"notification" payload:@5];

Subscribing to notifications from other actors

To subscribe to a notification set the notification name and a selector which takes the notification's payload as an argument:

[worker subscribe:@"notification" selector:@selector(handler:)];

- (void)handler:(NSNumber *)number
{
    // ...
}

To unsubscribe from a notification:

[worker unsubscribe:@"notification"];

Before destroying an actor you should unsubscribe from all notifications.

Actor Pools

The class TBActorPool is basically a proxy actor which mananges multiple actors of the same type. A message which is send to the pool will be forwarded to an actor inside the pool which has the lowest workload at the time the message is processed.

You can create an actor pool by invoking the method below on the class of your choice. An actor instance will be created and passed into the configuration block for further initialization:

TBActorPool *pool = [Worker poolWithSize:10 configuration:^(NSObject *actor) {
    Worker *worker = (Worker *)actor;
    worker.name = @"worker";
    worker.Id = @(123);
}];

You can send messages to the pool:

[pool.sync setName:@"worker"];
[pool.async doSomething];

Same goes for subscriptions:

[pool subscribe:@"notificationToWorkers" selector:@selector(handler:)];
[pool unsubscribe:@"notificationToWorkers"];

The handler will be executed by an available actor in the pool.

Broadcasts

To send an asynchronous message to all actors inside the pool:

[pool.broadcast ping];

Promises

Promise support using PromiseKit is available via the subspec Promises:

target 'MyApp', :exclusive => true do
  pod 'ActorKit/Promises'
end
#import <ActorKit/Promises.h>

Send a asynchronous message and receive a promise back:

((AnyPromise *)[worker.promise returnSomethingBlocking])
.then(^(id result) {
    
    // ...
});

Supervision and Linking of Actors

Supervision and Linking is available via the subspec Supervision:

target 'MyApp', :exclusive => true do
  pod 'ActorKit/Supervision'
end
#import <ActorKit/Supervision.h>

Supervised Actors

You can create supervised actors by passing an id and a creation block to a supervision pool:

TBActorSupervisionPool *actors = [TBActorSupervisionPool new];

[actors superviseWithId:@"master" creationBlock:^NSObject * {
    Worker *worker = Worker.new;
    worker.name = @"master";
    worker.Id = @(123);
    return worker;
}];

The creation block will be called whenever the actor needs to be (re)created.

Accessing Actors Inside the Supervision Pool

Access the supervised actor by its id on the supervision pool:

[actors[@"master"].sync doSomething];

Unsupervising Actors

To remove an actor from a supervision pool:

[actors unsuperviseActorWithId:@"master"];

Linking Actors

Links establish parent-child relationships between actors. Linked actors will be supervised depending on each other. If the parent actor crashes the child actor will be re-created as well. Whenever an actor is removed from the supervision pool its linked actors are removed as well.

[actors linkActor:@"child" toParentActor:@"master"];

To remove a link:

[actors unlinkActor:@"child" fromParentActor:@"master"];

Recovering from Crashes

Whenever a supervised actor crashes it is re-created and will resume processing pending messages from its mailbox.

Special behavior for pools:

  • when the pool actor itself crashes the whole pool is recreated completely and the content of all mailboxes will be processed by the new pool instance
  • when an actor inside the pool crashes only that instance is recreated and its mailbox content will be processed by its successor

You can also communicate a crash manually by calling crashWithError::

@implementation Worker

- (void)doSomething
{
    NSError *error = nil;
    [self _doSomethingInternal:&error];
    if (error) {
        [self crashWithError:error];
    }
}

@end

Attention: Cocoa is not a framework which employs exceptions as a legitimate means to communicate errors. There are a lot of layers which prevent exceptions to bubble up the stack until they can be handled by the supervisor (GCD etc.). So be prepared for exceptions which still can crash the application.

Warning: Scheduling your own operations on the actor queue directly is strongly discouraged since the supervision can not guarantee that this operations can be executed properly by the new actor instance.

Architecture

This framework seeks for a very simple implementation of actors. It basically consists of a category which lazily adds an NSOperationQueue to the NSObject which should work as an actor. Messages sent to the actor are forwarded by an NSProxy using NSInvocation and NSOperation objects. These classes represent mailboxes, threads and messages etc.

Example Project

To run the example project, clone the repo, and run pod install from the ./ActorKit directory first.

Useful Theory on Actors

Author

Julian Krumow, [email protected]

License

ActorKit is available under the MIT license. See the LICENSE file for more info.

actorkit's People

Contributors

dependabot[bot] avatar jkrumow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

actorkit's Issues

code

Worker *worker = [[Worker alloc] initWithName:@"Bee"];

where initWithName ??

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.