@@ -94,18 +94,22 @@ public ThreadCachingPool( int targetSize, Allocator<T> allocator, ValidationStra
94
94
95
95
public T acquire ( long timeout , TimeUnit unit ) throws InterruptedException
96
96
{
97
+ assert live .size () <= maxSize ;
97
98
long deadline = clock .millis () + unit .toMillis ( timeout );
98
99
99
100
// 1. Try and value an object from our local slot
100
101
Slot <T > slot = local .get ();
101
102
102
- if ( slot != null && slot .availableToClaimed () )
103
+ if ( slot != null && slot .availableToThreadLocalClaimed () )
103
104
{
104
105
if ( slot .isValid ( validationStrategy ) )
105
106
{
106
107
allocator .onAcquire ( slot .value );
107
108
return slot .value ;
108
109
}
110
+ else {
111
+ dispose ( slot );
112
+ }
109
113
110
114
//The slot was invalidated however we cannot put it to the
111
115
//disposed queue yet since it already exists in the live queue
@@ -177,14 +181,32 @@ else if ( slot.isClaimedOrAvailableToClaimed() )
177
181
178
182
// Keep this slot cached with our thread, so that we can grab this value quickly next time,
179
183
// assuming threads generally availableToClaimed one instance at a time
180
- local . set ( slot );
184
+ updateThreadLocal ( slot );
181
185
allocator .onAcquire ( slot .value );
182
186
return slot .value ;
183
187
}
184
188
189
+ private void updateThreadLocal (Slot <T > slot )
190
+ {
191
+ Slot <T > localSlot = local .get ();
192
+ if ( localSlot != null )
193
+ {
194
+ //The old slot is no longer in the tread local
195
+ localSlot .threadLocalClaimedToClaimed ();
196
+ }
197
+ else
198
+ {
199
+ //There was nothing stored in thread local
200
+ //no we must also add this slot to the live queue
201
+ live .add ( slot );
202
+ }
203
+ slot .claimByThreadLocal ();
204
+ local .set ( slot );
205
+ }
206
+
185
207
private void dispose ( Slot <T > slot )
186
208
{
187
- if ( slot .claimedToDisposed () )
209
+ if ( slot .claimedToDisposed () || slot . threadLocalClaimedToDisposed () )
188
210
{
189
211
// Done before below, in case dispose call fails. This is safe since objects on the
190
212
// pool are used for read-only operations
@@ -213,7 +235,7 @@ private Slot<T> allocate( int slotIndex )
213
235
// Return it :)
214
236
return slot ;
215
237
}
216
- catch ( Neo4jException e )
238
+ catch ( Neo4jException e )
217
239
{
218
240
// Failed to allocate slot, return it to the list of disposed slots, rethrow exception.
219
241
slot .claimedToDisposed ();
@@ -230,7 +252,7 @@ private Consumer<T> createDisposeCallback( final Slot<T> slot )
230
252
public void accept ( T t )
231
253
{
232
254
slot .updateUsageTimestamp ();
233
- if ( !slot .isValid ( validationStrategy ) )
255
+ if ( !slot .isValid ( validationStrategy ) )
234
256
{
235
257
dispose ( slot );
236
258
return ;
@@ -256,6 +278,17 @@ public void accept( T t )
256
278
}
257
279
}
258
280
}
281
+
282
+ // If we are claimed by thread local we are already in the live queue
283
+ if ( slot .threadLocalClaimedToAvailable () && stopped .get () )
284
+ {
285
+ // As above, try to claim the slot back and dispose
286
+ if ( slot .availableToClaimed () )
287
+ {
288
+ dispose ( slot );
289
+ }
290
+ }
291
+
259
292
}
260
293
};
261
294
}
@@ -286,6 +319,7 @@ class Slot<T>
286
319
enum State
287
320
{
288
321
AVAILABLE ,
322
+ THREAD_LOCAL_CLAIMED ,
289
323
CLAIMED ,
290
324
DISPOSED
291
325
}
@@ -318,6 +352,11 @@ public boolean availableToClaimed()
318
352
return state .compareAndSet ( State .AVAILABLE , State .CLAIMED );
319
353
}
320
354
355
+ public boolean availableToThreadLocalClaimed ()
356
+ {
357
+ return state .compareAndSet ( State .AVAILABLE , State .THREAD_LOCAL_CLAIMED );
358
+ }
359
+
321
360
public boolean claimedToAvailable ()
322
361
{
323
362
updateUsageTimestamp ();
@@ -329,6 +368,26 @@ public boolean claimedToDisposed()
329
368
return state .compareAndSet ( State .CLAIMED , State .DISPOSED );
330
369
}
331
370
371
+ public boolean threadLocalClaimedToDisposed ()
372
+ {
373
+ return state .compareAndSet ( State .THREAD_LOCAL_CLAIMED , State .DISPOSED );
374
+ }
375
+
376
+ public boolean threadLocalClaimedToClaimed ()
377
+ {
378
+ return state .compareAndSet ( State .THREAD_LOCAL_CLAIMED , State .CLAIMED );
379
+ }
380
+
381
+ public boolean threadLocalClaimedToAvailable ()
382
+ {
383
+ return state .compareAndSet ( State .THREAD_LOCAL_CLAIMED , State .AVAILABLE );
384
+ }
385
+
386
+ public void claimByThreadLocal ()
387
+ {
388
+ state .set ( State .THREAD_LOCAL_CLAIMED );
389
+ }
390
+
332
391
public boolean isClaimedOrAvailableToClaimed ()
333
392
{
334
393
return availableToClaimed () || state .get () == State .CLAIMED ;
0 commit comments