-
Notifications
You must be signed in to change notification settings - Fork 7
/
value.go
123 lines (99 loc) · 1.68 KB
/
value.go
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package janet
/*
#cgo CFLAGS: -std=c99
#cgo LDFLAGS: -lm -ldl
#include <janet.h>
#include <api.h>
*/
import "C"
import (
"context"
"fmt"
"github.com/sasha-s/go-deadlock"
)
var ERROR_FREED = fmt.Errorf("cannot use freed value")
type Value struct {
deadlock.RWMutex
vm *VM
janet C.Janet
wasFreed bool
}
func (v *VM) value(janet C.Janet) *Value {
C.janet_gcroot(janet)
return &Value{
vm: v,
janet: janet,
}
}
type unlockRequest struct {
Value *Value
}
func (v *Value) IsFree() bool {
v.RLock()
defer v.RUnlock()
return v.wasFreed
}
func (v *Value) unroot() {
C.janet_gcunroot(v.janet)
}
func (v *Value) Free() {
v.Lock()
defer v.Unlock()
if v.wasFreed {
return
}
v.wasFreed = true
v.vm.requests <- unlockRequest{
Value: v,
}
}
type unmarshalRequest struct {
source C.Janet
dest interface{}
errc chan error
}
func (v *Value) Unmarshal(dest interface{}) error {
if v.IsFree() {
return ERROR_FREED
}
return v.vm.Unmarshal(v.janet, dest)
}
type Table struct {
*Value
table *C.JanetTable
}
type Fiber struct {
*Value
fiber *C.JanetFiber
}
type Keyword string
type Function struct {
*Value
function *C.JanetFunction
}
type functionRequest struct {
Params
Args []interface{}
Function *Function
}
func (f *Function) CallContext(
ctx context.Context,
user interface{},
params ...interface{},
) error {
result := make(chan Result)
req := functionRequest{
Args: params,
Function: f,
Params: Params{
Context: ctx,
User: user,
Result: result,
},
}
f.vm.requests <- req
return req.Wait()
}
func (f *Function) Call(ctx context.Context, params ...interface{}) error {
return f.CallContext(ctx, nil, params...)
}