18
18
import java .time .Duration ;
19
19
import java .util .concurrent .CountDownLatch ;
20
20
import java .util .concurrent .TimeUnit ;
21
+ import java .util .concurrent .locks .Lock ;
22
+ import java .util .concurrent .locks .ReentrantLock ;
21
23
import java .util .function .Supplier ;
22
24
23
25
import org .springframework .dao .DataAccessResourceFailureException ;
39
41
*/
40
42
abstract class CursorReadingTask <T , R > implements Task {
41
43
42
- private final Object lifecycleMonitor = new Object ();
44
+ private final Lock lock = new ReentrantLock ();
43
45
44
46
private final MongoTemplate template ;
45
47
private final SubscriptionRequest <T , R , RequestOptions > request ;
@@ -86,19 +88,14 @@ public void run() {
86
88
}
87
89
} catch (InterruptedException e ) {
88
90
89
- synchronized (lifecycleMonitor ) {
90
- state = State .CANCELLED ;
91
- }
91
+ doWhileLocked (lock , () -> state = State .CANCELLED );
92
92
Thread .currentThread ().interrupt ();
93
93
break ;
94
94
}
95
95
}
96
96
} catch (RuntimeException e ) {
97
97
98
- synchronized (lifecycleMonitor ) {
99
- state = State .CANCELLED ;
100
- }
101
-
98
+ doWhileLocked (lock , () -> state = State .CANCELLED );
102
99
errorHandler .handleError (e );
103
100
}
104
101
}
@@ -114,40 +111,40 @@ public void run() {
114
111
*/
115
112
private void start () {
116
113
117
- synchronized ( lifecycleMonitor ) {
114
+ doWhileLocked ( lock , () -> {
118
115
if (!State .RUNNING .equals (state )) {
119
116
state = State .STARTING ;
120
117
}
121
- }
118
+ });
122
119
123
120
do {
124
121
125
- boolean valid = false ;
122
+ // boolean valid = false;
126
123
127
- synchronized ( lifecycleMonitor ) {
124
+ boolean valid = executeWhileLocked ( lock , () -> {
128
125
129
- if (State .STARTING .equals (state )) {
126
+ if (!State .STARTING .equals (state )) {
127
+ return false ;
128
+ }
130
129
131
- MongoCursor <T > cursor = execute (() -> initCursor (template , request .getRequestOptions (), targetType ));
132
- valid = isValidCursor (cursor );
133
- if (valid ) {
134
- this .cursor = cursor ;
135
- state = State .RUNNING ;
136
- } else if (cursor != null ) {
137
- cursor .close ();
138
- }
130
+ MongoCursor <T > cursor = execute (() -> initCursor (template , request .getRequestOptions (), targetType ));
131
+ boolean isValid = isValidCursor (cursor );
132
+ if (isValid ) {
133
+ this .cursor = cursor ;
134
+ state = State .RUNNING ;
135
+ } else if (cursor != null ) {
136
+ cursor .close ();
139
137
}
140
- }
138
+ return isValid ;
139
+ });
141
140
142
141
if (!valid ) {
143
142
144
143
try {
145
144
Thread .sleep (100 );
146
145
} catch (InterruptedException e ) {
147
146
148
- synchronized (lifecycleMonitor ) {
149
- state = State .CANCELLED ;
150
- }
147
+ doWhileLocked (lock , () -> state = State .CANCELLED );
151
148
Thread .currentThread ().interrupt ();
152
149
}
153
150
}
@@ -163,15 +160,15 @@ private void start() {
163
160
@ Override
164
161
public void cancel () throws DataAccessResourceFailureException {
165
162
166
- synchronized ( lifecycleMonitor ) {
163
+ doWhileLocked ( lock , () -> {
167
164
168
165
if (State .RUNNING .equals (state ) || State .STARTING .equals (state )) {
169
166
this .state = State .CANCELLED ;
170
167
if (cursor != null ) {
171
168
cursor .close ();
172
169
}
173
170
}
174
- }
171
+ });
175
172
}
176
173
177
174
@ Override
@@ -181,10 +178,7 @@ public boolean isLongLived() {
181
178
182
179
@ Override
183
180
public State getState () {
184
-
185
- synchronized (lifecycleMonitor ) {
186
- return state ;
187
- }
181
+ return executeWhileLocked (lock , () -> state );
188
182
}
189
183
190
184
@ Override
@@ -220,13 +214,12 @@ private void emitMessage(Message<T, R> message) {
220
214
@ Nullable
221
215
private T getNext () {
222
216
223
- synchronized ( lifecycleMonitor ) {
217
+ return executeWhileLocked ( lock , () -> {
224
218
if (State .RUNNING .equals (state )) {
225
219
return cursor .tryNext ();
226
220
}
227
- }
228
-
229
- throw new IllegalStateException (String .format ("Cursor %s is not longer open" , cursor ));
221
+ throw new IllegalStateException (String .format ("Cursor %s is not longer open" , cursor ));
222
+ });
230
223
}
231
224
232
225
private static boolean isValidCursor (@ Nullable MongoCursor <?> cursor ) {
@@ -263,4 +256,23 @@ private <V> V execute(Supplier<V> callback) {
263
256
throw translated != null ? translated : e ;
264
257
}
265
258
}
259
+
260
+ private static void doWhileLocked (Lock lock , Runnable action ) {
261
+
262
+ executeWhileLocked (lock , () -> {
263
+ action .run ();
264
+ return null ;
265
+ });
266
+ }
267
+
268
+ @ Nullable
269
+ private static <T > T executeWhileLocked (Lock lock , Supplier <T > stuff ) {
270
+
271
+ lock .lock ();
272
+ try {
273
+ return stuff .get ();
274
+ } finally {
275
+ lock .unlock ();
276
+ }
277
+ }
266
278
}
0 commit comments