001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.math3.stat.descriptive;
018
019import org.apache.commons.math3.exception.MathIllegalArgumentException;
020import org.apache.commons.math3.exception.NullArgumentException;
021import org.apache.commons.math3.util.MathUtils;
022
023/**
024 * Implementation of
025 * {@link org.apache.commons.math3.stat.descriptive.DescriptiveStatistics} that
026 * is safe to use in a multithreaded environment.  Multiple threads can safely
027 * operate on a single instance without causing runtime exceptions due to race
028 * conditions.  In effect, this implementation makes modification and access
029 * methods atomic operations for a single instance.  That is to say, as one
030 * thread is computing a statistic from the instance, no other thread can modify
031 * the instance nor compute another statistic.
032 *
033 * @since 1.2
034 */
035public class SynchronizedDescriptiveStatistics extends DescriptiveStatistics {
036
037    /** Serialization UID */
038    private static final long serialVersionUID = 1L;
039
040    /**
041     * Construct an instance with infinite window
042     */
043    public SynchronizedDescriptiveStatistics() {
044        // no try-catch or advertized IAE because arg is valid
045        this(INFINITE_WINDOW);
046    }
047
048    /**
049     * Construct an instance with finite window
050     * @param window the finite window size.
051     * @throws MathIllegalArgumentException if window size is less than 1 but
052     * not equal to {@link #INFINITE_WINDOW}
053     */
054    public SynchronizedDescriptiveStatistics(int window) throws MathIllegalArgumentException {
055        super(window);
056    }
057
058    /**
059     * A copy constructor. Creates a deep-copy of the {@code original}.
060     *
061     * @param original the {@code SynchronizedDescriptiveStatistics} instance to copy
062     * @throws NullArgumentException if original is null
063     */
064    public SynchronizedDescriptiveStatistics(SynchronizedDescriptiveStatistics original)
065    throws NullArgumentException {
066        copy(original, this);
067    }
068
069    /**
070     * {@inheritDoc}
071     */
072    @Override
073    public synchronized void addValue(double v) {
074        super.addValue(v);
075    }
076
077    /**
078     * {@inheritDoc}
079     */
080    @Override
081    public synchronized double apply(UnivariateStatistic stat) {
082        return super.apply(stat);
083    }
084
085    /**
086     * {@inheritDoc}
087     */
088    @Override
089    public synchronized void clear() {
090        super.clear();
091    }
092
093    /**
094     * {@inheritDoc}
095     */
096    @Override
097    public synchronized double getElement(int index) {
098        return super.getElement(index);
099    }
100
101    /**
102     * {@inheritDoc}
103     */
104    @Override
105    public synchronized long getN() {
106        return super.getN();
107    }
108
109    /**
110     * {@inheritDoc}
111     */
112    @Override
113    public synchronized double getStandardDeviation() {
114        return super.getStandardDeviation();
115    }
116
117    /**
118     * {@inheritDoc}
119     */
120    @Override
121    public synchronized double getQuadraticMean() {
122        return super.getQuadraticMean();
123    }
124
125    /**
126     * {@inheritDoc}
127     */
128    @Override
129    public synchronized double[] getValues() {
130        return super.getValues();
131    }
132
133    /**
134     * {@inheritDoc}
135     */
136    @Override
137    public synchronized int getWindowSize() {
138        return super.getWindowSize();
139    }
140
141    /**
142     * {@inheritDoc}
143     */
144    @Override
145    public synchronized void setWindowSize(int windowSize) throws MathIllegalArgumentException {
146        super.setWindowSize(windowSize);
147    }
148
149    /**
150     * {@inheritDoc}
151     */
152    @Override
153    public synchronized String toString() {
154        return super.toString();
155    }
156
157    /**
158     * Returns a copy of this SynchronizedDescriptiveStatistics instance with the
159     * same internal state.
160     *
161     * @return a copy of this
162     */
163    @Override
164    public synchronized SynchronizedDescriptiveStatistics copy() {
165        SynchronizedDescriptiveStatistics result =
166            new SynchronizedDescriptiveStatistics();
167        // No try-catch or advertised exception because arguments are guaranteed non-null
168        copy(this, result);
169        return result;
170    }
171
172    /**
173     * Copies source to dest.
174     * <p>Neither source nor dest can be null.</p>
175     * <p>Acquires synchronization lock on source, then dest before copying.</p>
176     *
177     * @param source SynchronizedDescriptiveStatistics to copy
178     * @param dest SynchronizedDescriptiveStatistics to copy to
179     * @throws NullArgumentException if either source or dest is null
180     */
181    public static void copy(SynchronizedDescriptiveStatistics source,
182                            SynchronizedDescriptiveStatistics dest)
183        throws NullArgumentException {
184        MathUtils.checkNotNull(source);
185        MathUtils.checkNotNull(dest);
186        synchronized (source) {
187            synchronized (dest) {
188                DescriptiveStatistics.copy(source, dest);
189            }
190        }
191    }
192}