Java Code Examples for java.util.concurrent.atomic.AtomicLong#get()

The following examples show how to use java.util.concurrent.atomic.AtomicLong#get() . These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
public static long allocSet(Heap heap, String string) {
    if (string == null) {
        return 0;
    }
    int size = string.length() * 3;
    long pResult = heap.alloc(HEADER_SIZE + size, false);;
    AtomicLong pData = new AtomicLong(pResult + HEADER_SIZE);
    Unsafe.putByte(pResult, Value.FORMAT_UTF8);
    Utf8.encode(string, n -> {
        Unsafe.putByte(pData.getAndIncrement(), (byte)n);
    });
    long realSize = pData.get() - pResult - HEADER_SIZE;
    if (realSize > 0xffffff) {
        throw new IllegalArgumentException();
    }
    Unsafe.putInt3(pResult + 1, (int)realSize);
    return pResult;
}
 
Example 2
Source Project: smallrye-mutiny   File: Subscriptions.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Atomically adds the positive value n to the requested value in the {@link AtomicLong} and
 * caps the result at {@link Long#MAX_VALUE} and returns the previous value and
 * considers {@link Long#MIN_VALUE} as a cancel indication (no addition then).
 *
 * @param requested the {@code AtomicLong} holding the current requested value
 * @param n the value to add, must be positive (not verified)
 * @return the original value before the add
 */
public static long addAndHandledAlreadyCancelled(AtomicLong requested, long n) {
    for (;;) {
        long r = requested.get();
        if (r == Long.MIN_VALUE) {
            return Long.MIN_VALUE;
        }
        if (r == Long.MAX_VALUE) {
            return Long.MAX_VALUE;
        }
        long u = add(r, n);
        if (requested.compareAndSet(r, u)) {
            return r;
        }
    }
}
 
Example 3
/**
 * Get the generated IDENTITY value for given table next to the one last
 * retrieved by this node. Also mark the value to have been read by the new
 * generating node that is reading this IDENTITY value.
 */
public long getAfterRetrievedValue(Object table, long start, long increment,
    DistributedMember idGeneratingNode) {
  this.generatedValuesLock.attemptWriteLock(-1);
  try {
    Object[] id = this.generatedValues.get(table);
    if (id != null) {
      AtomicLong currValue = (AtomicLong)id[0];
      id[1] = idGeneratingNode;
      return (currValue.get() + increment);
    }
    else {
      this.generatedValues.put(table, new Object[] { new AtomicLong(start),
          idGeneratingNode });
      return start;
    }
  } finally {
    this.generatedValuesLock.releaseWriteLock();
  }
}
 
Example 4
public static boolean max(AtomicLong x, long y) {
	for (;;) {
		long value = x.get();
		if (y > value) {
			if (!x.compareAndSet(value, y)) {
				continue;
			}
			return true;
		}
		else {
			return false;
		}
	}
}
 
Example 5
/**
 * Removes all mappings from this map whose values are zero.
 *
 * <p>This method is not atomic: the map may be visible in intermediate states, where some of the
 * zero values have been removed and others have not.
 */


public void removeAllZeros() {
  Iterator<Map.Entry<K, AtomicLong>> entryIterator = map.entrySet().iterator();
  while (entryIterator.hasNext()) {
    Map.Entry<K, AtomicLong> entry = entryIterator.next();
    AtomicLong atomic = entry.getValue();
    if (atomic != null && atomic.get() == 0L) {
      entryIterator.remove();
    }
  }
}
 
Example 6
Source Project: rocketmq   File: PullAPIWrapper.java    License: Apache License 2.0 5 votes vote down vote up
public long recalculatePullFromWhichNode(final MessageQueue mq) {
    if (this.isConnectBrokerByUser()) {
        return this.defaultBrokerId;
    }

    AtomicLong suggest = this.pullFromWhichNodeTable.get(mq);
    if (suggest != null) {
        return suggest.get();
    }

    return MixAll.MASTER_ID;
}
 
Example 7
protected void clearBit(AtomicLong atomic, long lMask) {
    long lWord;
    do {
        lWord = atomic.get();
    } while (!atomic.compareAndSet(lWord, lWord & ~lMask));

    if ((atomic.get() & lMask) != 0L) {
        throw new InternalError();
    }
}
 
Example 8
public void run() {
    phaser.arriveAndAwaitAdvance();
    phaser.arriveAndAwaitAdvance();
    AtomicLong a = adder;
    for (int i = 0; i < incs; ++i)
        a.getAndIncrement();
    result = a.get();
    phaser.arrive();
}
 
Example 9
/**
 * Returns an estimate of the total number of tasks stolen from
 * one thread's work queue by another. The reported value
 * underestimates the actual total number of steals when the pool
 * is not quiescent. This value may be useful for monitoring and
 * tuning fork/join programs: in general, steal counts should be
 * high enough to keep threads busy, but low enough to avoid
 * overhead and contention across threads.
 *
 * @return the number of steals
 */
public long getStealCount() {
    AtomicLong sc = stealCounter;
    long count = (sc == null) ? 0L : sc.get();
    WorkQueue[] ws; WorkQueue w;
    if ((ws = workQueues) != null) {
        for (int i = 1; i < ws.length; i += 2) {
            if ((w = ws[i]) != null)
                count += w.nsteals;
        }
    }
    return count;
}
 
Example 10
/**
 * Adds {@code delta} to the value currently associated with {@code key}, and returns the new
 * value.
 */

@CanIgnoreReturnValue
public long addAndGet(K key, long delta) {
  outer:
  while (true) {
    AtomicLong atomic = map.get(key);
    if (atomic == null) {
      atomic = map.putIfAbsent(key, new AtomicLong(delta));
      if (atomic == null) {
        return delta;
      }
      // atomic is now non-null; fall through
    }

    while (true) {
      long oldValue = atomic.get();
      if (oldValue == 0L) {
        // don't compareAndSet a zero
        if (map.replace(key, atomic, new AtomicLong(delta))) {
          return delta;
        }
        // atomic replaced
        continue outer;
      }
      long newValue = oldValue + delta;
      if (atomic.compareAndSet(oldValue, newValue)) {
        return newValue;
      }
      // value changed
    }
  }
}
 
Example 11
/**
 * Associates {@code newValue} with {@code key} in this map, and returns the value previously
 * associated with {@code key}, or zero if there was no such value.
 */
@CanIgnoreReturnValue
public long put(K key, long newValue) {
  outer:
  while (true) {
    AtomicLong atomic = map.get(key);
    if (atomic == null) {
      atomic = map.putIfAbsent(key, new AtomicLong(newValue));
      if (atomic == null) {
        return 0L;
      }
      // atomic is now non-null; fall through
    }

    while (true) {
      long oldValue = atomic.get();
      if (oldValue == 0L) {
        // don't compareAndSet a zero
        if (map.replace(key, atomic, new AtomicLong(newValue))) {
          return 0L;
        }
        // atomic replaced
        continue outer;
      }

      if (atomic.compareAndSet(oldValue, newValue)) {
        return oldValue;
      }
      // value changed
    }
  }
}
 
Example 12
Source Project: rocketmq   File: PullAPIWrapper.java    License: Apache License 2.0 5 votes vote down vote up
public long recalculatePullFromWhichNode(final MessageQueue mq) {
    if (this.isConnectBrokerByUser()) {
        return this.defaultBrokerId;
    }

    AtomicLong suggest = this.pullFromWhichNodeTable.get(mq);
    if (suggest != null) {
        return suggest.get();
    }

    return MixAll.MASTER_ID;
}
 
Example 13
Source Project: deeplearning4j   File: CBOW.java    License: Apache License 2.0 5 votes vote down vote up
public Sequence<T> applySubsampling(@NonNull Sequence<T> sequence, @NonNull AtomicLong nextRandom) {
    Sequence<T> result = new Sequence<>();

    // subsampling implementation, if subsampling threshold met, just continue to next element
    if (sampling > 0) {
        result.setSequenceId(sequence.getSequenceId());
        if (sequence.getSequenceLabels() != null)
            result.setSequenceLabels(sequence.getSequenceLabels());
        if (sequence.getSequenceLabel() != null)
            result.setSequenceLabel(sequence.getSequenceLabel());

        for (T element : sequence.getElements()) {
            double numWords = vocabCache.totalWordOccurrences();
            double ran = (Math.sqrt(element.getElementFrequency() / (sampling * numWords)) + 1)
                            * (sampling * numWords) / element.getElementFrequency();

            nextRandom.set(Math.abs(nextRandom.get() * 25214903917L + 11));

            if (ran < (nextRandom.get() & 0xFFFF) / (double) 65536) {
                continue;
            }
            result.addElement(element);
        }
        return result;
    } else
        return sequence;
}
 
Example 14
Source Project: deeplearning4j   File: CBOW.java    License: Apache License 2.0 4 votes vote down vote up
public void iterateSample(T currentWord, int[] windowWords, boolean[] wordStatuses, AtomicLong nextRandom, double alpha,
                          boolean isInference, int numLabels, boolean trainWords, INDArray inferenceVector) {
    int[] idxSyn1 = null;
    byte[] codes = null;

    if (configuration.isUseHierarchicSoftmax()) {
        idxSyn1 = new int[currentWord.getCodeLength()];
        codes = new byte[currentWord.getCodeLength()];
        for (int p = 0; p < currentWord.getCodeLength(); p++) {
            if (currentWord.getPoints().get(p) < 0)
                continue;

            codes[p] = currentWord.getCodes().get(p);
            idxSyn1[p] = currentWord.getPoints().get(p);
        }
    } else {
        idxSyn1 = new int[0];
        codes = new byte[0];
    }


    if (negative > 0) {
        if (syn1Neg == null) {
            ((InMemoryLookupTable<T>) lookupTable).initNegative();
            syn1Neg = new DeviceLocalNDArray(((InMemoryLookupTable<T>) lookupTable).getSyn1Neg());
        }
    }

    if (batches.get() == null)
        batches.set(new ArrayList<Aggregate>());

    /*AggregateCBOW(syn0.get(), syn1.get(), syn1Neg.get(), expTable.get(), table.get(),
            currentWord.getIndex(), windowWords, idxSyn1, codes, (int) negative, currentWord.getIndex(),
            lookupTable.layerSize(), alpha, nextRandom.get(), vocabCache.numWords(), numLabels, trainWords,
            inferenceVector);*/

    boolean useHS = configuration.isUseHierarchicSoftmax();
    boolean useNegative = configuration.getNegative() > 0;

    int[] inputStatuses = new int[windowWords.length];
    for (int i = 0; i < windowWords.length; ++i) {
        if (i < wordStatuses.length)
            inputStatuses[i] = wordStatuses[i] ? 1 : 0;
        else
            inputStatuses[i] = -1;
    }
    INDArray wordsStatuses = Nd4j.createFromArray(inputStatuses);

    CbowRound cbow = null;

    if (useHS && useNegative) {
        cbow = new CbowRound(Nd4j.scalar(currentWord.getIndex()), Nd4j.createFromArray(windowWords),
                wordsStatuses,
                Nd4j.scalar(currentWord.getIndex()),
                syn0.get(), syn1.get(), syn1Neg.get(),
                expTable.get(), table.get(), Nd4j.createFromArray(idxSyn1), Nd4j.createFromArray(codes),
                (int)negative, Nd4j.scalar(alpha), Nd4j.scalar(nextRandom.get()),
                inferenceVector != null ? inferenceVector : Nd4j.empty(syn0.get().dataType()),
                Nd4j.empty(DataType.INT),
                trainWords,
                workers);
    }
    else if (useHS) {
        cbow = new CbowRound(currentWord.getIndex(), windowWords, wordsStatuses.toIntVector(),
                syn0.get(), syn1.get(),
                expTable.get(), idxSyn1, codes, alpha, nextRandom.get(),
                inferenceVector != null ? inferenceVector : Nd4j.empty(syn0.get().dataType()), 0);
    }
    else if (useNegative) {
        cbow = new CbowRound(currentWord.getIndex(), windowWords, wordsStatuses.toIntVector(), currentWord.getIndex(),
                syn0.get(), syn1Neg.get(),
                expTable.get(), table.get(), (int)negative, alpha, nextRandom.get(),
                inferenceVector != null ? inferenceVector : Nd4j.empty(syn0.get().dataType()), 0);
    }

    nextRandom.set(Math.abs(nextRandom.get() * 25214903917L + 11));
    Nd4j.getExecutioner().exec(cbow);

    /*if (!isInference) {
        batches.get().add(cbow);
        if (batches.get().size() > 4096) {
            Nd4j.getExecutioner().exec(batches.get());
            batches.get().clear();
        }
    } else
        Nd4j.getExecutioner().exec(cbow);*/

}
 
Example 15
Source Project: Chronicle-Queue   File: JDBCServiceTest.java    License: Apache License 2.0 4 votes vote down vote up
private void doCreateTable(int repeats, int noUpdates) {
    for (int t = 0; t < repeats; t++) {
        long start = System.nanoTime(), written;
        File path1 = DirectoryUtils.tempDir("createTable1");
        File path2 = DirectoryUtils.tempDir("createTable2");
        File file = new File(OS.TARGET, "hsqldb-" + System.nanoTime());
        file.deleteOnExit();

        try (ChronicleQueue in = SingleChronicleQueueBuilder
                .binary(path1)
                .testBlockSize()
                .build();
             ChronicleQueue out = SingleChronicleQueueBuilder
                     .binary(path2)
                     .testBlockSize()
                     .build()) {

            JDBCService service = new JDBCService(in, out, () -> DriverManager.getConnection("jdbc:hsqldb:file:" + file.getAbsolutePath(), "SA", ""));

            JDBCStatement writer = service.createWriter();
            writer.executeUpdate("CREATE TABLE tableName (\n" +
                    "name VARCHAR(64) NOT NULL,\n" +
                    "num INT\n" +
                    ")\n");

            for (int i = 1; i < (long) noUpdates; i++)
                writer.executeUpdate("INSERT INTO tableName (name, num)\n" +
                        "VALUES (?, ?)", "name", i);

            written = System.nanoTime() - start;
            AtomicLong queries = new AtomicLong();
            AtomicLong updates = new AtomicLong();
            CountingJDBCResult countingJDBCResult = new CountingJDBCResult(queries, updates);
            MethodReader methodReader = service.createReader(countingJDBCResult);
            while (updates.get() < noUpdates) {
                if (!methodReader.readOne())
                    Thread.yield();
            }
            Closeable.closeQuietly(service);

            long time = System.nanoTime() - start;
            System.out.printf("Average time to write each update %.1f us, average time to perform each update %.1f us%n",
                    written / noUpdates / 1e3,
                    time / noUpdates / 1e3);
        } finally {
            try {
                IOTools.deleteDirWithFiles(path1, 2);
                IOTools.deleteDirWithFiles(path2, 2);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
 
Example 16
Source Project: mtas   File: CodecSearchTree.java    License: Apache License 2.0 4 votes vote down vote up
/**
 * Gets the mtas tree item.
 *
 * @param ref the ref
 * @param isSinglePoint the is single point
 * @param isStoreAdditionalIdAndRef the is store additional id and ref
 * @param nodeRefApproxOffset the node ref approx offset
 * @param in the in
 * @param objectRefApproxOffset the object ref approx offset
 * @return the mtas tree item
 * @throws IOException Signals that an I/O exception has occurred.
 */
private static MtasTreeItem getMtasTreeItem(Long ref,
    AtomicBoolean isSinglePoint, AtomicBoolean isStoreAdditionalIdAndRef,
    AtomicLong nodeRefApproxOffset, IndexInput in, long objectRefApproxOffset)
    throws IOException {
  try {
    Boolean isRoot = false;
    if (nodeRefApproxOffset.get() < 0) {
      isRoot = true;
    }
    in.seek(ref);
    if (isRoot) {
      nodeRefApproxOffset.set(in.readVLong());
      Byte flag = in.readByte();
      if ((flag
          & MtasTree.SINGLE_POSITION_TREE) == MtasTree.SINGLE_POSITION_TREE) {
        isSinglePoint.set(true);
      }
      if ((flag
          & MtasTree.STORE_ADDITIONAL_ID) == MtasTree.STORE_ADDITIONAL_ID) {
        isStoreAdditionalIdAndRef.set(true);
      }
    }
    int left = in.readVInt();
    int right = in.readVInt();
    int max = in.readVInt();
    Long leftChild = in.readVLong() + nodeRefApproxOffset.get();
    Long rightChild = in.readVLong() + nodeRefApproxOffset.get();
    int size = 1;
    if (!isSinglePoint.get()) {
      size = in.readVInt();
    }
    // initialize
    long[] objectRefs = new long[size];
    int[] objectAdditionalIds = null;
    long[] objectAdditionalRefs = null;
    // get first
    long objectRef = in.readVLong();
    long objectRefPrevious = objectRef + objectRefApproxOffset;
    objectRefs[0] = objectRefPrevious;
    if (isStoreAdditionalIdAndRef.get()) {
      objectAdditionalIds = new int[size];
      objectAdditionalRefs = new long[size];
      objectAdditionalIds[0] = in.readVInt();
      objectAdditionalRefs[0] = in.readVLong();
    }
    // get others
    for (int t = 1; t < size; t++) {
      objectRef = objectRefPrevious + in.readVLong();
      objectRefs[t] = objectRef;
      objectRefPrevious = objectRef;
      if (isStoreAdditionalIdAndRef.get()) {
        objectAdditionalIds[t] = in.readVInt();
        objectAdditionalRefs[t] = in.readVLong();
      }
    }
    return new MtasTreeItem(left, right, max, objectRefs, objectAdditionalIds,
        objectAdditionalRefs, ref, leftChild, rightChild);
  } catch (Exception e) {
    throw new IOException(e.getMessage());
  }
}
 
Example 17
/**
 * Returns a string identifying this pool, as well as its state,
 * including indications of run state, parallelism level, and
 * worker and task counts.
 *
 * @return a string identifying this pool, as well as its state
 */
public String toString() {
    // Use a single pass through workQueues to collect counts
    long qt = 0L, qs = 0L; int rc = 0;
    AtomicLong sc = stealCounter;
    long st = (sc == null) ? 0L : sc.get();
    long c = ctl;
    WorkQueue[] ws; WorkQueue w;
    if ((ws = workQueues) != null) {
        for (int i = 0; i < ws.length; ++i) {
            if ((w = ws[i]) != null) {
                int size = w.queueSize();
                if ((i & 1) == 0)
                    qs += size;
                else {
                    qt += size;
                    st += w.nsteals;
                    if (w.isApparentlyUnblocked())
                        ++rc;
                }
            }
        }
    }
    int pc = (config & SMASK);
    int tc = pc + (short)(c >>> TC_SHIFT);
    int ac = pc + (int)(c >> AC_SHIFT);
    if (ac < 0) // ignore transient negative
        ac = 0;
    int rs = runState;
    String level = ((rs & TERMINATED) != 0 ? "Terminated" :
                    (rs & STOP)       != 0 ? "Terminating" :
                    (rs & SHUTDOWN)   != 0 ? "Shutting down" :
                    "Running");
    return super.toString() +
        "[" + level +
        ", parallelism = " + pc +
        ", size = " + tc +
        ", active = " + ac +
        ", running = " + rc +
        ", steals = " + st +
        ", tasks = " + qt +
        ", submissions = " + qs +
        "]";
}
 
Example 18
Source Project: lucene-solr   File: TestIndexWriter.java    License: Apache License 2.0 4 votes vote down vote up
public void testMaxCompletedSequenceNumber() throws IOException, InterruptedException {
  try (Directory dir = newDirectory();
       IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig());) {
    assertEquals(1, writer.addDocument(new Document()));
    assertEquals(2, writer.updateDocument(new Term("foo", "bar"), new Document()));
    writer.flushNextBuffer();
    assertEquals(3, writer.commit());
    assertEquals(4, writer.addDocument(new Document()));
    assertEquals(4, writer.getMaxCompletedSequenceNumber());
    // commit moves seqNo by 2 since there is one DWPT that could still be in-flight
    assertEquals(6, writer.commit());
    assertEquals(6, writer.getMaxCompletedSequenceNumber());
    assertEquals(7, writer.addDocument(new Document()));
    writer.getReader().close();
    // getReader moves seqNo by 2 since there is one DWPT that could still be in-flight
    assertEquals(9, writer.getMaxCompletedSequenceNumber());
  }
  try (Directory dir = newDirectory();
       IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig());
       SearcherManager manager = new SearcherManager(writer, new SearcherFactory())) {
    CountDownLatch start = new CountDownLatch(1);
    int numDocs = 100 + random().nextInt(500);
    AtomicLong maxCompletedSeqID = new AtomicLong(-1);
    Thread[] threads = new Thread[2 + random().nextInt(2)];
    for (int i = 0; i < threads.length; i++) {
      int idx = i;
      threads[i] = new Thread(() -> {
        try {
          start.await();
          for (int j = 0; j < numDocs; j++) {
            Document doc = new Document();
            String id = idx +"-"+j;
            doc.add(new StringField("id", id, Field.Store.NO));
            long seqNo = writer.addDocument(doc);
            if (maxCompletedSeqID.get() < seqNo) {
              long maxCompletedSequenceNumber = writer.getMaxCompletedSequenceNumber();
              manager.maybeRefreshBlocking();
              maxCompletedSeqID.updateAndGet(oldVal-> Math.max(oldVal, maxCompletedSequenceNumber));
            }
            IndexSearcher acquire = manager.acquire();
            try {
              assertEquals(1, acquire.search(new TermQuery(new Term("id", id)), 10).totalHits.value);
            } finally {
              manager.release(acquire);
            }
          }
        } catch (Exception e) {
          throw new AssertionError(e);
        }
      });
      threads[i].start();
    }
    start.countDown();
    for (int i = 0; i < threads.length; i++) {
      threads[i].join();
    }
  }
}
 
Example 19
/**
 * Returns a string identifying this pool, as well as its state,
 * including indications of run state, parallelism level, and
 * worker and task counts.
 *
 * @return a string identifying this pool, as well as its state
 */
public String toString() {
    // Use a single pass through workQueues to collect counts
    long qt = 0L, qs = 0L; int rc = 0;
    AtomicLong sc = stealCounter;
    long st = (sc == null) ? 0L : sc.get();
    long c = ctl;
    WorkQueue[] ws; WorkQueue w;
    if ((ws = workQueues) != null) {
        for (int i = 0; i < ws.length; ++i) {
            if ((w = ws[i]) != null) {
                int size = w.queueSize();
                if ((i & 1) == 0)
                    qs += size;
                else {
                    qt += size;
                    st += w.nsteals;
                    if (w.isApparentlyUnblocked())
                        ++rc;
                }
            }
        }
    }
    int pc = (config & SMASK);
    int tc = pc + (short)(c >>> TC_SHIFT);
    int ac = pc + (int)(c >> AC_SHIFT);
    if (ac < 0) // ignore transient negative
        ac = 0;
    int rs = runState;
    String level = ((rs & TERMINATED) != 0 ? "Terminated" :
                    (rs & STOP)       != 0 ? "Terminating" :
                    (rs & SHUTDOWN)   != 0 ? "Shutting down" :
                    "Running");
    return super.toString() +
        "[" + level +
        ", parallelism = " + pc +
        ", size = " + tc +
        ", active = " + ac +
        ", running = " + rc +
        ", steals = " + st +
        ", tasks = " + qt +
        ", submissions = " + qs +
        "]";
}
 
Example 20
Source Project: jdk1.8-source-analysis   File: Random.java    License: Apache License 2.0 3 votes vote down vote up
/**
 * Generates the next pseudorandom number. Subclasses should
 * override this, as this is used by all other methods.
 *
 * <p>The general contract of {@code next} is that it returns an
 * {@code int} value and if the argument {@code bits} is between
 * {@code 1} and {@code 32} (inclusive), then that many low-order
 * bits of the returned value will be (approximately) independently
 * chosen bit values, each of which is (approximately) equally
 * likely to be {@code 0} or {@code 1}. The method {@code next} is
 * implemented by class {@code Random} by atomically updating the seed to
 *  <pre>{@code (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)}</pre>
 * and returning
 *  <pre>{@code (int)(seed >>> (48 - bits))}.</pre>
 *
 * This is a linear congruential pseudorandom number generator, as
 * defined by D. H. Lehmer and described by Donald E. Knuth in
 * <i>The Art of Computer Programming,</i> Volume 3:
 * <i>Seminumerical Algorithms</i>, section 3.2.1.
 *
 * @param  bits random bits
 * @return the next pseudorandom value from this random number
 *         generator's sequence
 * @since  1.1
 */
protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}