An open API service indexing awesome lists of open source software.

https://github.com/bitsydarel/executorservices

Dart executer services.
https://github.com/bitsydarel/executorservices

dart dart-library flutter isolate multithreading

Last synced: 6 months ago
JSON representation

Dart executer services.

Awesome Lists containing this project

README

          

[![Pub.dev](https://img.shields.io/pub/v/executorservices.svg?style=flat-square&logo=data:image/png;base64,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)](https://pub.dartlang.org/packages/executorservices) [![License](https://img.shields.io/github/license/bitsydarel/executorservices?style=flat-square&logo=github)](https://github.com/modulovalue/dart_fenwick_tree/blob/master/LICENSE)

A library for Dart and Flutter developers.

[license](https://github.com/bitsydarel/executorservices/blob/master/LICENSE).

## Description
It allows you to execute code in isolates or any executor currently supported.

Support concurrent execution of tasks or functions.

Support cleanup of unused isolates.

Support caching of isolate that allow you to reuse them (like thread).

It's extendable.

## Usage

### For tasks that return either a value or an error:

For submitting a top level or static function without arguments to the executorservice.
For task that return a value or a future the executorService.submit* return a future, to track the progress of the task.
```dart
import "dart:math";
import "package:executorservices/executorservices.dart";

void main() {
final executorService = ExecutorService.newSingleExecutor();

final Future futureResult = executorService.submitAction(_randomInt);

futureResult.then((result) => print(result));
}

int _randomInt() {
return Random.secure().nextInt(1000);
}
```

For submitting a top level or static function with one argument to the executorservice.
```dart
import "package:executorservices/executorservices.dart";

void main() {
final executorService = ExecutorService.newSingleExecutor();

final Future futureResult = executorService.submitCallable(expensiveHelloWorld, "Darel Bitsy");

futureResult.then((result) => print(result));
}

Future expensiveHelloWorld(final String name) async {
await Future.delayed(Duration(seconds: 1));
return "Hellow world $name";
}
```

For submitting a top level or static function with many other arguments to the executorservice.
The executorservice provide method like submitFunction2,submitFunction3,submitFunction4.
```dart
import "package:executorservices/executorservices.dart";

void main() {
final executorService = ExecutorService.newSingleExecutor();

final Future futureResult = executorService.submitFunction2(
expensiveHelloWorld,
"Darel Bitsy",
23,
);

futureResult.then((result) => print(result));
}

Future expensiveHelloWorld(final String name, final int age) async {
await Future.delayed(Duration(seconds: 1));
if (age >= 80) {
return "Hellow world elder $name";
} else {
return "Hellow world $name";
}
}
```

If you want to run a instance method of a existing class you need to make it extend the Task class.
If if you want to have more than five arguments function.
If you don't want to have the code as top level or static function.
```dart
import "dart:async";
import "dart:isolate";

import "package:executorservices/executorservices.dart";
import "package:http/http.dart" as http;

void main() {
final executorService = ExecutorService.newSingleExecutor();

final Future futureResult = executorService.submit(
GetPost("https://jsonplaceholder.typicode.com/posts", 5),
);

futureResult.then(
(result) => print(
"Recieved $result and it's running from ${Isolate.current.debugName}",
),
);
}

class GetPost extends Task {
GetPost(this.apiUrl, this.index);

final String apiUrl;
final int index;

@override
FutureOr execute() {
return http
.get("$apiUrl/$index")
.then((postResponse) => postResponse.body)
.then(
(json) {
print(
"about to return $json and it's running from ${Isolate.current.debugName}",
);
return json;
},
);
}
}
```

A example of chaining tasks.
```dart
import "dart:async";
import "dart:math";

import "package:executorservices/executorservices.dart";
import "package:http/http.dart" as http;

void main() {
final executorService = ExecutorService.newSingleExecutor();

executorService
.submitFunction2(_fullName, "Darel", "Bitsy")
.then(
(fullName) {
print("Hi, $fullName");
return executorService.submitAction(randomPostId);
},
)
.then(
(postId) => executorService.submit(
GetPost("https://jsonplaceholder.typicode.com/posts", postId),
),
)
.then(print);
}

int randomPostId() {
return Random.secure().nextInt(10);
}

Future _fullName(final String firstName, final String lastName) async {
await Future.delayed(Duration(milliseconds: 500));
return "$firstName, $lastName";
}

class GetPost extends Task {
GetPost(this.apiUrl, this.index);

final String apiUrl;
final int index;

@override
FutureOr execute() {
return http.get("$apiUrl/$index").then((postResponse) => postResponse.body);
}
}
```

### For tasks that emit events (Code that return a stream):

For executing to a top level or static function without arguments that return a stream to the executorservice.
```dart
import "dart:async";
import "dart:isolate";
import "dart:math";

import "package:executorservices/executorservices.dart";

void main() {
final executorService = ExecutorService.newSingleExecutor();

final Stream streamOfRandomNumber =
executorService.subscribeToAction(randomGenerator);

streamOfRandomNumber.listen(
(newData) => print(
"Received $newData and it's running on isolate: ${Isolate.current.debugName}",
),
onError: (error) => print(
"Received ${error.toString()} and it's running on isolate: ${Isolate.current.debugName}",
),
onDone: () => print(
"Task's done and it's running on isolate: ${Isolate.current.debugName}",
),
);
}

Stream randomGenerator() async* {
for (var i = 0; i < Random.secure().nextInt(10); i++) {
await Future.delayed(Duration(seconds: 1));
print(
"about to yield $i and it's running from ${Isolate.current.debugName}",
);
yield i;
}
}
```

Here are the analogical method for other type of top level, or static functions:
subscribeToCallable, subscribeToFunction2, subscribeToFunction3, subscribeToFunction4

If you want to run a instance method of a existing class you need to make it extend the SubscribableTask class.
If if you want to have more than five arguments function.
If you don't want to have the code as top level or static function.

```dart
import "dart:async";
import "dart:isolate";

import "package:executorservices/executorservices.dart";
import "package:http/http.dart" as http;

void main() {
final executorService = ExecutorService.newSingleExecutor();

final Stream streamOfPosts = executorService.subscribe(
GetPosts("https://jsonplaceholder.typicode.com/posts", 10),
);

streamOfPosts.listen(
(newData) => print(
"Received $newData and it's running on isolate: ${Isolate.current.debugName}",
),
onError: (error) => print(
"Received ${error.toString()} and it's running on isolate: ${Isolate.current.debugName}",
),
onDone: () => print(
"Task's done and it's running on isolate: ${Isolate.current.debugName}",
),
);
}

class GetPosts extends SubscribableTask {
GetPosts(this.apiUrl, this.maxPosts);

final String apiUrl;
final int maxPosts;

@override
Stream execute() async* {
for (var index = 0; index < maxPosts; index++) {
final postJson = await http
.get("$apiUrl/$index")
.then((postResponse) => postResponse.body);

print(
"about to yield $postJson and "
"it's running from ${Isolate.current.debugName}",
);

yield postJson;
}
}
}
```

A example of chaining tasks of different type together.
```dart
import "dart:async";
import "dart:io";

import "package:executorservices/executorservices.dart";
import "package:http/http.dart" as http;

void main() {
final executorService = ExecutorService.newUnboundExecutor();

executorService
.subscribeToAction(randomPostIds)
.asyncMap((randomPostId) => executorService.submit(GetPost(randomPostId)))
.listen(
(newData) => print("Received $newData"),
onError: (error) => print("Received ${error.toString()}"),
onDone: () {
print("Task's done");
exit(0);
},
);
}

Stream randomPostIds() async* {
for (var index = 0; index < 10; index++) {
await Future.delayed(Duration(milliseconds: 100));
yield index;
}
}

class GetPost extends Task {
GetPost(this.postId);

final int postId;

@override
Future execute() {
return http
.get("https://jsonplaceholder.typicode.com/posts/$postId")
.then((postResponse) => postResponse.body);
}
}
```

By default you can't re-submit the same instance of a ongoing Task to a ExecutorService multiple times.
Because the result of your submitted task is associated with the task instance identifier.
So by default submitting the same instance of a task multiple times will result in unexpected behaviors.

For example, this won't work:

```dart
main() {
final executors = ExecutorService.newUnboundExecutor();

final task = SameInstanceTask();

executors.submit(task);
executors.submit(task);
executors.submit(task);

for (var index = 0; index < 10; index++) {
executors.submit(task);
}
}

class SameInstanceTask extends Task {
@override
FutureOr execute() async {
await Future.delayed(Duration(seconds: 5));
return "Done executing same instance task";
}
}
```

But if you want to submit the same instance of a task multiple times you need to override the Task is clone method.

For example, this will now work:
```dart
main() {
final executors = ExecutorService.newUnboundExecutor();

final task = SameInstanceTask();

for (var index = 0; index < 10; index++) {
executors.submit(task);
}

final taskWithParams = SameInstanceTaskWithParams("Darel Bitsy");

for (var index = 0; index < 10; index++) {
executors.submit(taskWithParams);
}
}

class SameInstanceTask extends Task {
@override
FutureOr execute() async {
await Future.delayed(Duration(minutes: 5));
return "Done executing same instance task";
}

@override
SameInstanceTask clone() {
return SameInstanceTask();
}
}

class SameInstanceTaskWithParams extends Task {
SameInstanceTaskWithParams(this.name);

final String name;

@override
FutureOr execute() async {
await Future.delayed(Duration(minutes: 5));
return "Done executing same instance task with name: $name";
}

@override
SameInstanceTaskWithParams clone() {
return SameInstanceTaskWithParams(name);
}
}
```

## Features and bugs

Please file feature requests and bugs at the [issue tracker][tracker].

[tracker]:https://github.com/bitsydarel/executorservices/issues