All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.oschina.j2cache.hibernate4.util.SlewClock Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2015-2017.
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.oschina.j2cache.hibernate4.util; import java.util.concurrent.atomic.AtomicLong; public class SlewClock { private static final TimeProvider PROVIDER = TimeProviderLoader.getTimeProvider(); private static final long DRIFT_MAXIMAL = Integer.getInteger("net.oschina.j2cache.hibernate4.redis.util.Timestamper.drift.max", 50); private static final long SLEEP_MAXIMAL = Integer.getInteger("net.oschina.j2cache.hibernate4.redis.util.Timestamper.sleep.max", 50); private static final int SLEEP_BASE = Integer.getInteger("net.oschina.j2cache.hibernate4.redis.util.Timestamper.sleep.min", 25); private static final AtomicLong CURRENT = new AtomicLong(getCurrentTime()); private static final VicariousThreadLocal OFFSET = new VicariousThreadLocal(); private SlewClock() { } static long timeMillis() { boolean interrupted = false; try { while (true) { long mono = CURRENT.get(); long wall = getCurrentTime(); if (wall == mono) { OFFSET.remove(); return wall; } else if (wall >= mono) { if (CURRENT.compareAndSet(mono, wall)) { OFFSET.remove(); return wall; } } else { long delta = mono - wall; if (delta < DRIFT_MAXIMAL) { OFFSET.remove(); return mono; } else { Long lastDelta = OFFSET.get(); if (lastDelta == null || delta < lastDelta) { long update = wall - delta; update = update < mono ? mono + 1 : update; if (CURRENT.compareAndSet(mono, update)) { OFFSET.set(delta); return update; } } else { try { Thread.sleep(sleepTime(delta, lastDelta)); } catch (InterruptedException e) { interrupted = true; } } } } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } static boolean isThreadCatchingUp() { return OFFSET.get() != null; } static long behind() { Long offset = OFFSET.get(); return offset == null ? 0 : offset; } private static long sleepTime(final long current, final long previous) { long target = SLEEP_BASE + (current - previous) * 2; return Math.min(target > 0 ? target : SLEEP_BASE, SLEEP_MAXIMAL); } private static long getCurrentTime() { return PROVIDER.currentTimeMillis(); } interface TimeProvider { long currentTimeMillis(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy