I've written a Monte Carlo player for the board game Nine Men's Morris. Everything is basically immutable. The program involves lots of futures (hundreds) and a lot of modifying immutable Maps. Sometimes I get a crash with the following exception:
java.lang.NullPointerException
at scala.collection.mutable.HashTable$class.elemHashCode(HashTable.scala:154)
at scala.collection.immutable.HashMap.elemHashCode(HashMap.scala:41)
at scala.collection.mutable.HashTable$class.findEntry(HashTable.scala:66)
at scala.collection.immutable.HashMap.findEntry(HashMap.scala:41)
at scala.collection.immutable.HashMap.undo$1(HashMap.scala:132)
at scala.collection.immutable.HashMap.undo$1(HashMap.scala:130)
at scala.collection.immutable.HashMap.makeCopy(HashMap.scala:154)
at scala.collection.immutable.HashMap.makeCopyIfUpdated(HashMap.scala:161)
at scala.collection.immutable.HashMap.update(HashMap.scala:66)
at scala.collection.immutable.Map$class.$plus(Map.scala:66)
at scala.collection.immutable.HashMap.$plus(HashMap.scala:41)
at morris.players.MapBasedMorrisBoard.applyMove(MapBasedMorrisBoard.scala:30)
at morris.players.MonteCarloPlayer$$anonfun$main$1$$anonfun$apply$1.apply(MonteCarloPlayer.scala:77)
at morris.players.MonteCarloPlayer$$anonfun$main$1$$anonfun$apply$1.apply(MonteCarloPlayer.scala:77)
at scala.actors.Futures$$anonfun$2$$anonfun$apply$1.apply(Future.scala:45)
at scala.actors.Futures$$anonfun$2$$anonfun$apply$1.apply(Future.scala:44)
at scala.actors.Reaction.run(Reaction.scala:78)
at scala.actors.FJTask$Wrap.run(Unknown Source)
at scala.actors.FJTaskRunner.scanWhileIdling(Unknown Source)
at scala.actors.FJTaskRunner.run(Unknown Source)
I'm only using immutable Maps, so I wonder whether this is caused by a bug in my own code or maybe a bug in the scala library. When looking at the trace you can see, that there are calls to mutable HashTable further down the stack. Maybe this is causing problems with concurrency?
The code inside my program, where the exception occurs is just adding another collection to an immutable Map:
myMap ++ (someInteger -> aValue)
Edit: The same program without concurrency runs flawlessly.
I've filed a bug report for the Scala-library. As it turns out this is a known problem. The implementation of HashMap (which is used for as the standard Map type in Scala) is not suited to be used in concurrent programs since behind the scenes, it uses mutable types. This can also be observed in the stack-trace. The Scala people are hoping to replace the implementation in 2.8.
As a work-around it is suggested to use TreeHashMap, which is truly immutable. I've done this and can confirm that it works.
Link to original bug report
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With