얼마 전에 겜회사 면접 봤는데 포인터 관련된 부분이 나와서 다시 공부할 겸 짜봄


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#pragma once
 
#include <memory>
 
class memory_pool
{
public:
 
  memory_pool(size_t requested_size, size_t next_size = 32)
    : requested_size_(requested_size < min_size() ? min_size() : requested_size)
    , next_size_(next_size)
    , page_(nullptr)
    , first_(nullptr)
  {
  }
 
  ~memory_pool()
  {
    // 모든 페이지 해제
    void* next;
 
    while (page_)
    {
      next = next_of(page_);
      std::free(page_);
      page_ = next;
    }
  }
 
  // 요청된 크기를 반환합니다.
  size_t requested_size() const
  {
    return requested_size_;
  }
 
  // 메모리를 할당합니다.
  void* malloc()
  {
    if (empty()) grow();
 
    void* const ret = first_;
    
    first_ = next_of(first_);
 
    return ret;
  }
 
  // 메모리를 해제합니다.
  void free(void* chunk)
  {
    next_of(chunk) = first_;
    first_ = chunk;
  }
 
  // 여분 메모리가 존재하지 않는지 검사합니다.
  // true를 반환하는 상황에서 할당을 시도하면 메모리 풀의 성장이 일어납니다.
  bool empty() const
  {
    return first_ == nullptr;
  }
 
  // 풀을 확장합니다.
  void grow()
  {
    const size_t page_size = (requested_size_ * next_size_) + sizeof(void*);
 
    char* new_page = (char*)std::malloc(page_size);
 
    next_of(new_page) = page_;
 
    page_ = new_page;
 
    char* const end_of_page = new_page + page_size;
 
    new_page += sizeof(void*);
 
    while (new_page != end_of_page)
    {
      next_of(new_page) = first_;
      first_ = new_page;
      new_page += requested_size_;
    }
 
    next_size_ *= 2;
  }
 
private:
 
  // 할당한 청크 그 자체를 다음 노드의 포인터를 저장할 공간으로 사용합니다.
  // chunk: [     ] => [nextptr]
  static void*& next_of(void* const chunk)
  {
    return *static_cast<void**>(chunk);
  }
 
  // 블록의 최소 사이즈를 반환합니다.
  static constexpr size_t min_size()
  {
    return sizeof(void*);
  }
 
  void* page_;
  void* first_;
  size_t next_size_;
  const size_t requested_size_;
};
cs