Skip to content

Commit

Permalink
Merge pull request #142 from udlose/develop
Browse files Browse the repository at this point in the history
Add thread safety to fix race conditions around usage of static IDict…
  • Loading branch information
devlead committed Nov 19, 2023
2 parents 99ae103 + 9899787 commit ac3889c
Showing 1 changed file with 34 additions and 26 deletions.
60 changes: 34 additions & 26 deletions src/LitJson/JsonMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,13 @@ public class JsonMapper

private static readonly IDictionary<Type, ExporterFunc> base_exporters_table;
private static readonly IDictionary<Type, ExporterFunc> custom_exporters_table;
private static readonly object custom_exporters_table_lock = new Object();

private static readonly IDictionary<Type,
IDictionary<Type, ImporterFunc>> base_importers_table;
private static readonly IDictionary<Type,
IDictionary<Type, ImporterFunc>> custom_importers_table;
private static readonly object custom_importers_table_lock = new Object();

private static readonly IDictionary<Type, ArrayMetadata> array_metadata;
private static readonly object array_metadata_lock = new Object ();
Expand Down Expand Up @@ -341,25 +343,19 @@ private static object ReadValue (Type inst_type, JsonReader reader)
return reader.Value;

// If there's a custom importer that fits, use it
if (custom_importers_table.ContainsKey (json_type) &&
custom_importers_table[json_type].ContainsKey (
value_type)) {
lock (custom_importers_table_lock) {
if (custom_importers_table.TryGetValue(json_type, out IDictionary<Type, ImporterFunc> customImporterTablesValue) &&
customImporterTablesValue.TryGetValue(value_type, out ImporterFunc customImporter)) {

ImporterFunc importer =
custom_importers_table[json_type][value_type];

return importer (reader.Value);
return customImporter(reader.Value);
}
}

// Maybe there's a base importer that works
if (base_importers_table.ContainsKey (json_type) &&
base_importers_table[json_type].ContainsKey (
value_type)) {

ImporterFunc importer =
base_importers_table[json_type][value_type];
if (base_importers_table.TryGetValue(json_type, out IDictionary<Type, ImporterFunc> baseImporterTablesValue) &&
baseImporterTablesValue.TryGetValue(value_type, out ImporterFunc baseImporter)) {

return importer (reader.Value);
return baseImporter(reader.Value);
}

// Maybe it's an enum
Expand Down Expand Up @@ -560,6 +556,8 @@ private static void ReadSkip (JsonReader reader)

private static void RegisterBaseExporters ()
{
// This method is only called from the static initializer,
// so there is no need to explicitly lock any static members here
base_exporters_table[typeof (byte)] =
delegate (object obj, JsonWriter writer) {
writer.Write (Convert.ToInt32 ((byte) obj));
Expand Down Expand Up @@ -614,6 +612,8 @@ private static void RegisterBaseExporters ()

private static void RegisterBaseImporters ()
{
// This method is only called from the static initializer,
// so there is no need to explicitly lock any static members here
ImporterFunc importer;

importer = delegate (object input) {
Expand Down Expand Up @@ -810,17 +810,17 @@ private static void WriteValue (object obj, JsonWriter writer,
Type obj_type = obj.GetType ();

// See if there's a custom exporter for the object
if (custom_exporters_table.ContainsKey (obj_type)) {
ExporterFunc exporter = custom_exporters_table[obj_type];
exporter (obj, writer);
lock (custom_exporters_table_lock) {
if (custom_exporters_table.TryGetValue(obj_type, out ExporterFunc customExporter)) {
customExporter(obj, writer);

return;
return;
}
}

// If not, maybe there's a base exporter
if (base_exporters_table.ContainsKey (obj_type)) {
ExporterFunc exporter = base_exporters_table[obj_type];
exporter (obj, writer);
if (base_exporters_table.TryGetValue(obj_type, out ExporterFunc baseExporter)) {
baseExporter(obj, writer);

return;
}
Expand Down Expand Up @@ -959,7 +959,9 @@ public static void RegisterExporter<T> (ExporterFunc<T> exporter)
exporter ((T) obj, writer);
};

custom_exporters_table[typeof (T)] = exporter_wrapper;
lock (custom_exporters_table_lock) {
custom_exporters_table[typeof (T)] = exporter_wrapper;
}
}

public static void RegisterImporter<TJson, TValue> (
Expand All @@ -970,18 +972,24 @@ public static void RegisterImporter<TJson, TValue> (
return importer ((TJson) input);
};

RegisterImporter (custom_importers_table, typeof (TJson),
typeof (TValue), importer_wrapper);
lock (custom_importers_table_lock) {
RegisterImporter (custom_importers_table, typeof (TJson),
typeof (TValue), importer_wrapper);
}
}

public static void UnregisterExporters ()
{
custom_exporters_table.Clear ();
lock (custom_exporters_table_lock) {
custom_exporters_table.Clear();
}
}

public static void UnregisterImporters ()
{
custom_importers_table.Clear ();
lock (custom_importers_table_lock) {
custom_importers_table.Clear();
}
}
}
}

0 comments on commit ac3889c

Please sign in to comment.