Skip to content

feat: promote green threads from develop to main#15

Merged
zombocoder merged 12 commits into
zombocoder:mainfrom
sashml:feat/green-threads-to-main
May 4, 2026
Merged

feat: promote green threads from develop to main#15
zombocoder merged 12 commits into
zombocoder:mainfrom
sashml:feat/green-threads-to-main

Conversation

@sashml
Copy link
Copy Markdown
Contributor

@sashml sashml commented Apr 30, 2026

Summary

  • Ports all green threads (cooperative concurrency) work from develop into main
  • develop diverged from the current main tip (90207e2) and adds only green threads — zero conflicts
  • Includes the full implementation: spawn, Channel, Scheduler, Coroutine, IOThreadPool, ConcurrencyLibrary
  • Adds 11 test files covering scheduler logic, channel operations, IO yield, root exception propagation, shared state, and advanced concurrency patterns

What's included

  • src/Runtime/Scheduler, Coroutine, CoroutineHandle, ChannelInstance, IOThreadPool, ConcurrencyLibrary
  • src/AST/SpawnNode — new AST node for spawn keyword
  • Parser, Lexer, Interpreter wired up for spawn and Channel built-in
  • 11 new test files (test_scheduler, test_channel_basic/edge_cases, test_io_thread_pool, test_root_exception, test_shared_state, test_concurrency_advanced, etc.)
  • examples/concurrency.obq

sashml and others added 12 commits April 28, 2026 09:52
…, and async I/O

Introduces cooperative multitasking to O²L:

- `spawn <expr>` keyword: launches a new coroutine that runs cooperatively
  within the same OS thread (SpawnNode AST node, Lexer/Parser support)
- `Scheduler` (singleton run-loop): drives coroutines via a ready_queue_,
  timer_queue_, suspended_ map, and thread-safe IO completion queue
- `Coroutine`: owns body ASTNode + cloned Context; carries state
  (Ready/Running/Suspended/Completed/Failed) with block_resume_stack for
  nested block resumption
- `ChannelInstance`: buffered/unbuffered channel for send/receive between
  coroutines; senders suspend when full, receivers suspend when empty
- `ConcurrencyLibrary`: exposes `Channel.new(capacity)` and `io.sleep(ms)` /
  `io.yield()` to O²L programs
- `IOThreadPool`: fixed thread pool offloading blocking I/O; uses thread-safe
  `enqueueReady` to post completions back to the scheduler
- `Context::clone()`: deep-copies variable bindings for coroutine isolation
- `CArray.fromList()`: copies a ListInstance into a CArrayInstance for FFI
- BlockNode/WhileStatementNode: use block_resume_stack for correct nested
  coroutine resumption
- Cross-platform: MSVC Value variant alias, unistd.h for macOS/Linux,
  holds_Int_Value/holds_Long_Value helpers, Windows socket defines

All existing tests pass; adds 9 new concurrency test suites.
…lures

- Parser: accept keyword 'new' as method name after '.' so Channel.new()
  parses correctly (fixes ConcurrencyTest.channel_basic and
  ConcurrencyTest.concurrency_advanced)
- Scheduler: store root coroutine exception in root_exception_ and
  expose it via getRootException(); clear on reset()
- Interpreter: rethrow root coroutine exception after scheduler.run()
  so EvaluationErrors propagate to callers (fixes IntegrationTest
  DemoAccessError and ErrorHandling)
…plementation

- Fix YieldNode ODR violation between test_resume_logic.cpp and
  test_suspend_exception.cpp by wrapping each in anonymous namespaces
  (root cause of MSVC 0xc0000005 crash — linker picked wrong vtable)
- Fix YieldNode to check hasResumeValue() before yielding to prevent
  infinite re-suspension on resume
- Remove debug cerr prints from BlockNode, WhileStatementNode, Scheduler
- Remove unused <iostream> includes from BlockNode and WhileStatementNode
- Use EXPECT_EQ instead of assert in test_resume_logic
- Parser: simplify Channel.new() member name token handling
- Context::clone(): preserve this_stack_ for spawn inside object methods
- yield_in_false_loop: while(false) body never executes yield
- yield_single_iteration: loop terminates on first resume (condition false)
- yield_deeply_nested: 3 levels of BlockNode nesting exercises block_resume_stack depth
- root_exception_captured: root coroutine error stored in root_exception_, rethrowable
- non_root_exception_ignored: non-root errors don't set root_exception_
- root_exception_null_on_success: successful root leaves root_exception_ null
…mption

- error_after_resume: yield then throw on resume, verify root_exception_ captured
- scheduler_clean_after_run: isActive()==false after success, error, and yield+error
- error_in_condition_after_resume: condition throws after yield-resume cycle completes
- yield_nested_inner_loop: yield in inner while-while, 4 yields across 2*2 iterations
- yield_nested_outer_body: yield in outer body after inner loop completes, 2 yields
  Both exercise block_resume_stack at 4+ nesting levels
- channel_producer_consumer_values: producer sends 3 values via channel, consumer sums them
- three_coroutine_round_robin: 3 coroutines yield to shared log, verify deterministic order
- channel_multiple_producers: 2 producers send to one buffered channel
- channel_multiple_consumers: 2 consumers receive from one buffered channel
- channel_unbuffered_blocking: sender blocks until receiver is ready
- channel_buffered_full: sender blocks when buffer at capacity
- suspend_for_io_basic: IO lambda result delivered to coroutine on resume
- suspend_for_io_different_thread: IO work runs on a background thread
- suspend_for_io_multiple: 3 concurrent IO suspensions all complete correctly
feat: add green threads (cooperative concurrency) with spawn, Channel, and async I/O
- Add return type `: Unit` on workerRoutine method
- Add `@external` annotation for cross-object method access
- Use `sleep()` instead of `io.sleep()`
- Send Int values via channel instead of string concatenation
- Verified: runs successfully, 3 workers communicate via channel
@zombocoder zombocoder merged commit 0a1292a into zombocoder:main May 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants