summaryrefslogtreecommitdiff
path: root/vendor/github.com/ncruces/go-sqlite3/internal/util/handle.go
blob: 4584324c1b55b9e9f8a1ceedc0c37c69aa9993f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package util

import (
	"context"
	"io"
)

type handleState struct {
	handles []any
	holes   int
}

func (s *handleState) CloseNotify(ctx context.Context, exitCode uint32) {
	for _, h := range s.handles {
		if c, ok := h.(io.Closer); ok {
			c.Close()
		}
	}
	s.handles = nil
	s.holes = 0
}

func GetHandle(ctx context.Context, id uint32) any {
	if id == 0 {
		return nil
	}
	s := ctx.Value(moduleKey{}).(*moduleState)
	return s.handles[^id]
}

func DelHandle(ctx context.Context, id uint32) error {
	if id == 0 {
		return nil
	}
	s := ctx.Value(moduleKey{}).(*moduleState)
	a := s.handles[^id]
	s.handles[^id] = nil
	s.holes++
	if c, ok := a.(io.Closer); ok {
		return c.Close()
	}
	return nil
}

func AddHandle(ctx context.Context, a any) (id uint32) {
	if a == nil {
		panic(NilErr)
	}
	s := ctx.Value(moduleKey{}).(*moduleState)

	// Find an empty slot.
	if s.holes > cap(s.handles)-len(s.handles) {
		for id, h := range s.handles {
			if h == nil {
				s.holes--
				s.handles[id] = a
				return ^uint32(id)
			}
		}
	}

	// Add a new slot.
	s.handles = append(s.handles, a)
	return -uint32(len(s.handles))
}