addstorage.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #pragma once
  2. #include <util/system/align.h>
  3. #include <util/system/defaults.h>
  4. #include <new>
  5. namespace NPrivate {
  6. class TAdditionalStorageInfo {
  7. public:
  8. constexpr TAdditionalStorageInfo(size_t length) noexcept
  9. : Length_(length)
  10. {
  11. }
  12. constexpr size_t Length() const noexcept {
  13. return Length_;
  14. }
  15. private:
  16. size_t Length_;
  17. };
  18. }
  19. template <class T>
  20. class alignas(::NPrivate::TAdditionalStorageInfo) TAdditionalStorage {
  21. using TInfo = ::NPrivate::TAdditionalStorageInfo;
  22. public:
  23. inline TAdditionalStorage() noexcept = default;
  24. inline ~TAdditionalStorage() = default;
  25. inline void* operator new(size_t len1, size_t len2) {
  26. static_assert(alignof(T) >= alignof(TInfo));
  27. Y_ASSERT(len1 == sizeof(T));
  28. void* data = ::operator new(CombinedSizeOfInstanceWithTInfo() + len2);
  29. void* info = InfoPtr(static_cast<T*>(data));
  30. Y_UNUSED(new (info) TInfo(len2));
  31. return data;
  32. }
  33. inline void operator delete(void* ptr) noexcept {
  34. DoDelete(ptr);
  35. }
  36. inline void operator delete(void* ptr, size_t) noexcept {
  37. DoDelete(ptr);
  38. }
  39. inline void operator delete(void* ptr, size_t, size_t) noexcept {
  40. /*
  41. * this delete operator can be called automagically by compiler
  42. */
  43. DoDelete(ptr);
  44. }
  45. inline void* AdditionalData() const noexcept {
  46. return (char*)(static_cast<const T*>(this)) + CombinedSizeOfInstanceWithTInfo();
  47. }
  48. static inline T* ObjectFromData(void* data) noexcept {
  49. return reinterpret_cast<T*>(static_cast<char*>(data) - CombinedSizeOfInstanceWithTInfo());
  50. }
  51. inline size_t AdditionalDataLength() const noexcept {
  52. return InfoPtr(static_cast<const T*>(this))->Length();
  53. }
  54. private:
  55. static inline void DoDelete(void* ptr) noexcept {
  56. TInfo* info = InfoPtr(static_cast<T*>(ptr));
  57. info->~TInfo();
  58. ::operator delete(ptr);
  59. }
  60. static constexpr size_t CombinedSizeOfInstanceWithTInfo() noexcept {
  61. return AlignUp(sizeof(T), alignof(TInfo)) + sizeof(TInfo);
  62. }
  63. static constexpr TInfo* InfoPtr(T* instance) noexcept {
  64. return const_cast<TInfo*>(InfoPtr(static_cast<const T*>(instance)));
  65. }
  66. static constexpr const TInfo* InfoPtr(const T* instance) noexcept {
  67. return reinterpret_cast<const TInfo*>(reinterpret_cast<const char*>(instance) + CombinedSizeOfInstanceWithTInfo() - sizeof(TInfo));
  68. }
  69. private:
  70. void* operator new(size_t) = delete;
  71. };