// SharedPtr's reference counting, and its layout: IMVU's DLLs read and write these fields directly. #include #include #include #include "t5de/imvu/shared_ptr.hpp" using t5de::imvu::SharedPtr; namespace { int failures = 0; void check(bool ok, const char* what) { if (!ok) { std::printf("FAIL: %s\n", what); ++failures; } } struct Base { virtual ~Base() = default; }; struct Tracked : Base { explicit Tracked(int& alive) : alive_(alive) { ++alive_; } ~Tracked() override { --alive_; } int& alive_; }; // What boost's control block looks like from IMVU's side: a vtable pointer, then the counts. struct BoostCounts { void* vtable; long use; long weak; }; const BoostCounts& counts_of(const void* shared) { return **static_cast(static_cast(static_cast(shared) + 4)); } } // namespace int main() { int alive = 0; { SharedPtr a(std::make_unique(alive)); check(alive == 1 && a.use_count() == 1, "created"); check(counts_of(&a).use == 1 && counts_of(&a).weak == 1, "boost layout: counts after the vtable pointer"); { SharedPtr b = a; check(a.use_count() == 2 && counts_of(&a).use == 2, "copy shares"); SharedPtr base = b; check(a.use_count() == 3, "converted copy shares"); SharedPtr moved = std::move(base); check(a.use_count() == 3 && !base, "move transfers"); } check(alive == 1 && a.use_count() == 1, "copies released"); } check(alive == 0, "last owner deletes"); SharedPtr empty; check(!empty && empty.use_count() == 0, "empty"); check(sizeof(SharedPtr) == 8, "two pointers"); if (failures == 0) { std::printf("ok\n"); } return failures == 0 ? 0 : 1; }