[SERVER-47518] mitigate dtor-order fiasco with a utility for defining static duration immortal objects Created: 13/Apr/20  Updated: 29/Oct/23  Resolved: 07/May/20

Status: Closed
Project: Core Server
Component/s: Internal Code
Affects Version/s: None
Fix Version/s: 4.4.1, 4.7.0

Type: Improvement Priority: Major - P3
Reporter: Billy Donahue Assignee: Billy Donahue
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Backports
Backwards Compatibility: Fully Compatible
Backport Requested:
v4.4
Sprint: Service arch 2020-05-18
Participants:

 Description   

A template with an object-modeling API similar to std::optional,
with a value(), typedef value_type, operator* operator->.

Init examples from the unit test:

TEST(ImmortalTest, StaticDurationIdiom) {
    static auto&& x = Immortal<Indestructible>();
    static_assert(std::is_same_v<decltype(x), Immortal<Indestructible>&&>);
}
 
TEST(ImmortalTest, DeducedValueTypeCopyInit) {
    static const Immortal m = Map{{"hello", 123}, {"bye", 456}};
    ASSERT_EQ(m->find("bye")->second, 456);
}
 
TEST(ImmortalTest, DeducedValueTypeExpression) {
    static const Immortal m = [] { return Map{{"hello", 123}, {"bye", 456}}; }();
    ASSERT_EQ(m->find("bye")->second, 456);
}
 
TEST(ImmortalTest, BraceInit) {
    static const Immortal<Map> m{{{"hello", 123}, {"bye", 456}}};
    ASSERT_EQ(m->find("bye")->second, 456);
}
 
TEST(ImmortalTest, ListInit) {
    static const Immortal<Map> m = {{{"hello", 123}, {"bye", 456}}};
    ASSERT_EQ(m->find("bye")->second, 456);
}
 
TEST(ImmortalTest, EmptyBrace) {
    static const Immortal<Map> empty{};
    ASSERT_TRUE(empty->empty());
}

x is convertible to an Indestructible&, and can sometimes be passed directly.
We can also make the cast without naming the type with *x and x.value().

Immortal forwards (via placement new) its constructor arguments to T(args...). This performs a placement new onto a std::aligned_buffer_t, so there is no allocation as there would be with the traditional approach, and there is no destructor call.

Having a common idiom and place to hang documentation will be useful in cutting down on the very common misuses and bugs we have regarding init order and shutdown order.

Importantly, it becomes a "greppable" and auditable best practice to identify and contain such objects, which are often suspects in startup and shutdown problems, or need to be called out in refactorings to reduce shared global state.



 Comments   
Comment by Githook User [ 23/Oct/20 ]

Author:

{'name': 'Billy Donahue', 'email': 'billy.donahue@mongodb.com', 'username': 'BillyDonahue'}

Message: SERVER-47518 StaticImmortal<T>
Branch: v4.2
https://github.com/mongodb/mongo/commit/84b65f6e4cd9a143b2aaf9ae4062500d6bf59c98

Comment by Githook User [ 18/Aug/20 ]

Author:

{'name': 'Billy Donahue', 'email': 'billy.donahue@mongodb.com', 'username': 'BillyDonahue'}

Message: SERVER-47518 StaticImmortal<T>

(cherry picked from commit 59b1b711a622b6b1b77accbe459b064e52d45375)
Branch: v4.4
https://github.com/mongodb/mongo/commit/5f639b885bdc8a7b10c3b16978b8d22a4b43bbc0

Comment by Billy Donahue [ 07/May/20 ]

Testing it out it little https://mongodbcr.appspot.com/602000022/

Comment by Githook User [ 07/May/20 ]

Author:

{'name': 'Billy Donahue', 'email': 'billy.donahue@mongodb.com', 'username': 'BillyDonahue'}

Message: SERVER-47518 StaticImmortal<T>
Branch: master
https://github.com/mongodb/mongo/commit/59b1b711a622b6b1b77accbe459b064e52d45375

Comment by Billy Donahue [ 15/Apr/20 ]

CR: https://mongodbcr.appspot.com/575020038/

Generated at Thu Feb 08 05:14:24 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.