diff options
author | Raul Santos <raulsntos@gmail.com> | 2021-07-28 16:55:29 +0200 |
---|---|---|
committer | Raul Santos <raulsntos@gmail.com> | 2021-08-05 17:30:28 +0200 |
commit | 2deefd938fbbaf6c8472031de8b631ab505b3cfc (patch) | |
tree | 2be8e46ed440048aeb0d6bca8a028a13062c5180 /modules | |
parent | 0669ffcd157dffb3e284457e968e617431badfd7 (diff) |
Reduce C# Dictionary internal calls
- Implements new `KeyValuePairs` and `KeyValuePairAt` internal calls
to get the `key` and the `value` in one call.
- Caches the `DictionaryEntry` to reuse properties without repeating
internal calls.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs | 75 | ||||
-rw-r--r-- | modules/mono/glue/collections_glue.cpp | 15 |
2 files changed, 64 insertions, 26 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs index 3d98445b14..61a34bfc87 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs @@ -131,6 +131,14 @@ namespace Godot.Collections } } + private (Array keys, Array values, int count) GetKeyValuePairs() + { + int count = godot_icall_Dictionary_KeyValuePairs(GetPtr(), out IntPtr keysHandle, out IntPtr valuesHandle); + Array keys = new Array(new ArraySafeHandle(keysHandle)); + Array values = new Array(new ArraySafeHandle(valuesHandle)); + return (keys, values, count); + } + bool IDictionary.IsFixedSize => false; bool IDictionary.IsReadOnly => false; @@ -198,17 +206,13 @@ namespace Godot.Collections /// <param name="index">The index to start at.</param> public void CopyTo(System.Array array, int index) { - // TODO Can be done with single internal call - if (array == null) throw new ArgumentNullException(nameof(array), "Value cannot be null."); if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension."); - Array keys = (Array)Keys; - Array values = (Array)Values; - int count = Count; + var (keys, values, count) = GetKeyValuePairs(); if (array.Length < (index + count)) throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); @@ -226,24 +230,39 @@ namespace Godot.Collections private class DictionaryEnumerator : IDictionaryEnumerator { - private readonly Array keys; - private readonly Array values; + private readonly Dictionary dictionary; private readonly int count; private int index = -1; + private bool dirty = true; + + private DictionaryEntry entry; public DictionaryEnumerator(Dictionary dictionary) { - // TODO 3 internal calls, can reduce to 1 - keys = (Array)dictionary.Keys; - values = (Array)dictionary.Values; + this.dictionary = dictionary; count = dictionary.Count; } public object Current => Entry; - public DictionaryEntry Entry => - // TODO 2 internal calls, can reduce to 1 - new DictionaryEntry(keys[index], values[index]); + public DictionaryEntry Entry + { + get + { + if (dirty) + { + UpdateEntry(); + } + return entry; + } + } + + private void UpdateEntry() + { + dirty = false; + godot_icall_Dictionary_KeyValuePairAt(dictionary.GetPtr(), index, out object key, out object value); + entry = new DictionaryEntry(key, value); + } public object Key => Entry.Key; @@ -252,12 +271,14 @@ namespace Godot.Collections public bool MoveNext() { index++; + dirty = true; return index < count; } public void Reset() { index = -1; + dirty = true; } } @@ -295,6 +316,12 @@ namespace Godot.Collections internal extern static int godot_icall_Dictionary_Count(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_Dictionary_KeyValuePairs(IntPtr ptr, out IntPtr keys, out IntPtr values); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value); + + [MethodImpl(MethodImplOptions.InternalCall)] internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value); [MethodImpl(MethodImplOptions.InternalCall)] @@ -459,6 +486,12 @@ namespace Godot.Collections } } + private KeyValuePair<TKey, TValue> GetKeyValuePair(int index) + { + Dictionary.godot_icall_Dictionary_KeyValuePairAt(GetPtr(), index, out object key, out object value); + return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value); + } + /// <summary> /// Adds an object <paramref name="value"/> at key <paramref name="key"/> /// to this <see cref="Dictionary{TKey, TValue}"/>. @@ -548,9 +581,6 @@ namespace Godot.Collections if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension."); - // TODO 3 internal calls, can reduce to 1 - Array<TKey> keys = (Array<TKey>)Keys; - Array<TValue> values = (Array<TValue>)Values; int count = Count; if (array.Length < (arrayIndex + count)) @@ -558,8 +588,7 @@ namespace Godot.Collections for (int i = 0; i < count; i++) { - // TODO 2 internal calls, can reduce to 1 - array[arrayIndex] = new KeyValuePair<TKey, TValue>(keys[i], values[i]); + array[arrayIndex] = GetKeyValuePair(i); arrayIndex++; } } @@ -578,15 +607,9 @@ namespace Godot.Collections /// <returns>An enumerator.</returns> public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { - // TODO 3 internal calls, can reduce to 1 - Array<TKey> keys = (Array<TKey>)Keys; - Array<TValue> values = (Array<TValue>)Values; - int count = Count; - - for (int i = 0; i < count; i++) + for (int i = 0; i < Count; i++) { - // TODO 2 internal calls, can reduce to 1 - yield return new KeyValuePair<TKey, TValue>(keys[i], values[i]); + yield return GetKeyValuePair(i); } } diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp index 191f863350..86976de244 100644 --- a/modules/mono/glue/collections_glue.cpp +++ b/modules/mono/glue/collections_glue.cpp @@ -230,6 +230,19 @@ int32_t godot_icall_Dictionary_Count(Dictionary *ptr) { return ptr->size(); } +int32_t godot_icall_Dictionary_KeyValuePairs(Dictionary *ptr, Array **keys, Array **values) { + *keys = godot_icall_Dictionary_Keys(ptr); + *values = godot_icall_Dictionary_Values(ptr); + return godot_icall_Dictionary_Count(ptr); +} + +void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, MonoObject **key, MonoObject **value) { + Array *keys = godot_icall_Dictionary_Keys(ptr); + Array *values = godot_icall_Dictionary_Values(ptr); + *key = GDMonoMarshal::variant_to_mono_object(keys->get(index)); + *value = GDMonoMarshal::variant_to_mono_object(values->get(index)); +} + void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) { Variant varKey = GDMonoMarshal::mono_object_to_variant(key); Variant *ret = ptr->getptr(varKey); @@ -338,6 +351,8 @@ void godot_register_collections_icalls() { GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", godot_icall_Dictionary_Keys); GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", godot_icall_Dictionary_Values); GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", godot_icall_Dictionary_Count); + GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairs", godot_icall_Dictionary_KeyValuePairs); + GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt", godot_icall_Dictionary_KeyValuePairAt); GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", godot_icall_Dictionary_Add); GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", godot_icall_Dictionary_Clear); GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", godot_icall_Dictionary_Contains); |