final class · System.Reactive

Source

public final class Source

What effects depend on: tracked when read inside one, notifying its observers when written.

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

Herencia

Clases base
Any Source

Propiedades

i32 Observers { get; }
#

read-only

The number of effects it runs.

Métodos

Track()
#

Makes the running effect (if any) an observer.

static NextId() : i64
#

static

Notify()
#

Runs every observer again (once each, at the end of a batch).

Miembros privados e internos (9)

static i64 made
#

private static

List<Effect?> observers
#

private

Its observers in the order they began to observe; an effect that stops leaves a null slot (taken out together by Compact once they are half of them), so adding or removing one is a step, not a search.

List<i32> backs
#

private

For each slot, where this source is in its effect's list of sources.

i32 live
#

private

Effect? markEffect
#

private

The effect, and which of its runs, that tracked it last: reading it again in that run is found at once.

i64 markRun
#

private

i64 Id
#

internal

Its number (Effect keeps the numbers of its sources in a set once it has many).

Compact()
#

private

Takes out the null slots, keeping the order, and tells each effect that moves its new slot.

Miembros heredados (5)

Código fuente

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

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

import System;

into namespace System.Reactive
{
	/// What effects depend on: tracked when read inside one, notifying its observers when written.
	public final class Source
	{
		static i64 made;

		/// Its observers in the order they began to observe; an effect that stops leaves a null slot (taken out together
		/// by Compact once they are half of them), so adding or removing one is a step, not a search.
		List<Effect?> observers;

		/// For each slot, where this source is in its effect's list of sources.
		List<i32> backs;
		i32 live;

		/// The effect, and which of its runs, that tracked it last: reading it again in that run is found at once.
		Effect? markEffect;
		i64 markRun;

		/// Takes out the null slots, keeping the order, and tells each effect that moves its new slot.
		Compact()
		{
			i32 kept = 0;
			loop (i32 i = 0..observers.Count)
			{
				if (observers[i] is Effect effect)
				{
					i32 back = backs[i];
					observers[kept] = effect;
					backs[kept] = back;
					effect.Moved(back, kept);
					kept++;
				}
			}
			loop (observers.Count > kept)
			{
				observers.Pop();
				backs.Pop();
			}
		}

		internal:
			/// Its number (Effect keeps the numbers of its sources in a set once it has many).
			i64 Id;

			/// The effect in `slot` no longer observes it.
			Unlink(i32 slot)
			{
				observers[slot] = null;
				live--;
				if (observers.Count >= 32 && live * 2 < observers.Count)
					Compact();
			}

		public:
			/// Makes the running effect (if any) an observer.
			Track()
			{
				if (Reactive.Current is Effect current)
				{
					if (markEffect == current && markRun == current.Runs)
						return;
					markEffect = current;
					markRun = current.Runs;
					if (current.Reads(this))
						return;
					backs.Add(current.Watching(this, observers.Count));
					observers.Add(current);
					live++;
				}
			}

			static NextId() : i64
			{
				made++;
				return made;
			}

			/// Runs every observer again (once each, at the end of a batch).
			Notify()
			{
				Effect?[] running = new Effect?[live];
				i32 count = 0;
				loop (i32 i = 0..observers.Count)
				{
					if (observers[i] is Effect effect)
					{
						running[count] = effect;
						count++;
					}
				}
				loop (i32 i = 0..count)
				{
					if (running[i] is Effect effect)
						Reactive.Schedule(effect);
				}
			}

			/// The number of effects it runs.
			i32 Observers
			{
				get => live;
			}
	}
}
Esc