+++ /dev/null
-/*
- * Copyright © 2020 Damyan Ivanov.
- * This file is part of MoLe.
- * MoLe is free software: you can distribute it and/or modify it
- * under the term of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your opinion), any later version.
- *
- * MoLe is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License terms for details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package net.ktnx.mobileledger.utils;
-
-import android.os.Build;
-
-import androidx.annotation.RequiresApi;
-
-import java.util.Observable;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.IntBinaryOperator;
-import java.util.function.IntUnaryOperator;
-
-public class ObservableAtomicInteger extends Observable {
- private final AtomicInteger holder;
- ObservableAtomicInteger() {
- super();
- holder = new AtomicInteger();
- }
- public ObservableAtomicInteger(int initialValue) {
- this();
- holder.set(initialValue);
- }
- public int get() {
- return holder.get();
- }
- public void set(int newValue) {
-// debug("atomic", "set");
- holder.set(newValue);
- forceNotify();
- }
- private void forceNotify() {
- setChanged();
-// debug("atomic", String.format("notifying %d observers", countObservers()));
- notifyObservers();
- }
-// public void lazySet(int newValue) {
-// holder.lazySet(newValue);
-// forceNotify();
-// }
- public int getAndSet(int newValue) {
- int result = holder.getAndSet(newValue);
- forceNotify();
- return result;
- }
- public boolean compareAndSet(int expect, int update) {
- boolean result = holder.compareAndSet(expect, update);
- if (result) forceNotify();
- return result;
- }
-// public boolean weakCompareAndSet(int expect, int update) {
-// boolean result = holder.weakCompareAndSet(expect, update);
-// if (result) forceNotify();
-// return result;
-// }
- public int getAndIncrement() {
- int result = holder.getAndIncrement();
- forceNotify();
- return result;
- }
- public int getAndDecrement() {
- int result = holder.getAndDecrement();
- forceNotify();
- return result;
- }
- public int getAndAdd(int delta) {
- int result = holder.getAndAdd(delta);
- forceNotify();
- return result;
- }
- public int incrementAndGet() {
-// debug("atomic", "incrementAndGet");
- int result = holder.incrementAndGet();
- forceNotify();
- return result;
- }
- public int decrementAndGet() {
-// debug("atomic", "decrementAndGet");
- int result = holder.decrementAndGet();
- forceNotify();
- return result;
- }
- public int addAndGet(int delta) {
- int result = holder.addAndGet(delta);
- forceNotify();
- return result;
- }
- @RequiresApi(Build.VERSION_CODES.N)
- public int getAndUpdate(IntUnaryOperator updateFunction) {
- int result = holder.getAndUpdate(updateFunction);
- forceNotify();
- return result;
- }
- @RequiresApi(api = Build.VERSION_CODES.N)
- public int updateAndGet(IntUnaryOperator updateFunction) {
- int result = holder.updateAndGet(updateFunction);
- forceNotify();
- return result;
- }
- @RequiresApi(api = Build.VERSION_CODES.N)
- public int getAndAccumulate(int x, IntBinaryOperator accumulatorFunction) {
- int result = holder.getAndAccumulate(x, accumulatorFunction);
- forceNotify();
- return result;
- }
- @RequiresApi(api = Build.VERSION_CODES.N)
- public int accumulateAndGet(int x, IntBinaryOperator accumulatorFunction) {
- int result = holder.accumulateAndGet(x, accumulatorFunction);
- forceNotify();
- return result;
- }
- public int intValue() {
- return holder.intValue();
- }
- public long longValue() {
- return holder.longValue();
- }
- public float floatValue() {
- return holder.floatValue();
- }
- public double doubleValue() {
- return holder.doubleValue();
- }
- public byte byteValue() {
- return holder.byteValue();
- }
- public short shortValue() {
- return holder.shortValue();
- }
-}
+++ /dev/null
-/*
- * Copyright © 2020 Damyan Ivanov.
- * This file is part of MoLe.
- * MoLe is free software: you can distribute it and/or modify it
- * under the term of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your opinion), any later version.
- *
- * MoLe is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License terms for details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package net.ktnx.mobileledger.utils;
-
-import android.os.Build;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Observable;
-import java.util.Spliterator;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import java.util.stream.Stream;
-
-import static net.ktnx.mobileledger.utils.Logger.debug;
-
-public class ObservableList<T> extends Observable implements List<T> {
- private List<T> list;
- private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- private int notificationBlocks = 0;
- private boolean notificationWasBlocked = false;
- public ObservableList(List<T> list) {
- this.list = list;
- }
- private void forceNotify() {
- if (notificationBlocked()) return;
- setChanged();
- notifyObservers();
- }
- private boolean notificationBlocked() {
- return notificationWasBlocked = (notificationBlocks > 0);
- }
- private void forceNotify(int index) {
- if (notificationBlocked()) return;
- setChanged();
- notifyObservers(index);
- }
- public int size() {
- try (LockHolder lh = lockForReading()) {
- return list.size();
- }
- }
- public boolean isEmpty() {
- try (LockHolder lh = lockForReading()) {
- return list.isEmpty();
- }
- }
- public boolean contains(@Nullable Object o) {
- try (LockHolder lh = lockForReading()) {
- return list.contains(o);
- }
- }
- @NonNull
- public Iterator<T> iterator() {
- throw new RuntimeException("Iterators break encapsulation and ignore locking");
-// return list.iterator();
- }
- @NotNull
- public Object[] toArray() {
- try (LockHolder lh = lockForReading()) {
- return list.toArray();
- }
- }
- @Override
- @NotNull
- public <T1> T1[] toArray(@Nullable T1[] a) {
- try (LockHolder lh = lockForReading()) {
- return list.toArray(a);
- }
- }
- public boolean add(T t) {
- try (LockHolder lh = lockForWriting()) {
- boolean result = list.add(t);
- lh.downgrade();
- if (result)
- forceNotify();
- return result;
- }
- }
- public boolean remove(@Nullable Object o) {
- try (LockHolder lh = lockForWriting()) {
- boolean result = list.remove(o);
- lh.downgrade();
- if (result) forceNotify();
- return result;
- }
- }
- public T removeQuietly(int index) {
- return list.remove(index);
- }
- public boolean containsAll(@NonNull Collection<?> c) {
- try (LockHolder lh = lockForReading()) {
- return list.containsAll(c);
- }
- }
- public boolean addAll(@NonNull Collection<? extends T> c) {
- try (LockHolder lh = lockForWriting()) {
- boolean result = list.addAll(c);
- lh.downgrade();
- if (result) forceNotify();
- return result;
- }
- }
- public boolean addAll(int index, @NonNull Collection<? extends T> c) {
- try (LockHolder lh = lockForWriting()) {
- boolean result = list.addAll(index, c);
- lh.downgrade();
- if (result) forceNotify();
- return result;
- }
- }
- public boolean addAllQuietly(int index, Collection<? extends T> c) {
- return list.addAll(index, c);
- }
- public boolean removeAll(@NonNull Collection<?> c) {
- try (LockHolder lh = lockForWriting()) {
- boolean result = list.removeAll(c);
- lh.downgrade();
- if (result) forceNotify();
- return result;
- }
- }
- public boolean retainAll(@NonNull Collection<?> c) {
- try (LockHolder lh = lockForWriting()) {
- boolean result = list.retainAll(c);
- lh.downgrade();
- if (result) forceNotify();
- return result;
- }
- }
- @RequiresApi(api = Build.VERSION_CODES.N)
- public void replaceAll(@NonNull UnaryOperator<T> operator) {
- try (LockHolder lh = lockForWriting()) {
- list.replaceAll(operator);
- lh.downgrade();
- forceNotify();
- }
- }
- @RequiresApi(api = Build.VERSION_CODES.N)
- public void sort(@Nullable Comparator<? super T> c) {
- try (LockHolder lh = lockForWriting()) {
- lock.writeLock().lock();
- list.sort(c);
- lh.downgrade();
- forceNotify();
- }
- }
- public void clear() {
- try (LockHolder lh = lockForWriting()) {
- boolean wasEmpty = list.isEmpty();
- list.clear();
- lh.downgrade();
- if (!wasEmpty) forceNotify();
- }
- }
- public T get(int index) {
- try (LockHolder lh = lockForReading()) {
- return list.get(index);
- }
- }
- public T set(int index, T element) {
- try (LockHolder lh = lockForWriting()) {
- T result = list.set(index, element);
- lh.downgrade();
- forceNotify();
- return result;
- }
- }
- public void add(int index, T element) {
- try (LockHolder lh = lockForWriting()) {
- list.add(index, element);
- lh.downgrade();
- forceNotify();
- }
- }
- public T remove(int index) {
- try (LockHolder lh = lockForWriting()) {
- T result = list.remove(index);
- lh.downgrade();
- forceNotify();
- return result;
- }
- }
- public int indexOf(@Nullable Object o) {
- try (LockHolder lh = lockForReading()) {
- return list.indexOf(o);
- }
- }
- public int lastIndexOf(@Nullable Object o) {
- try (LockHolder lh = lockForReading()) {
- return list.lastIndexOf(o);
- }
- }
- @NotNull
- public ListIterator<T> listIterator() {
- if (!lock.isWriteLockedByCurrentThread()) throw new RuntimeException(
- "Iterators break encapsulation and ignore locking. Write-lock first");
- return list.listIterator();
- }
- @NotNull
- public ListIterator<T> listIterator(int index) {
- if (!lock.isWriteLockedByCurrentThread()) throw new RuntimeException(
- "Iterators break encapsulation and ignore locking. Write-lock first");
- return list.listIterator(index);
- }
- @NotNull
- public List<T> subList(int fromIndex, int toIndex) {
- try (LockHolder lh = lockForReading()) {
- return list.subList(fromIndex, toIndex);
- }
- }
- @NotNull
- @RequiresApi(api = Build.VERSION_CODES.N)
- public Spliterator<T> spliterator() {
- if (!lock.isWriteLockedByCurrentThread())
- throw new RuntimeException(
- "Iterators break encapsulation and ignore locking. Write-lock first");
- return list.spliterator();
- }
- @RequiresApi(api = Build.VERSION_CODES.N)
- public boolean removeIf(@NotNull Predicate<? super T> filter) {
- try (LockHolder lh = lockForWriting()) {
- boolean result = list.removeIf(filter);
- lh.downgrade();
- if (result)
- forceNotify();
- return result;
- }
- }
- @NotNull
- @RequiresApi(api = Build.VERSION_CODES.N)
- public Stream<T> stream() {
- if (!lock.isWriteLockedByCurrentThread()) throw new RuntimeException(
- "Iterators break encapsulation and ignore locking. Write-lock first");
- return list.stream();
- }
- @NotNull
- @RequiresApi(api = Build.VERSION_CODES.N)
- public Stream<T> parallelStream() {
- if (!lock.isWriteLockedByCurrentThread())
- throw new RuntimeException(
- "Iterators break encapsulation and ignore locking. Write-lock first");
- return list.parallelStream();
- }
- @RequiresApi(api = Build.VERSION_CODES.N)
- public void forEach(@NotNull Consumer<? super T> action) {
- try (LockHolder lh = lockForReading()) {
- list.forEach(action);
- }
- }
- public List<T> getList() {
- if (!lock.isWriteLockedByCurrentThread())
- throw new RuntimeException(
- "Direct list access breaks encapsulation and ignore locking. Write-lock first");
- return list;
- }
- public void setList(List<T> aList) {
- try (LockHolder lh = lockForWriting()) {
- list = aList;
- lh.downgrade();
- forceNotify();
- }
- }
- public void triggerItemChangedNotification(T item) {
- try (LockHolder lh = lockForReading()) {
- int index = list.indexOf(item);
- if (index == -1) {
- debug("ObList", "??? not sending notifications for item not found in the list");
- return;
- }
- debug("ObList", "Notifying item change observers");
- triggerItemChangedNotification(index);
- }
- }
- public void triggerItemChangedNotification(int index) {
- forceNotify(index);
- }
- public LockHolder lockForWriting() {
- ReentrantReadWriteLock.WriteLock wLock = lock.writeLock();
- wLock.lock();
-
- ReentrantReadWriteLock.ReadLock rLock = lock.readLock();
- rLock.lock();
-
- return new LockHolder(rLock, wLock);
- }
- public LockHolder lockForReading() {
- ReentrantReadWriteLock.ReadLock rLock = lock.readLock();
- rLock.lock();
- return new LockHolder(rLock);
- }
- public void blockNotifications() {
- notificationBlocks++;
- }
- public void unblockNotifications() {
- notificationBlocks--;
- if ((notificationBlocks == 0) && notificationWasBlocked) notifyObservers();
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright © 2020 Damyan Ivanov.
- * This file is part of MoLe.
- * MoLe is free software: you can distribute it and/or modify it
- * under the term of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your opinion), any later version.
- *
- * MoLe is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License terms for details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package net.ktnx.mobileledger.utils;
-
-import java.util.Observable;
-import java.util.Observer;
-
-public class ObservableValue<T> {
- private final ObservableValueImpl<T> impl = new ObservableValueImpl<>();
- public ObservableValue() {}
- public ObservableValue(T initialValue) {
- impl.setValue(initialValue, false);
- }
- public void set(T newValue) {
- impl.setValue(newValue);
- }
- public T get() {
- return impl.getValue();
- }
- public void addObserver(Observer o) {
- impl.addObserver(o);
- }
- public void deleteObserver(Observer o) {
- impl.deleteObserver(o);
- }
- public void notifyObservers() {
- impl.notifyObservers();
- }
- public void notifyObservers(T arg) {
- impl.notifyObservers(arg);
- }
- public void deleteObservers() {
- impl.deleteObservers();
- }
- public boolean hasChanged() {
- return impl.hasChanged();
- }
- public int countObservers() {
- return impl.countObservers();
- }
- public void forceNotifyObservers() {
- impl.setChanged();
- impl.notifyObservers();
- }
- private static class ObservableValueImpl<T> extends Observable {
- protected T value;
- public void setValue(T newValue) {
- setValue(newValue, true);
- }
- protected void setChanged() {
- super.setChanged();
- }
- private synchronized void setValue(T newValue, boolean notify) {
- if ((newValue == null) && (value == null))
- return;
-
- if ((newValue != null) && newValue.equals(value)) return;
-
- T oldValue = value;
- value = newValue;
- setChanged();
- if (notify) notifyObservers(oldValue);
- }
- public T getValue() {
- return value;
- }
- }
-}
\ No newline at end of file