SkFlattenable::Register now performs a sorted insert

In order to maintain the sorted quality of `Entry gEntries`, I updated SkFlattenable::Register to perform a sorted insert with the new element. To avoid possible threading issues, I added an SkSharedMutex.

Change-Id: I14a9001ef2822211bbcbe994b73b4671ae17844d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1252956
Reviewed-by: Kaylee Lubick <kjlubick@google.com>
Commit-Queue: Alexis Cruz-Ayala <alexisdavidc@google.com>
diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h
index 892a593..eaa790d 100644
--- a/include/core/SkFlattenable.h
+++ b/include/core/SkFlattenable.h
@@ -86,7 +86,6 @@
 
 private:
     static void RegisterFlattenablesIfNeeded();
-    static void Finalize();
 
     friend class SkGraphics;
 
diff --git a/src/core/SkFlattenable.cpp b/src/core/SkFlattenable.cpp
index e10f54e..62642aa 100644
--- a/src/core/SkFlattenable.cpp
+++ b/src/core/SkFlattenable.cpp
@@ -11,6 +11,7 @@
 #include "include/core/SkSerialProcs.h"
 #include "include/core/SkTypes.h"
 #include "include/private/base/SkTDArray.h"
+#include "src/base/SkSharedMutex.h"
 #include "src/core/SkPtrRecorder.h"
 #include "src/core/SkReadBuffer.h"
 #include "src/core/SkWriteBuffer.h"
@@ -80,25 +81,57 @@
 };
 
 int gCount = 0;
-Entry gEntries[128];
+Entry gEntries[128] = {};
+SkSharedMutex gEntriesMutex;
 
 }  // namespace
 
-void SkFlattenable::Finalize() {
-    std::sort(gEntries, gEntries + gCount, EntryComparator());
-}
-
 void SkFlattenable::Register(const char name[], Factory factory) {
+    SkAutoSharedMutexExclusive lock(gEntriesMutex);
     SkASSERT(name);
     SkASSERT(factory);
     SkASSERT(gCount < (int)std::size(gEntries));
 
+    /**
+     * We add the new Entry to gEntries using a sorted insertion
+     *
+     * We first find the position at which we must insert the new Entry (insertion_element =
+     * std::upper_bound). Then we add our new Entry to gEntries[gCount]
+     *
+     * Then we call std::rotate(first, middle, last) to place our new Entry at the beginning of
+     * insertion_element
+     * - first will be the beginning of the elements we want to shift
+     * - middle will be the new Entry we want to insert, the things before it will get shifted
+     * - last will be the element after the one we are inserting
+     *
+     * As an example, let's insert name = 'dragonfruit' into
+     * gEntries = ['apple', 'blueberry', 'coconut', 'elderberry', 'fig'] with
+     * gCount = 5
+     *
+     * After upper_bound, insertion_element points to 'elderberry' (the first element that comes
+     * after 'dragonfruit')
+     *
+     * After gEntries[gCount] = name, gEntries + gCount points to 'dragonfruit'
+     *
+     * now we have gEntries = ['apple', 'blueberry', 'coconut', 'elderberry', 'fig', 'dragonfruit']
+     *
+     * so std::rotate('elderberry', 'dragonfruit', 'dragonfruit'+1); will result in
+     * gEntries = ['apple', 'blueberry', 'coconut', 'dragonfruit', 'elderberry', 'fig']
+     *
+     * This will effectively move the new Entry to the insertion_element position, while maintaining
+     * the order of the other elements
+     */
+    Entry* insertion_element =
+            std::upper_bound(gEntries, gEntries + gCount, name, EntryComparator());
     gEntries[gCount].fName = name;
     gEntries[gCount].fFactory = factory;
+
+    std::rotate(insertion_element, gEntries + gCount, gEntries + gCount + 1);
     gCount += 1;
 }
 
 SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
+    SkAutoSharedMutexShared lock(gEntriesMutex);
     RegisterFlattenablesIfNeeded();
 
     SkASSERT(std::is_sorted(gEntries, gEntries + gCount, EntryComparator()));
@@ -110,6 +143,7 @@
 }
 
 const char* SkFlattenable::FactoryToName(Factory fact) {
+    SkAutoSharedMutexShared lock(gEntriesMutex);
     RegisterFlattenablesIfNeeded();
 
     const Entry* entries = gEntries;
diff --git a/src/core/SkGlobalInitialization_core.cpp b/src/core/SkGlobalInitialization_core.cpp
index c189a32..e580c21 100644
--- a/src/core/SkGlobalInitialization_core.cpp
+++ b/src/core/SkGlobalInitialization_core.cpp
@@ -13,6 +13,5 @@
     once([]{
         SkFlattenable::PrivateInitializer::InitEffects();
         SkFlattenable::PrivateInitializer::InitImageFilters();
-        SkFlattenable::Finalize();
     });
 }