/*
This file is part of Reactive Cascade which is released under The MIT License.
See license.md , https://github.com/futurice/cascade and http://reactivecascade.com for details.
This is open source for the common good. Please contribute improvements by pull request or contact paulirotta@gmail.com
*/
package com.reactivecascade.reactive;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.reactivecascade.i.IActionOne;
import com.reactivecascade.i.IActionOneR;
import com.reactivecascade.i.IThreadType;
import com.reactivecascade.util.RCLog;
/**
* An {@link Integer} which can be updated in an atomic, thread-safe manner.
* <p>
* This is similar to an {@link java.util.concurrent.atomic.AtomicInteger} with reactive bindings to
* get and set the from in reactive chains (function sequences that can fire multiple times).
* <p>
* Created by phou on 30-04-2015.
*/
public class ReactiveInteger extends ReactiveValue<Integer> {
/**
* Create a new atomic integer
*
* @param name
* @param initialValue
*/
public ReactiveInteger(@NonNull String name,
int initialValue) {
super(name, initialValue);
}
/**
* Create a new atomic integer
*
* @param threadType
* @param name
* @param onFireAction a mapping for incoming values, for example <code>i -> Math.max(0, i)</code>
* @param onError
*/
public ReactiveInteger(@NonNull IThreadType threadType,
@NonNull String name,
@Nullable IActionOneR<Integer, Integer> onFireAction,
@NonNull IActionOne<Exception> onError) {
super(name, threadType, onFireAction, onError);
}
/**
* Add two integers in a thread-safe manner
*
* @param i
* @return
*/
@CallSuper
public int addAndGet(int i) {
while (true) {
final int currentValue = get();
if (compareAndSet(currentValue, currentValue + i)) {
return currentValue;
}
RCLog.d(this, "Collision concurrent add, will try again: " + currentValue);
}
}
/**
* Multiply two integers in a thread-safe manner
*
* @param i
* @return
*/
@CallSuper
public int multiplyAndGet(int i) {
while (true) {
final int currentValue = get();
if (compareAndSet(currentValue, currentValue * i)) {
return currentValue;
}
RCLog.d(this, "Collision concurrent add, will try again: " + currentValue);
}
}
/**
* Increment the integer in a thread-safe manner
*
* @return the from after increment
*/
@CallSuper
public int incrementAndGet() {
return addAndGet(1);
}
/**
* Decrement the integer in a thread-safe manner
*
* @return the from after decriment
*/
@CallSuper
public int decrementAndGet() {
return addAndGet(-1);
}
}