Skip to content

Commit ac3889c

Browse files
authored
Merge pull request #142 from udlose/develop
Add thread safety to fix race conditions around usage of static IDict…
2 parents 99ae103 + 9899787 commit ac3889c

1 file changed

Lines changed: 34 additions & 26 deletions

File tree

src/LitJson/JsonMapper.cs

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,13 @@ public class JsonMapper
106106

107107
private static readonly IDictionary<Type, ExporterFunc> base_exporters_table;
108108
private static readonly IDictionary<Type, ExporterFunc> custom_exporters_table;
109+
private static readonly object custom_exporters_table_lock = new Object();
109110

110111
private static readonly IDictionary<Type,
111112
IDictionary<Type, ImporterFunc>> base_importers_table;
112113
private static readonly IDictionary<Type,
113114
IDictionary<Type, ImporterFunc>> custom_importers_table;
115+
private static readonly object custom_importers_table_lock = new Object();
114116

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

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

348-
ImporterFunc importer =
349-
custom_importers_table[json_type][value_type];
350-
351-
return importer (reader.Value);
350+
return customImporter(reader.Value);
351+
}
352352
}
353353

354354
// Maybe there's a base importer that works
355-
if (base_importers_table.ContainsKey (json_type) &&
356-
base_importers_table[json_type].ContainsKey (
357-
value_type)) {
358-
359-
ImporterFunc importer =
360-
base_importers_table[json_type][value_type];
355+
if (base_importers_table.TryGetValue(json_type, out IDictionary<Type, ImporterFunc> baseImporterTablesValue) &&
356+
baseImporterTablesValue.TryGetValue(value_type, out ImporterFunc baseImporter)) {
361357

362-
return importer (reader.Value);
358+
return baseImporter(reader.Value);
363359
}
364360

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

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

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

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

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

817-
return;
817+
return;
818+
}
818819
}
819820

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

825825
return;
826826
}
@@ -959,7 +959,9 @@ public static void RegisterExporter<T> (ExporterFunc<T> exporter)
959959
exporter ((T) obj, writer);
960960
};
961961

962-
custom_exporters_table[typeof (T)] = exporter_wrapper;
962+
lock (custom_exporters_table_lock) {
963+
custom_exporters_table[typeof (T)] = exporter_wrapper;
964+
}
963965
}
964966

965967
public static void RegisterImporter<TJson, TValue> (
@@ -970,18 +972,24 @@ public static void RegisterImporter<TJson, TValue> (
970972
return importer ((TJson) input);
971973
};
972974

973-
RegisterImporter (custom_importers_table, typeof (TJson),
974-
typeof (TValue), importer_wrapper);
975+
lock (custom_importers_table_lock) {
976+
RegisterImporter (custom_importers_table, typeof (TJson),
977+
typeof (TValue), importer_wrapper);
978+
}
975979
}
976980

977981
public static void UnregisterExporters ()
978982
{
979-
custom_exporters_table.Clear ();
983+
lock (custom_exporters_table_lock) {
984+
custom_exporters_table.Clear();
985+
}
980986
}
981987

982988
public static void UnregisterImporters ()
983989
{
984-
custom_importers_table.Clear ();
990+
lock (custom_importers_table_lock) {
991+
custom_importers_table.Clear();
992+
}
985993
}
986994
}
987995
}

0 commit comments

Comments
 (0)