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

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:collection';
       3             : 
       4             : import 'package:combine/src/combine_worker/combine_task_executor.dart';
       5             : import 'package:combine/src/combine_worker/combine_worker_manager.dart';
       6             : import 'package:combine/src/combine_worker/tasks.dart';
       7             : import 'package:combine/src/combine_worker_singleton.dart';
       8             : 
       9             : class NativeWorkerManager extends CombineWorkerManager {
      10           1 :   NativeWorkerManager({
      11             :     required this.isolatesCount,
      12             :     required this.tasksPerIsolate,
      13             :   });
      14             : 
      15             :   final int isolatesCount;
      16             :   final int tasksPerIsolate;
      17             :   final _taskExecutors = <CombineTaskExecutor>[];
      18             :   final _tasksQueue = Queue<TaskInfo>();
      19             :   final _initializationCompleter = Completer();
      20             :   final _lastTaskCompleter = Completer();
      21             :   var _isClosed = false;
      22             : 
      23           1 :   @override
      24             :   Future<void> initialize({
      25             :     WorkerInitializer? initializer,
      26             :     required String isolatesPrefix,
      27             :   }) async {
      28             :     assert(
      29           3 :       !_initializationCompleter.isCompleted,
      30             :       "Internal error. Worker manager is initialized twice.",
      31             :     );
      32           1 :     await Future.wait(
      33           1 :       [
      34           3 :         for (var i = 0; i < isolatesCount; i++)
      35           1 :           CombineTaskExecutor.createExecutor(
      36           1 :             _tasksQueue,
      37           1 :             tasksPerIsolate,
      38             :             initializer,
      39           2 :             '$isolatesPrefix-${i + 1}',
      40           2 :           ).then(_addTaskExecutor),
      41             :       ],
      42             :     );
      43           2 :     _initializationCompleter.complete();
      44             :   }
      45             : 
      46           1 :   void _addTaskExecutor(CombineTaskExecutor taskExecutor) {
      47           2 :     _taskExecutors.add(taskExecutor);
      48           1 :     _tryToStartExecution();
      49             :   }
      50             : 
      51           1 :   @override
      52             :   Future<T> execute<T>(ExecutableTask<T> task) async {
      53           2 :     assert(!_isClosed, "Internal error. Can't execute task in closed manager");
      54             : 
      55           1 :     final completer = Completer();
      56           3 :     _tasksQueue.add(TaskInfo(task, completer));
      57           1 :     _tryToStartExecution();
      58           1 :     final result = await completer.future;
      59           1 :     _markLastTaskAsCompletedIfNeeded();
      60             :     return result;
      61             :   }
      62             : 
      63             :   /// Schedule execution.
      64             :   ///
      65             :   /// Firstly try to schedule for free executors which are not working.
      66             :   /// Then try to schedule for working but not busy executors.
      67           1 :   void _tryToStartExecution() {
      68           1 :     _taskExecutors
      69           3 :         .where((executor) => !executor.isWorking)
      70           2 :         .forEach(_triggerExecutor);
      71           1 :     _taskExecutors
      72           3 :         .where((executor) => !executor.isFullOfTasks)
      73           2 :         .forEach(_triggerExecutor);
      74             :   }
      75             : 
      76           1 :   void _triggerExecutor(CombineTaskExecutor executor) {
      77           1 :     executor.tryToExecuteActionIfAny();
      78             :   }
      79             : 
      80           1 :   @override
      81             :   Future<void> close({bool waitForRemainingTasks = false}) async {
      82             :     // Ensure that initialization is completed and isolates are created.
      83           2 :     await _initializationCompleter.future;
      84             :     assert(
      85           2 :       _taskExecutors.isNotEmpty,
      86             :       "Internal error. "
      87             :       "Seems like initialization is incomplete and isolates are not created",
      88             :     );
      89           1 :     _isClosed = true;
      90             : 
      91             :     if (waitForRemainingTasks) {
      92           1 :       _markLastTaskAsCompletedIfNeeded();
      93           2 :       await _lastTaskCompleter.future;
      94             :     } else {
      95           2 :       for (final task in _tasksQueue) {
      96           3 :         task.resultCompleter.completeError(CombineWorkerClosedException());
      97             :       }
      98             :     }
      99             : 
     100           2 :     for (final taskExecutor in _taskExecutors) {
     101           1 :       taskExecutor.close();
     102             :     }
     103             :   }
     104             : 
     105             :   /// This function is used to wait for remaining tasks
     106             :   /// when worker is [close]d with `waitForRemainingTasks` parameter.
     107           1 :   void _markLastTaskAsCompletedIfNeeded() {
     108           2 :     final executorsAreWorking = _taskExecutors.any(
     109           2 :       (executor) => executor.isWorking,
     110             :     );
     111           3 :     if (_isClosed && !executorsAreWorking && _tasksQueue.isEmpty) {
     112           2 :       _lastTaskCompleter.complete();
     113             :     }
     114             :   }
     115             : }

Generated by: LCOV version 1.16