Merge pull request #2372 from RosettaCommons/vmullig/threadsafe_scoringmanager
Make the lazily-loaded data in the ScoringManager threadsafe
This pull request aims to add mutexes to all of the lazily-loaded data in the ScoringManager, allowing the relevant objects to be locked temporarily by one thread as it loads the data for the first time (preventing concurrent reads and writes to these objects, or multiple threads all trying to write to these objects).
Tasks:
- [x] Implement proper double-checked locking scheme (using `std::atomic_thread_fence()` -- see http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/) for each relevant ScoringManager function that loads data.
- [x] Encase relevant stuff in `#ifdef` statements so that it only affects multi-threaded compilations of Rosetta.
- [x] Think about organizing code to minimize the number of scattered `#ifdef` statements. Maybe this is an appropriate place to violate the community rule against macros? --> Yes, added some suitable macros.
- [x] Check whether any of the objects stored in ScoringManager has mutable data likely to be altered when multiple threads are doing supposedly const access.
- [x] Implement for all scoring functions in the ScoringManager.
- [x] Add function that can do a threadsafe check of whether a key is in a map of (string->OP), and, if it is not, can add an object with the given key to the map.
- [x] Implement for all maps in the ScoringManager.
- [x] Implement for other functions in the ScoringManager.
- [x] Test that scoring is unchanged in cxx11thread/serialization build.
- [x] Check integration tests in cxx11thread/serialization build.
- Confirmed: all changes are due either to expected failures of fundamentally non-threadsafe scoring objects which now throw if you try to use them in a multi-threaded context, or are extra output due to loading of all extra rama CDFs in a multi-threaded context.
- [x] Beauty.