Buf.cpp 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2024-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #include "Buf.hpp"
  14. #ifdef __WINDOWS__
  15. #define sched_yield() Sleep(0)
  16. #endif
  17. namespace ZeroTier {
  18. static std::atomic<uintptr_t> s_pool(0);
  19. #define ZT_ATOMIC_PTR_LOCKED (~((uintptr_t)0))
  20. void *Buf::operator new(std::size_t sz)
  21. {
  22. uintptr_t bb;
  23. for (;;) {
  24. bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED);
  25. if (bb != ZT_ATOMIC_PTR_LOCKED)
  26. break;
  27. sched_yield();
  28. }
  29. Buf *b;
  30. if (bb) {
  31. b = (Buf *)bb;
  32. s_pool.store(b->__nextInPool);
  33. } else {
  34. s_pool.store(0);
  35. b = (Buf *)malloc(sz);
  36. if (!b)
  37. throw std::bad_alloc();
  38. }
  39. b->__refCount.store(0);
  40. return (void *)b;
  41. }
  42. void Buf::operator delete(void *ptr)
  43. {
  44. if (ptr) {
  45. uintptr_t bb;
  46. for (;;) {
  47. bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED);
  48. if (bb != ZT_ATOMIC_PTR_LOCKED)
  49. break;
  50. sched_yield();
  51. }
  52. ((Buf *)ptr)->__nextInPool = bb;
  53. s_pool.store((uintptr_t)ptr);
  54. }
  55. }
  56. void Buf::freePool() noexcept
  57. {
  58. uintptr_t bb;
  59. for (;;) {
  60. bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED);
  61. if (bb != ZT_ATOMIC_PTR_LOCKED)
  62. break;
  63. sched_yield();
  64. }
  65. s_pool.store(0);
  66. while (bb != 0) {
  67. uintptr_t next = ((Buf *)bb)->__nextInPool;
  68. free((void *)bb);
  69. bb = next;
  70. }
  71. }
  72. } // namespace ZeroTier