@pistonite/pure 0.26.2 → 0.26.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/memory/asyncerc.ts +179 -0
- package/src/memory/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pistonite/pure",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Pure TypeScript libraries for my projects",
|
|
6
6
|
"homepage": "https://github.com/Pistonite/pure",
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"vitest": "^3.1.1",
|
|
34
|
-
"mono-dev": "0.1.
|
|
34
|
+
"mono-dev": "0.1.2"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A holder for an externally ref-counted object, where free and addref
|
|
3
|
+
* operations are asynchronous.
|
|
4
|
+
*
|
|
5
|
+
* See {@link makeErcType} for how to use
|
|
6
|
+
*/
|
|
7
|
+
export type AsyncErc<TName, TRepr = number> = {
|
|
8
|
+
readonly type: TName;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Underlying object representation.
|
|
12
|
+
*
|
|
13
|
+
* The repr should not be undefinable. undefined means nullptr
|
|
14
|
+
*/
|
|
15
|
+
readonly value: TRepr | undefined;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Free the underlying object.
|
|
19
|
+
*
|
|
20
|
+
* All weak references will be immediately invalidated, and this Erc becomes
|
|
21
|
+
* empty. Awaiting on the promise will ensure that the object is freed externally
|
|
22
|
+
*/
|
|
23
|
+
free: () => Promise<void>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Assign a new value to this Erc.
|
|
27
|
+
*
|
|
28
|
+
* The old value will be freed, and all weak references will be invalidated.
|
|
29
|
+
*/
|
|
30
|
+
assign: (value: TRepr | undefined) => Promise<void>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Take the inner value without freeing it.
|
|
34
|
+
*
|
|
35
|
+
* All weak references will be invalidated, and this Erc will become
|
|
36
|
+
* empty
|
|
37
|
+
*/
|
|
38
|
+
take: () => TRepr | undefined;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create a weak reference to the inner value.
|
|
42
|
+
*
|
|
43
|
+
* When this Erc is freed, all weak references will be invalidated.
|
|
44
|
+
*/
|
|
45
|
+
getWeak: () => AsyncErcRef<TName, TRepr>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Create a strong reference to the inner value, essentially
|
|
49
|
+
* incrementing the ref count.
|
|
50
|
+
*/
|
|
51
|
+
getStrong: () => Promise<AsyncErc<TName, TRepr>>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Weak reference to an externally ref-counted object.
|
|
56
|
+
*
|
|
57
|
+
* See {@link makeErcType} for how to use
|
|
58
|
+
*/
|
|
59
|
+
export type AsyncErcRef<TName, TRepr = number> = {
|
|
60
|
+
readonly type: TName;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The underlying object representation.
|
|
64
|
+
*
|
|
65
|
+
* This may become undefined across async calls if the weak reference
|
|
66
|
+
* is invalidated
|
|
67
|
+
*/
|
|
68
|
+
readonly value: TRepr | undefined;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Create a strong reference to the inner value, essentially
|
|
72
|
+
* incrementing the ref count.
|
|
73
|
+
*/
|
|
74
|
+
getStrong: () => Promise<AsyncErc<TName, TRepr>>;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export type AsyncErcRefType<T> =
|
|
78
|
+
T extends AsyncErc<infer TName, infer TRepr>
|
|
79
|
+
? AsyncErcRef<TName, TRepr>
|
|
80
|
+
: never;
|
|
81
|
+
|
|
82
|
+
export type AsyncErcTypeConstructor<TName, TRepr> = {
|
|
83
|
+
/**
|
|
84
|
+
* A marker value for the underlying object type.
|
|
85
|
+
*
|
|
86
|
+
* This is commonly a string literal or a symbol.
|
|
87
|
+
*/
|
|
88
|
+
marker: TName;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The function to free the underlying object.
|
|
92
|
+
*/
|
|
93
|
+
free: (value: TRepr) => Promise<void> | void;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Given a value, increase the ref count and return the new reference.
|
|
97
|
+
* The returned representation should be a different value if double indirection
|
|
98
|
+
* is used (each value is a pointer to the smart pointer), or the same value
|
|
99
|
+
* if single indirection is used (the value is pointing to the object itself).
|
|
100
|
+
*/
|
|
101
|
+
addRef: (value: TRepr) => Promise<TRepr> | TRepr;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/** See {@link makeErcType} */
|
|
105
|
+
export const makeAsyncErcType = <TName, TRepr>({
|
|
106
|
+
marker,
|
|
107
|
+
free,
|
|
108
|
+
addRef,
|
|
109
|
+
}: AsyncErcTypeConstructor<TName, TRepr>): ((
|
|
110
|
+
value: TRepr | undefined,
|
|
111
|
+
) => AsyncErc<TName, TRepr>) => {
|
|
112
|
+
const createStrongRef = (
|
|
113
|
+
value: TRepr | undefined,
|
|
114
|
+
): AsyncErc<TName, TRepr> => {
|
|
115
|
+
let weakRef:
|
|
116
|
+
| (AsyncErcRef<TName, TRepr> & { invalidate: () => void })
|
|
117
|
+
| undefined = undefined;
|
|
118
|
+
const invalidateWeakRef = () => {
|
|
119
|
+
if (!weakRef) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const oldWeakRef = weakRef;
|
|
123
|
+
weakRef = undefined;
|
|
124
|
+
oldWeakRef.invalidate();
|
|
125
|
+
};
|
|
126
|
+
const createWeakRef = (initialValue: TRepr | undefined) => {
|
|
127
|
+
const weak = {
|
|
128
|
+
type: marker,
|
|
129
|
+
value: initialValue,
|
|
130
|
+
invalidate: () => {
|
|
131
|
+
weak.value = undefined;
|
|
132
|
+
},
|
|
133
|
+
getStrong: async () => {
|
|
134
|
+
if (weak.value === undefined) {
|
|
135
|
+
return createStrongRef(undefined);
|
|
136
|
+
}
|
|
137
|
+
return createStrongRef(await addRef(weak.value));
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
return weak;
|
|
141
|
+
};
|
|
142
|
+
const erc = {
|
|
143
|
+
type: marker,
|
|
144
|
+
value,
|
|
145
|
+
free: async () => {
|
|
146
|
+
if (erc.value !== undefined) {
|
|
147
|
+
invalidateWeakRef();
|
|
148
|
+
const freePromise = free(erc.value);
|
|
149
|
+
erc.value = undefined;
|
|
150
|
+
await freePromise;
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
assign: async (newValue: TRepr | undefined) => {
|
|
154
|
+
await erc.free();
|
|
155
|
+
erc.value = newValue;
|
|
156
|
+
},
|
|
157
|
+
take: () => {
|
|
158
|
+
invalidateWeakRef();
|
|
159
|
+
const oldValue = erc.value;
|
|
160
|
+
erc.value = undefined;
|
|
161
|
+
return oldValue;
|
|
162
|
+
},
|
|
163
|
+
getWeak: () => {
|
|
164
|
+
if (!weakRef) {
|
|
165
|
+
weakRef = createWeakRef(erc.value);
|
|
166
|
+
}
|
|
167
|
+
return weakRef;
|
|
168
|
+
},
|
|
169
|
+
getStrong: async () => {
|
|
170
|
+
if (erc.value === undefined) {
|
|
171
|
+
return createStrongRef(undefined);
|
|
172
|
+
}
|
|
173
|
+
return createStrongRef(await addRef(erc.value));
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
return erc;
|
|
177
|
+
};
|
|
178
|
+
return createStrongRef;
|
|
179
|
+
};
|
package/src/memory/index.ts
CHANGED