Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
manually-drop.hh
1#pragma once
3#include <atomic>
4#include <cassert>
5#include <utility>
6
7namespace nix {
8
10template<typename T>
11class ManuallyDrop
12{
13 alignas(alignof(T)) char data[sizeof(T)];
14 // We have to use atomic<bool> here since once_flag reattempts if the
15 // callee throws (double destruction? yikes)
16 std::atomic<bool> destroyed = false;
17
18public:
19 explicit ManuallyDrop(T && t)
20 {
21 ::new (data) T(std::move(t));
22 }
23
25 template<typename... Arg>
26 ManuallyDrop(std::in_place_t, Arg &&... args)
27 {
28 ::new (data) T(std::forward<Arg>(args)...);
29 }
30
32 {
33 ::new (data) ManuallyDrop<T>(other.take());
34 }
35
36 ~ManuallyDrop() {}
37
38 // FIXME(jade): do some "deducing this" nonsense to implement all the const
39 // whatevers for this class. my clangd didn't like it when i tried, so that
40 // is Later Work. this language is horrific.
41
43 T & get()
44 {
45 // SAFETY: this should genuinely never happen and it doesn't matter the
46 // ordering of other stuff relative to it.
47 assert(!destroyed.load(std::memory_order_relaxed));
48 return reinterpret_cast<T &>(data);
49 }
50
51 T & operator*()
52 {
53 return get();
54 }
55
56 T * operator->()
57 {
58 return &get();
59 }
60
71 T && take() &&
72 {
73 // SAFETY: this is relatively lock-like in structure, reordering-wise
74 bool wasDestroyed = destroyed.exchange(true, std::memory_order_acq_rel);
75 assert(!wasDestroyed);
76 return std::move(reinterpret_cast<T &>(data));
77 }
78
80 void destroy()
81 {
82 // SAFETY: this is relatively lock-like in structure, reordering-wise
83 bool wasDestroyed = destroyed.exchange(true, std::memory_order_acq_rel);
84 if (!wasDestroyed) {
85 get().~T();
86 }
87 }
88};
89}
Definition manually-drop.hh:12
T & get()
Definition manually-drop.hh:43
void destroy()
Definition manually-drop.hh:80
T && take() &&
Definition manually-drop.hh:71
ManuallyDrop(std::in_place_t, Arg &&... args)
Definition manually-drop.hh:26