One Engine Instance Per Call


* A system where scripts are called a _lot_, in tight loops or in parallel.

* Keeping a global [`Engine`] instance is sub-optimal due to contention and locking.

* Scripts need to be executed independently from each other, perhaps concurrently.

* Scripts are used to [create Rust closures][`Func`] that are stored and may be called at any time,
  perhaps concurrently. In this case, the [`Engine`] instance is usually moved into the closure itself.

* Rhai's [`AST`] structure is sharable – meaning that one copy of the [`AST`] can be run on
  multiple instances of [`Engine`] simultaneously.

* Rhai's [packages] and [modules] are also sharable.

* This means that [`Engine`] instances can be _decoupled_ from the base system ([packages] and
  [modules]) as well as the scripts ([`AST`]) so they can be created very cheaply.

Procedure

Examples

use rhai::def_package;
use rhai::packages::{Package, StandardPackage};

// Define the custom package 'MyCustomPackage'.
def_package! {
    /// My own personal super-duper custom package
    pub MyCustomPackage(module) {
      // Aggregate other packages simply by calling 'init' on each.
      StandardPackage::init(module);

      // Register additional Rust functions using 'Module::set_native_fn'.
      let hash = module.set_native_fn("foo", |s: ImmutableString| {
          Ok(foo(s.into_owned()))
      });

      // Remember to update the parameter names/types and return type metadata
      // when using the 'metadata' feature.
      // 'Module::set_native_fn' by default does not set function metadata.
      module.update_fn_metadata(hash, &["s: ImmutableString", "i64"]);
  }
}

let ast = /* ... some AST ... */;

let custom_pkg = MyCustomPackage::new();

// The following loop creates 10,000 Engine instances!

for x in 0..10_000 {
    // Create a raw Engine - extremely cheap
    let mut engine = Engine::new_raw();

    // Register custom package - cheap
    engine.register_global_module(custom_pkg.as_shared_module());

    // Evaluate script
    engine.run_ast(&ast)?;
}