summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2013-12-13 12:24:57 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-12-13 12:24:57 -0800
commit5aeb4123a3ef3ba009e3a44c22d79f622425fea7 (patch)
tree7a260e6a76d8e8f9addbfef97e763440c0dc32c6 /src
parent247939f857ce8f8fe5785cab549ee5f11df74f57 (diff)
parenta5fc6e69e0c26ca8537e01d17109e1037600af76 (diff)
downloadscala-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')
-rw-r--r--src/library/scala/collection/immutable/List.scala58
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