LCOV - code coverage report
Current view: top level - src - combine_worker_singleton.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 9 9 100.0 %
Date: 2022-12-12 00:09:36 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:isolate';
       3             : 
       4             : import 'package:combine/src/combine_isolate/combine_isolate.dart';
       5             : import 'package:combine/src/combine_singleton.dart';
       6             : import 'package:combine/src/combine_worker/combine_worker_impl.dart';
       7             : import 'package:combine/src/combine_worker/tasks.dart';
       8             : import 'package:flutter/foundation.dart';
       9             : 
      10             : const defaultTasksPerIsolate = 2;
      11             : const defaultIsolatePrefix = 'combine-worker';
      12             : 
      13             : /// {@template combine_worker_singleton}
      14             : /// Combine Worker is a pool of [CombineIsolate]s that efficiently executes
      15             : /// tasks in them. It is primarily used to reduce the number of isolates
      16             : /// and provide more performant and easy way to execute tasks.
      17             : ///
      18             : /// In comparison to Fluter's [compute] method which creates an isolate each time
      19             : /// it's called, Combine Worker creates a pool of isolates and efficiently
      20             : /// reuses them. At the same time, it has all of the advantages of [CombineIsolate],
      21             : /// allowing you to work with platform channels in an isolate.
      22             : ///
      23             : /// If you want to create a single [CombineIsolate], take a look at [Combine].
      24             : /// {@endtemplate}
      25             : abstract class CombineWorker {
      26             :   /// {@macro combine_worker_singleton}
      27           2 :   factory CombineWorker() => _instance;
      28             : 
      29             :   /// Creates a new instance of the [CombineWorker].
      30           2 :   factory CombineWorker.newInstance() => CombineWorkerImpl();
      31             : 
      32           3 :   static late final _instance = CombineWorker.newInstance();
      33             : 
      34             :   /// {@template combine_worker_initialize}
      35             :   /// Initializes worker.
      36             :   ///
      37             :   /// Worker manager can be lazily initialized on the first execution,
      38             :   /// so you can omit calling `initialize`.
      39             :   ///
      40             :   /// To initialize worker with a custom amount of isolates, use the
      41             :   /// [isolatesCount] parameter.
      42             :   /// Default value is calculated by the following formula:
      43             :   /// `max(1, (numberOfProcessors / 2).floor())`
      44             :   /// Please keep in mind that Flutter already uses 3 threads:
      45             :   /// Dart main, native main and GPU. So your [isolatesCount] should be less
      46             :   /// than `numberOfProcessors - 3`.
      47             :   ///
      48             :   /// Each isolate can execute one or more tasks asynchronously
      49             :   /// (thanks to async IO and event loop).
      50             :   /// [tasksPerIsolate] parameter is used to set maximum number of tasks that
      51             :   /// one isolate can perform asynchronously.
      52             :   ///
      53             :   /// [initializer] is a function that will be executed in the each worker
      54             :   /// isolate. It can be used to initialize something in the worker isolate.
      55             :   ///
      56             :   /// [isolatesPrefix] will be used to set isolates debug name. Debug name will
      57             :   /// be visible in the debugger.
      58             :   /// {@endtemplate}
      59             :   Future<void> initialize({
      60             :     int? isolatesCount,
      61             :     int tasksPerIsolate = defaultTasksPerIsolate,
      62             :     WorkerInitializer? initializer,
      63             :     String isolatesPrefix = defaultIsolatePrefix,
      64             :   });
      65             : 
      66             :   /// {@template combine_worker_execute}
      67             :   /// Executes given [task] in combine isolate.
      68             :   /// {@endtemplate}
      69             :   ///
      70             :   /// {@template combine_worker_execute_exception}
      71             :   /// This future may complete with:
      72             :   /// - [CombineWorkerClosedException] if you [close] worker
      73             :   ///   with `waitForRemainingTasks` flag set to `false`.
      74             :   /// - [UnsupportedIsolateArgumentError] if you send to/from isolate
      75             :   ///   some unsupported object like [ReceivePort].
      76             :   /// - an original exception thrown by the [task].
      77             :   /// {@endtemplate}
      78             :   Future<T> execute<T>(Task<T> task);
      79             : 
      80             :   /// {@template combine_worker_execute_with_arg}
      81             :   /// Executes given [task] with given [argument] in combine isolate.
      82             :   /// {@endtemplate}
      83             :   ///
      84             :   /// {@macro combine_worker_execute_exception}
      85             :   Future<T> executeWithArg<T, Q>(Task1<T, Q> task, Q argument);
      86             : 
      87             :   /// {@template combine_worker_execute_with_2_args}
      88             :   /// Executes given [task] with given [argument] and [argument2] in combine isolate.
      89             :   /// {@endtemplate}
      90             :   ///
      91             :   /// {@macro combine_worker_execute_exception}
      92             :   Future<T> executeWith2Args<T, Q, C>(
      93             :     Task2<T, Q, C> task,
      94             :     Q argument,
      95             :     C argument2,
      96             :   );
      97             : 
      98             :   /// {@template combine_worker_execute_with_multiple_args}
      99             :   /// Executes given [task] with given arguments in combine isolate.
     100             :   /// {@endtemplate}
     101             :   ///
     102             :   /// {@macro combine_worker_execute_exception}
     103             :   Future<T> executeWith3Args<T, Q, C, A>(
     104             :     Task3<T, Q, C, A> task,
     105             :     Q argument,
     106             :     C argument2,
     107             :     A argument3,
     108             :   );
     109             : 
     110             :   /// {@template combine_worker_execute_with_multiple_args}
     111             :   /// Executes given [task] with given arguments in combine isolate.
     112             :   /// {@endtemplate}
     113             :   ///
     114             :   /// {@macro combine_worker_execute_exception}
     115             :   Future<T> executeWith4Args<T, Q, C, A, B>(
     116             :     Task4<T, Q, C, A, B> task,
     117             :     Q argument,
     118             :     C argument2,
     119             :     A argument3,
     120             :     B argument4,
     121             :   );
     122             : 
     123             :   /// {@template combine_worker_execute_with_multiple_args}
     124             :   /// Executes given [task] with given arguments in combine isolate.
     125             :   /// {@endtemplate}
     126             :   ///
     127             :   /// {@macro combine_worker_execute_exception}
     128             :   Future<T> executeWith5Args<T, Q, C, A, B, D>(
     129             :     Task5<T, Q, C, A, B, D> task,
     130             :     Q argument,
     131             :     C argument2,
     132             :     A argument3,
     133             :     B argument4,
     134             :     D argument5,
     135             :   );
     136             : 
     137             :   /// {@template combine_worker_execute_with_multiple_args}
     138             :   /// Dynamically execute [task] with the specified arguments in combine isolate
     139             :   /// It works like [Function.apply].
     140             :   ///
     141             :   /// Acts the same as calling function with positional arguments
     142             :   /// corresponding to the elements of [positionalArguments] and
     143             :   /// named arguments corresponding to the elements of [namedArguments].
     144             :   ///
     145             :   /// This includes giving the same errors if [task] isn't callable or
     146             :   /// if it expects different parameters.
     147             :   ///
     148             :   /// Don't use this method while you can use [executeWith5Args],
     149             :   /// [executeWith4Args], [executeWith3Args] etc.
     150             :   /// These methods are typesafe unlike [executeWithApply].
     151             :   /// {@endtemplate}
     152             :   ///
     153             :   /// {@macro combine_worker_execute_exception}
     154             :   Future<T> executeWithApply<T>(
     155             :     TaskApply task,
     156             :     List<dynamic> positionalArguments, [
     157             :     Map<Symbol, dynamic>? namedArguments,
     158             :   ]);
     159             : 
     160             :   /// {@template combine_worker_close}
     161             :   /// Closes the current Worker.
     162             :   /// [CombineWorker] is a singleton but under the hood it uses a worker manager instance
     163             :   /// which can be closed and recreated. It may be useful if you want to cancel
     164             :   /// all running and awaiting tasks (i. e. on user logout).
     165             :   ///
     166             :   /// If `waitForRemainingTasks` flag is set to `true` then
     167             :   /// worker will be marked as closed but will finish all its tasks.
     168             :   /// Otherwise all remaining tasks will complete with [CombineWorkerClosedException].
     169             :   ///
     170             :   /// You can call [execute] or [initialize] methods without awaiting for this future.
     171             :   /// In that case new isolates' pool will be created.
     172             :   /// {@endtemplate}
     173             :   Future<void> close({bool waitForRemainingTasks = false});
     174             : }
     175             : 
     176             : /// Typedef for the function that will be executed in the each worker isolate.
     177             : typedef WorkerInitializer = FutureOr<void> Function();
     178             : 
     179             : class CombineWorkerClosedException implements Exception {
     180           1 :   @override
     181             :   String toString() {
     182             :     return "The CombineWorker has been `close`d with `waitForRemainingTasks: false`. "
     183             :         "So task can't be finished.\n"
     184             :         "If you want to close the Worker and wait for remaining tasks call the "
     185             :         "`close` method with the `waitForRemainingTasks: false` parameter.";
     186             :   }
     187             : }
     188             : 
     189             : /// This exception is thrown when when you send to/from isolate some unsupported data like [ReceivePort].
     190             : class UnsupportedIsolateArgumentError extends ArgumentError {
     191           1 :   UnsupportedIsolateArgumentError(this.originalError);
     192             : 
     193             :   final ArgumentError originalError;
     194             : 
     195             :   /// Name of the invalid argument, if available.
     196           1 :   @override
     197           2 :   String? get name => originalError.name;
     198             : 
     199             :   /// Message describing the problem.
     200           1 :   @override
     201           2 :   dynamic get message => originalError.message;
     202             : }

Generated by: LCOV version 1.16