@@ -47,8 +47,8 @@ public:
47
47
uint32_t count);
48
48
// Grow as necessary and return pointer for id.
49
49
TYPE *ensureId (ObjectId id);
50
- TYPE *pointer (ObjectId id) const ;
51
- TYPE &ref (ObjectId id) const ;
50
+ TYPE *pointer (ObjectId id);
51
+ TYPE &ref (ObjectId id);
52
52
size_t size () const { return size_; }
53
53
void clear ();
54
54
@@ -66,11 +66,8 @@ private:
66
66
BlockIdx free_block_idx_;
67
67
// Index of next free object in free_block_idx_.
68
68
ObjectIdx free_idx_;
69
- // Don't use std::vector so growing blocks_ can be thread safe.
70
- size_t blocks_size_;
71
- size_t blocks_capacity_;
72
- ArrayBlock<TYPE> *blocks_;
73
- ArrayBlock<TYPE> *prev_blocks_;
69
+ std::vector<ArrayBlock<TYPE>> blocks_;
70
+ std::vector<ArrayBlock<TYPE>> prev_blocks_;
74
71
// Linked list of free arrays indexed by array size.
75
72
std::vector<ObjectId> free_list_;
76
73
static constexpr ObjectId idx_mask_ = block_size - 1 ;
@@ -80,28 +77,24 @@ template <class TYPE>
80
77
ArrayTable<TYPE>::ArrayTable() :
81
78
size_ (0 ),
82
79
free_block_idx_(block_idx_null),
83
- free_idx_(object_idx_null),
84
- blocks_size_(0 ),
85
- blocks_capacity_(1024 ),
86
- blocks_(new ArrayBlock<TYPE>[blocks_capacity_]),
87
- prev_blocks_(nullptr )
80
+ free_idx_(object_idx_null)
88
81
{
82
+ blocks_.reserve (1024 );
89
83
}
90
84
91
85
template <class TYPE >
92
86
ArrayTable<TYPE>::~ArrayTable ()
93
87
{
94
88
deleteBlocks ();
95
- delete [] blocks_;
96
- delete [] prev_blocks_;
97
89
}
98
90
99
91
template <class TYPE >
100
92
void
101
93
ArrayTable<TYPE>::deleteBlocks()
102
94
{
103
- for (size_t i = 0 ; i < blocks_size_ ; i++)
95
+ for (size_t i = 0 ; i < blocks_. size () ; i++)
104
96
blocks_[i].free ();
97
+ blocks_.clear ();
105
98
}
106
99
107
100
template <class TYPE >
@@ -120,12 +113,12 @@ ArrayTable<TYPE>::make(uint32_t count,
120
113
free_list_[count] = *head;
121
114
}
122
115
else {
123
- ArrayBlock<TYPE> *block = blocks_size_ ? &blocks_[free_block_idx_] : nullptr ;
116
+ ArrayBlock<TYPE> *block = blocks_. size () ? &blocks_[free_block_idx_] : nullptr ;
124
117
if ((free_idx_ == object_idx_null
125
118
&& free_block_idx_ == block_idx_null)
126
119
|| free_idx_ + count >= block->size ()) {
127
120
uint32_t size = block_size;
128
- if (blocks_size_ == 0
121
+ if (blocks_. size () == 0
129
122
// First block starts at idx 1.
130
123
&& count > block_size - 1 )
131
124
size = count + 1 ;
@@ -145,7 +138,7 @@ template <class TYPE>
145
138
ArrayBlock<TYPE> *
146
139
ArrayTable<TYPE>::makeBlock(uint32_t size)
147
140
{
148
- BlockIdx block_idx = blocks_size_ ;
141
+ BlockIdx block_idx = blocks_. size () ;
149
142
pushBlock (size);
150
143
free_block_idx_ = block_idx;
151
144
// ObjectId zero is reserved for object_id_null.
@@ -157,21 +150,17 @@ template <class TYPE>
157
150
void
158
151
ArrayTable<TYPE>::pushBlock(size_t size)
159
152
{
160
- auto blk_idx = blocks_size_++;
161
- blocks_[blk_idx] = ArrayBlock<TYPE>(size);
153
+ blocks_.push_back (ArrayBlock<TYPE>(size));
162
154
163
- if (blocks_size_ >= block_id_max)
155
+ if (blocks_. size () >= block_id_max)
164
156
criticalError (223 , " max array table block count exceeded." );
165
- if (blocks_size_ == blocks_capacity_) {
166
- size_t new_capacity = blocks_capacity_ * 1.5 ;
167
- ArrayBlock<TYPE>* new_blocks = new ArrayBlock<TYPE>[new_capacity];
168
- memcpy (new_blocks, blocks_, blocks_capacity_ * sizeof (ArrayBlock<TYPE>));
169
- if (prev_blocks_)
170
- delete [] prev_blocks_;
157
+ if (blocks_.size () == blocks_.capacity ()) {
158
+ prev_blocks_.reserve (blocks_.capacity () * 1.5 );
159
+ const auto blocks_mid = blocks_.begin () + prev_blocks_.size ();
160
+ std::copy (blocks_.begin (), blocks_mid, prev_blocks_.begin ());
161
+ prev_blocks_.insert (prev_blocks_.end (), blocks_mid, blocks_.end ());
171
162
// Preserve block array for other threads to reference.
172
- prev_blocks_ = blocks_;
173
- blocks_ = new_blocks;
174
- blocks_capacity_ = new_capacity;
163
+ blocks_.swap (prev_blocks_);
175
164
}
176
165
}
177
166
@@ -192,7 +181,7 @@ ArrayTable<TYPE>::destroy(ObjectId id,
192
181
193
182
template <class TYPE >
194
183
TYPE *
195
- ArrayTable<TYPE>::pointer(ObjectId id) const
184
+ ArrayTable<TYPE>::pointer(ObjectId id)
196
185
{
197
186
if (id == object_id_null)
198
187
return nullptr ;
@@ -210,15 +199,15 @@ ArrayTable<TYPE>::ensureId(ObjectId id)
210
199
BlockIdx blk_idx = id >> idx_bits;
211
200
ObjectIdx obj_idx = id & idx_mask_;
212
201
// Make enough blocks for blk_idx to be valid.
213
- for (BlockIdx i = blocks_size_ ; i <= blk_idx; i++) {
202
+ for (BlockIdx i = blocks_. size () ; i <= blk_idx; i++) {
214
203
pushBlock (block_size);
215
204
}
216
205
return blocks_[blk_idx].pointer (obj_idx);
217
206
}
218
207
219
208
template <class TYPE >
220
209
TYPE &
221
- ArrayTable<TYPE>::ref(ObjectId id) const
210
+ ArrayTable<TYPE>::ref(ObjectId id)
222
211
{
223
212
if (id == object_id_null)
224
213
criticalError (222 , " null ObjectId reference is undefined." );
233
222
ArrayTable<TYPE>::clear()
234
223
{
235
224
deleteBlocks ();
236
- blocks_size_ = 0 ;
237
225
size_ = 0 ;
238
226
free_block_idx_ = block_idx_null;
239
227
free_idx_ = object_idx_null;
0 commit comments