1
1
import { EventEmitter } from 'stream'
2
+ import { assert } from 'console'
2
3
3
4
/**
4
5
* 非同期反復可能な先入れ先出し型の待ち行列への非同期反復子
@@ -39,7 +40,11 @@ class AIQAsyncIterator<T> implements AsyncIterator<T> {
39
40
/**
40
41
* 非同期反復可能な先入れ先出し型の待ち行列の状態を表す型
41
42
*/
42
- type AIQState = 'ending' | 'finished'
43
+ enum AIQState {
44
+ ending = 1 ,
45
+ finished = 2 ,
46
+ undefined = 0 ,
47
+ }
43
48
44
49
/**
45
50
* 非同期反復可能な先入れ先出し型の待ち行列
@@ -63,18 +68,14 @@ export class AsyncIterableQueue<T> implements AsyncIterable<T> {
63
68
/**
64
69
* この待ち行列の現在の状態
65
70
*/
66
- #state?: AIQState
71
+ readonly #state = new Uint8Array ( [ AIQState . undefined ] )
67
72
68
73
/**
69
74
* コンストラクタ
70
75
*/
71
76
constructor ( ) {
72
77
const resolveAsync = createAsyncResolver ( {
73
- finish : ( ) => {
74
- const state = this . #state
75
- this . #state = 'finished'
76
- return state
77
- } ,
78
+ finish : ( ) => Atomics . exchange ( this . #state, 0 , AIQState . finished ) ,
78
79
resolvers : this . #resolvers,
79
80
} )
80
81
this . #emitter. on ( 'deq' , async ( ) => {
@@ -95,10 +96,14 @@ export class AsyncIterableQueue<T> implements AsyncIterable<T> {
95
96
end ( cb ?: NoParameterCallback ) : Promise < void > {
96
97
return new Promise (
97
98
( resolve : Resolver < void > , reject : SingleParameterAction < unknown > ) => {
98
- const state = this . #state
99
- if ( state )
100
- return reject ( new Error ( state ) )
101
- this . #state = 'ending'
99
+ const state = Atomics . compareExchange (
100
+ this . #state,
101
+ 0 ,
102
+ AIQState . undefined ,
103
+ AIQState . ending ,
104
+ )
105
+ if ( state !== AIQState . undefined )
106
+ return reject ( new Error ( AIQState [ state ] ) )
102
107
this . #emitter. emit ( 'enq' , new Terminator ( cb ) )
103
108
return resolve ( )
104
109
}
@@ -112,9 +117,9 @@ export class AsyncIterableQueue<T> implements AsyncIterable<T> {
112
117
push ( value : T ) : Promise < void > {
113
118
return new Promise (
114
119
( resolve : Resolver < void > , reject : SingleParameterAction < unknown > ) => {
115
- const state = this . #state
116
- if ( state )
117
- return reject ( new Error ( state ) )
120
+ const state = Atomics . load ( this . #state, 0 )
121
+ if ( state !== AIQState . undefined )
122
+ return reject ( new Error ( AIQState [ state ] ) )
118
123
this . #emitter. emit ( 'enq' , value )
119
124
return resolve ( )
120
125
}
@@ -220,8 +225,8 @@ const createAsyncResolver = <T>(param: AsyncResolverCreateParameter<T>) => {
220
225
if ( value instanceof Terminator ) {
221
226
const state = param . finish ( )
222
227
await resolveAsync ( { done : true } as IteratorResult < T > )
223
- if ( state === ' ending' )
224
- await value . call ( )
228
+ assert ( state === AIQState . ending )
229
+ await value . call ( )
225
230
}
226
231
else
227
232
await resolveAsync ( {
0 commit comments