Apollo  6.0
Open source self driving car software
object_pool.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2018 The Apollo Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 
17 #ifndef CYBER_BASE_OBJECT_POOL_H_
18 #define CYBER_BASE_OBJECT_POOL_H_
19 
20 #include <algorithm>
21 #include <cstdlib>
22 #include <cstring>
23 #include <functional>
24 #include <iostream>
25 #include <memory>
26 #include <new>
27 #include <utility>
28 
29 #include "cyber/base/for_each.h"
30 #include "cyber/base/macros.h"
31 
32 namespace apollo {
33 namespace cyber {
34 namespace base {
35 
36 template <typename T>
37 class ObjectPool : public std::enable_shared_from_this<ObjectPool<T>> {
38  public:
39  using InitFunc = std::function<void(T *)>;
40  using ObjectPoolPtr = std::shared_ptr<ObjectPool<T>>;
41 
42  template <typename... Args>
43  explicit ObjectPool(uint32_t num_objects, Args &&... args);
44 
45  template <typename... Args>
46  ObjectPool(uint32_t num_objects, InitFunc f, Args &&... args);
47 
48  virtual ~ObjectPool();
49 
50  std::shared_ptr<T> GetObject();
51 
52  private:
53  struct Node {
54  T object;
55  Node *next;
56  };
57 
58  ObjectPool(ObjectPool &) = delete;
59  ObjectPool &operator=(ObjectPool &) = delete;
60  void ReleaseObject(T *);
61 
62  uint32_t num_objects_ = 0;
63  char *object_arena_ = nullptr;
64  Node *free_head_ = nullptr;
65 };
66 
67 template <typename T>
68 template <typename... Args>
69 ObjectPool<T>::ObjectPool(uint32_t num_objects, Args &&... args)
70  : num_objects_(num_objects) {
71  const size_t size = sizeof(Node);
72  object_arena_ = static_cast<char *>(std::calloc(num_objects_, size));
73  if (object_arena_ == nullptr) {
74  throw std::bad_alloc();
75  }
76 
77  FOR_EACH(i, 0, num_objects_) {
78  T *obj = new (object_arena_ + i * size) T(std::forward<Args>(args)...);
79  reinterpret_cast<Node *>(obj)->next = free_head_;
80  free_head_ = reinterpret_cast<Node *>(obj);
81  }
82 }
83 
84 template <typename T>
85 template <typename... Args>
86 ObjectPool<T>::ObjectPool(uint32_t num_objects, InitFunc f, Args &&... args)
87  : num_objects_(num_objects) {
88  const size_t size = sizeof(Node);
89  object_arena_ = static_cast<char *>(std::calloc(num_objects_, size));
90  if (object_arena_ == nullptr) {
91  throw std::bad_alloc();
92  }
93 
94  FOR_EACH(i, 0, num_objects_) {
95  T *obj = new (object_arena_ + i * size) T(std::forward<Args>(args)...);
96  f(obj);
97  reinterpret_cast<Node *>(obj)->next = free_head_;
98  free_head_ = reinterpret_cast<Node *>(obj);
99  }
100 }
101 
102 template <typename T>
104  if (object_arena_ != nullptr) {
105  const size_t size = sizeof(Node);
106  FOR_EACH(i, 0, num_objects_) {
107  reinterpret_cast<Node *>(object_arena_ + i * size)->object.~T();
108  }
109  std::free(object_arena_);
110  }
111 }
112 
113 template <typename T>
114 void ObjectPool<T>::ReleaseObject(T *object) {
115  if (cyber_unlikely(object == nullptr)) {
116  return;
117  }
118 
119  reinterpret_cast<Node *>(object)->next = free_head_;
120  free_head_ = reinterpret_cast<Node *>(object);
121 }
122 
123 template <typename T>
124 std::shared_ptr<T> ObjectPool<T>::GetObject() {
125  if (cyber_unlikely(free_head_ == nullptr)) {
126  return nullptr;
127  }
128 
129  auto self = this->shared_from_this();
130  auto obj =
131  std::shared_ptr<T>(reinterpret_cast<T *>(free_head_),
132  [self](T *object) { self->ReleaseObject(object); });
133  free_head_ = free_head_->next;
134  return obj;
135 }
136 
137 } // namespace base
138 } // namespace cyber
139 } // namespace apollo
140 
141 #endif // CYBER_BASE_OBJECT_POOL_H_
ObjectPool(uint32_t num_objects, Args &&... args)
Definition: object_pool.h:69
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
virtual ~ObjectPool()
Definition: object_pool.h:103
std::shared_ptr< T > GetObject()
Definition: object_pool.h:124
#define FOR_EACH(i, begin, end)
Definition: for_each.h:44
std::function< void(T *)> InitFunc
Definition: object_pool.h:39
std::shared_ptr< ObjectPool< T > > ObjectPoolPtr
Definition: object_pool.h:40
Definition: object_pool.h:37
#define cyber_unlikely(x)
Definition: macros.h:28