mirror of
https://github.com/github/codeql.git
synced 2025-12-17 17:23:36 +01:00
139 lines
3.6 KiB
C++
139 lines
3.6 KiB
C++
#if !defined(CODEQL_MEMORY_H)
|
|
#define CODEQL_MEMORY_H
|
|
|
|
namespace std {
|
|
namespace detail {
|
|
template<typename T>
|
|
class compressed_pair_element {
|
|
T element;
|
|
|
|
public:
|
|
compressed_pair_element() = default;
|
|
compressed_pair_element(const T& t) : element(t) {}
|
|
|
|
T& get() { return element; }
|
|
|
|
const T& get() const { return element; }
|
|
};
|
|
|
|
template<typename T, typename U>
|
|
struct compressed_pair : private compressed_pair_element<T>, private compressed_pair_element<U> {
|
|
compressed_pair() = default;
|
|
compressed_pair(T& t) : compressed_pair_element<T>(t), compressed_pair_element<U>() {}
|
|
compressed_pair(const compressed_pair&) = delete;
|
|
compressed_pair(compressed_pair<T, U>&&) noexcept = default;
|
|
|
|
T& first() { return static_cast<compressed_pair_element<T>&>(*this).get(); }
|
|
U& second() { return static_cast<compressed_pair_element<U>&>(*this).get(); }
|
|
|
|
const T& first() const { return static_cast<const compressed_pair_element<T>&>(*this).get(); }
|
|
const U& second() const { return static_cast<const compressed_pair_element<U>&>(*this).get(); }
|
|
};
|
|
}
|
|
|
|
template<class T>
|
|
struct default_delete {
|
|
void operator()(T* ptr) const { delete ptr; }
|
|
};
|
|
|
|
template<class T>
|
|
struct default_delete<T[]> {
|
|
template<class U>
|
|
void operator()(U* ptr) const { delete[] ptr; }
|
|
};
|
|
|
|
template<class T, class Deleter = default_delete<T> >
|
|
class unique_ptr {
|
|
private:
|
|
detail::compressed_pair<T*, Deleter> data;
|
|
public:
|
|
constexpr unique_ptr() noexcept {}
|
|
explicit unique_ptr(T* ptr) noexcept : data(ptr) {}
|
|
unique_ptr(const unique_ptr& ptr) = delete;
|
|
unique_ptr(unique_ptr&& ptr) noexcept = default;
|
|
|
|
unique_ptr& operator=(unique_ptr&& ptr) noexcept = default;
|
|
|
|
T& operator*() const { return *get(); }
|
|
T* operator->() const noexcept { return get(); }
|
|
|
|
T* get() const noexcept { return data.first(); }
|
|
T* release() noexcept {
|
|
Deleter& d = data.second();
|
|
d(data.first());
|
|
data.first() = nullptr;
|
|
}
|
|
|
|
~unique_ptr() {
|
|
Deleter& d = data.second();
|
|
d(data.first());
|
|
}
|
|
};
|
|
|
|
template<typename T, class... Args> unique_ptr<T> make_unique(Args&&... args) {
|
|
return unique_ptr<T>(new T(args...)); // std::forward calls elided for simplicity.
|
|
}
|
|
|
|
class ctrl_block {
|
|
unsigned uses;
|
|
|
|
public:
|
|
ctrl_block() : uses(1) {}
|
|
|
|
void inc() { ++uses; }
|
|
bool dec() { return --uses == 0; }
|
|
|
|
virtual void destroy() = 0;
|
|
virtual ~ctrl_block() {}
|
|
};
|
|
|
|
template<typename T, class Deleter = default_delete<T> >
|
|
struct ctrl_block_impl: public ctrl_block {
|
|
T* ptr;
|
|
Deleter d;
|
|
|
|
ctrl_block_impl(T* ptr, Deleter d) : ptr(ptr), d(d) {}
|
|
virtual void destroy() override { d(ptr); }
|
|
};
|
|
|
|
template<class T>
|
|
class shared_ptr {
|
|
private:
|
|
ctrl_block* ctrl;
|
|
T* ptr;
|
|
|
|
void dec() {
|
|
if(ctrl->dec()) {
|
|
ctrl->destroy();
|
|
delete ctrl;
|
|
}
|
|
}
|
|
|
|
void inc() {
|
|
ctrl->inc();
|
|
}
|
|
|
|
public:
|
|
constexpr shared_ptr() noexcept = default;
|
|
shared_ptr(T* ptr) : ctrl(new ctrl_block_impl<T>(ptr, default_delete<T>())) {}
|
|
shared_ptr(const shared_ptr& s) noexcept : ptr(s.ptr), ctrl(s.ctrl) {
|
|
inc();
|
|
}
|
|
shared_ptr(shared_ptr&& s) noexcept = default;
|
|
shared_ptr(unique_ptr<T>&& s) : shared_ptr(s.release()) {
|
|
}
|
|
T* operator->() const { return ptr; }
|
|
|
|
T& operator*() const { return *ptr; }
|
|
|
|
T* get() const noexcept { return ptr; }
|
|
|
|
~shared_ptr() { dec(); }
|
|
};
|
|
|
|
template<typename T, class... Args> shared_ptr<T> make_shared(Args&&... args) {
|
|
return shared_ptr<T>(new T(args...)); // std::forward calls elided for simplicity.
|
|
}
|
|
}
|
|
|
|
#endif |