public static Object getValueOrCachedValue(Record record, SerializationService serializationService) {
        Object cachedValue = record.getCachedValueUnsafe();
        if (cachedValue == NOT_CACHED) {
            //record does not support caching at all
            return record.getValue();
        }
        for (; ; ) {
            if (cachedValue == null) {
                Object valueBeforeCas = record.getValue();
                if (!shouldCache(valueBeforeCas)) {
                    //it's either a null or value which we do not want to cache. let's just return it.
                    return valueBeforeCas;
                }
                Object fromCache = tryStoreIntoCache(record, valueBeforeCas, serializationService);
                if (fromCache != null) {
                    return fromCache;
                }
            } else if (cachedValue instanceof Thread) {
                //the cachedValue is either locked by another thread or it contains a wrapped thread
                cachedValue = ThreadWrapper.unwrapOrNull(cachedValue);
                if (cachedValue != null) {
                    //exceptional case: the cachedValue is not locked, it just contains an instance of Thread.
                    //this can happen when user put an instance of Thread into a map
                    //(=it should never happen, but never say never...)
                    return cachedValue;
                }
                //it looks like some other thread actually locked the cachedValue. let's give it another try (iteration)
            } else {
                //it's not the 'in-progress' marker/lock && it's not a null -> it has to be the actual cachedValue
                return cachedValue;
            }
            Thread.yield();
            cachedValue = record.getCachedValueUnsafe();
        }
    }
@Test
    public void givenCachedDataRecord_whenThreadIsInside_thenGetValueOrCachedValueReturnsTheThread() {
        // given
        Record record = new CachedDataRecordWithStats();

        // when
        SerializableThread objectPayload = new SerializableThread();
        Data dataPayload = serializationService.toData(objectPayload);
        record.setValue(dataPayload);

        // then
        Object cachedValue = Records.getValueOrCachedValue(record, serializationService);
        assertInstanceOf(SerializableThread.class, cachedValue);
    }