Description
The PrettyPrinter, according to the docs:
Class for pretty printing. After instantiating, you can use the format() and formatNode() methods to convert XML to a formatted string. The class can be reused to pretty print any number of XML nodes.
The last sentence about being able to print any number of xml nodes I took to mean that the class operates in a pure manner and I could use this a concurrent environment. That was probably a bad assumption on my part. But here's a test case to reproduce the problem:
import scala.concurrent._
import scala.xml._
import java.util.concurrent.CountDownLatch
import scala.concurrent.ExecutionContext.Implicits.global
val p = new PrettyPrinter(width = Int.MaxValue, step = 2)
def xmlNode() = <A><B><C>Hello</C><D>There</D></B></A>
val latch = new CountDownLatch(1)
val futurePretty = (0 to 10).map { _ =>
Future {
val x = xmlNode()
latch.await()
p.format(x)
}
}
latch.countDown()
val l = Future.sequence(futurePretty)
l.value.map(println)
On a run on my machine I see the result of that last console command as:
scala> l.value.map(println)
Success(Vector(<A>
<B>
<B>
<C>Hello</C>
<C>Hello</C>
<C>Hello</C>
<D>There</D>
</B>
<D>There</D>
</B></B>
<D>There</D>
</A>, <A>
<B>
<B>
<C>Hello</C>
<C>Hello</C>
... snipped for brevity...
Which clearly indicates to me that the pretty printer is using some buffer internal to the instance and therefore calling .format
from different threads causes this buffer to be filled with values from each calling thread. This jumbles things up a bit.
If it's unlikely that this issue will be fixed at any point, could we please update the documentation to leave an explicit note that the class is not thread safe and should not be used like that?