mirror of
https://github.com/nlohmann/json.git
synced 2026-10-14 18:27:13 +00:00
Parsing from a FILE* reads one character at a time with std::fgetc, which locks and unlocks the FILE object for every character. file_input_adapter now locks the file once when it is created and unlocks it when it is destroyed - also when parsing throws - and reads with the unlocked stdio functions in between: flockfile/getc_unlocked/funlockfile with glibc, Apple, Android, and the BSDs, and _lock_file/_fgetc_nolock/_unlock_file with the Microsoft C runtime. Other C libraries keep std::fgetc. The lock is recursive, so fread() in the binary readers and stdio calls of a SAX handler or parser callback on the same thread keep working. On an Apple M1 Max, parsing from a FILE* is 2.9 to 4.0 times as fast (twitter.json 14.3 -> 4.1 ms, citm_catalog.json 35.4 -> 8.8 ms); with glibc, whose locking is cheaper, 1.1 to 1.3 times. The values and the position of the file after parsing are unchanged. Other threads that use the same FILE object now wait until parsing is done instead of interleaving their reads with the parser's. JSON_DISABLE_UNLOCKED_FILE_IO restores std::fgetc, for programs in which a SAX handler waits for another thread that uses the same FILE. The new tests check from a second thread that the lock is released after success and after a parse error, and run again with the macro. Signed-off-by: Niels Lohmann <mail@nlohmann.me>