Created
January 11, 2013 17:09
-
-
Save anonymous/4512368 to your computer and use it in GitHub Desktop.
List serialization, supports long lists, requires thread-local variable - 2 Booleans.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// package ... | |
import java.io.{ObjectInputStream, FileInputStream, FileOutputStream, ObjectOutputStream} | |
object ListSer { | |
sealed abstract class List[+A] extends Serializable { | |
def isEmpty: Boolean | |
def head: A | |
def tail: List[A] | |
def ::[B >: A] (x: B): List[B] = new ::(x, this) | |
} | |
object List { | |
private val tlSerCtrl = new ThreadLocal[SerCtrl] | |
private[scala] class SerCtrl { | |
var seen: Boolean = false | |
var inLoop: Boolean = false | |
} | |
private[scala] def serCtrl = { | |
var instance = tlSerCtrl.get | |
if (instance == null) { | |
instance = new SerCtrl | |
tlSerCtrl.set(instance) | |
} | |
instance | |
} | |
// private val tlSerCtrl = new ThreadLocal[Array[Boolean]] | |
} | |
final case class ::[B](private var hd: B, private 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 writeObject(out: ObjectOutputStream) { | |
val serCtrl = List.serCtrl | |
val inLoop = serCtrl.inLoop | |
serCtrl.inLoop = false | |
out.writeObject(hd) | |
if (!inLoop) { | |
var current = tl | |
while (!current.isEmpty) { | |
serCtrl.seen = false | |
serCtrl.inLoop = true | |
out.writeObject(current) | |
if (!serCtrl.seen) | |
current = Nil | |
else | |
current = current.tail | |
} | |
serCtrl.inLoop = false | |
out.writeObject(ListSerializeEnd) | |
} | |
serCtrl.seen = true | |
} | |
private def readObject(in: ObjectInputStream) { | |
val serCtrl = List.serCtrl | |
val inLoop = serCtrl.inLoop | |
serCtrl.inLoop = false | |
hd = in.readObject.asInstanceOf[B] | |
assert(hd != ListSerializeEnd) | |
if (!inLoop) { | |
var parent: ::[B] = this | |
while (parent != null) { | |
serCtrl.seen = false | |
serCtrl.inLoop = true | |
in.readObject match { | |
case ListSerializeEnd => | |
parent.tl = Nil | |
parent = null | |
case current: ::[B] => | |
parent.tl = current | |
if (!serCtrl.seen) | |
parent = null | |
else | |
parent = current | |
} | |
} | |
serCtrl.inLoop = false | |
} | |
serCtrl.seen = true | |
} | |
} | |
case object Nil extends List[Nothing] { | |
override def isEmpty = true | |
override def head: Nothing = | |
throw new NoSuchElementException("head of empty list") | |
override def tail: List[Nothing] = | |
throw new UnsupportedOperationException("tail of empty list") | |
// Removal of equals method here might lead to an infinite recursion similar to IntMap.equals. | |
override def equals(that: Any) = that match { | |
case that1: collection.Seq[_] => that1.isEmpty | |
case _ => false | |
} | |
} | |
@SerialVersionUID(0L - 8476791151975527571L) | |
private case object ListSerializeEnd | |
def main(args: Array[String]) { | |
var r: List[Int] = Nil | |
var i = 0 | |
while (i < 1000000) { | |
r = i :: r | |
i += 1 | |
} | |
val largeList = r | |
// val largeList = r :: r | |
val oos = new ObjectOutputStream(new FileOutputStream("C:\\misc\\largeList.ser")) | |
oos.writeObject(largeList) | |
oos.flush() | |
oos.close() | |
val ois = new ObjectInputStream(new FileInputStream("C:\\misc\\largeList.ser")) | |
val read = ois.readObject().asInstanceOf[List[_]] | |
println(read.isEmpty) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment