Java Code Examples for java.util.concurrent.atomic.AtomicInteger#compareAndSet()

The following examples show how to use java.util.concurrent.atomic.AtomicInteger#compareAndSet() . 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
@Group("g4")
@GroupThreads(2)
@Benchmark
public void queueDrainAtomic4() {
    AtomicInteger w = wip;
    if (w.getAndIncrement() == 0) {
        int missed = 1;

        for (;;) {
            counter++;

            if (w.compareAndSet(missed, 0)) {
                break;
            }
            missed = w.get();
        }
    }
}
 
Example 2
Source Project: akarnokd-misc   File: QueueDrainPerf.java    License: Apache License 2.0 6 votes vote down vote up
@Benchmark
public void queueDrainAtomic4() {
    AtomicInteger w = wip;
    if (w.getAndIncrement() == 0) {
        int missed = 1;

        for (;;) {
            counter++;

            if (w.compareAndSet(missed, 0)) {
                break;
            }
            missed = w.get();
        }
    }
}
 
Example 3
/**
 * Attempts to increment the given AtomicInteger without exceeding the
 * specified maximum value. If the AtomicInteger cannot be incremented
 * without exceeding the maximum, false is returned.
 *
 * @param counter
 *     The AtomicInteger to attempt to increment.
 *
 * @param max
 *     The maximum value that the given AtomicInteger should contain, or
 *     zero if no limit applies.
 *
 * @return
 *     true if the AtomicInteger was successfully incremented without
 *     exceeding the specified maximum, false if the AtomicInteger could
 *     not be incremented.
 */
private boolean tryIncrement(AtomicInteger counter, int max) {

    // Repeatedly attempt to increment the given AtomicInteger until we
    // explicitly succeed or explicitly fail
    while (true) {

        // Get current value
        int count = counter.get();

        // Bail out if the maximum has already been reached
        if (count >= max && max != 0)
            return false;

        // Attempt to increment
        if (counter.compareAndSet(count, count+1))
            return true;

        // Try again if unsuccessful

    }

}
 
Example 4
static boolean openQueryRequest(String project, int maxConcurrentQuery) {
    if (maxConcurrentQuery == 0) {
        return true;
    }
    try {
        AtomicInteger nRunningQueries = runningStats.get(project);
        for (;;) {
            int nRunning = nRunningQueries.get();
            if (nRunning < maxConcurrentQuery) {
                if (nRunningQueries.compareAndSet(nRunning, nRunning + 1)) {
                    return true;
                }
            } else {
                return false;
            }
        }
    } catch (ExecutionException e) {
        throw new RuntimeException(e);
    }
}
 
Example 5
@AfterClass
public static void end() throws InterruptedException{
	AtomicInteger mutex = new AtomicInteger(objectsToDelete.size());
	for(ObjectToDelete o : objectsToDelete){
		DBManager.deleteObject(o.getClassName(),o.getKey(),new DeleteCallback() {

			@Override
			public void done(ParseException arg0) {
				synchronized (mutex) {
					mutex.decrementAndGet();
				}
				
			}});
	}
	while (!mutex.compareAndSet(0, 0));
}
 
Example 6
/**
 * Attempts to increment the given AtomicInteger without exceeding the
 * specified maximum value. If the AtomicInteger cannot be incremented
 * without exceeding the maximum, false is returned.
 *
 * @param counter
 *     The AtomicInteger to attempt to increment.
 *
 * @param max
 *     The maximum value that the given AtomicInteger should contain, or
 *     zero if no limit applies.
 *
 * @return
 *     true if the AtomicInteger was successfully incremented without
 *     exceeding the specified maximum, false if the AtomicInteger could
 *     not be incremented.
 */
private boolean tryIncrement(AtomicInteger counter, int max) {

    // Repeatedly attempt to increment the given AtomicInteger until we
    // explicitly succeed or explicitly fail
    while (true) {

        // Get current value
        int count = counter.get();

        // Bail out if the maximum has already been reached
        if (count >= max && max != 0)
            return false;

        // Attempt to increment
        if (counter.compareAndSet(count, count+1))
            return true;

        // Try again if unsuccessful

    }

}
 
Example 7
/**
 * Removes a number of occurrences of the specified element from this multiset. If the multiset
 * contains fewer than this number of occurrences to begin with, all occurrences will be removed.
 *
 * @param element the element whose occurrences should be removed
 * @param occurrences the number of occurrences of the element to remove
 * @return the count of the element before the operation; possibly zero
 * @throws IllegalArgumentException if {@code occurrences} is negative
 */
/*
 * TODO(cpovirk): remove and removeExactly currently accept null inputs only
 * if occurrences == 0. This satisfies both NullPointerTester and
 * CollectionRemoveTester.testRemove_nullAllowed, but it's not clear that it's
 * a good policy, especially because, in order for the test to pass, the
 * parameter must be misleadingly annotated as @Nullable. I suspect that
 * we'll want to remove @Nullable, add an eager checkNotNull, and loosen up
 * testRemove_nullAllowed.
 */

@CanIgnoreReturnValue
@Override
public int remove(@Nullable Object element, int occurrences) {
  if (occurrences == 0) {
    return count(element);
  }
  CollectPreconditions.checkPositive(occurrences, "occurences");
  AtomicInteger existingCounter = Maps.safeGet(countMap, element);
  if (existingCounter == null) {
    return 0;
  }
  while (true) {
    int oldValue = existingCounter.get();
    if (oldValue != 0) {
      int newValue = Math.max(0, oldValue - occurrences);
      if (existingCounter.compareAndSet(oldValue, newValue)) {
        if (newValue == 0) {
          // Just CASed to 0; remove the entry to clean up the map. If the removal fails,
          // another thread has already replaced it with a new counter, which is fine.
          countMap.remove(element, existingCounter);
        }
        return oldValue;
      }
    } else {
      return 0;
    }
  }
}
 
Example 8
Source Project: gemfirexd-oss   File: GFXDServiceImpl.java    License: Apache License 2.0 5 votes vote down vote up
private static int getNextId(final AtomicInteger id) {
  while (true) {
    int currentId = id.get();
    int nextId = currentId + 1;
    if (nextId == INVALID_ID) {
      nextId++;
    }
    if (id.compareAndSet(currentId, nextId)) {
      return currentId;
    }
  }
}
 
Example 9
Source Project: ignite   File: GridUnsafeLru.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Atomically increments the given value by one, re-starting from 0 when the specified maximum is reached.
 *
 * @param value Value to increment.
 * @param max Maximum after reaching which the value is reset to 0.
 * @return Incremented value.
 */
private int incrementAndGet(AtomicInteger value, int max) {
    while (true) {
        int cur = value.get();
        int next = cur == max ? 0 : cur + 1;

        if (value.compareAndSet(cur, next))
            return next;
    }
}
 
Example 10
Source Project: ecp-uid   File: CachedUidGeneratorTest.java    License: Apache License 2.0 5 votes vote down vote up
public int updateAndGet(AtomicInteger control) {
    int prev, next;
    do {
        prev = control.get();
        next = prev == SIZE ? SIZE : prev + 1;
    } while (!control.compareAndSet(prev, next));
    return next;
}
 
Example 11
Source Project: RxJava3-preview   File: HalfSerializer.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Emits the given value if possible and terminates if there was an onComplete or onError
 * while emitting, drops the value otherwise.
 * @param <T> the value type
 * @param observer the target Observer to emit to
 * @param value the value to emit
 * @param wip the serialization work-in-progress counter/indicator
 * @param error the holder of Throwables
 */
public static <T> void onNext(Observer<? super T> observer, T value,
        AtomicInteger wip, AtomicThrowable error) {
    if (wip.get() == 0 && wip.compareAndSet(0, 1)) {
        observer.onNext(value);
        if (wip.decrementAndGet() != 0) {
            Throwable ex = error.terminate();
            if (ex != null) {
                observer.onError(ex);
            } else {
                observer.onComplete();
            }
        }
    }
}
 
Example 12
/**
 * Removes exactly the specified number of occurrences of {@code element}, or makes no
 * change if this is not possible.
 *
 * <p>This method, in contrast to {@link #remove(Object, int)}, has no effect when the
 * element count is smaller than {@code occurrences}.
 *
 * @param element the element to remove
 * @param occurrences the number of occurrences of {@code element} to remove
 * @return {@code true} if the removal was possible (including if {@code occurrences} is zero)
 * @throws IllegalArgumentException if {@code occurrences} is negative
 */

@CanIgnoreReturnValue
public boolean removeExactly(@Nullable Object element, int occurrences) {
  if (occurrences == 0) {
    return true;
  }
  CollectPreconditions.checkPositive(occurrences, "occurences");
  AtomicInteger existingCounter = Maps.safeGet(countMap, element);
  if (existingCounter == null) {
    return false;
  }
  while (true) {
    int oldValue = existingCounter.get();
    if (oldValue < occurrences) {
      return false;
    }


    int newValue = oldValue - occurrences;
    if (existingCounter.compareAndSet(oldValue, newValue)) {
      if (newValue == 0) {
        // Just CASed to 0; remove the entry to clean up the map. If the removal fails,
        // another thread has already replaced it with a new counter, which is fine.
        countMap.remove(element, existingCounter);
      }
      return true;
    }
  }
}
 
Example 13
/**
 * compareAndSet in one thread enables another waiting for value
 * to succeed
 */
public void testCompareAndSetInMultipleThreads() throws Exception {
    final AtomicInteger ai = new AtomicInteger(1);
    Thread t = new Thread(new CheckedRunnable() {
        public void realRun() {
            while (!ai.compareAndSet(2, 3))
                Thread.yield();
        }});

    t.start();
    assertTrue(ai.compareAndSet(1, 2));
    t.join(LONG_DELAY_MS);
    assertFalse(t.isAlive());
    assertEquals(3, ai.get());
}
 
Example 14
Source Project: lucene-solr   File: TestIndexWriter.java    License: Apache License 2.0 4 votes vote down vote up
public void testRandomOperationsWithSoftDeletes() throws Exception {
  IndexWriterConfig iwc = newIndexWriterConfig();
  AtomicInteger seqNo = new AtomicInteger(-1);
  AtomicInteger retainingSeqNo = new AtomicInteger();
  iwc.setSoftDeletesField("soft_deletes");
  iwc.setMergePolicy(new SoftDeletesRetentionMergePolicy("soft_deletes",
      () -> LongPoint.newRangeQuery("seq_no", retainingSeqNo.longValue(), Long.MAX_VALUE), newMergePolicy()));
  try (Directory dir = newDirectory();
       IndexWriter writer = new IndexWriter(dir, iwc);
       SearcherManager sm = new SearcherManager(writer, new SearcherFactory())) {
    Semaphore numOperations = new Semaphore(10 + random().nextInt(1000));
    boolean singleDoc = random().nextBoolean();
    Thread[] threads = new Thread[1 + random().nextInt(4)];
    CountDownLatch latch = new CountDownLatch(threads.length);
    for (int i = 0; i < threads.length; i++) {
      threads[i] = new Thread(() -> {
        latch.countDown();
        try {
          latch.await();
          while (numOperations.tryAcquire()) {
            String id = singleDoc ? "1" : Integer.toString(random().nextInt(10));
            Document doc = new Document();
            doc.add(new StringField("id", id, Field.Store.YES));
            doc.add(new LongPoint("seq_no", seqNo.getAndIncrement()));
            if (random().nextInt(10) <= 2) {
              if (random().nextBoolean()) {
                doc.add(new NumericDocValuesField(iwc.softDeletesField, 1));
              }
              writer.softUpdateDocument(new Term("id", id), doc, new NumericDocValuesField(iwc.softDeletesField, 1));
            } else {
              writer.addDocument(doc);
            }
            if (random().nextInt(100) < 10) {
              int min = retainingSeqNo.get();
              int max = seqNo.get();
              if (min < max && random().nextBoolean()) {
                retainingSeqNo.compareAndSet(min, min - random().nextInt(max - min));
              }
            }
            if (random().nextInt(100) < 10) {
              sm.maybeRefreshBlocking();
            }
            if (random().nextInt(100) < 5) {
              writer.commit();
            }
            if (random().nextInt(100) < 1) {
              writer.forceMerge(1 + random().nextInt(10), random().nextBoolean());
            }
          }
        } catch (Exception e) {
          throw new AssertionError(e);
        }
      });
      threads[i].start();
    }
    for (Thread thread : threads) {
      thread.join();
    }
  }
}
 
Example 15
/**
 * Sets the number of occurrences of {@code element} to {@code newCount}, but only if
 * the count is currently {@code expectedOldCount}. If {@code element} does not appear
 * in the multiset exactly {@code expectedOldCount} times, no changes will be made.
 *
 * @return {@code true} if the change was successful. This usually indicates
 *     that the multiset has been modified, but not always: in the case that
 *     {@code expectedOldCount == newCount}, the method will return {@code true} if
 *     the condition was met.
 * @throws IllegalArgumentException if {@code expectedOldCount} or {@code newCount} is negative
 */

@CanIgnoreReturnValue
@Override
public boolean setCount(E element, int expectedOldCount, int newCount) {
  checkNotNull(element);
  checkNonnegative(expectedOldCount, "oldCount");
  checkNonnegative(newCount, "newCount");
  AtomicInteger existingCounter = Maps.safeGet(countMap, element);
  if (existingCounter == null) {
    if (expectedOldCount != 0) {
      return false;
    } else if (newCount == 0) {
      return true;
    } else {
      // if our write lost the race, it must have lost to a nonzero value, so we can stop
      return countMap.putIfAbsent(element, new AtomicInteger(newCount)) == null;
    }
  }


  int oldValue = existingCounter.get();
  if (oldValue == expectedOldCount) {
    if (oldValue == 0) {
      if (newCount == 0) {
        // Just observed a 0; try to remove the entry to clean up the map
        countMap.remove(element, existingCounter);
        return true;
      } else {
        AtomicInteger newCounter = new AtomicInteger(newCount);
        return (countMap.putIfAbsent(element, newCounter) == null)
          || countMap.replace(element, existingCounter, newCounter);
      }
    } else {
      if (existingCounter.compareAndSet(oldValue, newCount)) {
        if (newCount == 0) {
          // Just CASed to 0; remove the entry to clean up the map. If the removal fails,
          // another thread has already replaced it with a new counter, which is fine.
          countMap.remove(element, existingCounter);
        }
        return true;
      }
    }
  }
  return false;
}
 
Example 16
/**
 * Sets the number of occurrences of {@code element} to {@code newCount}, but only if
 * the count is currently {@code expectedOldCount}. If {@code element} does not appear
 * in the multiset exactly {@code expectedOldCount} times, no changes will be made.
 *
 * @return {@code true} if the change was successful. This usually indicates
 *     that the multiset has been modified, but not always: in the case that
 *     {@code expectedOldCount == newCount}, the method will return {@code true} if
 *     the condition was met.
 * @throws IllegalArgumentException if {@code expectedOldCount} or {@code newCount} is negative
 */

@CanIgnoreReturnValue
@Override
public boolean setCount(E element, int expectedOldCount, int newCount) {
  checkNotNull(element);
  checkNonnegative(expectedOldCount, "oldCount");
  checkNonnegative(newCount, "newCount");
  AtomicInteger existingCounter = Maps.safeGet(countMap, element);
  if (existingCounter == null) {
    if (expectedOldCount != 0) {
      return false;
    } else if (newCount == 0) {
      return true;
    } else {
      // if our write lost the race, it must have lost to a nonzero value, so we can stop
      return countMap.putIfAbsent(element, new AtomicInteger(newCount)) == null;
    }
  }


  int oldValue = existingCounter.get();
  if (oldValue == expectedOldCount) {
    if (oldValue == 0) {
      if (newCount == 0) {
        // Just observed a 0; try to remove the entry to clean up the map
        countMap.remove(element, existingCounter);
        return true;
      } else {
        AtomicInteger newCounter = new AtomicInteger(newCount);
        return (countMap.putIfAbsent(element, newCounter) == null)
          || countMap.replace(element, existingCounter, newCounter);
      }
    } else {
      if (existingCounter.compareAndSet(oldValue, newCount)) {
        if (newCount == 0) {
          // Just CASed to 0; remove the entry to clean up the map. If the removal fails,
          // another thread has already replaced it with a new counter, which is fine.
          countMap.remove(element, existingCounter);
        }
        return true;
      }
    }
  }
  return false;
}
 
Example 17
@Benchmark
public void wipCas() {
    AtomicInteger v = value;
    int w = v.get();
    v.compareAndSet(w, w - 1);
}
 
Example 18
/**
 * Sets the number of occurrences of {@code element} to {@code newCount}, but only if
 * the count is currently {@code expectedOldCount}. If {@code element} does not appear
 * in the multiset exactly {@code expectedOldCount} times, no changes will be made.
 *
 * @return {@code true} if the change was successful. This usually indicates
 *     that the multiset has been modified, but not always: in the case that
 *     {@code expectedOldCount == newCount}, the method will return {@code true} if
 *     the condition was met.
 * @throws IllegalArgumentException if {@code expectedOldCount} or {@code newCount} is negative
 */

@CanIgnoreReturnValue
@Override
public boolean setCount(E element, int expectedOldCount, int newCount) {
  checkNotNull(element);
  checkNonnegative(expectedOldCount, "oldCount");
  checkNonnegative(newCount, "newCount");
  AtomicInteger existingCounter = Maps.safeGet(countMap, element);
  if (existingCounter == null) {
    if (expectedOldCount != 0) {
      return false;
    } else if (newCount == 0) {
      return true;
    } else {
      // if our write lost the race, it must have lost to a nonzero value, so we can stop
      return countMap.putIfAbsent(element, new AtomicInteger(newCount)) == null;
    }
  }


  int oldValue = existingCounter.get();
  if (oldValue == expectedOldCount) {
    if (oldValue == 0) {
      if (newCount == 0) {
        // Just observed a 0; try to remove the entry to clean up the map
        countMap.remove(element, existingCounter);
        return true;
      } else {
        AtomicInteger newCounter = new AtomicInteger(newCount);
        return (countMap.putIfAbsent(element, newCounter) == null)
          || countMap.replace(element, existingCounter, newCounter);
      }
    } else {
      if (existingCounter.compareAndSet(oldValue, newCount)) {
        if (newCount == 0) {
          // Just CASed to 0; remove the entry to clean up the map. If the removal fails,
          // another thread has already replaced it with a new counter, which is fine.
          countMap.remove(element, existingCounter);
        }
        return true;
      }
    }
  }
  return false;
}
 
Example 19
/**
 * Adds a number of occurrences of the specified element to this multiset.
 *
 * @param element the element to add
 * @param occurrences the number of occurrences to add
 * @return the previous count of the element before the operation; possibly zero
 * @throws IllegalArgumentException if {@code occurrences} is negative, or if
 *     the resulting amount would exceed {@link Integer#MAX_VALUE}
 */

@CanIgnoreReturnValue
@Override
public int add(E element, int occurrences) {
  checkNotNull(element);
  if (occurrences == 0) {
    return count(element);
  }
  CollectPreconditions.checkPositive(occurrences, "occurences");
  while (true) {
    AtomicInteger existingCounter = Maps.safeGet(countMap, element);
    if (existingCounter == null) {
      existingCounter = countMap.putIfAbsent(element, new AtomicInteger(occurrences));
      if (existingCounter == null) {
        return 0;
      }
      // existingCounter != null: fall through to operate against the existing AtomicInteger
    }
    while (true) {
      int oldValue = existingCounter.get();
      if (oldValue != 0) {
        try {
          int newValue = IntMath.checkedAdd(oldValue, occurrences);
          if (existingCounter.compareAndSet(oldValue, newValue)) {
            // newValue can't == 0, so no need to check & remove
            return oldValue;
          }
        } catch (ArithmeticException overflow) {
          throw new IllegalArgumentException("Overflow adding " + occurrences + " occurrences to a count of " + oldValue);
        }
      } else {
        // In the case of a concurrent remove, we might observe a zero value, which means another
        // thread is about to remove (element, existingCounter) from the map. Rather than wait,
        // we can just do that work here.
        AtomicInteger newCounter = new AtomicInteger(occurrences);
        if ((countMap.putIfAbsent(element, newCounter) == null)
            || countMap.replace(element, existingCounter, newCounter)) {
          return 0;
        }
        break;
      }
    }

    // If we're still here, there was a race, so just try again.
  }
}
 
Example 20
/**
 * Adds a number of occurrences of the specified element to this multiset.
 *
 * @param element the element to add
 * @param occurrences the number of occurrences to add
 * @return the previous count of the element before the operation; possibly zero
 * @throws IllegalArgumentException if {@code occurrences} is negative, or if
 *     the resulting amount would exceed {@link Integer#MAX_VALUE}
 */
@CanIgnoreReturnValue
@Override
public int add(E element, int occurrences) {
  checkNotNull(element);
  if (occurrences == 0) {
    return count(element);
  }
  CollectPreconditions.checkPositive(occurrences, "occurences");

  while (true) {
    AtomicInteger existingCounter = Maps.safeGet(countMap, element);
    if (existingCounter == null) {
      existingCounter = countMap.putIfAbsent(element, new AtomicInteger(occurrences));
      if (existingCounter == null) {
        return 0;
      }
      // existingCounter != null: fall through to operate against the existing AtomicInteger
    }

    while (true) {
      int oldValue = existingCounter.get();
      if (oldValue != 0) {
        try {
          int newValue = IntMath.checkedAdd(oldValue, occurrences);
          if (existingCounter.compareAndSet(oldValue, newValue)) {
            // newValue can't == 0, so no need to check & remove
            return oldValue;
          }
        } catch (ArithmeticException overflow) {
          throw new IllegalArgumentException(
              "Overflow adding " + occurrences + " occurrences to a count of " + oldValue);
        }
      } else {
        // In the case of a concurrent remove, we might observe a zero value, which means another
        // thread is about to remove (element, existingCounter) from the map. Rather than wait,
        // we can just do that work here.
        AtomicInteger newCounter = new AtomicInteger(occurrences);
        if ((countMap.putIfAbsent(element, newCounter) == null)
            || countMap.replace(element, existingCounter, newCounter)) {
          return 0;
        }
        break;
      }
    }

    // If we're still here, there was a race, so just try again.
  }
}