/* * JBoss, Home of Professional Open Source * Copyright 2009, JBoss Inc., and others contributors as indicated * by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * (C) 2009, * @author mark.little@jboss.com */ package org.jboss.stm.internal.types; import java.io.IOException; import java.util.ArrayList; import org.jboss.stm.annotations.ReadLock; import org.jboss.stm.annotations.RestoreState; import org.jboss.stm.annotations.SaveState; import org.jboss.stm.annotations.Transactional; import org.jboss.stm.annotations.WriteLock; import org.jboss.stm.internal.RecoverableContainer; import org.jboss.stm.types.AtomicArray; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.ats.arjuna.state.InputObjectState; import com.arjuna.ats.arjuna.state.OutputObjectState; import com.arjuna.ats.internal.arjuna.common.UidHelper; // TODO maybe pull all of this into a separate jar /* * TODO currently does not assume sparse list, i.e., requires * contiguous. */ @Transactional public class AtomicArrayImpl<E> implements AtomicArray<E> { public static final int DEFAULT_SIZE = 10; public AtomicArrayImpl () { this(DEFAULT_SIZE); } public AtomicArrayImpl (int size) { _size = size; _array = new ArrayList<E>(size); for (int i = 0; i < _size; i++) _array.add(i, null); } @WriteLock public synchronized void empty () { _array = new ArrayList<E>(_size); } @ReadLock public synchronized E get (int index) { return _array.get(index); } @ReadLock public synchronized boolean isEmpty () { return _array.isEmpty(); } @WriteLock public synchronized void set (int index, E val) { if (basicType(val)) _array.set(index, val); else { if (_container == null) _container = new RecoverableContainer<E>(); _array.set(index, _container.enlist(val)); } } @ReadLock public synchronized int size () { return _array.size(); } @SaveState public void save_state (OutputObjectState os) throws IOException { if (_type == null) _type = _array.get(0).getClass(); os.packInt(_size); for (int i = 0; i < _array.size(); i++) { Object inst = _array.get(i); if (_type.equals(Boolean.class)) os.packBoolean(((Boolean) inst).booleanValue()); else if (_type.equals(Byte.class)) os.packByte(((Byte) inst).byteValue()); else if (_type.equals(Short.class)) os.packShort(((Short) inst).shortValue()); else if (_type.equals(Integer.class)) os.packInt(((Integer) inst).intValue()); else if (_type.equals(Long.class)) os.packLong(((Long) inst).longValue()); else if (_type.equals(Float.class)) os.packFloat(((Float) inst).floatValue()); else if (_type.equals(Double.class)) os.packDouble(((Double) inst).doubleValue()); else if (_type.equals(Character.class)) os.packChar(((Character) inst).charValue()); else if (_type.equals(String.class)) os.packString((String) inst); else { if (inst == null) os.packBoolean(false); else { os.packBoolean(true); Uid temp = _container.getUidForHandle(_array.get(i)); /* * Assume transactional object! Responsible for its own state, so we only * track references. */ try { UidHelper.packInto(temp, os); } catch (final Exception ex) { throw new IOException(ex); } } } } } @SuppressWarnings("unchecked") @RestoreState public void restore_state (InputObjectState os) throws IOException { _size = os.unpackInt(); _array = new ArrayList<E>(_size); for (int i = 0; i < _size; i++) _array.add(i, null); for (int i = 0; i < _size; i++) _array.add(i, null); for (int i = 0; i < _size; i++) { if (_type.equals(Boolean.class)) _array.set(i, (E) ((Boolean) os.unpackBoolean())); else if (_type.equals(Byte.class)) _array.set(i, (E) ((Byte) os.unpackByte())); else if (_type.equals(Short.class)) _array.set(i, (E) ((Short) os.unpackShort())); else if (_type.equals(Integer.class)) _array.set(i, (E) ((Integer) os.unpackInt())); else if (_type.equals(Long.class)) _array.set(i, (E) ((Long) os.unpackLong())); else if (_type.equals(Float.class)) _array.set(i, (E) ((Float) os.unpackFloat())); else if (_type.equals(Double.class)) _array.set(i, (E) ((Double) os.unpackDouble())); else if (_type.equals(Character.class)) _array.set(i, (E) ((Character) os.unpackChar())); else if (_type.equals(String.class)) _array.set(i, (E) os.unpackString()); else { boolean ptr = os.unpackBoolean(); if (!ptr) _array.set(i, null); else { /* * Assume transactional object! Responsible for its own state, so we only * track references. */ try { Uid temp = UidHelper.unpackFrom(os); _array.set(i, _container.getHandle(temp)); } catch (final Exception ex) { throw new IOException(ex); } } } } } private boolean basicType (E val) { if (_type == null) _type = val.getClass(); if (_type.equals(Boolean.class)) return true; else if (_type.equals(Byte.class)) return true; else if (_type.equals(Short.class)) return true; else if (_type.equals(Integer.class)) return true; else if (_type.equals(Long.class)) return true; else if (_type.equals(Float.class)) return true; else if (_type.equals(Double.class)) return true; else if (_type.equals(Character.class)) return true; else if (_type.equals(String.class)) return true; else return false; } private ArrayList<E> _array; private int _size; private Class<?> _type; private RecoverableContainer<E> _container; // used for non-basic types }