I've spent some time refining the notion of const and immutability for concurrency. Immutability is the term to mean something can't change making it thread safe. Const is a special case of immutability applying to types and slots. Lists and Maps are never const, but may be immutable.
I added Obj.isImmutable which determines if an Obj is immutable and safe to share between threads. Instances of const classes are automatically immutable. I also refactored List.toConst and Map.toConst into toImmutable, they too will return true for isImmutable. Everything else is assumed to be mutable.
The previous implementations of List.toConst and Map.toConst weren't really safe to use in runtime because they relied on the compiler to check the type declarations, and then optimized into a ro() accordingly. Now even if they are called at runtime, they guarantee the result is truly immutable. If any item isn't immutable, then NotImmutableErr will be thrown.
The other change I made was to have the compiler analyze methods to determine if they are thread safe. When the compiler determines that a method is thread safe, then it returns true for the Slot.isConst method:
static methods are always automatically const
instance methods are never const (I need to think about this one a bit more)
closures which don't capture any variables from their scope are automatically const
curried methods which only capture const variables from their scope are automatically const
This actually illustrates a big difference between closures and curried methods. Closures share variable storage, which means the variable can change what it references regardless if const or not. Curried methods on the other hand capture a specific reference when created - so if we can determine that all references captured are to const objects, we know that once created the curried method is effectively immutable. In this regard, curried methods will be a bit more flexible then closures for threading. It also leads to the desire to mark parameters and locals with the const keyword to achieve similiar results with closures (like Java did for inner classes) - but we can live without that feature for now.
How this applies to various APIs:
Map.set and Map.add now require key to be immutable
Thread.sendSync and sendAsync require immutable messages
brian Sat 3 Feb 2007
I've spent some time refining the notion of const and immutability for concurrency. Immutability is the term to mean something can't change making it thread safe. Const is a special case of immutability applying to types and slots. Lists and Maps are never const, but may be immutable.
I added Obj.isImmutable which determines if an Obj is immutable and safe to share between threads. Instances of const classes are automatically immutable. I also refactored List.toConst and Map.toConst into toImmutable, they too will return true for isImmutable. Everything else is assumed to be mutable.
The previous implementations of List.toConst and Map.toConst weren't really safe to use in runtime because they relied on the compiler to check the type declarations, and then optimized into a ro() accordingly. Now even if they are called at runtime, they guarantee the result is truly immutable. If any item isn't immutable, then NotImmutableErr will be thrown.
The other change I made was to have the compiler analyze methods to determine if they are thread safe. When the compiler determines that a method is thread safe, then it returns true for the Slot.isConst method:
This actually illustrates a big difference between closures and curried methods. Closures share variable storage, which means the variable can change what it references regardless if const or not. Curried methods on the other hand capture a specific reference when created - so if we can determine that all references captured are to const objects, we know that once created the curried method is effectively immutable. In this regard, curried methods will be a bit more flexible then closures for threading. It also leads to the desire to mark parameters and locals with the const keyword to achieve similiar results with closures (like Java did for inner classes) - but we can live without that feature for now.
How this applies to various APIs: