Reference:
Storing data in pointers
#include <cstddef>
#include <cstdint>
#include <iostream>
enum ListType {
kNone,
kReady,
kDeleting,
};
static constexpr uintptr_t kListTypeMask = 0b11;
static constexpr uintptr_t kCleanPtrMask = ~kListTypeMask;
struct Tree;
struct Node{
void set_list_type(ListType list_type) {
uintptr_t t = static_cast<uintptr_t>(list_type);
uintptr_t v = ptr_and_list_type_ & kCleanPtrMask;
ptr_and_list_type_ = (v | t);
}
ListType list_type() const {
return static_cast<ListType>(ptr_and_list_type_ & kListTypeMask);
}
void set_prev_next_ptr(Node** p) {
uintptr_t t = ptr_and_list_type_ & kListTypeMask;
uintptr_t v = reinterpret_cast<uintptr_t>(p);
ptr_and_list_type_ = (v | t);
}
Node** prev_next_ptr() const {
return reinterpret_cast<Node**>(ptr_and_list_type_ & kCleanPtrMask);
}
Tree* tree_ = nullptr;
Node* parent_ = nullptr;
Node* next_ = nullptr;
uintptr_t ptr_and_list_type_ = 0;
};
struct Tree{
void MarkReady(Node* p) {
p->next_ = ready_;
p->set_prev_next_ptr(&ready_);
if (ready_ != nullptr) {
ready_->set_prev_next_ptr(&p->next_);
}
ready_ = p;
p->set_list_type(kReady);
}
int padding;
Node* ready_ = nullptr;
};
int main() {
// Print 8 since padding is type of int occupies 8 bytes.
std::cout << "offset of ready_: " <<
reinterpret_cast<void*>(&((Tree*)0)->ready_) << "\n";
Tree* tree = new Tree{};
std::cout << "tree: " << reinterpret_cast<void *>(&tree) << "\n";
std::cout << "tree offset of ready: " <<
reinterpret_cast<void *>(&tree->ready_) << "\n";
Node p;
p.tree_ = tree;
tree->MarkReady(&p);
std::cout << reinterpret_cast<void *>(p.prev_next_ptr()) << "\n";
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.