Home > OS >  Access variables in external scope when using isolation in Dart
Access variables in external scope when using isolation in Dart

Time:01-11

In Isolates, I can refer to a local variable from an outer scope or a field variable of a class without passing it as a separate message.
Is this implicitly copying the values into the new isolation's memory area?
I'm curious about the details.

Example

class Person {
  Person(this._baseNum);

  /// access [_baseNum] in isolate
  final int _baseNum;
  int age = 0;

  /// access [extraAge] in isolate
  Future<void> addAge(int extraAge) async {
    final mainReceivePort = ReceivePort();

    await Isolate.spawn((SendPort sendPort) async {
      sendPort.send(await _calcAge(_baseNum, extraAge));
    }, mainReceivePort.sendPort);

    age = await mainReceivePort.first;
    mainReceivePort.close();
  }

  static Future<int> _calcAge(int someNum, int age) async {
    // ... heavy work ...
    return age   someNum;
  }
}

// ...

void main() {
  test('test', () async {
    final p = Person(10);
    await p.addAge(3);
    expect(p.age, 13);
  });
}

CodePudding user response:

In Isolates, I can refer to a local variable from an outer scope or a field variable of a class without passing it as a separate message.

Is this implicitly copying the values into the new isolation's memory area?

Yes it is.

One way to demonstrate this is if you take one of these variables from an outer scope or field variable, and update the value within the isolate. What you will see is that from outside the isolate, the value will not be updated. This is because they are working with independent copies of the variable.

import 'dart:isolate';
import 'package:test/test.dart';

class Person {
  Person(this._baseNum);

  /// access [_baseNum] in isolate
  int _baseNum;
  int age = 0;

  /// access [extraAge] in isolate
  Future<void> addAge(int extraAge) async {
    final mainReceivePort = ReceivePort();

    await Isolate.spawn((SendPort sendPort) async {
      _baseNum  ; // modify _baseNum
      sendPort.send(await _calcAge(_baseNum, extraAge));
    }, mainReceivePort.sendPort);

    age = await mainReceivePort.first;
    mainReceivePort.close();
  }

  static Future<int> _calcAge(int someNum, int age) async {
    // ... heavy work ...
    return age   someNum;
  }
}

// ...

void main() {
  test('test', () async {
    final p = Person(10);
    await p.addAge(3);
    expect(p.age, 14);
    expect(p._baseNum, 10); // _baseNum still 10 despite _baseNum   in isolate
  });
}
  • Related