Files
five/hbrt/goroutine.go
Charles KWON OhJun 59568f3301 Five v0.9 — Harbour + Go fusion language
- Compiler: PP → Lexer → Parser → Analyzer → Gengo pipeline
- Parser: 232/236 (98%) Harbour compatibility, registry-based dispatch
- RTL: 351 Harbour-compatible functions
- RDD: DBF/NTX/CDX engines with Rushmore bitmap optimization
- Go Interop: IMPORT + pkg.Func() + obj:Method() with FastPath (15M calls/sec)
- HB_FUNC API: Full Harbour C API compatible Go bridge
- Concurrency: SPAWN/LAUNCH/GOROUTINE, <-, WATCH, PARALLEL FOR, ASYNC/AWAIT
- Extensions: Multi-return, DEFER, Slice, f-string, Nil-safe ?:, CONST
- Macro Compiler: Runtime AST parsing and evaluation
- Debugger: TUI debugger with source display, breakpoints, stepping
- FRB: Native + Pcode dual mode runtime binary
- Tests: 13 packages ALL PASS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:41:50 +09:00

137 lines
2.6 KiB
Go

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
// Goroutine support for Five runtime.
// Provides Go's goroutine, channel, and WaitGroup primitives
// as first-class Harbour values.
package hbrt
import (
"sync"
)
// --- Channel ---
// HbChannel wraps Go's chan Value for use in PRG code.
type HbChannel struct {
Ch chan Value
}
// MakeChannel creates a channel Value with optional buffer size.
func MakeChannel(size int) Value {
return MakePointer(&HbChannel{Ch: make(chan Value, size)})
}
// AsChannel extracts HbChannel from a Pointer value.
func (v Value) AsChannel() *HbChannel {
if !v.IsPointer() {
return nil
}
if ch, ok := v.AsPointer().(*HbChannel); ok {
return ch
}
return nil
}
// Send sends a value into the channel.
func (ch *HbChannel) Send(val Value) {
ch.Ch <- val
}
// Receive receives a value from the channel.
func (ch *HbChannel) Receive() Value {
return <-ch.Ch
}
// TryReceive attempts non-blocking receive. Returns (value, true) or (nil, false).
func (ch *HbChannel) TryReceive() (Value, bool) {
select {
case v := <-ch.Ch:
return v, true
default:
return MakeNil(), false
}
}
// Close closes the channel.
func (ch *HbChannel) Close() {
close(ch.Ch)
}
// --- WaitGroup ---
// HbWaitGroup wraps sync.WaitGroup.
type HbWaitGroup struct {
WG sync.WaitGroup
}
// MakeWaitGroup creates a WaitGroup Value with initial count.
func MakeWaitGroup(n int) Value {
wg := &HbWaitGroup{}
if n > 0 {
wg.WG.Add(n)
}
return MakePointer(wg)
}
// AsWaitGroup extracts HbWaitGroup from a Pointer value.
func (v Value) AsWaitGroup() *HbWaitGroup {
if !v.IsPointer() {
return nil
}
if wg, ok := v.AsPointer().(*HbWaitGroup); ok {
return wg
}
return nil
}
// --- Mutex ---
// HbMutex wraps sync.Mutex.
type HbMutex struct {
Mu sync.Mutex
}
// MakeMutex creates a Mutex Value.
func MakeMutex() Value {
return MakePointer(&HbMutex{})
}
// AsMutex extracts HbMutex from a Pointer value.
func (v Value) AsMutex() *HbMutex {
if !v.IsPointer() {
return nil
}
if mu, ok := v.AsPointer().(*HbMutex); ok {
return mu
}
return nil
}
// --- GoRoutine launcher ---
// GoLaunch spawns a new goroutine that runs a function on a new Thread.
func (vm *VM) GoLaunch(fn func(*Thread), args []Value) {
go func() {
t := vm.NewThread()
for _, a := range args {
t.push(a)
}
t.PendingParams2(len(args))
fn(t)
}()
}
// GoLaunchBlock spawns a goroutine that evaluates a code block.
func (vm *VM) GoLaunchBlock(blk *HbBlock, args []Value) {
go func() {
t := vm.NewThread()
for _, a := range args {
t.push(a)
}
t.PendingParams2(len(args))
blk.Fn(t)
}()
}