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

net.openhft.chronicle.bytes.MappedUniqueTimeProvider Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2016-2022 chronicle.software
 *
 *     https://chronicle.software
 *
 * 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.openhft.chronicle.bytes;

import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.core.OS;
import net.openhft.chronicle.core.io.IORuntimeException;
import net.openhft.chronicle.core.io.Monitorable;
import net.openhft.chronicle.core.io.ReferenceOwner;
import net.openhft.chronicle.core.time.SystemTimeProvider;
import net.openhft.chronicle.core.time.TimeProvider;

import java.io.File;

/**
 * Provides timestamps that are guaranteed to be unique across threads and processes on a single machine.
 * 

* This class utilizes a shared timestamp file, named with the user's name and located in a defined directory, to ensure the uniqueness of timestamps. * By default, the file is located in the system's temporary directory. *

* Each timestamp generated by an instance of this class is globally unique, making it ideal for synchronization and ordering across different threads and processes. */ public enum MappedUniqueTimeProvider implements TimeProvider, ReferenceOwner { INSTANCE; private static final int LAST_TIME = 128; private static final int NANOS_PER_MICRO = 1000; private final BytesStore bytesStore; private TimeProvider provider = SystemTimeProvider.INSTANCE; MappedUniqueTimeProvider() { try { String user = Jvm.getProperty("user.name", "unknown"); String timeStampDir = Jvm.getProperty("timestamp.dir", OS.TMP); final File timeStampPath = new File(timeStampDir, ".time-stamp." + user + ".dat"); MappedFile file = MappedFile.ofSingle(timeStampPath, PageUtil.getPageSize(timeStampPath.getAbsolutePath()), false); final Bytes bytes = file.acquireBytesForWrite(this, 0); bytes.append8bit("&TSF\nTime stamp file used for sharing a unique id\n"); this.bytesStore = bytes.bytesStore(); Monitorable.unmonitor(file); Monitorable.unmonitor(bytes); } catch (Exception ioe) { throw new IORuntimeException(ioe); } } // Todo: Handle thread safety public MappedUniqueTimeProvider provider(TimeProvider provider) { this.provider = provider; return this; } /** * @return Ordinary millisecond timestamp */ @Override public long currentTimeMillis() { return provider.currentTimeMillis(); } @Override public long currentTimeMicros() throws IllegalStateException { long timeus = provider.currentTimeMicros(); while (true) { final long time0 = lastTimeStored(); long time0us = time0 / NANOS_PER_MICRO; long time; if (time0us >= timeus) time = (time0us + 1) * NANOS_PER_MICRO; else time = timeus * NANOS_PER_MICRO; if (casLastTimeStored(time0, time)) return time / NANOS_PER_MICRO; Jvm.nanoPause(); } } @Override public long currentTimeNanos() throws IllegalStateException { long time = provider.currentTimeNanos(); long time5 = time >>> 5; long time0 = lastTimeStored(); long timeNanos5 = time0 >>> 5; if (time5 > timeNanos5 && casLastTimeStored(time0, time)) return time; while (true) { time0 = lastTimeStored(); long next = (time0 + 0x20) & ~0x1f; if (casLastTimeStored(time0, next)) return next; Jvm.nanoPause(); } } private long lastTimeStored() { return bytesStore.readVolatileLong(LAST_TIME); } private boolean casLastTimeStored(final long expected, final long value) { return ((RandomDataOutput) bytesStore).compareAndSwapLong(LAST_TIME, expected, value); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy