001/*
002 * Copyright 2013 Alex Kasko (alexkasko.com)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.alexkasko.unsafe.offheaplong;
018
019import com.alexkasko.unsafe.offheap.OffHeapDisposable;
020import com.alexkasko.unsafe.offheap.OffHeapDisposableIterator;
021import com.alexkasko.unsafe.offheap.OffHeapMemory;
022
023/**
024 * <p>Implementation of array of long using {@link com.alexkasko.unsafe.offheap.OffHeapMemory}.
025 *
026 * <p>Default implementation uses {@code sun.misc.Unsafe}, with all operations guarded with {@code assert} keyword.
027 * With assertions enabled in runtime ({@code -ea} java switch) {@link AssertionError}
028 * will be thrown on illegal index access. Without assertions illegal index will crash JVM.
029 *
030 * <p>Array won't be zeroed after creation (will contain garbage by default).
031 * Allocated memory may be freed manually using {@link #free()} (thread-safe
032 * and may be called multiple times) or it will be freed after {@link OffHeapLongArray}
033 * will be garbage collected.
034 *
035 * <p>Note: while class implements Iterable, iterator will create new autoboxed Long object
036 * <b>on every</b> {@code next()} call, this behaviour is inevitable with iterators in java 6/7.
037 *
038 * @author alexkasko
039 * Date: 2/22/13
040 */
041public class OffHeapLongArray implements OffHeapLongAddressable, OffHeapDisposable, Iterable<Long> {
042    private static final int ELEMENT_LENGTH = 8;
043
044    private final OffHeapMemory ohm;
045
046    /**
047     * Constructor
048     *
049     * @param size number of elements in array
050     */
051    public OffHeapLongArray(long size) {
052        this.ohm = OffHeapMemory.allocateMemory(size * ELEMENT_LENGTH);
053    }
054
055    /**
056     * Private constructor for {@link #clone()} support
057     *
058     * @param ohm cloned memory instance
059     */
060    private OffHeapLongArray(OffHeapMemory ohm) {
061        this.ohm = ohm;
062    }
063
064    /**
065     * Whether unsafe implementation of {@link OffHeapMemory} is used
066     *
067     * @return whether unsafe implementation of {@link OffHeapMemory} is used
068     */
069    public boolean isUnsafe() {
070        return ohm.isUnsafe();
071    }
072
073    /**
074     * Gets the element at position {@code index}
075     *
076     * @param index array index
077     * @return long value
078     */
079    @Override
080    public long get(long index) {
081        return ohm.getLong(index * ELEMENT_LENGTH);
082    }
083
084    /**
085     * Sets the element at position {@code index} to the given value
086     *
087     * @param index array index
088     * @param value long value
089     */
090    @Override
091    public void set(long index, long value) {
092        ohm.putLong(index * ELEMENT_LENGTH, value);
093    }
094
095    /**
096     * Returns number of elements in array
097     *
098     * @return number of elements in array
099     */
100    @Override
101    public long size() {
102        return ohm.length() / ELEMENT_LENGTH;
103    }
104
105    /**
106     * Frees allocated memory, may be called multiple times from any thread
107     */
108    public void free() {
109        ohm.free();
110    }
111
112    /**
113     * {@inheritDoc}
114     */
115    @Override
116    public OffHeapDisposableIterator<Long> iterator() {
117        return new OffHeapLongIterator(this);
118    }
119
120    /**
121     * {@inheritDoc}
122     */
123    @Override
124    public OffHeapLongArray clone() {
125        OffHeapMemory cloned = ohm.clone();
126        return new OffHeapLongArray(cloned);
127    }
128
129    /**
130     * {@inheritDoc}
131     */
132    @Override
133    public String toString() {
134        final StringBuilder sb = new StringBuilder();
135        sb.append("OffHeapLongArray");
136        sb.append("{size=").append(size());
137        sb.append(", unsafe=").append(isUnsafe());
138        sb.append('}');
139        return sb.toString();
140    }
141}