Skip to content

Instantly share code, notes, and snippets.

Created January 11, 2013 17:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/4512368 to your computer and use it in GitHub Desktop.
Save anonymous/4512368 to your computer and use it in GitHub Desktop.
List serialization, supports long lists, requires thread-local variable - 2 Booleans.
// 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