diff --git a/sources/Data/Collections/Tests/MockItem.uc b/sources/Data/Collections/Tests/MockItem.uc index bbcf4ed..7e4857c 100644 --- a/sources/Data/Collections/Tests/MockItem.uc +++ b/sources/Data/Collections/Tests/MockItem.uc @@ -37,7 +37,7 @@ public function bool IsEqual(Object other) return true; } -public function int GetHashCode() +protected function int CalculateHashCode() { return 0; } diff --git a/sources/Text/MutableText.uc b/sources/Text/MutableText.uc index a216a70..92b4bda 100644 --- a/sources/Text/MutableText.uc +++ b/sources/Text/MutableText.uc @@ -358,7 +358,7 @@ private final function FormattedBlock CreateFormattedBlock(bool isOpening) * * @return Hash code for the caller `MutableText`. */ -public function int GetHashCode() +protected function int CalculateHashCode() { return super(AcediaObject).GetHashCode(); } diff --git a/sources/Text/Text.uc b/sources/Text/Text.uc index 557a513..8296a97 100644 --- a/sources/Text/Text.uc +++ b/sources/Text/Text.uc @@ -418,7 +418,7 @@ protected final function ConvertCase(bool toLower) * * @return Hash, that depends on textual contents only. */ -public function int GetHashCode() +protected function int CalculateHashCode() { local int i; local int hash; diff --git a/sources/Types/AcediaActor.uc b/sources/Types/AcediaActor.uc index 82f26df..df43dec 100644 --- a/sources/Types/AcediaActor.uc +++ b/sources/Types/AcediaActor.uc @@ -52,9 +52,10 @@ var private bool _isAllocated; // called for this object. var private bool _staticConstructorWasCalled; -// We want to have a common `GetHashCode()` method for all Acedia's objects. -// Just randomizing one at the time of allocation seems like a great idea. -var private int _randomizedHashCode; +// We only want to compute hash code once and reuse generated value later, +// since it cannot changed without reallocation. +var private int _cachedHashCode; +var private bool _hashCodeWasCached; // This object will provide hashed `string` to `Text` map, necessary for // efficient and convenient conversion methods. @@ -111,11 +112,11 @@ public function _constructor() if (_isAllocated) return; _isAllocated = true; _lifeVersion += 1; - _randomizedHashCode = Rand(MaxInt); if (_ == none) { default._ = class'Global'.static.GetInstance(); _ = default._; } + _hashCodeWasCached = false; Constructor(); } @@ -261,19 +262,42 @@ public function bool IsEqual(Object other) } /** - * Returns hash of an object. + * Calculated hash of an object. Overload this method if you want to change + * how object's hash is computed. + * + * `GetHashCode()` method uses it to calculate had code once and then cache it. * * If you overload `IsEqual()` method to allow two different objects to - * be equal, you must implement `GetHashCode()` to return the same hash + * be equal, you must implement `CalculateHashCode()` to return the same hash * for them. * * By default it is just a random value, generated at the time of allocation. * - * @return Hash code for the caller actor. + * @return Hash code for the caller object. + */ +protected function int CalculateHashCode() +{ + return Rand(MaxInt); +} + +/** + * Returns hash of an object. + * + * Calculated hash only once, later using internally cached value. + * + * By default it is just a random value. + * See `CalculateHashCode()` if you wish to change how hash code is computed. + * + * @return Hash code for the caller object. */ -public function int GetHashCode() +public final function int GetHashCode() { - return _randomizedHashCode; + if (_hashCodeWasCached) { + return _cachedHashCode; + } + _hashCodeWasCached = true; + _cachedHashCode = CalculateHashCode(); + return _cachedHashCode; } /** diff --git a/sources/Types/AcediaObject.uc b/sources/Types/AcediaObject.uc index 6a11470..0c8567d 100644 --- a/sources/Types/AcediaObject.uc +++ b/sources/Types/AcediaObject.uc @@ -53,9 +53,10 @@ var private bool _isAllocated; // called for this object. var private bool _staticConstructorWasCalled; -// We want to have a common `GetHashCode()` method for all Acedia's objects. -// Just randomizing one at the time of allocation seems like a great idea. -var private int _randomizedHashCode; +// We only want to compute hash code once and reuse generated value later, +// since it cannot changed without reallocation. +var private int _cachedHashCode; +var private bool _hashCodeWasCached; // This object will provide hashed `string` to `Text` map, necessary for // efficient and convenient conversion methods. @@ -112,7 +113,6 @@ public final function _constructor() if (_isAllocated) return; _isAllocated = true; _lifeVersion += 1; - _randomizedHashCode = Rand(MaxInt); if (_ == none) { default._ = class'Global'.static.GetInstance(); _ = default._; @@ -121,6 +121,7 @@ public final function _constructor() StaticConstructor(); default._staticConstructorWasCalled = true; } + _hashCodeWasCached = false; Constructor(); } @@ -266,19 +267,42 @@ public function bool IsEqual(Object other) } /** - * Returns hash of an object. + * Calculated hash of an object. Overload this method if you want to change + * how object's hash is computed. + * + * `GetHashCode()` method uses it to calculate had code once and then cache it. * * If you overload `IsEqual()` method to allow two different objects to - * be equal, you must implement `GetHashCode()` to return the same hash + * be equal, you must implement `CalculateHashCode()` to return the same hash * for them. * * By default it is just a random value, generated at the time of allocation. * * @return Hash code for the caller object. */ -public function int GetHashCode() +protected function int CalculateHashCode() { - return _randomizedHashCode; + return Rand(MaxInt); +} + +/** + * Returns hash of an object. + * + * Calculated hash only once, later using internally cached value. + * + * By default it is just a random value. + * See `CalculateHashCode()` if you wish to change how hash code is computed. + * + * @return Hash code for the caller object. + */ +public final function int GetHashCode() +{ + if (_hashCodeWasCached) { + return _cachedHashCode; + } + _hashCodeWasCached = true; + _cachedHashCode = CalculateHashCode(); + return _cachedHashCode; } /** diff --git a/sources/Types/Boxes/Native/BoolArrayBox.uc b/sources/Types/Boxes/Native/BoolArrayBox.uc index bfd0eb9..b3800f5 100644 Binary files a/sources/Types/Boxes/Native/BoolArrayBox.uc and b/sources/Types/Boxes/Native/BoolArrayBox.uc differ diff --git a/sources/Types/Boxes/Native/BoolBox.uc b/sources/Types/Boxes/Native/BoolBox.uc index 4c082e3..a2fe692 100644 Binary files a/sources/Types/Boxes/Native/BoolBox.uc and b/sources/Types/Boxes/Native/BoolBox.uc differ diff --git a/sources/Types/Boxes/Native/ByteArrayBox.uc b/sources/Types/Boxes/Native/ByteArrayBox.uc index 9bc8035..7b9ebcb 100644 Binary files a/sources/Types/Boxes/Native/ByteArrayBox.uc and b/sources/Types/Boxes/Native/ByteArrayBox.uc differ diff --git a/sources/Types/Boxes/Native/ByteBox.uc b/sources/Types/Boxes/Native/ByteBox.uc index f98f5d8..59e06dc 100644 Binary files a/sources/Types/Boxes/Native/ByteBox.uc and b/sources/Types/Boxes/Native/ByteBox.uc differ diff --git a/sources/Types/Boxes/Native/FloatArrayBox.uc b/sources/Types/Boxes/Native/FloatArrayBox.uc index ff9e694..d6d4342 100644 Binary files a/sources/Types/Boxes/Native/FloatArrayBox.uc and b/sources/Types/Boxes/Native/FloatArrayBox.uc differ diff --git a/sources/Types/Boxes/Native/FloatBox.uc b/sources/Types/Boxes/Native/FloatBox.uc index c81fcbc..7bcc75a 100644 Binary files a/sources/Types/Boxes/Native/FloatBox.uc and b/sources/Types/Boxes/Native/FloatBox.uc differ diff --git a/sources/Types/Boxes/Native/IntArrayBox.uc b/sources/Types/Boxes/Native/IntArrayBox.uc index da790d1..333b721 100644 Binary files a/sources/Types/Boxes/Native/IntArrayBox.uc and b/sources/Types/Boxes/Native/IntArrayBox.uc differ diff --git a/sources/Types/Boxes/Native/IntBox.uc b/sources/Types/Boxes/Native/IntBox.uc index 53dc7af..a11a718 100644 Binary files a/sources/Types/Boxes/Native/IntBox.uc and b/sources/Types/Boxes/Native/IntBox.uc differ diff --git a/sources/Types/Boxes/Native/StringArrayBox.uc b/sources/Types/Boxes/Native/StringArrayBox.uc index ba5a9e1..c1b1b92 100644 Binary files a/sources/Types/Boxes/Native/StringArrayBox.uc and b/sources/Types/Boxes/Native/StringArrayBox.uc differ diff --git a/sources/Types/Boxes/Native/StringBox.uc b/sources/Types/Boxes/Native/StringBox.uc index 5f1cb05..2fc8f62 100644 Binary files a/sources/Types/Boxes/Native/StringBox.uc and b/sources/Types/Boxes/Native/StringBox.uc differ