1 /*
   2  * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.word;
  24 
  25 import java.util.concurrent.atomic.AtomicLong;
  26 import java.util.concurrent.atomic.AtomicReference;
  27 
  28 /**
  29  * A {@link WordBase word} value that may be updated atomically. See the
  30  * {@link java.util.concurrent.atomic} package specification for description of the properties of
  31  * atomic variables.
  32  *
  33  * Similar to {@link AtomicReference}, but for {@link WordBase word} types. A dedicated
  34  * implementation is necessary because Object and word types cannot be mixed.
  35  */
  36 public class AtomicWord<T extends WordBase> {
  37 
  38     /**
  39      * For simplicity, we convert the word value to a long and delegate to existing atomic
  40      * operations.
  41      */
  42     protected final AtomicLong value;
  43 
  44     /**
  45      * Creates a new AtomicLong with initial value {@link Word#zero}.
  46      */
  47     public AtomicWord() {
  48         value = new AtomicLong();
  49     }
  50 
  51     /**
  52      * Gets the current value.
  53      *
  54      * @return the current value
  55      */
  56     @SuppressWarnings("unchecked")
  57     public final T get() {
  58         return (T) Word.unsigned(value.get());
  59     }
  60 
  61     /**
  62      * Sets to the given value.
  63      *
  64      * @param newValue the new value
  65      */
  66     public final void set(T newValue) {
  67         value.set(newValue.rawValue());
  68     }
  69 
  70     /**
  71      * Atomically sets to the given value and returns the old value.
  72      *
  73      * @param newValue the new value
  74      * @return the previous value
  75      */
  76     @SuppressWarnings("unchecked")
  77     public final T getAndSet(T newValue) {
  78         return (T) Word.unsigned(value.getAndSet(newValue.rawValue()));
  79     }
  80 
  81     /**
  82      * Atomically sets the value to the given updated value if the current value {@code ==} the
  83      * expected value.
  84      *
  85      * @param expect the expected value
  86      * @param update the new value
  87      * @return {@code true} if successful. False return indicates that the actual value was not
  88      *         equal to the expected value.
  89      */
  90     public final boolean compareAndSet(T expect, T update) {
  91         return value.compareAndSet(expect.rawValue(), update.rawValue());
  92     }
  93 }