mempool.h 16.8 KB
Newer Older
W
wangguibao 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once
W
wangguibao 已提交
16 17 18 19 20

#ifdef BCLOUD
#include <base/atomicops.h>
#include <base/logging.h>
#else
W
wangguibao 已提交
21 22
#include <butil/atomicops.h>
#include <butil/logging.h>
W
wangguibao 已提交
23 24
#endif

W
wangguibao 已提交
25 26
#include <execinfo.h>
#include <pthread.h>
W
wangguibao 已提交
27
#include <iostream>
W
wangguibao 已提交
28 29 30
#include <new>
#include <sstream>
#include <string>
W
wangguibao 已提交
31 32 33 34

namespace im {
namespace fugue {

W
wangguibao 已提交
35 36 37 38
#ifdef BCLOUD
namespace butil = base;
#endif

W
wangguibao 已提交
39 40
namespace lockfree {

H
HexToString 已提交
41 42 43 44 45 46 47 48 49 50
/*
struct BigNode {
    BigNode* next;
    char data[0];
  };
*/
// template T is BigNode
// which is a node of variable length memory linked list
// _head is a BigNode* ptr, always points to the head node of the Stack.
// so PushOnlyStack is the head node of the Stack with some member function.
W
wangguibao 已提交
51 52
template <class T>
class PushOnlyStack {
W
wangguibao 已提交
53 54
 public:
  PushOnlyStack() { _head.store(NULL, butil::memory_order_relaxed); }
W
wangguibao 已提交
55

W
wangguibao 已提交
56 57 58 59 60 61
  void push(T* node) {
    T* head = _head.load(butil::memory_order_relaxed);
    node->next = head;
    while (
        !_head.compare_exchange_weak(head, node, butil::memory_order_relaxed)) {
      node->next = head;
W
wangguibao 已提交
62
    }
W
wangguibao 已提交
63
  }
W
wangguibao 已提交
64

H
HexToString 已提交
65 66 67
  T* releaseAndGetHeadPtr() {
    return _head.exchange(NULL, butil::memory_order_relaxed);
  }
W
wangguibao 已提交
68

W
wangguibao 已提交
69 70
 private:
  butil::atomic<T*> _head;
W
wangguibao 已提交
71 72
};

H
HexToString 已提交
73 74 75 76 77 78
// T can be class Block or class BlockReference
// class Block is 2M bytes memory
// class BlockReference is class Block* ptr.
// so the main member of FreeListNode is 2M bytes or class Block* ptr
// int 'id' is the index of itself in a FreeList.
// int 'next' is the index of next FreeListNode<T> in a FreeList.
W
wangguibao 已提交
79 80
template <class T>
struct FreeListNode {
W
wangguibao 已提交
81 82 83
  uint64_t id;
  uint64_t next;
  T data;
W
wangguibao 已提交
84 85
};

H
HexToString 已提交
86 87 88 89 90
// T can be class Block or class BlockReference
// CAP means capicity
// the main member of FreeList is FreeListNode<T>* [CAP].
// FreeList doesn`t realse the block data, it`s only an array of
// FreeListNode<T>* ptr.
W
wangguibao 已提交
91 92
template <class T, int CAP>
class FreeList {
W
wangguibao 已提交
93 94 95
 public:
  typedef FreeListNode<T> Node;
  static const uint64_t EMPTY = 0xFFFFFFFFFFFFFFFF;
W
wangguibao 已提交
96

H
HexToString 已提交
97
  // get the head Node`s member data ptr(T*)
W
wangguibao 已提交
98 99 100 101
  T* get() {
    uint64_t head = _head.load(butil::memory_order_acquire);
    if (head == EMPTY) {
      return new_node();
W
wangguibao 已提交
102 103
    }

H
HexToString 已提交
104 105 106 107 108 109 110 111 112 113
    // _head is atomic<int>, which means the head index.
    // head is the tempValue of _head.
    // maybe _head is not equals head anymore.
    // cause other thread may change the _head.
    /*compare_exchange_weak
    When the current value is equal to the expected value, modify the current
    value to the set value and return true
    When the current value is not equal to the expected value, modify the
    expected value to the current value and return false
    */
W
wangguibao 已提交
114 115 116 117 118 119 120 121 122 123
    Node* node = address(head);
    while (!_head.compare_exchange_weak(
        head, node->next, butil::memory_order_acquire)) {
      if (head == EMPTY) {
        return new_node();
      }
      node = address(head);
    }
    return &node->data;
  }
W
wangguibao 已提交
124

W
wangguibao 已提交
125
  void put(T* value) {
H
HexToString 已提交
126 127 128 129 130 131 132 133 134
    /*
    container_of
    according to the member(pointer type) of a Class
    to get the class Pointer
    for example
    T is the member of class Node, T data, 'data' is the name.
    T* value is the member(pointer type) class Node
    so we can get the Node* by calling container_of(value, Node, data)
    */
W
wangguibao 已提交
135
    Node* node = container_of(value, Node, data);
W
wangguibao 已提交
136

W
wangguibao 已提交
137
    uint64_t head = _head.load(butil::memory_order_acquire);
H
HexToString 已提交
138 139 140 141 142

    // node->id is int64. slot index is int32.
    // address(): slot = static_cast<uint32_t>(node->id)
    // will this be wrong?
    // add version? maybe this is different from new node?
W
wangguibao 已提交
143 144
    node->id += (1UL << 32);
    node->next = head;
W
wangguibao 已提交
145

W
wangguibao 已提交
146 147 148 149 150 151
    // NOTE: we MUST use a temp var *head* to call compare_exchange_weak
    // because Boost.Atomic will update the *expected* even success
    // std::atomic do not have this limitation
    while (!_head.compare_exchange_weak(
        head, node->id, butil::memory_order_release)) {
      node->next = head;
W
wangguibao 已提交
152
    }
W
wangguibao 已提交
153
  }
W
wangguibao 已提交
154

H
HexToString 已提交
155 156 157
  // F is callable class, class PutBlockByReference.
  // actually, F is the function put.
  // this function put the reuse the used block or blockReference
W
wangguibao 已提交
158 159 160 161 162
  template <class F>
  void unsafe_foreach() {
    uint32_t used_blk_cnt = _slot_index.load(butil::memory_order_relaxed);
    for (uint32_t i = 0; i < used_blk_cnt; ++i) {
      F()(&_node[i]->data);
W
wangguibao 已提交
163
    }
W
wangguibao 已提交
164
  }
W
wangguibao 已提交
165

W
wangguibao 已提交
166 167 168 169 170
  uint32_t real_used_size() const {
    uint32_t used_blk_cnt = _slot_index.load(butil::memory_order_relaxed);
    uint64_t used_bytes = 0;
    for (uint32_t i = 0; i < used_blk_cnt; ++i) {
      used_bytes += _node[i]->data.offset;
W
wangguibao 已提交
171
    }
H
HexToString 已提交
172
    // used_bytes/1024 = KB
W
wangguibao 已提交
173 174
    return used_bytes >> 10;
  }
W
wangguibao 已提交
175

H
HexToString 已提交
176
  uint32_t get_number_of_allocate_blocks() const {
W
wangguibao 已提交
177 178
    return _slot_index.load(butil::memory_order_relaxed);
  }
W
wangguibao 已提交
179

H
HexToString 已提交
180
  uint32_t get_number_of_free_blocks() const {
W
wangguibao 已提交
181 182 183 184 185 186
    uint64_t head = _head.load(butil::memory_order_relaxed);
    uint32_t size = 0;
    while (head != FreeList::EMPTY) {
      const Node* head_ptr = address(head);
      head = head_ptr->next;
      ++size;
W
wangguibao 已提交
187
    }
W
wangguibao 已提交
188 189
    return size;
  }
W
wangguibao 已提交
190

W
wangguibao 已提交
191 192 193 194
  void reset() {
    _head.store(FreeList::EMPTY, butil::memory_order_relaxed);
    _slot_index.store(0, butil::memory_order_relaxed);
  }
W
wangguibao 已提交
195

W
wangguibao 已提交
196 197 198
  FreeList() {
    for (int i = 0; i < CAP; ++i) {
      _node[i] = NULL;
W
wangguibao 已提交
199
    }
W
wangguibao 已提交
200 201
    reset();
  }
W
wangguibao 已提交
202

W
wangguibao 已提交
203 204
 private:
  uint32_t slot(uint64_t id) const { return static_cast<uint32_t>(id); }
W
wangguibao 已提交
205

W
wangguibao 已提交
206 207 208 209 210
  T* new_node() {
    uint32_t index = _slot_index.fetch_add(1, butil::memory_order_relaxed);
    if (index >= CAP) {
      return NULL;
    }
W
wangguibao 已提交
211

W
wangguibao 已提交
212 213 214
    if (_node[index] != NULL) {
      return &(_node[index]->data);
    }
W
wangguibao 已提交
215

W
wangguibao 已提交
216 217
    Node* node = reinterpret_cast<Node*>(malloc(sizeof(Node)));
    new (node) Node;
W
wangguibao 已提交
218

W
wangguibao 已提交
219 220
    node->id = index;
    _node[index] = node;
W
wangguibao 已提交
221

W
wangguibao 已提交
222 223
    return &node->data;
  }
W
wangguibao 已提交
224

W
wangguibao 已提交
225
  Node* address(uint64_t id) { return _node[slot(id)]; }
W
wangguibao 已提交
226

W
wangguibao 已提交
227
  const Node* address(uint64_t id) const { return _node[slot(id)]; }
W
wangguibao 已提交
228

W
wangguibao 已提交
229 230 231 232 233
  butil::atomic<uint64_t> _head;
  butil::atomic<uint32_t> _slot_index;
  Node* _node[CAP];
};
}  // namespace lockfree
W
wangguibao 已提交
234 235 236

namespace memory {

H
HexToString 已提交
237
// Memory is 2M bytes
W
wangguibao 已提交
238
struct Block {
H
HexToString 已提交
239
  static const int BLOCK_SIZE = 2 * 1024 * 1024;  // 2MB
W
wangguibao 已提交
240
  char data[BLOCK_SIZE];
W
wangguibao 已提交
241 242
};

H
HexToString 已提交
243
// Block* and offset
W
wangguibao 已提交
244
struct BlockReference {
W
wangguibao 已提交
245 246 247
  BlockReference() : offset(0), block(NULL) {
    // do nothing
  }
W
wangguibao 已提交
248

W
wangguibao 已提交
249 250 251 252
  void reset() {
    offset = 0;
    block = NULL;
  }
W
wangguibao 已提交
253

W
wangguibao 已提交
254 255
  uint32_t offset;
  Block* block;
W
wangguibao 已提交
256 257
};

H
HexToString 已提交
258 259 260 261 262 263 264 265 266
// This is a real singleton class FreeList<Block,MAX_BLOCK_COUNT>
// FreeList is always an array of FreeListNode<Block>* ptr.
// Block(2MB) is created when get() is called.

// because BlockFreeList is a threal-safe Singleton.
// so we don`t release Block, it is global memory.
// total number is 32*1024
class BlockFreeList {
 public:
H
HexToString 已提交
267
  static const int MAX_BLOCK_COUNT = 256 * 1024;
H
HexToString 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280
  typedef lockfree::FreeList<Block, MAX_BLOCK_COUNT> BlockFreeListType;
  static BlockFreeListType* instance() {
    static BlockFreeListType singleton;
    return &singleton;
  }
};

// _big_mem_capacity: a large memory is owned by Region.
// _bigNode_Stack: A list of bigNode(variable length memory)is owned by
// Region,the number is unlimit.
// _blockReference_FreeList: a FreeList of Block(2MB) is owned by singleton
// BlockFreeList, which is global.
// we can borrow 1024*Block from BlockFreeList.
W
wangguibao 已提交
281
class Region {
W
wangguibao 已提交
282
 public:
H
HexToString 已提交
283
  struct PutBlockByReference {
W
wangguibao 已提交
284 285
    void operator()(BlockReference* block_ref) {
      if (block_ref->block != NULL) {
H
HexToString 已提交
286
        BlockFreeList::instance()->put(block_ref->block);
W
wangguibao 已提交
287 288 289 290
      }
      block_ref->reset();
    }
  };
W
wangguibao 已提交
291

H
HexToString 已提交
292
  // this is a variable length memory node.
W
wangguibao 已提交
293 294 295 296
  struct BigNode {
    BigNode* next;
    char data[0];
  };
W
wangguibao 已提交
297

W
wangguibao 已提交
298 299 300 301 302
  ~Region() {
    reset();
    delete[] _big_mem_start;
    _big_mem_start = NULL;
  }
W
wangguibao 已提交
303

W
wangguibao 已提交
304
  char const* debug_str() const {
H
HexToString 已提交
305 306 307 308
    uint32_t alloc_blocks =
        _blockReference_FreeList.get_number_of_allocate_blocks();
    uint32_t free_blocks = _blockReference_FreeList.get_number_of_free_blocks();
    uint32_t used_mem_mb = _blockReference_FreeList.real_used_size();
W
wangguibao 已提交
309 310
    uint32_t big_buf_size = _big_mem_size.load(butil::memory_order_relaxed);
    uint32_t big_buf_count = _big_mem_count.load(butil::memory_order_relaxed);
H
HexToString 已提交
311 312 313 314
    uint32_t mlc_mem_size =
        _total_bigNode_size.load(butil::memory_order_relaxed);
    uint32_t mlc_mem_count =
        _total_bigNode_count.load(butil::memory_order_relaxed);
W
wangguibao 已提交
315

W
wangguibao 已提交
316 317 318 319 320 321 322
    std::ostringstream oss;
    oss << "[alloc_blks:" << alloc_blocks << ",free_blks:" << free_blocks
        << ",used_mem_kb:" << used_mem_mb
        << ",big_mem_kb:" << (big_buf_size >> 10)
        << ",big_buf_cnt:" << big_buf_count
        << ",mlc_mem_kb:" << (mlc_mem_size >> 10)
        << ",mlc_cnt:" << mlc_mem_count << "]";
W
wangguibao 已提交
323

W
wangguibao 已提交
324 325
    return oss.str().c_str();
  }
W
wangguibao 已提交
326

W
wangguibao 已提交
327
  Region();
W
wangguibao 已提交
328

W
wangguibao 已提交
329
  void init();
W
wangguibao 已提交
330

W
wangguibao 已提交
331
  void reset();
W
wangguibao 已提交
332

W
wangguibao 已提交
333
  BlockReference* get();
W
wangguibao 已提交
334

W
wangguibao 已提交
335
  void* malloc(size_t size);
W
wangguibao 已提交
336

H
HexToString 已提交
337
  void put(BlockReference* blockReference);
W
wangguibao 已提交
338

H
HexToString 已提交
339 340 341 342
  static const int MAX_BLOCK_COUNT = 1024;  // each Block is 2MB
  static const int BIG_MEM_THRESHOLD =
      2 * 1024 *
      1024;  // 2MB,means when you need less than 2M, get memory from Block.
H
HexToString 已提交
343

H
HexToString 已提交
344 345 346
  // 64MB,means when you need less than 64MB, get memory from BigMemory instead
  // of BigNode
  static const int BIGNODE_MEM_THRESHOLD = (64 * 1024 * 1024 + 1);
H
HexToString 已提交
347 348
  static const int COUNTER_SIZE =
      BIGNODE_MEM_THRESHOLD / BIG_MEM_THRESHOLD + 1;  // this is not used
W
wangguibao 已提交
349

W
wangguibao 已提交
350
 private:
H
HexToString 已提交
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
  lockfree::FreeList<BlockReference, MAX_BLOCK_COUNT> _blockReference_FreeList;

  // _total_bigNode_size is the total size of BigNodeStack.
  // _total_bigNode_count is the total count of BigNodeStack.
  // BigNode is variable length memory.
  lockfree::PushOnlyStack<BigNode> _bigNode_Stack;
  butil::atomic<uint32_t> _total_bigNode_size;
  butil::atomic<uint32_t> _total_bigNode_count;

  // '_big_mem_start' points to a single big memory belong to Region.
  // _big_mem_capacity is the size of single big memory.
  // _big_mem_size is the already used size.
  // _big_mem_count is the used count.
  char* _big_mem_start;
  uint32_t _big_mem_capacity;  // 32M
W
wangguibao 已提交
366 367 368 369 370
  butil::atomic<uint32_t> _big_mem_size;
  butil::atomic<uint32_t> _big_mem_count;
};
}  // namespace memory
}  // namespace fugue
W
wangguibao 已提交
371 372

class Mempool {
W
wangguibao 已提交
373 374 375
 public:
  void* malloc(size_t size) {
    size = _align(size);
H
HexToString 已提交
376 377
    // It does not enter the if statement the first time.
    // Because the block has not been used up, it will enter.
W
wangguibao 已提交
378 379 380 381 382
    if (size <= _free_size) {
      void* p = _free_cursor;
      _free_size -= size;
      _free_cursor += size;
      return p;
W
wangguibao 已提交
383 384
    }

W
wangguibao 已提交
385 386
    return malloc_from_region(size);
  }
W
wangguibao 已提交
387

W
wangguibao 已提交
388
  void free(void* p, size_t size) {
H
HexToString 已提交
389 390 391
    // size>Block(2M)
    // other memory is managed by Region,no need to release here.
    if (size > fugue::memory::Region::BIG_MEM_THRESHOLD) {
W
wangguibao 已提交
392
      return;
W
wangguibao 已提交
393 394
    }

H
HexToString 已提交
395
    // memory in Block,update the pointer.
W
wangguibao 已提交
396
    if (_free_cursor - size == static_cast<char*>(p)) {
H
HexToString 已提交
397 398
      // for example, you need to release -(8+1)bytes
      // you can only release -8bytes,cause -(8+2)byte is used by other.
W
wangguibao 已提交
399 400 401 402 403
      size_t down_aligned = _down_align(size);
      _free_cursor -= down_aligned;
      _free_size += down_aligned;
    }
  }
W
wangguibao 已提交
404

W
wangguibao 已提交
405
  void* realloc(void* old_data, size_t old_size, size_t new_size) {
H
HexToString 已提交
406
    // Return the pointer directly and reuse it without expansion.
W
wangguibao 已提交
407 408 409
    if (old_size >= new_size) {
      return old_data;
    }
W
wangguibao 已提交
410

W
wangguibao 已提交
411 412 413 414 415 416 417
    size_t required = new_size - old_size;
    if (_free_cursor == static_cast<char*>(old_data) + old_size) {
      if (_free_size >= required) {
        _free_cursor += required;
        _free_size -= required;
        return old_data;
      } else {
H
HexToString 已提交
418 419 420
        // old_data will copy to other structure
        // so _free_cursor rollback,means the memory used by old_data can be
        // used.
W
wangguibao 已提交
421 422 423
        _free_cursor = static_cast<char*>(old_data);
        _free_size += old_size;
      }
W
wangguibao 已提交
424 425
    }

H
HexToString 已提交
426
    // 可能返回的是单独Region中malloc的内存。
H
HexToString 已提交
427 428
    // 也可能是Block,例如new_size=1M, old_data原本的指针头就在1.2M处,old_size
    // =
H
HexToString 已提交
429 430 431
    // 0.5M
    // 此时,_free_size = 0.3M,new_size<2M,但是required = 1-0.5 >0.3
    // 分配出来的就是Block,但是该Block没有并很完美的利用完全。
W
wangguibao 已提交
432 433 434 435
    void* p = this->malloc_from_region(new_size);
    if (p != NULL) {
      memcpy(p, old_data, old_size);
      return p;
W
wangguibao 已提交
436 437
    }

W
wangguibao 已提交
438 439 440
    return NULL;
  }

H
HexToString 已提交
441 442 443
  explicit Mempool(fugue::memory::Region* region)
      : _free_size(0), _free_cursor(NULL), _region(region) {
    _blockReference = NULL;
W
wangguibao 已提交
444 445 446 447 448
  }

  ~Mempool() { release_block(); }

  void release_block() {
H
HexToString 已提交
449 450 451
    if (_blockReference) {
      _blockReference->offset = fugue::memory::Block::BLOCK_SIZE - _free_size;
      _region->put(_blockReference);
W
wangguibao 已提交
452 453
    }

W
wangguibao 已提交
454 455
    _free_size = 0;
    _free_cursor = NULL;
H
HexToString 已提交
456
    _blockReference = NULL;
W
wangguibao 已提交
457
  }
W
wangguibao 已提交
458

W
wangguibao 已提交
459 460
 private:
  void* malloc_from_region(size_t size) {
H
HexToString 已提交
461 462 463 464
    // if greater than BIG_MEM_THRESHOLD, _region->malloc
    // else get the memory from the Block.
    if (size > fugue::memory::Region::BIG_MEM_THRESHOLD) {
      return _region->malloc(size);
W
wangguibao 已提交
465 466
    }

W
wangguibao 已提交
467
    while (true) {
H
HexToString 已提交
468 469
      fugue::memory::BlockReference* blockReference = _region->get();
      if (blockReference == NULL) {
W
wangguibao 已提交
470 471
        return NULL;
      }
W
wangguibao 已提交
472

H
HexToString 已提交
473 474 475
      uint32_t free_size =
          fugue::memory::Block::BLOCK_SIZE - blockReference->offset;
      // 若未能满足要求,则while下一次循环,那么上次的block必然成为野值。
W
wangguibao 已提交
476
      if (size <= free_size) {
H
HexToString 已提交
477 478 479 480 481 482 483
        // 试图更新该节点的offset,但是该结点已经变成了野值,无法被再次使用了,只有等待归还。
        // 应将该节点put进队列,进入该判断语句内,证明本来get已肯定可以return.
        // 此时,上次没用完的值,应该更新offset后,还回去,下次没准还能用,不至于浪费。
        if (_blockReference) {
          _blockReference->offset =
              fugue::memory::Block::BLOCK_SIZE - _free_size;
          _region->put(_blockReference);
W
wangguibao 已提交
484
        }
W
wangguibao 已提交
485

H
HexToString 已提交
486
        char* p = blockReference->block->data + blockReference->offset;
W
wangguibao 已提交
487 488
        _free_size = free_size - size;
        _free_cursor = p + size;
H
HexToString 已提交
489
        _blockReference = blockReference;
W
wangguibao 已提交
490 491
        return p;
      }
W
wangguibao 已提交
492
    }
H
HexToString 已提交
493 494
    // It's not executed at all, for the sake of syntax.
    return _region->malloc(size);
W
wangguibao 已提交
495
  }
W
wangguibao 已提交
496

W
wangguibao 已提交
497
  static const int ALIGN_SIZE = sizeof(void*);
W
wangguibao 已提交
498

H
HexToString 已提交
499
  // align to the 8bytes, if (8+1), it will be (8+8)bytes.
W
wangguibao 已提交
500 501 502
  inline size_t _align(size_t size) const {
    return (size + (ALIGN_SIZE - 1)) & ~(ALIGN_SIZE - 1);
  }
W
wangguibao 已提交
503

H
HexToString 已提交
504
  // down_align to 8bytes, if (8+1), it will be (8+0)bytes.
W
wangguibao 已提交
505 506 507
  inline size_t _down_align(size_t size) const {
    return size & ~(ALIGN_SIZE - 1);
  }
W
wangguibao 已提交
508

W
wangguibao 已提交
509 510
  size_t _free_size;
  char* _free_cursor;
W
wangguibao 已提交
511

H
HexToString 已提交
512 513
  fugue::memory::Region* _region;
  fugue::memory::BlockReference* _blockReference;
W
wangguibao 已提交
514 515
};

H
HexToString 已提交
516 517 518
// use threal-local key instead of __thread.
// it`s not referenced.
/*
W
wangguibao 已提交
519
extern __thread Mempool* g_mempool;
H
HexToString 已提交
520 521 522 523 524
*/

// class mempool is a Interface.
// it`s not necessary at all.
/*
W
wangguibao 已提交
525
class mempool {
W
wangguibao 已提交
526 527 528 529
 public:
  virtual void* malloc(size_t size) = 0;
  virtual void free(void* p, size_t size) = 0;
  inline virtual ~mempool() {}
W
wangguibao 已提交
530
};
H
HexToString 已提交
531
*/
W
wangguibao 已提交
532

H
HexToString 已提交
533 534 535 536 537
// GlobalMempool is a Singleton-RAII class.
// It`s propose is to manage the thread-local pointer 'g_mempool'(class
// Mempool*)
// It`s not referenced, so it`s useless.
/*
W
wangguibao 已提交
538
class GlobalMempool : public mempool {
W
wangguibao 已提交
539 540 541 542
 public:
  GlobalMempool() {
    // do nothing;
  }
W
wangguibao 已提交
543

W
wangguibao 已提交
544 545 546
  virtual ~GlobalMempool() {
    // do nothing;
  }
W
wangguibao 已提交
547

W
wangguibao 已提交
548 549 550 551
  static GlobalMempool* instance() {
    static GlobalMempool singleton;
    return &singleton;
  }
W
wangguibao 已提交
552

W
wangguibao 已提交
553
  void reset(Mempool* mempool) { g_mempool = mempool; }
W
wangguibao 已提交
554

W
wangguibao 已提交
555
  void* malloc(size_t size) { return g_mempool->malloc(size); }
W
wangguibao 已提交
556

W
wangguibao 已提交
557 558 559
  void* realloc(void* old_data, size_t old_size, size_t new_size) {
    return g_mempool->realloc(old_data, old_size, new_size);
  }
W
wangguibao 已提交
560

W
wangguibao 已提交
561
  void free(void* p, size_t s) { g_mempool->free(p, s); }
W
wangguibao 已提交
562

W
wangguibao 已提交
563
  void clear() { g_mempool->release_block(); }
W
wangguibao 已提交
564

W
wangguibao 已提交
565
  Mempool* get() { return g_mempool; }
W
wangguibao 已提交
566
};
H
HexToString 已提交
567
*/
W
wangguibao 已提交
568

H
HexToString 已提交
569 570 571 572 573
// MempoolGuard is a RAII class.
// It`s propose is to manage the thread-local pointer 'g_mempool'(class
// Mempool*)
// It`s not referenced, so it`s useless.
/*
W
wangguibao 已提交
574
class MempoolGuard {
W
wangguibao 已提交
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
 public:
  explicit MempoolGuard(fugue::memory::Region* region) : _mempool(region) {
    acquire();
  }

  void acquire() {
    _saved_mempool = g_mempool;
    g_mempool = &_mempool;
  }

  void release() {
    _mempool.release_block();
    g_mempool = _saved_mempool;
  }

  ~MempoolGuard() { release(); }

 private:
  Mempool _mempool;
  Mempool* _saved_mempool;
W
wangguibao 已提交
595
};
H
HexToString 已提交
596
*/
W
wangguibao 已提交
597
inline std::string print_trace() {
W
wangguibao 已提交
598 599
  static const int BT_BUF_SIZE = 400;
  std::stringstream debug_stream;
W
wangguibao 已提交
600

W
wangguibao 已提交
601 602 603
  void* buffer[BT_BUF_SIZE];
  int nptrs = backtrace(buffer, BT_BUF_SIZE);
  char** strings = backtrace_symbols(buffer, nptrs);
W
wangguibao 已提交
604

W
wangguibao 已提交
605 606 607
  for (int j = 0; j < nptrs; j++) {
    debug_stream << strings[j] << "\t";
  }
W
wangguibao 已提交
608

W
wangguibao 已提交
609
  return debug_stream.str();
W
wangguibao 已提交
610
}
W
wangguibao 已提交
611
}  // namespace im