|
12 | 12 | import java.util.concurrent.atomic.AtomicBoolean; |
13 | 13 | import java.util.concurrent.atomic.AtomicLong; |
14 | 14 | import java.util.concurrent.atomic.AtomicReference; |
| 15 | +import java.util.concurrent.locks.ReentrantLock; |
15 | 16 |
|
16 | 17 | import org.slf4j.Logger; |
17 | 18 | import org.slf4j.LoggerFactory; |
@@ -44,6 +45,7 @@ public abstract class WriterImpl extends GrpcStreamRetrier { |
44 | 45 | private final AtomicReference<CompletableFuture<InitResult>> initResultFutureRef = new AtomicReference<>(null); |
45 | 46 | // Messages that are waiting for being put into sending queue due to queue overflow |
46 | 47 | private final Queue<IncomingMessage> incomingQueue = new LinkedList<>(); |
| 48 | + private final ReentrantLock incomingQueueLock = new ReentrantLock(); |
47 | 49 | // Messages that are currently encoding |
48 | 50 | private final Queue<EnqueuedMessage> encodingMessages = new LinkedList<>(); |
49 | 51 | // Messages that are taken into send buffer, are already compressed and are waiting for being sent |
@@ -99,7 +101,9 @@ private IncomingMessage(EnqueuedMessage message) { |
99 | 101 | } |
100 | 102 |
|
101 | 103 | public CompletableFuture<Void> tryToEnqueue(EnqueuedMessage message, boolean instant) { |
102 | | - synchronized (incomingQueue) { |
| 104 | + incomingQueueLock.lock(); |
| 105 | + |
| 106 | + try { |
103 | 107 | if (currentInFlightCount >= settings.getMaxSendBufferMessagesCount()) { |
104 | 108 | if (instant) { |
105 | 109 | logger.info("[{}] Rejecting a message due to reaching message queue in-flight limit of {}", id, |
@@ -137,10 +141,12 @@ public CompletableFuture<Void> tryToEnqueue(EnqueuedMessage message, boolean ins |
137 | 141 | IncomingMessage incomingMessage = new IncomingMessage(message); |
138 | 142 | incomingQueue.add(incomingMessage); |
139 | 143 | return incomingMessage.future; |
| 144 | + } finally { |
| 145 | + incomingQueueLock.unlock(); |
140 | 146 | } |
141 | 147 | } |
142 | 148 |
|
143 | | - // should be done under synchronized incomingQueue |
| 149 | + // should be done under incomingQueueLock |
144 | 150 | private void acceptMessageIntoSendingQueue(EnqueuedMessage message) { |
145 | 151 | this.lastAcceptedMessageFuture = message.getFuture(); |
146 | 152 | this.currentInFlightCount++; |
@@ -187,7 +193,9 @@ private void moveEncodedMessagesToSendingQueue() { |
187 | 193 | boolean haveNewMessagesToSend = false; |
188 | 194 | // Working with encodingMessages under synchronized incomingQueue to prevent deadlocks |
189 | 195 | // while working with free method |
190 | | - synchronized (incomingQueue) { |
| 196 | + incomingQueueLock.lock(); |
| 197 | + |
| 198 | + try { |
191 | 199 | // Taking all encoded messages to sending queue |
192 | 200 | while (true) { |
193 | 201 | EnqueuedMessage encodedMessage = encodingMessages.peek(); |
@@ -217,6 +225,8 @@ private void moveEncodedMessagesToSendingQueue() { |
217 | 225 | break; |
218 | 226 | } |
219 | 227 | } |
| 228 | + } finally { |
| 229 | + incomingQueueLock.unlock(); |
220 | 230 | } |
221 | 231 | if (haveNewMessagesToSend) { |
222 | 232 | session.sendDataRequestIfNeeded(); |
@@ -264,15 +274,21 @@ protected CompletableFuture<Void> flushImpl() { |
264 | 274 | if (this.lastAcceptedMessageFuture == null) { |
265 | 275 | return CompletableFuture.completedFuture(null); |
266 | 276 | } |
267 | | - synchronized (incomingQueue) { |
| 277 | + incomingQueueLock.lock(); |
| 278 | + |
| 279 | + try { |
268 | 280 | return this.lastAcceptedMessageFuture.isDone() |
269 | 281 | ? CompletableFuture.completedFuture(null) |
270 | 282 | : this.lastAcceptedMessageFuture.thenApply(v -> null); |
| 283 | + } finally { |
| 284 | + incomingQueueLock.unlock(); |
271 | 285 | } |
272 | 286 | } |
273 | 287 |
|
274 | 288 | private void free(int messageCount, long sizeBytes) { |
275 | | - synchronized (incomingQueue) { |
| 289 | + incomingQueueLock.lock(); |
| 290 | + |
| 291 | + try { |
276 | 292 | currentInFlightCount -= messageCount; |
277 | 293 | availableSizeBytes += sizeBytes; |
278 | 294 | if (logger.isTraceEnabled()) { |
@@ -301,6 +317,8 @@ private void free(int messageCount, long sizeBytes) { |
301 | 317 | } |
302 | 318 | logger.trace("[{}] All messages from incomingQueue are accepted into send buffer", id); |
303 | 319 | } |
| 320 | + } finally { |
| 321 | + incomingQueueLock.unlock(); |
304 | 322 | } |
305 | 323 | } |
306 | 324 |
|
|
0 commit comments