// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// Explicit pool used for managing resources.

import "dart:async";
import 'dart:ffi';

import 'package:ffi/ffi.dart';

import '../calloc.dart';

/// An [Allocator] which frees all allocations at the same time.
///
/// The pool allows you to allocate heap memory, but ignores calls to [free].
/// Instead you call [releaseAll] to release all the allocations at the same
/// time.
///
/// Also allows other resources to be associated with the pool, through the
/// [using] method, to have a release function called for them when the pool is
/// released.
///
/// An [Allocator] can be provided to do the actual allocation and freeing.
/// Defaults to using [calloc].
class Pool implements Allocator {
  /// The [Allocator] used for allocation and freeing.
  final Allocator _wrappedAllocator;

  /// Native memory under management by this [Pool].
  final List<Pointer<NativeType>> _managedMemoryPointers = [];

  /// Callbacks for releasing native resources under management by this [Pool].
  final List<Function()> _managedResourceReleaseCallbacks = [];

  bool _inUse = true;

  /// Creates a pool of allocations.
  ///
  /// The [allocator] is used to do the actual allocation and freeing of
  /// memory. It defaults to using [calloc].
  Pool([Allocator allocator = calloc]) : _wrappedAllocator = allocator;

  /// Allocates memory and includes it in the pool.
  ///
  /// Uses the allocator provided to the [Pool] constructor to do the
  /// allocation.
  ///
  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
  /// satisfied.
  @override
  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
    _ensureInUse();
    final p = _wrappedAllocator.allocate<T>(byteCount, alignment: alignment);
    _managedMemoryPointers.add(p);
    return p;
  }

  /// Registers [resource] in this pool.
  ///
  /// Executes [releaseCallback] on [releaseAll].
  T using<T>(T resource, Function(T) releaseCallback) {
    _ensureInUse();
    releaseCallback = Zone.current.bindUnaryCallback(releaseCallback);
    _managedResourceReleaseCallbacks.add(() => releaseCallback(resource));
    return resource;
  }

  /// Registers [releaseResourceCallback] to be executed on [releaseAll].
  void onReleaseAll(Function() releaseResourceCallback) {
    _managedResourceReleaseCallbacks.add(releaseResourceCallback);
  }

  /// Releases all resources that this [Pool] manages.
  ///
  /// If [reuse] is `true`, the pool can be used again after resources
  /// have been released. If not, the default, then the [allocate]
  /// and [using] methods must not be called after a call to `releaseAll`.
  void releaseAll({bool reuse = false}) {
    if (!reuse) {
      _inUse = false;
    }
    while (_managedResourceReleaseCallbacks.isNotEmpty) {
      _managedResourceReleaseCallbacks.removeLast()();
    }
    for (final p in _managedMemoryPointers) {
      _wrappedAllocator.free(p);
    }
    _managedMemoryPointers.clear();
  }

  /// Does nothing, invoke [releaseAll] instead.
  @override
  void free(Pointer<NativeType> pointer) {}

  void _ensureInUse() {
    if (!_inUse) {
      throw StateError(
          "Pool no longer in use, `releaseAll(reuse: false)` was called.");
    }
  }
}

/// Runs [computation] with a new [Pool], and releases all allocations at the end.
///
/// If [R] is a [Future], all allocations are released when the future completes.
///
/// If the isolate is shut down, through `Isolate.kill()`, resources are _not_
/// cleaned up.
R using<R>(R Function(Pool) computation,
    [Allocator wrappedAllocator = calloc]) {
  final pool = Pool(wrappedAllocator);
  bool isAsync = false;
  try {
    final result = computation(pool);
    if (result is Future) {
      isAsync = true;
      return (result.whenComplete(pool.releaseAll) as R);
    }
    return result;
  } finally {
    if (!isAsync) {
      pool.releaseAll();
    }
  }
}

/// Creates a zoned [Pool] to manage native resources.
///
/// The pool is availabe through [zonePool].
///
/// If the isolate is shut down, through `Isolate.kill()`, resources are _not_ cleaned up.
R withZonePool<R>(R Function() computation,
    [Allocator wrappedAllocator = calloc]) {
  final pool = Pool(wrappedAllocator);
  var poolHolder = [pool];
  bool isAsync = false;
  try {
    return runZoned(() {
      final result = computation();
      if (result is Future) {
        isAsync = true;
        result.whenComplete(pool.releaseAll);
      }
      return result;
    }, zoneValues: {#_pool: poolHolder});
  } finally {
    if (!isAsync) {
      pool.releaseAll();
      poolHolder.remove(pool);
    }
  }
}

/// A zone-specific [Pool].
///
/// Asynchronous computations can share a [Pool]. Use [withZonePool] to create
/// a new zone with a fresh [Pool], and that pool will then be released
/// automatically when the function passed to [withZonePool] completes.
/// All code inside that zone can use `zonePool` to access the pool.
///
/// The current pool must not be accessed by code which is not running inside
/// a zone created by [withZonePool].
Pool get zonePool {
  final List<Pool>? poolHolder = Zone.current[#_pool];
  if (poolHolder == null) {
    throw StateError("Not inside a zone created by `usePool`");
  }
  if (!poolHolder.isEmpty) {
    return poolHolder.single;
  }
  throw StateError("Pool as already been cleared with releaseAll.");
}
