Add a class template for objects that can only be initialized once
Categories
(Core :: MFBT, task)
Tracking
()
Tracking | Status | |
---|---|---|
firefox75 | --- | fixed |
People
(Reporter: sg, Assigned: sg)
Details
Attachments
(2 files)
When working on dom/indexedDB, a class template that is initializable only once has shown to be useful to avoid usage errors and reduce the number of state assertions. It is based on mozilla::Maybe
and exposes a small subset of its interface.
I feel this might be useful for other code as well, so it might be moved to MFBT. I can do this and add appropriate tests if this makes sense.
My initial version looks like this:
// A kind of mozilla::Maybe that can only be initialized and cleared once. It
// cannot be re-initialized. This is a more stateful than a const Maybe<T> in
// that it can be cleared, but much less stateful than a non-const Maybe<T>
// which could be reinitialized multiple times. Use with a const T to ensure
// that the contents cannot be modified either.
template <typename T, bool AllowLazy = false>
class InitializedOnce {
public:
template <typename Dummy = void>
InitializedOnce(std::enable_if_t<AllowLazy, Dummy>* = nullptr) {}
template <typename... Args>
InitializedOnce(Args&&... aArgs)
: mMaybe{Some(T{std::forward<Args>(aArgs)...})} {}
InitializedOnce& operator=(const InitializedOnce&) = delete;
InitializedOnce& operator=(InitializedOnce&&) = delete;
template <typename... Args, typename Dummy = void>
std::enable_if_t<AllowLazy, Dummy> init(Args&&... aArgs) {
MOZ_ASSERT(mMaybe.isNothing());
mMaybe.emplace(T{std::forward<Args>(aArgs)...});
}
explicit operator bool() const { return isSome(); }
bool isSome() const { return mMaybe.isSome(); }
bool isNothing() const { return mMaybe.isNothing(); }
T& operator*() const { return *mMaybe; }
T* operator->() const { return mMaybe.operator->(); }
void reset() {
MOZ_ASSERT(mMaybe.isSome());
mMaybe.reset();
}
private:
Maybe<T> mMaybe;
};
Comment 1•5 years ago
|
||
Why have AllowLazy = true
if that just makes the class equivalent to Maybe
with a slightly different spelling?
Assignee | ||
Comment 2•5 years ago
|
||
(In reply to Nathan Froyd [:froydnj] from comment #1)
Why have
AllowLazy = true
if that just makes the class equivalent toMaybe
with a slightly different spelling?
With AllowLazy = true
, you do not need to initialize it on construction, but it may still be initialized only once (either on construction or lazily with init
). Maybe
would allow to initialize it multiple times by reassigning or emplace
.
What I missed until now is to disable the assignment operators.
Comment 3•5 years ago
|
||
(In reply to Simon Giesecke [:sg] [he/him] from comment #2)
(In reply to Nathan Froyd [:froydnj] from comment #1)
Why have
AllowLazy = true
if that just makes the class equivalent toMaybe
with a slightly different spelling?With
AllowLazy = true
, you do not need to initialize it on construction, but it may still be initialized only once (either on construction or lazily withinit
).Maybe
would allow to initialize it multiple times by reassigning oremplace
.What I missed until now is to disable the assignment operators.
But you have reset
, so you can just reset
and then init
again, no?
Assignee | ||
Comment 4•5 years ago
|
||
(In reply to Nathan Froyd [:froydnj] from comment #3)
(In reply to Simon Giesecke [:sg] [he/him] from comment #2)
(In reply to Nathan Froyd [:froydnj] from comment #1)
Why have
AllowLazy = true
if that just makes the class equivalent toMaybe
with a slightly different spelling?With
AllowLazy = true
, you do not need to initialize it on construction, but it may still be initialized only once (either on construction or lazily withinit
).Maybe
would allow to initialize it multiple times by reassigning oremplace
.What I missed until now is to disable the assignment operators.
But you have
reset
, so you can justreset
and theninit
again, no?
Mh, yes, that's true. Another flag would probably be needed to prohibit such a usage sequence as well.
Assignee | ||
Comment 5•5 years ago
|
||
FYI, this is the patch which ought to add this locally to dom/indexedDB and also uses it at a few places: https://phabricator.services.mozilla.com/D53951
Assignee | ||
Comment 6•5 years ago
|
||
It has now landed and been extended a bit to allow checking for valid values at the time of initialization: https://searchfox.org/mozilla-central/source/dom/indexedDB/InitializedOnce.h
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Comment 7•5 years ago
|
||
Updated•5 years ago
|
Comment 9•5 years ago
|
||
bugherder |
Assignee | ||
Comment 10•5 years ago
|
||
Depends on D65568
Comment 11•5 years ago
|
||
Comment 12•5 years ago
|
||
Backed out 10 changesets (Bug 1623278, Bug 1617170, Bug 1620273, Bug 1597954) for causing bustages.
Backout link: https://hg.mozilla.org/integration/autoland/rev/0e7e76826ace75277a1f892dc14358c675d1c911
Failure log: https://treeherder.mozilla.org/logviewer.html#/jobs?job_id=293829628&repo=autoland&lineNumber=45369
Comment 13•5 years ago
|
||
Comment 14•5 years ago
|
||
bugherder |
Description
•