/*
 * Copyright 2000-2011 JetBrains s.r.o.
 *
 * 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 com.intellij.openapi.editor.impl;

import java.util.concurrent.atomic.AtomicLong;

/**
 * Low-contention counter.
 * Repeated calls to {@link #next()} return numbers which are unique across all calling threads, and which are increasing over calls within one thread.
 */
public class StripedIDGenerator {
  private static final int CHUNK_SIZE = 1000;
  private final AtomicLong nextChunkStart = new AtomicLong();
  // must not be static since we might want to have several instances of this class
  private final ThreadLocal<NextPair> localCounter = new ThreadLocal<>();
  private static class NextPair {
    long nextId;
    final long limit;

    private NextPair(long nextId, long limit) {
      this.nextId = nextId;
      this.limit = limit;
    }
  }

  public long next() {
    NextPair nextPair = localCounter.get();
    if (nextPair == null || nextPair.nextId == nextPair.limit) {
      long start = nextChunkStart.getAndAdd(CHUNK_SIZE);
      nextPair = new NextPair(start, start + CHUNK_SIZE);
      localCounter.set(nextPair);
    }
    long result = nextPair.nextId;
    nextPair.nextId++;
    return result;
  }
}
