Repository: commons-rng Updated Branches: refs/heads/RNG-10__no_serializable [created] 7245cca9f
RNG-10 Simplified handling of RNG internal state. Removed marker interface and private implementation. The state is explicitly assumed to be conveyed in a byte array. Project: http://git-wip-us.apache.org/repos/asf/commons-rng/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-rng/commit/f6528f0a Tree: http://git-wip-us.apache.org/repos/asf/commons-rng/tree/f6528f0a Diff: http://git-wip-us.apache.org/repos/asf/commons-rng/diff/f6528f0a Branch: refs/heads/RNG-10__no_serializable Commit: f6528f0a9b584c959a63fde8e2035f34fc5ab236 Parents: 94e3702 Author: Gilles <er...@apache.org> Authored: Sat Aug 20 00:48:27 2016 +0200 Committer: Gilles <er...@apache.org> Committed: Sat Aug 20 02:25:43 2016 +0200 ---------------------------------------------------------------------- .../org/apache/commons/rng/RandomSource.java | 50 +++++++++++---- .../commons/rng/internal/BaseProvider.java | 66 ++++++-------------- .../commons/rng/internal/StateSettable.java | 47 -------------- .../rng/ProvidersCommonParametricTest.java | 12 +--- 4 files changed, 60 insertions(+), 115 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-rng/blob/f6528f0a/src/main/java/org/apache/commons/rng/RandomSource.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/rng/RandomSource.java b/src/main/java/org/apache/commons/rng/RandomSource.java index 195c5ec..1254d10 100644 --- a/src/main/java/org/apache/commons/rng/RandomSource.java +++ b/src/main/java/org/apache/commons/rng/RandomSource.java @@ -16,6 +16,7 @@ */ package org.apache.commons.rng; +import java.util.Arrays; import org.apache.commons.rng.internal.ProviderBuilder; import org.apache.commons.rng.internal.BaseProvider; import org.apache.commons.rng.internal.util.SeedFactory; @@ -129,8 +130,8 @@ import org.apache.commons.rng.internal.source64.TwoCmres; * This factory thus provides a method for * {@link #saveState(UniformRandomProvider) saving} the internal * state of a generator. - * The state is encapsulated in an {@link State "opaque object"} to be - * used for {@link #restoreState(UniformRandomProvider,State) restoring} + * The state is encapsulated in an {@link SourceState "opaque object"} + * to be used for {@link #restoreState(UniformRandomProvider,SourceState) restoring} * a generator (of the same type) to an identical state (e.g. to allow * persistent storage, or to continue a sequence from where the original * instance left off). @@ -215,6 +216,39 @@ public enum RandomSource { private final ProviderBuilder.RandomSourceInternal internalIdentifier; /** + * Wraps the internal state of a {@link UniformRandomProvider}. + * Its purpose is to store all the data needed to recover the same + * state in order to restart a sequence where it left off. + * External code should not to modify the data contained in instances + * of this class. + */ + public static class State { + /** Internal state. */ + private final byte[] state; + + /** + * Initializes an instance. + * The contents of the {@code state} argument is unspecified, and is + * guaranteed to be valid only if it was generated by implementations + * provided by this library. + * + * @param state Mapping of all the data which an implementation of + * {@link UniformRandomProvider} needs in order to reset its internal + * state. + */ + public State(byte[] state) { + this.state = Arrays.copyOf(state, state.length); + } + + /** + * @return the internal state. + */ + public byte[] getState() { + return Arrays.copyOf(state, state.length); + } + } + + /** * @param id Internal identifier. */ RandomSource(ProviderBuilder.RandomSourceInternal id) { @@ -241,12 +275,6 @@ public enum RandomSource { } /** - * Marker interface used to define the "save" and "restore" - * functionality of the generators. - */ - public interface State {} - - /** * Creates a random number generator with a random seed. * * <p> @@ -340,13 +368,13 @@ public enum RandomSource { * not an object created by this factory or the underlying source of * randomness does not support this functionality. * - * @see #restoreState(UniformRandomProvider,RandomSource.State) + * @see #restoreState(UniformRandomProvider,State) */ public static State saveState(UniformRandomProvider provider) { if (!(provider instanceof BaseProvider)) { throw new UnsupportedOperationException(); } else { - return ((BaseProvider) provider).getState(); + return new State(((BaseProvider) provider).getState()); } } @@ -372,7 +400,7 @@ public enum RandomSource { if (!(provider instanceof BaseProvider)) { throw new UnsupportedOperationException(); } else { - ((BaseProvider) provider).setState(state); + ((BaseProvider) provider).setState(state.getState()); } } http://git-wip-us.apache.org/repos/asf/commons-rng/blob/f6528f0a/src/main/java/org/apache/commons/rng/internal/BaseProvider.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/rng/internal/BaseProvider.java b/src/main/java/org/apache/commons/rng/internal/BaseProvider.java index 5a31fdf..c9ed7b3 100644 --- a/src/main/java/org/apache/commons/rng/internal/BaseProvider.java +++ b/src/main/java/org/apache/commons/rng/internal/BaseProvider.java @@ -17,17 +17,13 @@ package org.apache.commons.rng.internal; -import java.util.Arrays; -import java.io.Serializable; import org.apache.commons.rng.UniformRandomProvider; -import org.apache.commons.rng.RandomSource; /** * Base class with default implementation for common methods. */ public abstract class BaseProvider - implements UniformRandomProvider, - StateSettable { + implements UniformRandomProvider { /** {@inheritDoc} */ @Override public int nextInt(int n) { @@ -67,18 +63,25 @@ public abstract class BaseProvider return getClass().getName(); } - /** {@inheritDoc} */ - @Override - public RandomSource.State getState() { - return new State(getStateInternal()); + /** + * Gets the instance's state. + * + * @return the current state. The given argument can then be passed + * to {@link #setState(byte[])} in order to recover the + * current state. + */ + public byte[] getState() { + return getStateInternal(); } - /** {@inheritDoc} */ - @Override - public void setState(RandomSource.State state) { - // Cast will intentionally fail if the argument is not one we created. - final State s = (State) state; - setStateInternal(s.getState()); + /** + * Sets the instance's state. + * + * @param state State. The given argument must have been retrieved + * by a call to {@link #getState()}. + */ + public void setState(byte[] state) { + setStateInternal(state); } /** @@ -150,37 +153,4 @@ public abstract class BaseProvider throw new IllegalArgumentException("Must be strictly positive: " + n); } } - - /** - * "Black-box" state. - * Its sole purpose is to store all the data needed to recover - * the same state in order to restart a sequence where it left - * off. - * External code should not to modify the data contained in - * instances of this class. - */ - private static class State - implements RandomSource.State, - Serializable { - /** Serializable version identifier. */ - private static final long serialVersionUID = 4720160226L; - /** Internal state. */ - private byte[] state; - - /** - * @param state Mapping of all the data which a subclass of - * {@link BaseProvider} needs in order to reset its internal - * state. - */ - State(byte[] state) { - this.state = Arrays.copyOf(state, state.length); - } - - /** - * @return the internal state. - */ - byte[] getState() { - return Arrays.copyOf(state, state.length); - } - } } http://git-wip-us.apache.org/repos/asf/commons-rng/blob/f6528f0a/src/main/java/org/apache/commons/rng/internal/StateSettable.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/rng/internal/StateSettable.java b/src/main/java/org/apache/commons/rng/internal/StateSettable.java deleted file mode 100644 index e2d4ae2..0000000 --- a/src/main/java/org/apache/commons/rng/internal/StateSettable.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.rng.internal; - -import org.apache.commons.rng.RandomSource; - -/** - * Indicates that the state of the instance can be saved and restored. - * - * @since 1.0 - */ -public interface StateSettable { - /** - * Sets the instance's state. - * - * @param state State. The given argument must have been retrieved - * by a call to {@link #getState()}. - * - * @throws UnsupportedOperationException if not implemented. - */ - void setState(RandomSource.State state); - - /** - * Gets the instance's state. - * - * @return the current state. The given argument can then be passed - * to {@link #setState(RandomSource.State)} in order to recover the - * current state. - * - * @throws UnsupportedOperationException if not implemented. - */ - RandomSource.State getState(); -} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/f6528f0a/src/test/java/org/apache/commons/rng/ProvidersCommonParametricTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/rng/ProvidersCommonParametricTest.java b/src/test/java/org/apache/commons/rng/ProvidersCommonParametricTest.java index b1aea81..6ea361a 100644 --- a/src/test/java/org/apache/commons/rng/ProvidersCommonParametricTest.java +++ b/src/test/java/org/apache/commons/rng/ProvidersCommonParametricTest.java @@ -292,7 +292,7 @@ public class ProvidersCommonParametricTest { } @Test - public void testSerializedState() + public void testSerializingState() throws IOException, ClassNotFoundException { // Large "n" is not necessary here as we only test the serialization. @@ -302,7 +302,7 @@ public class ProvidersCommonParametricTest { final RandomSource.State stateOrig = RandomSource.saveState(generator); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(stateOrig); + oos.writeObject(stateOrig.getState()); // Store some values. final List<Number> listOrig = makeList(n); @@ -315,7 +315,7 @@ public class ProvidersCommonParametricTest { // Retrieve from serialized stream. ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); - final RandomSource.State stateNew = (RandomSource.State) ois.readObject(); + final RandomSource.State stateNew = new RandomSource.State((byte[]) ois.readObject()); Assert.assertTrue(stateOrig != stateNew); @@ -330,12 +330,6 @@ public class ProvidersCommonParametricTest { Assert.assertTrue(listOrig.equals(listReplay)); } - @Test(expected=ClassCastException.class) - public void testStateWrongClass() { - // Try to restore with an invalid state. - RandomSource.restoreState(generator, new RandomSource.State() {}); - } - @Test(expected=IllegalArgumentException.class) public void testStateWrongSize() { // We don't know what is the state of "java.lang.Random": skipping.