diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-12-13 12:24:57 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-12-13 12:24:57 -0800 |
commit | 5aeb4123a3ef3ba009e3a44c22d79f622425fea7 (patch) | |
tree | 7a260e6a76d8e8f9addbfef97e763440c0dc32c6 /src/library | |
parent | 247939f857ce8f8fe5785cab549ee5f11df74f57 (diff) | |
parent | a5fc6e69e0c26ca8537e01d17109e1037600af76 (diff) | |
download | scala-5aeb4123a3ef3ba009e3a44c22d79f622425fea7.tar.gz scala-5aeb4123a3ef3ba009e3a44c22d79f622425fea7.tar.bz2 scala-5aeb4123a3ef3ba009e3a44c22d79f622425fea7.zip |
Merge pull request #3233 from scottcarey/SI-8042
Use Serialization Proxy Pattern in List
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/collection/immutable/List.scala | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 57618d64a5..90aabc5a9a 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -322,6 +322,39 @@ sealed abstract class List[+A] extends AbstractSeq[A] override def toStream : Stream[A] = if (isEmpty) Stream.Empty else new Stream.Cons(head, tail.toStream) + + // Create a proxy for Java serialization that allows us to avoid mutation + // during de-serialization. This is the Serialization Proxy Pattern. + protected final def writeReplace(): AnyRef = new SerializationProxy(this) +} + +@SerialVersionUID(1L) +private class SerializationProxy[B](@transient private var orig: List[B]) extends Serializable { + + private def writeObject(out: ObjectOutputStream) { + var xs: List[B] = orig + while (!xs.isEmpty) { + out.writeObject(xs.head) + xs = xs.tail + } + out.writeObject(ListSerializeEnd) + } + + // Java serialization calls this before readResolve during de-serialization. + // Read the whole list and store it in `orig`. + private def readObject(in: ObjectInputStream) { + val builder = List.newBuilder[B] + while (true) in.readObject match { + case ListSerializeEnd => + orig = builder.result() + return + case a => + builder += a.asInstanceOf[B] + } + } + + // Provide the result stored in `orig` for Java serialization + private def readResolve(): AnyRef = orig } /** The empty list. @@ -352,33 +385,10 @@ case object Nil extends List[Nothing] { * @version 1.0, 15/07/2003 * @since 2.8 */ -@SerialVersionUID(0L - 8476791151983527571L) -final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B] { +final case class ::[B](private val hd: B, private[scala] var tl: List[B]) extends List[B] { override def head : B = hd override def tail : List[B] = tl override def isEmpty: Boolean = false - - private def readObject(in: ObjectInputStream) { - val firstObject = in.readObject() - hd = firstObject.asInstanceOf[B] - assert(hd != ListSerializeEnd) - var current: ::[B] = this - while (true) in.readObject match { - case ListSerializeEnd => - current.tl = Nil - return - case a => - val list : ::[B] = new ::(a.asInstanceOf[B], Nil) - current.tl = list - current = list - } - } - - private def writeObject(out: ObjectOutputStream) { - var xs: List[B] = this - while (!xs.isEmpty) { out.writeObject(xs.head); xs = xs.tail } - out.writeObject(ListSerializeEnd) - } } /** $factoryInfo |