github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/rtutils/singlethread/singlethread.go (about)

     1  package singlethread
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  )
     7  
     8  type callback struct {
     9  	funcToCall func() error
    10  	funcResult chan (error)
    11  }
    12  
    13  type Thread struct {
    14  	callback chan (callback)
    15  	closed   bool
    16  	mutex    *sync.Mutex
    17  }
    18  
    19  func New() *Thread {
    20  	t := &Thread{
    21  		make(chan (callback)),
    22  		false,
    23  		&sync.Mutex{},
    24  	}
    25  	go t.run()
    26  	return t
    27  }
    28  
    29  func (t *Thread) run() {
    30  	for {
    31  		callback, gotCallback := <-t.callback
    32  		if gotCallback {
    33  			callback.funcResult <- callback.funcToCall()
    34  		} else {
    35  			return
    36  		}
    37  	}
    38  }
    39  
    40  func (t *Thread) Run(funcToCall func() error) error {
    41  	t.mutex.Lock()
    42  	defer t.mutex.Unlock()
    43  
    44  	if t.closed {
    45  		return fmt.Errorf("thread is closed")
    46  	}
    47  
    48  	callback := callback{funcToCall, make(chan (error))}
    49  	t.callback <- callback
    50  	return <-callback.funcResult
    51  }
    52  
    53  func (t *Thread) Close() {
    54  	t.mutex.Lock()
    55  	defer t.mutex.Unlock()
    56  
    57  	close(t.callback)
    58  	t.closed = true
    59  }