Aladdin - Scala Bugtracking
[#992] project: compiler priority: low category: bug
submitter assigned to status date submitted
Nikolay Sean fixed 2007-03-12 09:19:51.0
subject [contrib #368] Symbol interning isn't thread-safe
code
import scala.actors._

object T5 extends Application {
  import Actor._

  class Interner extends Actor {
    def act() : Unit = react {
      case s : String => 
	Leader ! Symbol(s).intern
        act()
    }
  }

  val interner1 = new Interner 
  val interner2 = new Interner

  object Leader extends Actor {
    def listen(i : int) : All = {
      val s = i.toString
      Console.println(s)
      interner1 ! s
      interner2 ! s
      val s1 = ?.asInstanceOf[Symbol]
      val s2 = ?.asInstanceOf[Symbol]
      if (!(s1 eq s2)) {
	Console.println("Interned symbols differ!")
	exit(())
      }
      listen(i + 1)
    }
    def act() : Unit = listen(0)
  }

  Leader.link(interner1)
  Leader.link(interner2)
  interner1.start()
  interner2.start()
  Leader.start()
}
what happened
Sample output:

.
.
.
930
931
932
Interned symbols differ!
what expected

Should run indefinitely (or at least until out of memory). The problem of course is that there is no synchronization in Symbol.intern.

The Symbol interface is also problematic in that it still allows the existence of uninterned symbols. This breaks the central property of symbols, which is that s1.toString == s2.toString implies s1 eq s2. I strongly think that the raw constructor to Symbol should be made private (or at least deprecated), and the basic way to create symbols should be Symbol("foo") which would always give an interned symbol.

[back to overview]
Changes of this bug report
Nikolay  edited on  2007-03-12 09:24:02.0
contribution #367. I assigned to Sean because IIRC at the last Scala meeting he said he fixed the interning of Symbol. However, the last commit to Symbol.scala was on Jan 31. Hopefully, Sean already has the solution up his sleeve.
Sean  edited on  2007-07-17 18:01:00.0
patch consumed.