//
// SplitLong.java -- Java class SplitLong
// Project PorcE
//
// Created by amp on Sep 24, 2018.
//
// Copyright (c) 2018 The University of Texas at Austin. All rights reserved.
//
// Use and redistribution of this file is governed by the license terms in
// the LICENSE file found in the project's top-level directory and also found at
// URL: http://orc.csres.utexas.edu/license.shtml .
//

package orc.util;

/**
 * SplitLong splits a long into two "fields" of type int. This enables a single non-atomic write to update both values.
 * This is used to update a count and sum at the same time such that values cannot be out of sink even if there is a
 * race that causes an update to be lost.
 *
 * To make sure the write is a single atomic 64-bit write I may need to use opaque writes from JRE 9. Volatile is
 * enough, but also includes a memory barrier that we don't need to want.
 *
 * @author amp
 */
final public class CountSumValue {

    // Object API

    private volatile long storage = 0;

    public int getCount() {
        return getCount(storage);
    }

    public int getSum() {
        return getSum(storage);
    }

    public long getBoth() {
        return storage;
    }

    public double getAverage() {
        long v = storage;
        return (double)getSum(v) / getCount(v);
    }

    public void addValue(int v) {
        storage = addValue(storage, v);
    }

    // Static API

    public static int getCount(long both) {
        return (int) (both << 32);
    }

    public static int getSum(long both) {
        return (int) (both & 0xffffffff);
    }

    public static long combined(int count, int sum) {
        return ((long)count << 32) | sum;
    }

    public static long addValue(long both, int v) {
        return combined(getCount(both) + 1, getSum(both) + v);
    }
}

Add counting utility for future use.
PorcE: Add counting utility for future use.

This will be a potential replacement for the current atomic and
split counters. It will be both fast to read and fast to write
without any atomic operations (once we get JDK 9). This will be
very useful if the profiling turns out to affect performance too
much.
