001/*
002 * JPPF.
003 * Copyright (C) 2005-2016 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;
020
021/**
022 * Holds a mutable object reference witho no locking or synchronization mechanism.
023 * This can be used in anonymous classes for mutating values without the cost of synchronization such as implemented in {@link java.util.concurrent.atomic.AtomicReference}.
024 * <p>For thread-safe access, instances of this class <i>must</i> be synchronized externally or by using the
025 * {code getSynchronized(Object)} and {@code setSynchronized(E, Object)} methods.
026 * @param <E> The type of reference to handle.
027 * @author Laurent Cohen
028 * @since 5.0
029 */
030public class MutableReference<E> {
031  /**
032   * The object held by this reference.
033   */
034  private E referend;
035
036  /**
037   * Initiaize this reference with the referend set to null.
038   */
039  public MutableReference() {
040    this.referend = null;
041  }
042
043  /**
044   * Initiaize this reference with the specified referend.
045   * @param referend the object held by this reference.
046   */
047  public MutableReference(final E referend) {
048    this.referend = referend;
049  }
050
051  /**
052   * Get the object held by this reference.
053   * @return an object of the reference type.
054   */
055  public E get() {
056    return referend;
057  }
058
059  /**
060   * Set the object held by this reference.
061   * @param referend an object of the reference type.
062   * @return the new referend.
063   */
064  public E set(final E referend) {
065    return this.referend = referend;
066  }
067
068  /**
069   * Get the referend within a block synchronized on the specified monitor.
070   * @param monitor an object on which to synchronize.
071   * @throws IllegalArgumentException if the monitor is null.
072   * @return an object of the reference type.
073   */
074  public E getSynchronized(final Object monitor) throws IllegalArgumentException {
075    if (monitor == null) throw new IllegalArgumentException("the monitor cannot be null");
076    synchronized(monitor) {
077      return referend;
078    }
079  }
080
081  /**
082   * Set the referend within a block synchronized on the specified monitor.
083   * @param referend the value to set for this reference.
084   * @param monitor an object on which to synchronize.
085   * @return the new referend.
086   * @throws IllegalArgumentException if the monitor is null.
087   */
088  public E setSynchronized(final E referend, final Object monitor) throws IllegalArgumentException {
089    if (monitor == null) throw new IllegalArgumentException("the monitor cannot be null");
090    synchronized(monitor) {
091      return this.referend = referend;
092    }
093  }
094}