@but212/atom-effect 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -205,6 +205,7 @@ export declare interface DebugConfig {
205
205
  export declare interface Dependency {
206
206
  readonly id: DependencyId;
207
207
  version: number;
208
+ flags: number;
208
209
  /**
209
210
  * Last epoch seen by this dependency (used for invalidation)
210
211
  */
@@ -362,7 +363,6 @@ export declare function isEffect(obj: unknown): obj is EffectObject;
362
363
 
363
364
  /**
364
365
  * Interface for nodes that support phase-shift priority calculation.
365
- * Used by Scheduler to determine job urgency.
366
366
  */
367
367
  declare interface PhaseShiftNode {
368
368
  getShift(cachedVersion: number): number;
@@ -419,28 +419,13 @@ export declare interface ReadonlyAtom<T = unknown> {
419
419
  }
420
420
 
421
421
  /**
422
- * Scheduler for reactive updates with phase-shift priority scheduling.
423
- *
424
- * Features:
425
- * - Double-buffered queue for efficient processing
426
- * - Urgent queue for high-priority updates (glitch reduction)
427
- * - Branchless priority calculation using phase-shift
428
- * - Batching support for transactional updates
429
- *
430
- * Priority Logic:
431
- * When a job's phase shift exceeds PHASE_THRESHOLD (90° equivalent),
432
- * it's considered "urgent" and processed before normal jobs.
433
- * This reduces glitches by prioritizing stale updates.
422
+ * Scheduler for reactive updates with double-buffered priority queues.
434
423
  */
435
424
  declare class Scheduler {
436
- private queueA;
437
- private queueB;
438
- private queue;
439
- private queueSize;
440
- private urgentQueueA;
441
- private urgentQueueB;
442
- private urgentQueue;
443
- private urgentQueueSize;
425
+ private _queueBuffers;
426
+ private _bufferIndices;
427
+ private _sizes;
428
+ private _activeQueues;
444
429
  private _epoch;
445
430
  private isProcessing;
446
431
  isBatching: boolean;
@@ -449,66 +434,51 @@ declare class Scheduler {
449
434
  private batchQueueSize;
450
435
  private isFlushingSync;
451
436
  private maxFlushIterations;
437
+ constructor();
438
+ /**
439
+ * Returns the current operational phase of the scheduler.
440
+ */
452
441
  get phase(): SchedulerPhase;
442
+ /** Current number of pending normal jobs. */
443
+ get queueSize(): number;
444
+ /** Current number of pending urgent jobs. */
445
+ get urgentQueueSize(): number;
453
446
  /**
454
447
  * Schedules a task for execution with optional priority based on phase shift.
455
- *
456
- * Priority Calculation (Branchless):
457
- * - If sourceNode and cachedVersion are provided, calculates shift
458
- * - Jobs with shift >= PHASE_THRESHOLD go to urgentQueue
459
- * - Uses branchless bit manipulation: ((shift - THRESHOLD) >>> 31) ^ 1
460
- *
461
- * @param callback - The function to execute
462
- * @param sourceNode - Optional reactive node for shift calculation
463
- * @throws {SchedulerError} If the callback is not a function
464
448
  */
465
449
  schedule(callback: SchedulerJob, sourceNode?: PhaseShiftNode): void;
466
450
  /**
467
451
  * Calculates urgency flag using branchless bit manipulation.
468
452
  *
469
- * Formula: ((shift - PHASE_THRESHOLD) >>> 31) ^ 1
470
- * - If shift >= THRESHOLD: (negative >>> 31) = 0, XOR 1 = 1 (urgent)
471
- * - If shift < THRESHOLD: (positive >>> 31) = 0... wait, that's wrong
453
+ * Logic:
454
+ * 1. Calculate the 'shift' (rotation distance) from the cached version.
455
+ * 2. Compare against PHASE_THRESHOLD (180° rotation equivalent).
456
+ * 3. Use (N >>> 31) to extract the sign bit in O(1) time.
472
457
  *
473
- * Correct formula: (shift >= THRESHOLD) ? 1 : 0
474
- * Branchless: ((PHASE_THRESHOLD - 1 - shift) >>> 31)
475
- *
476
- * @returns 1 if urgent, 0 if normal
458
+ * @returns 1 if urgent (shift >= PHASE_THRESHOLD), 0 otherwise.
477
459
  */
478
460
  private _calculateUrgency;
461
+ /**
462
+ * Schedules a microtask-based flush of the queues.
463
+ * Coalesces multiple schedule calls into a single microtask execution.
464
+ */
479
465
  private flush;
480
- private flushSync;
481
- private _mergeBatchQueue;
482
466
  /**
483
- * Drains all queues, processing urgent queue completely first.
484
- *
485
- * Processing Order:
486
- * 1. Process all urgent jobs (high phase shift = stale updates)
487
- * 2. Process normal jobs
488
- * 3. Repeat until both queues are empty
489
- *
490
- * This ordering reduces glitches by ensuring that the most
491
- * impactful state changes are propagated first.
467
+ * Immediately flushes all queues synchronously.
468
+ * Used at the end of a batch block or when immediate reflection is required.
492
469
  */
493
- private _drainQueue;
470
+ private flushSync;
494
471
  /**
495
- * Processes the urgent queue using double-buffering.
472
+ * Merges jobs from the batching queue into the primary normal queue.
473
+ * Increments the epoch/uses provided epoch to ensure deduplication.
496
474
  */
497
- private _processUrgentQueue;
498
- private _processCurrentQueue;
475
+ private _mergeBatchQueue;
476
+ private _drainQueue;
477
+ private _processQueue;
499
478
  private _handleFlushOverflow;
500
479
  private _processJobs;
501
- /** Starts a new batch of updates. Updates will be deferred until endBatch is called. */
502
480
  startBatch(): void;
503
- /**
504
- * Ends the current batch. If the batch depth reaches zero, all pending updates are flushed synchronously.
505
- */
506
481
  endBatch(): void;
507
- /**
508
- * Configures the maximum number of iterations allowed during a synchronous flush.
509
- * Used to prevent infinite loops.
510
- * @param max - Maximum iterations count.
511
- */
512
482
  setMaxFlushIterations(max: number): void;
513
483
  }
514
484
 
@@ -537,6 +507,8 @@ export declare const SCHEDULER_CONFIG: {
537
507
  readonly MAX_FLUSH_ITERATIONS: 1000;
538
508
  /** Minimum allowed value for max flush iterations */
539
509
  readonly MIN_FLUSH_ITERATIONS: 10;
510
+ /** Threshold for shrinking the batch queue to assist GC */
511
+ readonly BATCH_QUEUE_SHRINK_THRESHOLD: 1000;
540
512
  };
541
513
 
542
514
  /**
@@ -556,7 +528,6 @@ export declare class SchedulerError extends AtomError {
556
528
 
557
529
  /**
558
530
  * Scheduler job interface with phase-shift tracking support.
559
- * _cachedVersion enables priority calculation based on staleness.
560
531
  */
561
532
  declare interface SchedulerJob {
562
533
  (): void;
@@ -566,9 +537,15 @@ declare interface SchedulerJob {
566
537
  _cachedVersion?: number;
567
538
  }
568
539
 
540
+ /**
541
+ * Current state of the scheduler.
542
+ */
569
543
  declare enum SchedulerPhase {
544
+ /** No pending jobs, not currently flushing. */
570
545
  IDLE = 0,
546
+ /** Currently within a batch() block. */
571
547
  BATCHING = 1,
548
+ /** Currently executing queued jobs. */
572
549
  FLUSHING = 2
573
550
  }
574
551