001/*
002 * JPPF.
003 * Copyright (C) 2005-2018 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.jppf.utils.concurrent;
020
021import org.jppf.utils.ComparisonOperator;
022
023/**
024 * A long value on which a set of operations can be performed atomically.
025 * @author Laurent Cohen
026 */
027public class SynchronizedLong {
028  /**
029   * The long value.
030   */
031  private long value;
032
033  /**
034   * Initialize with a value of 0.
035   */
036  public SynchronizedLong() {
037  }
038
039  /**
040   * Initialize with the specified value.
041   * @param value the initial value.
042   */
043  public SynchronizedLong(final long value) {
044    this.value = value;
045  }
046
047  /**
048   * Get the value.
049   * @return the current value.
050   */
051  public synchronized long get() {
052    return value;
053  }
054
055  /**
056   * Set to a new value.
057   * @param newValue the value to set.
058   */
059  public synchronized void set(final long newValue) {
060    value = newValue;
061  }
062
063  /**
064   * Increment the value.
065   * @return the new value.
066   */
067  public synchronized long incrementAndGet() {
068    return ++value;
069  }
070
071  /**
072   * Increment the value.
073   * @return the new value.
074   */
075  public synchronized long decrementAndGet() {
076    return --value;
077  }
078
079  /**
080   * Add the specified update and return the new value.
081   * @param update the value to add.
082   * @return the new value.
083   */
084  public synchronized long addAndGet(final long update) {
085    value += update;
086    return value;
087  }
088
089  /**
090   * Set a new value and return the old value.
091   * @param newValue the value to set.
092   * @return the value before the set.
093   */
094  public synchronized long getAndSet(final long newValue) {
095    final long oldValue = value;
096    value = newValue;
097    return oldValue;
098  }
099
100  /**
101   * Compare the value witht he expected value, and set it to the update value if they are equal.
102   * @param expected the expected value.
103   * @param update the new value to set to if the comparison succeeds.
104   * @return {@code true} if the update was performed, {@code false} otherwise.
105   */
106  public synchronized boolean compareAndSet(final long expected, final long update) {
107    if (value == expected) {
108      value = update;
109      return true;
110    }
111    return false;
112  }
113
114  /**
115   * Compare the value with the expected value using the specified operator, and set it to the update value if the comparison succeeds.
116   * @param operator the comparison operator.
117   * @param expected the expected value.
118   * @param update the new value to set to if the comparison succeeds.
119   * @return {@code true} if the update was performed, {@code false} otherwise.
120   */
121  public synchronized boolean compareAndSet(final ComparisonOperator operator, final long expected, final long update) {
122    if (operator.evaluate(value, expected)) {
123      value = update;
124      return true;
125    }
126    return false;
127  }
128
129  /**
130   * Compare the value with the expected update value using the specified operator, and set it to this update value if the comparison succeeds.
131   * @param operator the comparison operator.
132   * @param expectedUpdate the expected value.
133   * @return {@code true} if the update was performed, {@code false} otherwise.
134   */
135  public synchronized boolean compareAndSet(final ComparisonOperator operator, final long expectedUpdate) {
136    if (operator.evaluate(value, expectedUpdate)) {
137      value = expectedUpdate;
138      return true;
139    }
140    return false;
141  }
142
143  /**
144   * Compare the value with the expected value, and run the action if they are equal.
145   * @param operator the comparison operator.
146   * @param expected the expected value.
147   * @param action the action to run if the comparison succeeds.
148   * @return {@code true} if the update was performed, {@code false} otherwise.
149   */
150  public synchronized boolean compareAndRun(final ComparisonOperator operator, final long expected, final Runnable action) {
151    if (operator.evaluate(value, expected)) {
152      if (action != null) action.run();
153      return true;
154    }
155    return false;
156  }
157
158  /**
159   * Run the specified action if the value is within the specified bounds.
160   * @param lower the lower bound of the between comparison.
161   * @param upper the upper bound of the between comparison.
162   * @param action the action to run if the comparison succeeds.
163   * @return {@code true} if the update was performed, {@code false} otherwise.
164   */
165  public synchronized boolean runIfBetween(final long lower, final long upper, final Runnable action) {
166    if ((value > lower) && (value < upper)) {
167      if (action != null) action.run();
168      return true;
169    }
170    return false;
171  }
172
173  /**
174   * Run the specified action if the value is outside the specified bounds.
175   * @param lower the lower bound of the between comparison.
176   * @param upper the upper bound of the between comparison.
177   * @param action the action to run if the comparison succeeds.
178   * @return {@code true} if the update was performed, {@code false} otherwise.
179   */
180  public synchronized boolean runIfNotBetween(final long lower, final long upper, final Runnable action) {
181    if ((value <= lower) || (value >= upper)) {
182      if (action != null) action.run();
183      return true;
184    }
185    return false;
186  }
187}