github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/events/onSecondsElapsed/timer.go (about)

     1  package onsecondselapsed
     2  
     3  import (
     4  	"errors"
     5  	"strconv"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/lmorg/murex/builtins/events"
    10  	"github.com/lmorg/murex/lang"
    11  	"github.com/lmorg/murex/lang/ref"
    12  )
    13  
    14  const eventType = "onSecondsElapsed"
    15  
    16  func init() {
    17  	t := newTimer()
    18  	events.AddEventType(eventType, t, nil)
    19  	go t.init()
    20  }
    21  
    22  type timer struct {
    23  	mutex  sync.Mutex
    24  	events []timeEvent
    25  }
    26  
    27  type timeEvent struct {
    28  	Name     string
    29  	Interval int
    30  	Block    []rune
    31  	state    int
    32  	FileRef  *ref.File
    33  }
    34  
    35  func newTimer() (t *timer) {
    36  	t = new(timer)
    37  	t.events = make([]timeEvent, 0)
    38  	return
    39  }
    40  
    41  func (t *timer) init() {
    42  	for {
    43  		time.Sleep(1 * time.Second)
    44  
    45  		t.mutex.Lock()
    46  		for i := range t.events {
    47  			t.events[i].state++
    48  			if t.events[i].state == t.events[i].Interval {
    49  				t.events[i].state = 0
    50  				go events.Callback(
    51  					t.events[i].Name,
    52  					t.events[i].Interval,
    53  					t.events[i].Block,
    54  					t.events[i].FileRef,
    55  					lang.ShellProcess.Stdout,
    56  					true,
    57  				)
    58  			}
    59  		}
    60  		t.mutex.Unlock()
    61  	}
    62  }
    63  
    64  // Add a path to the watch event list
    65  func (t *timer) Add(name, interrupt string, block []rune, fileRef *ref.File) (err error) {
    66  	interval, err := strconv.Atoi(interrupt)
    67  	if err != nil {
    68  		return errors.New("interrupt should be an integer for `" + eventType + "` events")
    69  	}
    70  
    71  	t.mutex.Lock()
    72  	defer t.mutex.Unlock()
    73  
    74  	for i := range t.events {
    75  		if t.events[i].Name == name {
    76  			t.events[i].Interval = interval
    77  			t.events[i].Block = block
    78  			return nil
    79  		}
    80  	}
    81  
    82  	t.events = append(t.events, timeEvent{
    83  		Name:     name,
    84  		Interval: interval,
    85  		Block:    block,
    86  		FileRef:  fileRef,
    87  	})
    88  
    89  	return
    90  }
    91  
    92  // Remove a path to the watch event list
    93  func (t *timer) Remove(name string) (err error) {
    94  	t.mutex.Lock()
    95  	defer t.mutex.Unlock()
    96  
    97  	if len(t.events) == 0 {
    98  		return errors.New("no events have been created for this listener")
    99  	}
   100  
   101  	for i := range t.events {
   102  		if t.events[i].Name == name {
   103  			switch {
   104  			case len(t.events) == 1:
   105  				t.events = make([]timeEvent, 0)
   106  			case i == 0:
   107  				t.events = t.events[1:]
   108  			case i == len(t.events)-1:
   109  				t.events = t.events[:len(t.events)-1]
   110  			default:
   111  				t.events = append(t.events[:i], t.events[i+1:]...)
   112  			}
   113  			return nil
   114  		}
   115  	}
   116  
   117  	return errors.New("no event found for this listener with the name `" + name + "`.")
   118  }
   119  
   120  // Dump returns all the events in w
   121  func (t *timer) Dump() map[string]events.DumpT {
   122  	dump := make(map[string]events.DumpT)
   123  
   124  	t.mutex.Lock()
   125  
   126  	for i := range t.events {
   127  		dump[t.events[i].Name] = events.DumpT{
   128  			Interrupt: time.Duration(t.events[i].Interval * int(time.Second)).String(),
   129  			Block:     string(t.events[i].Block),
   130  			FileRef:   t.events[i].FileRef,
   131  		}
   132  	}
   133  
   134  	t.mutex.Unlock()
   135  
   136  	return dump
   137  }