{"id":13550785,"url":"https://github.com/GlebBatykov/ossa","last_synced_at":"2025-04-03T00:34:54.815Z","repository":{"id":61974979,"uuid":"471119625","full_name":"GlebBatykov/ossa","owner":"GlebBatykov","description":"A simple package for working with multithreading, using an interface similar to Task in C#.","archived":false,"fork":false,"pushed_at":"2022-06-15T21:56:06.000Z","size":68,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T07:03:04.186Z","etag":null,"topics":["concurrency","dart","flutter","isolate","multithreading","task","thread"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GlebBatykov.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-17T19:42:15.000Z","updated_at":"2022-10-24T03:38:16.000Z","dependencies_parsed_at":"2022-10-24T13:45:29.750Z","dependency_job_id":null,"html_url":"https://github.com/GlebBatykov/ossa","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlebBatykov%2Fossa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlebBatykov%2Fossa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlebBatykov%2Fossa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GlebBatykov%2Fossa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GlebBatykov","download_url":"https://codeload.github.com/GlebBatykov/ossa/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246916735,"owners_count":20854511,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concurrency","dart","flutter","isolate","multithreading","task","thread"],"created_at":"2024-08-01T12:01:37.557Z","updated_at":"2025-04-03T00:34:49.803Z","avatar_url":"https://github.com/GlebBatykov.png","language":"Dart","readme":"\u003cdiv align=\"center\"\u003e\n\n[![pub package](https://img.shields.io/pub/v/ossa.svg?label=ossa\u0026color=blue)](https://pub.dev/packages/ossa)\n\n**Languages:**\n  \n[![English](https://img.shields.io/badge/Language-English-blue?style=?style=flat-square)](README.md)\n[![Russian](https://img.shields.io/badge/Language-Russian-blue?style=?style=flat-square)](README.ru.md)\n\n\u003c/div\u003e\n\n- [Introduction](#introduction)\n- [About Ossa](#about-ossa)\n- [Installing](#installing)\n- [What is Task](#what-is-task)\n  - [Task types](#task-types)\n  - [Task run](#task-run)\n  - [Get result](#get-result)\n  - [Passing data to task](#passing-data-to-task)\n  - [Task status](#task-status)\n- [Error handling](#error-handling)\n\n# Introduction\n\nEarlier, in order to simplify interactions with isolates in Dart, I started developing actor framework - [Theater](https://github.com/GlebBatykov/theater).\n\nHowever, not everyone can like both the actor model itself, which is implemented by isolates in Dart, and the actor framework.\n\nIn addition to Dart, I also write in C# and, as for me, it has a convenient wrapper for working with multithreading - Task.\n\nI decided to do something in Dart as similar as possible to Task in C#, but with some nuances due to the fact that isolates are still used under the hood.\n\n# About Ossa\n\nProvides a convenient wrapper for working with isolates similar to Task in C#.\n\n# Installing\n\nAdd Ossa to your pubspec.yaml file:\n\n```dart\ndependencies:\n  ossa: ^1.0.4\n```\n\nImport ossa in file that it will be used:\n\n```dart\nimport 'package:ossa/ossa.dart';\n```\n\n# What is Task\n\nEach task is started and runs in a separate isolate, tasks can return some result.\n\nAs already mentioned in the introduction, I tried to make the tasks as similar as possible to the Task in C#. However, there are differences.\n\nFor example, instead of a pool of isolates (in C#, a pool of threads) to which tasks are redirected and then executed, in Ossa, each task you create has its own isolate.\n\nEach task manages the lifecycle of its isolate.\n\n## Task types\n\nThere are two types of tasks:\n\n- one shot (default);\n- reusable.\n\nThe difference between these two types is that one shot tasks, after completing the task (including if the execution failed), call their dispose method, destroy their isolate and close all StreamController-s used by them, that is, releases all resources used by it. Reusable tasks do not do this, it is calculated that after creating a task you will use it repeatedly.\n\nWhy use a reused task instead of creating a new task in the future, if necessary? - so as not to create a new isolate every time.\n\n## Task run\n\nThere are two ways to start a task:\n\n- using the run method;\n- creating task, initializing it and running it yourself.\n\nExample of create and start task using the run method:\n\n```dart\nvoid main() async {\n  // Create and run Task using run method\n  var task = await Task.run((context) {\n    print('Hello, from task!');\n  });\n\n  // Wait when task is completed\n  await task.result();\n}\n```\n\nExample of create task, initializing it and starting:\n\n```dart\nvoid main() async {\n  // Create task\n  var task = Task((context) {\n    print('Hello, from task!');\n  });\n\n  // Initialize task before work with him\n  await task.initialize();\n\n  // Start task\n  await task.start();\n\n  // Wait when task is completed\n  await task.result();\n}\n```\n\n## Get result\n\nThe task can return the result of execution. When creating a task yourself, or creating and running using the run method, you can specify a Generic type that should return a Task.\n\nYou can process the result both asynchronously using the onDone handler, and wait for the result to be received using the Future received when calling the result method.\n\nThe result method, when the task is running, will wait for the result from the isolate, and then return it. If the task has already been completed at the time of calling the result method and has not been started again, it will return the result from the previous task run.\n\nGetting the result from the Future received when calling the result method:\n\n```dart\nvoid main() async {\n  // Create and run Task with double return type using run method\n  var task = await Task.run\u003cdouble\u003e((context) =\u003e 3 * 7);\n\n  // Wait result from Task\n  var result = await task.result();\n\n  print(result);\n}\n```\n\nExpacted output:\n\n```dart\n21\n```\n\nAsynchronous receipt of the result using the onDone handler:\n\n```dart\nvoid main() async {\n  // Create and run task with int return type, set onDone handler\n  var task = await Task.run\u003cint\u003e((context) {\n    return 5 * 10;\n  }, onDone: (value) async {\n    print(value);\n  });\n}\n```\n\nExpected output:\n\n```dart\n50\n```\n\n## Passing data to task\n\nEach task is executed in its own isolate. Isolates do not have shared memory with each other. Therefore, the data that the task should work with is passed to it using the data parameter in the run and start methods.\n\nExample of transferring data to a task:\n\n```dart\nvoid main() async {\n  // We have some data\n  var number = 100;\n\n  // Create and run task using run method, passing data to task\n  var task = await Task.run\u003cint\u003e((context) {\n    var number = context.get\u003cint\u003e('number');\n\n    return number * 10;\n  }, data: {'number': number});\n\n  // Wait when task is completed\n  var result = await task.result();\n\n  print(result);\n}\n```\n\nExpected output:\n\n```dart\n1000\n```\n\n## Task status\n\nA task has different statuses during its life cycle:\n\n- not initialized (notInitialized);\n- waiting to start (waitingToRun);\n- running (running);\n- paused (paused);\n- disposed (disposed).\n\nThe task is not initialized when created without using the run method, before executing the initialize method. At this point, the task isolate has not yet been created and requires initialization before the task can be executed.\n\nAfter starting the initialize method, the task is waiting to be started. It is ready to be executed and is waiting for the start method to be executed.\n\nThe task is in the execution status after the start method is executed, it can be paused (the task isolate is paused).\n\nIf the task is paused, then its execution can be resumed.\n\nAfter disposed the task, its isolate is destroyed, all Stream Controllers are closed. Further use of this task instance is not possible.\n\n# Error handling\n\nAn exception may occur during the execution of the task.\n\nThere are options for processing it:\n\n- processing using the onError handler;\n- conclusion of a part of the code with the expectation of a result in try/catch.\n\nExample of handling an exception using the onError handler, asynchronously processing the result of the task execution:\n\n```dart\nvoid main() async {\n  late Task task;\n\n  // Create and run Task using run method, set onError handler\n  task = await Task.run\u003cvoid\u003e((context) {\n    throw FormatException();\n  }, onError: (error) async {\n    print(error.object.toString());\n\n    task.dispose();\n  });\n}\n```\n\nIf the onError handler was not set at the start of the task, then there are 2 scenarios what will happen to it:\n\n- if you are waiting for the result of the task asynchronously, that is, using the onDone handler, then nothing will happen, the exception will not be handled in any way. The task will change from the running status to the ready for execution status (waitingToRun);\n- if you are waiting for the result of the task using the result method, the exception will be called again called already in the result method.\n\nExample of handling an exception without onError handler, waiting for the result using the result method:\n\n```dart\nvoid main() async {\n  // Create and run Task using run method\n  var task = await Task.run((context) {\n    throw FormatException();\n  });\n\n  try {\n    // Wait when task is completed\n    await task.result();\n  } catch (object) {\n    // Handle error\n\n    if (object is TaskCompleteException) {\n      print(object);\n\n      await task.dispose();\n    }\n  }\n}\n```\n","funding_links":[],"categories":["Dart"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGlebBatykov%2Fossa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGlebBatykov%2Fossa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGlebBatykov%2Fossa/lists"}