@@ -240,31 +240,23 @@ public static class CurrentContextState implements ContextState {
240240 // the default field values are set before 'this' is accessible, hence
241241 // they should be the very first value observable even in presence of
242242 // unsafe publication of this object.
243- private static final int VALID = 0 ;
244- private static final int INVALID = 1 ;
245- private static final VarHandle IS_VALID ;
243+ private static final VarHandle STATE_UPDATER ;
246244
247- private static final int FALSE = 0 ;
248- private static final int TRUE = 1 ;
249- private static final VarHandle INITIALIZED_FIRED ;
250- private static final VarHandle BEFORE_DESTROYED_FIRED ;
245+ private static final byte INVALID_MASK = 0b00000001;
246+ private static final byte INITIALIZED_FIRED_MASK = 0b00000010;
247+ private static final byte BEFORE_DESTROYED_FIRED_MASK = 0b00000100;
251248
252249 static {
253250 try {
254- IS_VALID = MethodHandles .lookup ().findVarHandle (CurrentContextState .class , "isValid" , int .class );
255- INITIALIZED_FIRED = MethodHandles .lookup ().findVarHandle (CurrentContextState .class , "initializedFired" ,
256- int .class );
257- BEFORE_DESTROYED_FIRED = MethodHandles .lookup ().findVarHandle (CurrentContextState .class , "beforeDestroyedFired" ,
258- int .class );
251+ STATE_UPDATER = MethodHandles .lookup ().findVarHandle (CurrentContextState .class , "state" , byte .class );
259252 } catch (ReflectiveOperationException e ) {
260253 throw new Error (e );
261254 }
262255 }
263256
264257 private final ContextInstances contextInstances ;
265- private volatile int isValid ;
266- private volatile int initializedFired ;
267- private volatile int beforeDestroyedFired ;
258+ // it contains 3 states: isValid, initializedFired and beforeDestroyedFired
259+ private volatile byte state ;
268260
269261 CurrentContextState (ContextInstances contextInstances ) {
270262 this .contextInstances = Objects .requireNonNull (contextInstances );
@@ -280,23 +272,39 @@ public Map<InjectableBean<?>, Object> getContextualInstances() {
280272 * @return {@code true} if the state was successfully invalidated, {@code false} otherwise
281273 */
282274 boolean invalidate () {
283- // Atomically sets the value just like AtomicBoolean.compareAndSet(boolean, boolean)
284- return IS_VALID .compareAndSet (this , VALID , INVALID );
275+ return set (INVALID_MASK );
285276 }
286277
287278 @ Override
288279 public boolean isValid () {
289- return isValid == VALID ;
280+ return isNotSet ( INVALID_MASK ) ;
290281 }
291282
292283 boolean shouldFireInitializedEvent () {
293- return INITIALIZED_FIRED . compareAndSet ( this , FALSE , TRUE );
284+ return set ( INITIALIZED_FIRED_MASK );
294285 }
295286
296287 boolean shouldFireBeforeDestroyedEvent () {
297- return BEFORE_DESTROYED_FIRED . compareAndSet ( this , FALSE , TRUE );
288+ return set ( BEFORE_DESTROYED_FIRED_MASK );
298289 }
299290
300- }
291+ private boolean isNotSet (byte bitMask ) {
292+ return (state & bitMask ) == 0 ;
293+ }
294+
295+ private boolean set (byte bitMask ) {
296+ byte state = this .state ;
297+ for (;;) {
298+ if ((state & bitMask ) != 0 ) {
299+ return false ;
300+ }
301+ final byte newState = (byte ) (state | bitMask );
302+ state = (byte ) STATE_UPDATER .compareAndExchange (this , state , newState );
303+ if (state == newState ) {
304+ return true ;
305+ }
306+ }
307+ }
301308
309+ }
302310}
0 commit comments