lock method

  1. @nonVirtual
Future<bool> lock(
  1. ProviderModelProcess process, {
  2. ProviderLockKey? lockKey,
  3. bool override = false,
  4. bool overridable = false,
  5. FutureOr<void> onOverride()?,
  6. bool waitForMicrotasks = true,
  7. bool waitForTimers = false,
  8. bool waitForPeriodicTimers = false,
})

Queue up to lock this ProviderModel to safely modify it's ProviderModelVariable members. The process passed here is guarunteed to be executed sequentially and non-parallel to other proccesses passed to lock.

If override is true, all previously queued lock calls with overridable or onOverride set will be cancelled. If not started yet, it will be skipped, if started, it will stop execution on the next asynchronous tick. When cancelled, no notifications will be sent even if ProviderModelBatch.commit is executed. if override is false, process won't be called until all previous locks have been completed.

Returns a bool signifying whether execution of process completed without erroring, overriding, or cancelling.

A lockKey can be passed to prevent multiple batches from being created at the same time with the same lockKey. Every ProviderModel has a default ProviderLockKey that this function will default to if lockKey is not set.

For details on what waitForMicrotasks, waitForTimers, and waitForPeriodicTimers do, see SequentialWorkQueue.add.

Implementation

@nonVirtual
Future<bool> lock(
  ProviderModelProcess process, {
  ProviderLockKey? lockKey,
  bool override = false,
  bool overridable = false,
  FutureOr<void> Function()? onOverride,
  bool waitForMicrotasks = true,
  bool waitForTimers = false,
  bool waitForPeriodicTimers = false,
}) async {
  assert(!_disposed, 'ProviderModel was already disposed.');
  assert(
    Zone.current[#providerModelUseSubscription] == null,
    'lock() cannot be called while a use callback is being executed.',
  );

  lockKey ??= _defaultLockKey;
  _lockQueues ??= <ProviderLockKey, SequentialWorkQueue>{};

  final tQueue = _lockQueues!.putIfAbsent(
    lockKey,
    () => SequentialWorkQueue(),
  );

  if (override) {
    tQueue.clear();
  }

  final tBatch = ProviderModelBatch._internalCreate(this);

  return await tQueue.add<bool>(
        () async {
          await process(tBatch);

          return tBatch.valid && !disposed;
        },
        onCancel: () async {
          if (onOverride != null) {
            tBatch._disable();
            await onOverride();

            return true;
          } else if (overridable) {
            tBatch._disable();

            return true;
          }

          return false;
        },
        waitForMicrotasks: waitForMicrotasks,
        waitForTimers: waitForTimers,
        waitForPeriodicTimers: waitForPeriodicTimers,
      ) ==
      true;
}