vibetunnel/linux/pkg/session/eventloop_other.go
2025-06-21 02:49:38 +02:00

148 lines
2.5 KiB
Go

//go:build !linux && !darwin && !freebsd && !openbsd && !netbsd
// +build !linux,!darwin,!freebsd,!openbsd,!netbsd
package session
import (
"fmt"
"sync"
"time"
)
// selectEventLoop implements EventLoop using select() as a fallback
type selectEventLoop struct {
mu sync.Mutex
running bool
stopChan chan struct{}
fds map[int]*fdInfo
}
type fdInfo struct {
fd int
events EventType
data interface{}
}
func newPlatformEventLoop() (EventLoop, error) {
return &selectEventLoop{
stopChan: make(chan struct{}),
fds: make(map[int]*fdInfo),
}, nil
}
func (e *selectEventLoop) Add(fd int, events EventType, data interface{}) error {
e.mu.Lock()
defer e.mu.Unlock()
e.fds[fd] = &fdInfo{
fd: fd,
events: events,
data: data,
}
return nil
}
func (e *selectEventLoop) Remove(fd int) error {
e.mu.Lock()
defer e.mu.Unlock()
delete(e.fds, fd)
return nil
}
func (e *selectEventLoop) Modify(fd int, events EventType) error {
e.mu.Lock()
defer e.mu.Unlock()
if info, ok := e.fds[fd]; ok {
info.events = events
}
return nil
}
func (e *selectEventLoop) Run(handler EventHandler) error {
e.mu.Lock()
if e.running {
e.mu.Unlock()
return fmt.Errorf("event loop already running")
}
e.running = true
e.mu.Unlock()
defer func() {
e.mu.Lock()
e.running = false
e.mu.Unlock()
}()
for {
select {
case <-e.stopChan:
return nil
default:
}
// Use existing select-based polling as fallback
// This is not as efficient as epoll/kqueue but works everywhere
if err := e.RunOnce(handler, 10); err != nil {
return err
}
}
}
func (e *selectEventLoop) RunOnce(handler EventHandler, timeoutMs int) error {
e.mu.Lock()
fdList := make([]int, 0, len(e.fds))
for fd := range e.fds {
fdList = append(fdList, fd)
}
e.mu.Unlock()
if len(fdList) == 0 {
time.Sleep(time.Duration(timeoutMs) * time.Millisecond)
return nil
}
// Use the existing selectRead function
ready, err := selectRead(fdList, time.Duration(timeoutMs)*time.Millisecond)
if err != nil {
return err
}
// Process ready file descriptors
for _, fd := range ready {
e.mu.Lock()
info, ok := e.fds[fd]
e.mu.Unlock()
if ok {
handler(Event{
FD: fd,
Events: EventRead, // select only supports read events
Data: info.data,
})
}
}
return nil
}
func (e *selectEventLoop) Stop() error {
close(e.stopChan)
e.stopChan = make(chan struct{})
return nil
}
func (e *selectEventLoop) Close() error {
e.mu.Lock()
defer e.mu.Unlock()
if e.running {
e.Stop()
time.Sleep(10 * time.Millisecond)
}
return nil
}