All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tonivade.purefun.effect.Ref Maven / Gradle / Ivy

/*
 * Copyright (c) 2018-2022, Antonio Gabriel Muñoz Conejo 
 * Distributed under the terms of the MIT License
 */
package com.github.tonivade.purefun.effect;

import static com.github.tonivade.purefun.Precondition.checkNonNull;
import static com.github.tonivade.purefun.Unit.unit;

import java.util.concurrent.atomic.AtomicReference;

import com.github.tonivade.purefun.Function1;
import com.github.tonivade.purefun.Operator1;
import com.github.tonivade.purefun.Tuple2;
import com.github.tonivade.purefun.Unit;

public final class Ref {

  private final AtomicReference value;

  private Ref(AtomicReference value) {
    this.value = checkNonNull(value);
  }

  public UIO get() {
    return UIO.task(value::get);
  }

  public UIO set(A newValue) {
    return UIO.task(() -> { value.set(newValue); return unit(); });
  }
  
  public  UIO modify(Function1> change) {
    return UIO.task(() -> {
      var loop = true;
      B result = null;
      while (loop) {
        A current = value.get();
        var tuple = change.apply(current);
        result = tuple.get1();
        loop = !value.compareAndSet(current, tuple.get2());
      }
      return result;
    });
  }

  public UIO lazySet(A newValue) {
    return UIO.task(() -> { value.lazySet(newValue); return unit(); });
  }

  public UIO getAndSet(A newValue) {
    return UIO.task(() -> value.getAndSet(newValue));
  }

  public UIO updateAndGet(Operator1 update) {
    return UIO.task(() -> value.updateAndGet(update::apply));
  }

  public UIO getAndUpdate(Operator1 update) {
    return UIO.task(() -> value.getAndUpdate(update::apply));
  }
  
  public static  UIO> make(A value) {
    return UIO.pure(of(value));
  }

  public static  Ref of(A value) {
    return new Ref<>(new AtomicReference<>(value));
  }

  @Override
  public String toString() {
    return String.format("Ref(%s)", value.get());
  }
}