This PR turned out to be rather large. I implemented inter-region person transfer but had to change a lot of crucial data structures in the process.
I also got rid of a lot of baroque hacks and replaced them with "modern" C++ constructs.
For example, Cluster used to store raw pointers to Person in a std::vector<std::pair<Person*, bool>>. These Person* values would then point to locations in Population, which literally inherited from std::vector<Person> at the time. So a single push_*/emplace_*/erase/emplace/insert on the simulator's Population can cause the clusters to segfault because the Population/std::vector<Person> might reallocate its underlying buffer.
Population contains (but does not inherit from!) an std::map now (apparently, changing the ordering of a Population makes the simulator spit out entirely different results). Person*/Person& have been replaced by Person, which is now a pair that consists of an (immutable) id and an std::shared_ptr<PersonData>. PersonData is a mutable data structure.
In other news: I included only one unit test for this PR. It checks that multi-region simulations do not segfault. Incidentally, I consider that to be my crowning achievement. The sheer amount of hacks and poorly-maintained invariants in the stride codebase have resulted in a veritable cascade of segfaults and other hard-to-detect bugs. But the refactors I made don't actually add new functionality. So they should really be covered by pre-existing tests.
This PR turned out to be rather large. I implemented inter-region person transfer but had to change a lot of crucial data structures in the process.
I also got rid of a lot of baroque hacks and replaced them with "modern" C++ constructs.
For example,
Cluster
used to store raw pointers toPerson
in astd::vector<std::pair<Person*, bool>>
. ThesePerson*
values would then point to locations inPopulation
, which literally inherited fromstd::vector<Person>
at the time. So a singlepush_*
/emplace_*
/erase
/emplace
/insert
on the simulator'sPopulation
can cause the clusters to segfault because thePopulation
/std::vector<Person>
might reallocate its underlying buffer.Population
contains (but does not inherit from!) anstd::map
now (apparently, changing the ordering of aPopulation
makes the simulator spit out entirely different results).Person*
/Person&
have been replaced byPerson
, which is now a pair that consists of an (immutable) id and anstd::shared_ptr<PersonData>
.PersonData
is a mutable data structure.In other news: I included only one unit test for this PR. It checks that multi-region simulations do not segfault. Incidentally, I consider that to be my crowning achievement. The sheer amount of hacks and poorly-maintained invariants in the stride codebase have resulted in a veritable cascade of segfaults and other hard-to-detect bugs. But the refactors I made don't actually add new functionality. So they should really be covered by pre-existing tests.