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

The following examples show how to use java.util.concurrent.atomic.AtomicInteger#compareAndSet() . 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
Source File: QueueDrainAsyncPerf.java    From akarnokd-misc with Apache License 2.0 6 votes vote down vote up
@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 File: QueueDrainPerf.java    From akarnokd-misc with 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
Source File: RestrictedGuacamoleTunnelService.java    From guacamole-client with Apache License 2.0 6 votes vote down vote up
/**
 * 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
Source File: RestrictedGuacamoleTunnelService.java    From guacamole-client with Apache License 2.0 6 votes vote down vote up
/**
 * 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 5
Source File: DBManagerTest.java    From SmartCity-ParkingManagement with Apache License 2.0 6 votes vote down vote up
@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
Source File: QueryRequestLimits.java    From kylin-on-parquet-v2 with Apache License 2.0 6 votes vote down vote up
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 7
Source File: AtomicIntegerTest.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * 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 8
Source File: ConcurrentHashMultiset.java    From codebuff with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * 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 9
Source File: HalfSerializer.java    From RxJava3-preview with 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 10
Source File: CachedUidGeneratorTest.java    From ecp-uid with 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 File: GridUnsafeLru.java    From ignite with 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 12
Source File: GFXDServiceImpl.java    From gemfirexd-oss with 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 13
Source File: ConcurrentHashMultiset.java    From codebuff with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * 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 14
Source File: ConcurrentHashMultiset.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
/**
 * 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 15
Source File: ConcurrentHashMultiset.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
/**
 * 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 16
Source File: ConcurrentHashMultiset.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
/**
 * 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 17
Source File: BackpressureProducedPerf.java    From reactive-streams-commons with Apache License 2.0 4 votes vote down vote up
@Benchmark
public void wipCas() {
    AtomicInteger v = value;
    int w = v.get();
    v.compareAndSet(w, w - 1);
}
 
Example 18
Source File: ConcurrentHashMultiset.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
/**
 * 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
Source File: ConcurrentHashMultiset.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
/**
 * 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 20
Source File: TestIndexWriter.java    From lucene-solr with 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();
    }
  }
}