diff --git a/docs/BITWISE_OPERATIONS.md b/docs/BITWISE_OPERATIONS.md new file mode 100644 index 0000000..2393300 --- /dev/null +++ b/docs/BITWISE_OPERATIONS.md @@ -0,0 +1,146 @@ +# Bitwise Operations in the Reactive System + +## Overview +The reactive system uses bitwise operations to efficiently track and manage various states of effects and computations. This document explains how these operations work and their purpose in the system. + +## Flag Definitions + +The system uses several flags to represent different states: + +```typescript +// Error state flag +const ERROR_BIT = 1 << 0; // Binary: 0001 + +// Loading state flag +const LOADING_BIT = 1 << 1; // Binary: 0010 + +// Uninitialized state flag +const UNINITIALIZED_BIT = 1 << 2; // Binary: 0100 +``` + +## Common Operations + +### 1. Setting Flags +To set multiple flags: + +```typescript +// Set error and loading flags +let flags = ERROR_BIT | LOADING_BIT; // Binary: 0011 +``` + +### 2. Checking Flags +To check if a flag is set: + +```typescript +// Check if error flag is set +if (flags & ERROR_BIT) { + // Handle error state +} + +// Check if either error or loading flag is set +if (flags & (ERROR_BIT | LOADING_BIT)) { + // Handle error or loading state +} +``` + +### 3. Removing Flags +To remove a flag: + +```typescript +// Remove loading flag +flags &= ~LOADING_BIT; +``` + +## Usage in the System + +### 1. Effect States +Effects use flags to track their current state: + +```typescript +// Notify queue about loading and error states +this._queue.notify(this, LOADING_BIT | ERROR_BIT, flags); +``` + +### 2. Boundary Conditions +Boundaries use flags to control propagation: + +```typescript +// Set propagation mask for boundary +this._propagationMask = disabled ? ERROR_BIT | LOADING_BIT : 0; +``` + +### 3. State Management +Computations use flags to manage their state: + +```typescript +// Check loading state +if (this._stateFlags & LOADING_BIT) { + throw new NotReadyError(); +} +``` + +## Benefits of Bitwise Operations + +1. **Efficiency** + - Single number can represent multiple states + - Bitwise operations are very fast + - Uses minimal memory + +2. **Flexibility** + - Easy to combine states + - Easy to check multiple states + - Easy to modify states + +3. **Type Safety** + - TypeScript can type-check the flags + - Prevents invalid state combinations + - Makes state management more predictable + +## Common Flag Combinations + +| Combination | Description | +|------------|-------------| +| `ERROR_BIT` | Error state only | +| `LOADING_BIT` | Loading state only | +| `ERROR_BIT | LOADING_BIT` | Both error and loading states | +| `LOADING_BIT | UNINITIALIZED_BIT` | Loading and uninitialized states | + +## Best Practices + +1. **Flag Definition** + - Use powers of 2 for flag values + - Document flag purposes + - Keep flag names descriptive + +2. **Flag Operations** + - Use bitwise OR (`|`) to combine flags + - Use bitwise AND (`&`) to check flags + - Use bitwise NOT (`~`) to remove flags + +3. **State Management** + - Clear flags when no longer needed + - Check flags before operations + - Handle all possible flag combinations + +## Example Usage + +```typescript +// Create an effect with initial flags +const effect = new Effect(initialValue, compute, effectFn); + +// Set multiple flags +effect.write(newValue, ERROR_BIT | LOADING_BIT); + +// Check flags +if (effect._stateFlags & LOADING_BIT) { + // Handle loading state +} + +// Remove flag +effect._stateFlags &= ~ERROR_BIT; +``` + +## Related Documentation +- See [QUEUE_NOTIFICATION_SYSTEM.md](./QUEUE_NOTIFICATION_SYSTEM.md) for details on how flags are used in the queue system +- See [EFFECTS.md](./EFFECTS.md) for details on effect implementation +- See [BOUNDARIES.md](./BOUNDARIES.md) for details on boundary implementation \ No newline at end of file diff --git a/docs/QUEUE_EXECUTION_CONTROL.md b/docs/QUEUE_EXECUTION_CONTROL.md new file mode 100644 index 0000000..2a29611 --- /dev/null +++ b/docs/QUEUE_EXECUTION_CONTROL.md @@ -0,0 +1,167 @@ +# Queue System: Execution Control + +## Overview +The queue system is primarily responsible for managing the execution of effects in the reactive system. While it also handles state notifications (see [QUEUE_NOTIFICATION_SYSTEM.md](./QUEUE_NOTIFICATION_SYSTEM.md)), its core purpose is to ensure effects run in the correct order, handle batching of updates, and coordinate execution across different parts of the application. + +## Core Concepts + +### 1. Effect Types +The system distinguishes between different types of effects: + +- **Pure Effects**: Computations that derive values +- **Render Effects**: Effects that update the UI +- **User Effects**: Custom effects created by the user + +### 2. Execution Queues +Each queue maintains three separate queues for different effect types: + +```typescript +_queues: [Computation[], Effect[], Effect[]] = [[], [], []]; +``` + +This separation ensures: +- Pure computations run before effects +- Render effects run before user effects +- Effects of the same type run in the order they were created + +## Execution Flow + +### 1. Enqueuing Effects +When an effect needs to run: + +```typescript +enqueue(type: number, node: T): void { + this._queues[0].push(node as any); + if (type) this._queues[type].push(node as any); + schedule(); +} +``` + +This: +- Adds the effect to the general queue +- Adds it to its specific type queue +- Schedules execution + +### 2. Execution Scheduling +Effects are executed in batches: + +```typescript +flush() { + if (this._running) return; + this._running = true; + try { + while (this.run(EFFECT_PURE)) {} + incrementClock(); + scheduled = false; + this.run(EFFECT_RENDER); + this.run(EFFECT_USER); + } finally { + this._running = false; + } +} +``` + +The order is important: +1. Pure computations run first (may repeat if new computations are added) +2. Clock is incremented to mark the batch +3. Render effects run +4. User effects run + +### 3. Effect Execution +Each effect type has its own execution strategy: + +```typescript +run(type: number) { + if (this._queues[type].length) { + if (type === EFFECT_PURE) { + runPureQueue(this._queues[type]); + this._queues[type] = []; + } else { + const effects = this._queues[type] as Effect[]; + this._queues[type] = []; + runEffectQueue(effects); + } + } + // ... handle child queues +} +``` + +## Specialized Execution Control + +### 1. Conditional Execution +Some queues can conditionally execute effects: + +```typescript +class ConditionalQueue extends Queue { + run(type: number) { + if (type && this._disabled.read()) return; + return super.run(type); + } +} +``` + +This allows: +- Pausing effect execution based on conditions +- Resuming execution when conditions change +- Managing execution in boundary contexts + +### 2. Collection-based Execution +Queues can manage execution based on collections: + +```typescript +class CollectionQueue extends Queue { + _disabled: Computation = new Computation(false, null); + + run(type: number) { + if (this._disabled.read()) return; + return super.run(type); + } +} +``` + +This enables: +- Group-based execution control +- Automatic enabling/disabling based on collection state +- Coordinated execution of related effects + +## Best Practices + +### 1. Effect Creation +- Use appropriate effect types +- Consider execution order requirements +- Handle cleanup properly + +### 2. Queue Management +- Create appropriate queue hierarchies +- Use specialized queues when needed +- Ensure proper cleanup + +### 3. Execution Control +- Batch related updates +- Handle edge cases (errors, loading states) +- Consider performance implications + +## Example Usage + +```typescript +// Create a queue with execution control +const queue = new Queue(); + +// Create different types of effects +const pureEffect = new Computation(initialValue, compute); +const renderEffect = new Effect(initialValue, compute, effectFn, { render: true }); +const userEffect = new Effect(initialValue, compute, effectFn); + +// Effects will be executed in the correct order +queue.enqueue(EFFECT_PURE, pureEffect); +queue.enqueue(EFFECT_RENDER, renderEffect); +queue.enqueue(EFFECT_USER, userEffect); + +// Execute all effects +queue.flush(); +``` + +## Related Documentation +- See [QUEUE_NOTIFICATION_SYSTEM.md](./QUEUE_NOTIFICATION_SYSTEM.md) for details on the secondary notification system +- See [BITWISE_OPERATIONS.md](./BITWISE_OPERATIONS.md) for details on state management +- See [EFFECTS.md](./EFFECTS.md) for details on effect implementation \ No newline at end of file diff --git a/docs/QUEUE_NOTIFICATION_SYSTEM.md b/docs/QUEUE_NOTIFICATION_SYSTEM.md new file mode 100644 index 0000000..3c0151f --- /dev/null +++ b/docs/QUEUE_NOTIFICATION_SYSTEM.md @@ -0,0 +1,131 @@ +# Queue System: Notification System + +## Overview +The queue notification system manages how state changes propagate through the reactive system. It's responsible for coordinating the flow of information about loading states, errors, and other state changes between different parts of the application. + +## Key Components + +### 1. Base Queue +The base `Queue` class handles basic notification propagation: +- Receives notifications about state changes +- Propagates notifications to parent queues +- Forms the foundation for specialized notification handling + +### 2. Specialized Queues + +#### ConditionalQueue +Manages notifications in boundary contexts: +- Can be enabled/disabled based on conditions +- Stores notifications when disabled +- Releases stored notifications when enabled +- Used for implementing features like suspense boundaries + +Example: +```typescript +class ConditionalQueue extends Queue { + notify(node: Effect, type: number, flags: number) { + if (this._disabled.read()) { + // Store notifications when disabled + if (type === LOADING_BIT) { + flags & LOADING_BIT ? this._pendingNodes.add(node) : this._pendingNodes.delete(node); + } + if (type === ERROR_BIT) { + flags & ERROR_BIT ? this._errorNodes.add(node) : this._errorNodes.delete(node); + } + return true; + } + return super.notify(node, type, flags); + } +} +``` + +#### CollectionQueue +Manages collections of effects in specific states: +- Tracks effects in loading or error states +- Controls notification propagation based on collection state +- Used for implementing features like error boundaries + +Example: +```typescript +class CollectionQueue extends Queue { + notify(node: Effect, type: number, flags: number) { + if (!(type & this._collectionType)) return super.notify(node, type, flags); + if (flags & this._collectionType) { + this._nodes.add(node); + if (this._nodes.size === 1) this._disabled.write(true); + } else { + this._nodes.delete(node); + if (this._nodes.size === 0) this._disabled.write(false); + } + type &= ~this._collectionType; + return type ? super.notify(node, type, flags) : true; + } +} +``` + +## Notification Flow + +1. **State Change** + - An effect's state changes (loading, error, etc.) + - It notifies its queue about the change + +2. **Notification Processing** + - The queue receives the notification + - Handles its specific responsibilities + - May store the notification if disabled + - May propagate the notification to parent queues + +3. **State Propagation** + - Notifications flow up the queue hierarchy + - Each queue can modify or filter notifications + - State changes are properly propagated through the system + +## Common Use Cases + +### Loading States +- Effects can enter loading states +- Queues track and propagate loading states +- Loading boundaries can show fallback content + +### Error Handling +- Effects can enter error states +- Error boundaries catch and handle errors +- Error states can be reset and retried + +### Boundary Conditions +- Queues can be temporarily disabled +- Notifications are stored during disabled state +- Stored notifications are released when enabled + +## Best Practices + +1. **Queue Hierarchy** + - Create appropriate queue hierarchies + - Use specialized queues for specific needs + - Ensure proper cleanup of queues + +2. **State Management** + - Handle loading and error states properly + - Implement proper fallback behavior + - Handle state resets appropriately + +## Example Usage + +```typescript +// Create a boundary queue +const queue = new ConditionalQueue(disabledComputation); + +// Create an effect that uses the queue +const effect = new Effect(initialValue, compute, effectFn, { + queue: queue +}); + +// The effect will notify the queue of state changes +effect.write(newValue, flags); +``` + +## Related Documentation +- See [EXECUTION_CONTROL.md](./EXECUTION_CONTROL.md) for details on how effects are executed +- See [BITWISE_OPERATIONS.md](./BITWISE_OPERATIONS.md) for details on the flag system +- See [EFFECTS.md](./EFFECTS.md) for details on effect implementation +- See [BOUNDARIES.md](./BOUNDARIES.md) for details on boundary implementation \ No newline at end of file