handle.go

 1package util
 2
 3import (
 4	"context"
 5	"io"
 6)
 7
 8type handleState struct {
 9	handles []any
10	holes   int
11}
12
13func (s *handleState) CloseNotify(ctx context.Context, exitCode uint32) {
14	for _, h := range s.handles {
15		if c, ok := h.(io.Closer); ok {
16			c.Close()
17		}
18	}
19	s.handles = nil
20	s.holes = 0
21}
22
23func GetHandle(ctx context.Context, id Ptr_t) any {
24	if id == 0 {
25		return nil
26	}
27	s := ctx.Value(moduleKey{}).(*moduleState)
28	return s.handles[^id]
29}
30
31func DelHandle(ctx context.Context, id Ptr_t) error {
32	if id == 0 {
33		return nil
34	}
35	s := ctx.Value(moduleKey{}).(*moduleState)
36	a := s.handles[^id]
37	s.handles[^id] = nil
38	if l := Ptr_t(len(s.handles)); l == ^id {
39		s.handles = s.handles[:l-1]
40	} else {
41		s.holes++
42	}
43	if c, ok := a.(io.Closer); ok {
44		return c.Close()
45	}
46	return nil
47}
48
49func AddHandle(ctx context.Context, a any) Ptr_t {
50	if a == nil {
51		panic(NilErr)
52	}
53
54	s := ctx.Value(moduleKey{}).(*moduleState)
55
56	// Find an empty slot.
57	if s.holes > cap(s.handles)-len(s.handles) {
58		for id, h := range s.handles {
59			if h == nil {
60				s.holes--
61				s.handles[id] = a
62				return ^Ptr_t(id)
63			}
64		}
65	}
66
67	// Add a new slot.
68	s.handles = append(s.handles, a)
69	return -Ptr_t(len(s.handles))
70}