Remove mutex and simplify dimension handling

Lookups are now done via a slice where possible.
This commit is contained in:
kortschak
2013-10-10 12:19:41 +10:30
parent d3da6ef3ad
commit 7601daed10

View File

@@ -3,7 +3,6 @@ package unit
import ( import (
"sort" "sort"
"strconv" "strconv"
"sync"
) )
// Uniter is an interface representing a type that can be converted // Uniter is an interface representing a type that can be converted
@@ -36,84 +35,86 @@ const (
TemperatureDim TemperatureDim
TimeDim TimeDim
// Other common SI Dimensions // Other common SI Dimensions
AngleDim // e.g. radians AngleDim // e.g. radians
lastPackageDimension // Used in create dimension
) )
var lastCreatedDimension Dimension = lastPackageDimension var (
var dimensionToSymbol map[Dimension]string = map[Dimension]string{ symbols = []string{
CurrentDim: "A", CurrentDim: "A",
LengthDim: "m", LengthDim: "m",
LuminousIntensityDim: "cd", LuminousIntensityDim: "cd",
MassDim: "kg", MassDim: "kg",
TemperatureDim: "K", TemperatureDim: "K",
TimeDim: "s", TimeDim: "s",
AngleDim: "rad", AngleDim: "rad",
} }
var symbolToDimension map[string]Dimension = map[string]Dimension{
"A": CurrentDim,
"m": LengthDim,
"cd": LuminousIntensityDim,
"kg": MassDim,
"K": TemperatureDim,
"s": TimeDim,
"rad": AngleDim,
// Reserve common SI symbols // for guaranteeing there aren't two identical symbols
// base units dimensions = map[string]Dimension{
"mol": reserved, "A": CurrentDim,
// prefixes "m": LengthDim,
"Y": reserved, "cd": LuminousIntensityDim,
"Z": reserved, "kg": MassDim,
"E": reserved, "K": TemperatureDim,
"P": reserved, "s": TimeDim,
"T": reserved, "rad": AngleDim,
"G": reserved,
"M": reserved, // Reserve common SI symbols
"k": reserved, // base units
"h": reserved, "mol": reserved,
"da": reserved, // prefixes
"d": reserved, "Y": reserved,
"c": reserved, "Z": reserved,
"μ": reserved, "E": reserved,
"n": reserved, "P": reserved,
"p": reserved, "T": reserved,
"f": reserved, "G": reserved,
"a": reserved, "M": reserved,
"z": reserved, "k": reserved,
"y": reserved, "h": reserved,
// SI Derived units with special symbols "da": reserved,
"sr": reserved, "d": reserved,
"F": reserved, "c": reserved,
"C": reserved, "μ": reserved,
"S": reserved, "n": reserved,
"H": reserved, "p": reserved,
"V": reserved, "f": reserved,
"Ω": reserved, "a": reserved,
"J": reserved, "z": reserved,
"N": reserved, "y": reserved,
"Hz": reserved, // SI Derived units with special symbols
"lx": reserved, "sr": reserved,
"lm": reserved, "F": reserved,
"Wb": reserved, "C": reserved,
"W": reserved, "S": reserved,
"Pa": reserved, "H": reserved,
"Bq": reserved, "V": reserved,
"Gy": reserved, "Ω": reserved,
"Sv": reserved, "J": reserved,
"kat": reserved, "N": reserved,
// Units in use with SI "Hz": reserved,
"ha": reserved, "lx": reserved,
"L": reserved, "lm": reserved,
"l": reserved, "Wb": reserved,
// Units in Use Temporarily with SI "W": reserved,
"bar": reserved, "Pa": reserved,
"b": reserved, "Bq": reserved,
"Ci": reserved, "Gy": reserved,
"R": reserved, "Sv": reserved,
"rd": reserved, "kat": reserved,
"rem": reserved, // Units in use with SI
} // for guaranteeing there aren't two identical symbols "ha": reserved,
"L": reserved,
"l": reserved,
// Units in Use Temporarily with SI
"bar": reserved,
"b": reserved,
"Ci": reserved,
"R": reserved,
"rd": reserved,
"rem": reserved,
}
)
// TODO: Should we actually reserve "common" SI unit symbols ("N", "J", etc.) so there isn't confusion // TODO: Should we actually reserve "common" SI unit symbols ("N", "J", etc.) so there isn't confusion
// TODO: If we have a fancier ParseUnit, maybe the 'reserved' symbols should be a different map // TODO: If we have a fancier ParseUnit, maybe the 'reserved' symbols should be a different map
@@ -124,8 +125,6 @@ var symbolToDimension map[string]Dimension = map[string]Dimension{
// dimension is zero. Dimensions is used in conjuction with NewUnit // dimension is zero. Dimensions is used in conjuction with NewUnit
type Dimensions map[Dimension]int type Dimensions map[Dimension]int
var newUnitMutex *sync.Mutex = &sync.Mutex{} // so there is no race condition for dimension
// NewDimension returns a new dimension variable which will have a // NewDimension returns a new dimension variable which will have a
// unique representation across packages to prevent accidental overlap. // unique representation across packages to prevent accidental overlap.
// The input string represents a symbol name which will be used for printing // The input string represents a symbol name which will be used for printing
@@ -138,18 +137,16 @@ var newUnitMutex *sync.Mutex = &sync.Mutex{} // so there is no race condition fo
// if the symbol matching an existing symbol // if the symbol matching an existing symbol
// NewDimension should only be called for unit types that are actually orthogonal // NewDimension should only be called for unit types that are actually orthogonal
// to the base dimensions defined in this package. Please see the package-level // to the base dimensions defined in this package. Please see the package-level
// documentation for further explanation // documentation for further explanation. Calls to NewDimension are not thread safe.
func NewDimension(symbol string) Dimension { func NewDimension(symbol string) Dimension {
newUnitMutex.Lock() _, ok := dimensions[symbol]
defer newUnitMutex.Unlock()
lastCreatedDimension++
_, ok := symbolToDimension[symbol]
if ok { if ok {
panic("unit: dimension string " + symbol + " already used") panic("unit: dimension string " + symbol + " already used")
} }
dimensionToSymbol[lastCreatedDimension] = symbol symbols = append(symbols, symbol)
symbolToDimension[symbol] = lastCreatedDimension d := Dimension(len(symbols))
return lastCreatedDimension dimensions[symbol] = d
return d
} }
// Unit is a type a value with generic SI units. Most useful for // Unit is a type a value with generic SI units. Most useful for
@@ -272,7 +269,7 @@ func (u *Unit) String() string {
data := make(unitPrinters, 0, 10) data := make(unitPrinters, 0, 10)
for dimension, power := range u.dimensions { for dimension, power := range u.dimensions {
if power != 0 { if power != 0 {
data = append(data, symbolString{dimensionToSymbol[dimension], power}) data = append(data, symbolString{symbols[dimension], power})
} }
} }
sort.Sort(data) sort.Sort(data)