6
6
7
7
package kotlinx.rpc.grpc.internal
8
8
9
- import cnames.structs.grpc_call
10
9
import kotlinx.atomicfu.atomic
11
10
import kotlinx.atomicfu.locks.SynchronizedObject
12
11
import kotlinx.atomicfu.locks.synchronized
13
12
import kotlinx.cinterop.*
14
- import kotlinx.coroutines.CompletableDeferred
15
13
import libgrpcpp_c.*
16
14
import platform.posix.memset
17
15
import kotlin.experimental.ExperimentalNativeApi
18
16
import kotlin.native.ref.createCleaner
19
17
20
18
internal sealed interface BatchResult {
21
- object Success : BatchResult
22
- object ResultError : BatchResult
23
19
object CQShutdown : BatchResult
24
20
data class CallError (val error : grpc_call_error) : BatchResult
21
+ data class Called (val future : CallbackFuture <Boolean >) : BatchResult
25
22
}
26
23
27
24
/* *
@@ -45,7 +42,7 @@ internal class CompletionQueue {
45
42
// internal as it must be accessible from the SHUTDOWN_CB,
46
43
// but it shouldn't be used from outside this file.
47
44
@Suppress(" PropertyName" )
48
- internal val _shutdownDone = CompletableDeferred <Unit >()
45
+ internal val _shutdownDone = CallbackFuture <Unit >()
49
46
50
47
// used for spinning lock. false means not used (available)
51
48
private val batchStartGuard = SynchronizedObject ()
@@ -72,40 +69,41 @@ internal class CompletionQueue {
72
69
require(kgrpc_iomgr_run_in_background()) { " The gRPC iomgr is not running background threads, required for callback based APIs." }
73
70
}
74
71
75
- // TODO: Remove this method
76
- fun runBatch (call : NativeClientCall <* , * >, ops : CPointer <grpc_op>, nOps : ULong ) =
77
- runBatch(call.raw, ops, nOps)
78
-
79
- fun runBatch (call : CPointer <grpc_call>, ops : CPointer <grpc_op>, nOps : ULong ): CompletableDeferred <BatchResult > {
80
- val completion = CompletableDeferred <BatchResult >()
72
+ fun runBatch (call : NativeClientCall <* , * >, ops : CPointer <grpc_op>, nOps : ULong ): BatchResult {
73
+ val completion = CallbackFuture <Boolean >()
81
74
val tag = newCbTag(completion, OPS_COMPLETE_CB )
82
75
83
76
var err = grpc_call_error.GRPC_CALL_ERROR
77
+
84
78
synchronized(batchStartGuard) {
85
- // synchronizes access to grpc_call_start_batch
79
+ if (_state .value == State .SHUTTING_DOWN && ops.pointed.op == GRPC_OP_RECV_STATUS_ON_CLIENT ) {
80
+ // if the queue is in the process of a SHUTDOWN,
81
+ // new call status receive batches will be rejected.
82
+ deleteCbTag(tag)
83
+ return BatchResult .CQShutdown
84
+ }
85
+
86
86
if (forceShutdown || _state .value == State .CLOSED ) {
87
87
// if the queue is either closed or in the process of a FORCE shutdown,
88
88
// new batches will instantly fail.
89
89
deleteCbTag(tag)
90
- completion.complete(BatchResult .CQShutdown )
91
- return completion
90
+ return BatchResult .CQShutdown
92
91
}
93
92
94
- err = grpc_call_start_batch(call, ops, nOps, tag, null )
93
+ err = grpc_call_start_batch(call.raw , ops, nOps, tag, null )
95
94
}
96
95
97
96
if (err != grpc_call_error.GRPC_CALL_OK ) {
98
97
// if the call was not successful, the callback will not be invoked.
99
98
deleteCbTag(tag)
100
- completion.complete(BatchResult .CallError (err))
101
- return completion
99
+ return BatchResult .CallError (err)
102
100
}
103
101
104
- return completion
102
+ return BatchResult . Called ( completion)
105
103
}
106
104
107
105
// must not be canceled as it cleans resources and sets the state to CLOSED
108
- fun shutdown (force : Boolean = false): CompletableDeferred <Unit > {
106
+ fun shutdown (force : Boolean = false): CallbackFuture <Unit > {
109
107
if (force) {
110
108
forceShutdown = true
111
109
}
@@ -130,10 +128,9 @@ internal class CompletionQueue {
130
128
@CName(" kq_ops_complete_cb" )
131
129
private fun opsCompleteCb (functor : CPointer <grpc_completion_queue_functor>? , ok : Int ) {
132
130
val tag = functor!! .reinterpret< grpc_cb_tag> ()
133
- val cont = tag.pointed.user_data!! .asStableRef<CompletableDeferred < BatchResult >>().get()
131
+ val cont = tag.pointed.user_data!! .asStableRef<CallbackFuture < Boolean >>().get()
134
132
deleteCbTag(tag)
135
- if (ok != 0 ) cont.complete(BatchResult .Success )
136
- else cont.complete(BatchResult .ResultError )
133
+ cont.complete(ok != 0 )
137
134
}
138
135
139
136
@CName(" kq_shutdown_cb" )
0 commit comments