final class · System.Reactive

Effect

public final class Effect

A computation that runs again whenever a Source it read notifies, until disposed.

Tipo
final class
Espacio de nombres
System.Reactive
Ensamblado
System.Core
Acceso
public, final
Archivo fuente
Reactive.ant

Herencia

Clases base
Any Effect

Constructores

new(func body)
#

Propiedades

i32 Sources { get; }
#

read-only

How many sources its last run read.

bool Disposed { get; }
#

read-only

Métodos

Run()
#

Runs the computation, tracking what it reads (not while it already runs, nor once disposed). It starts from no dependencies: only what this run reads keeps running it.

Trigger()
#

What a change does to it: runs it, or (lazy) marks it stale once and notifies what depends on it.

Dispose()
#

Stops it: it never runs again, and no Source keeps it.

Miembros privados e internos (16)

func body
#

private

bool running
#

private

bool disposed
#

private

List<Source> sources
#

private

List<i32> slots
#

private

For each source, its slot in that source's observers.

HashSet<i64>? ids
#

private

The ids of sources once there are more than a few (below that a search of the list is quicker).

bool Pending
#

internal

i32 PendingAt
#

internal

Where it is in the batch's pending effects (while Pending).

i64 Runs
#

internal

How many times it let go of its sources: a Source's mark of one of its runs holds until then.

bool Lazy
#

internal

A lazy effect (a Computed's) does not run when notified: it goes stale, and tells Dependents.

bool Stale
#

internal

Source? Dependents
#

internal

Reads(Source source) : bool
#

internal

Whether this run read source already.

Watching(Source source, i32 slot) : i32
#

internal

source keeps it in slot: where the source is in its list.

Moved(i32 back, i32 slot)
#

internal

The source at back moved it to slot.

Release()
#

private

Miembros heredados (5)

Código fuente

Effect en Antril, descompilado a partir de su Larva HIR.

System.Reactive.Effect.ant
// System.Reactive.Effect — System.Core (decompiled from Larva HIR)

import System;

into namespace System.Reactive
{
	/// A computation that runs again whenever a Source it read notifies, until disposed.
	public final class Effect
	{
		func body;
		bool running;
		bool disposed;
		List<Source> sources;

		/// For each source, its slot in that source's observers.
		List<i32> slots;

		/// The ids of `sources` once there are more than a few (below that a search of the list is quicker).
		HashSet<i64>? ids;

		Release()
		{
			loop (i32 i = 0..sources.Count)
				sources[i].Unlink(slots[i]);
			sources.Clear();
			slots.Clear();
			ids = null;
			Runs++;
		}

		internal:
			bool Pending;

			/// Where it is in the batch's pending effects (while Pending).
			i32 PendingAt;

			/// How many times it let go of its sources: a Source's mark of one of its runs holds until then.
			i64 Runs;

			/// A lazy effect (a Computed's) does not run when notified: it goes stale, and tells `Dependents`.
			bool Lazy;
			bool Stale;
			Source? Dependents;

			/// Whether this run read `source` already.
			Reads(Source source) : bool
			{
				if (ids is HashSet<i64> known)
					return known.Contains(source.Id);
				loop (i32 i = 0..sources.Count)
				{
					if (sources[i] == source)
						return true;
				}
				return false;
			}

			/// `source` keeps it in `slot`: where the source is in its list.
			Watching(Source source, i32 slot) : i32
			{
				sources.Add(source);
				slots.Add(slot);
				if (ids is HashSet<i64> known)
					known.Add(source.Id);
				else if (sources.Count > 8)
				{
					HashSet<i64> all = new HashSet<i64>();
					loop (i32 i = 0..sources.Count)
						all.Add(sources[i].Id);
					ids = all;
				}
				return sources.Count - 1;
			}

			/// The source at `back` moved it to `slot`.
			Moved(i32 back, i32 slot)
			{
				slots[back] = slot;
			}

		public:
			new(func body)
			{
				sources = new List<Source>();
				slots = new List<i32>();
				this.body = body;
			}

			/// Runs the computation, tracking what it reads (not while it already runs, nor once disposed). It starts
			/// from no dependencies: only what this run reads keeps running it.
			Run()
			{
				if (running || disposed)
					return;
				running = true;
				Release();
				Effect? previous = Reactive.Current;
				Reactive.Current = this;
				try
				{
					body();
				}
				finally
				{
					Reactive.Current = previous;
					running = false;
					Stale = false;
				}
			}

			/// What a change does to it: runs it, or (lazy) marks it stale once and notifies what depends on it.
			Trigger()
			{
				if (!Lazy)
				{
					Run();
					return;
				}
				if (Stale || disposed)
					return;
				Stale = true;
				if (Dependents is Source dependents)
					dependents.Notify();
			}

			/// Stops it: it never runs again, and no Source keeps it.
			Dispose()
			{
				disposed = true;
				Release();
			}

			/// How many sources its last run read.
			i32 Sources
			{
				get => sources.Count;
			}

			bool Disposed
			{
				get => disposed;
			}
	}
}
Esc