1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "array.h"
26
27 #include <assert.h>
28 #include <new>
29 #include <common.h>
30 #include "types.h"
31 #include "instance.h"
32
33 MI_BEGIN_NAMESPACE
34
35 struct header
36 {
37 AtomicType m_refCounter;
38 MI_Uint32 m_capacity;
39 };
40
41 struct Array_data
42 {
43 mike 1.1 void* p;
44 MI_Uint32 size;
45 };
46
47 //==============================================================================
48 //
49 // Traits for 'raw' types.
50 //
51 //==============================================================================
52
53 static ArrayTraits _uint8Traits =
54 {
55 sizeof(Uint8), 0, 0,
56 };
57
58 static ArrayTraits _uint16Traits =
59 {
60 sizeof(Uint16), 0, 0,
61 };
62
63 static ArrayTraits _uint32Traits =
64 mike 1.1 {
65 sizeof(Uint32), 0, 0,
66 };
67
68 static ArrayTraits _uint64Traits =
69 {
70 sizeof(Uint64), 0, 0,
71 };
72
73 static ArrayTraits _datetimeTraits =
74 {
75 sizeof(Datetime), 0, 0,
76 };
77
78 static void _stringCtor(void* dest_, const void* src_, MI_Uint32 size)
79 {
80 String* dest = (String*)dest_;
81 const String* src = (const String*)src_;
82
83 while(size--)
84 new(dest++) String(*src++);
85 mike 1.1 }
86
87 static void _stringDtor(void* data_, MI_Uint32 size)
88 {
89 String* data = (String*)data_;
90
91 while (size--)
92 data++->~String();
93 }
94
95 static ArrayTraits _stringTraits =
96 {
97 sizeof(String), _stringCtor, _stringDtor,
98 };
99
100 static void _instanceCtor(void* dest_, const void* src_, MI_Uint32 size)
101 {
102 Instance* dest = (Instance*)dest_;
103 const Instance* src = (const Instance*)src_;
104
105 while(size--)
106 mike 1.1 new(dest++) Instance(*src++);
107 }
108
109 static void _instanceDtor(void* data_, MI_Uint32 size)
110 {
111 Instance* data = (Instance*)data_;
112
113 while (size--)
114 data++->~Instance();
115 }
116
117 static ArrayTraits _instanceTraits =
118 {
119 sizeof(Instance), _instanceCtor, _instanceDtor,
120 };
121
122 /* Indexable by scalar type */
123 const ArrayTraits* __traits[16] =
124 {
125 &_uint8Traits, /* boolean */
126 &_uint8Traits, /* uint8 */
127 mike 1.1 &_uint8Traits, /* sint8 */
128 &_uint16Traits, /* uint16 */
129 &_uint16Traits, /* sint64 */
130 &_uint32Traits, /* uint32 */
131 &_uint32Traits, /* sint32 */
132 &_uint64Traits, /* uint64 */
133 &_uint64Traits, /* sint64 */
134 &_uint32Traits, /* real32 */
135 &_uint64Traits, /* real64 */
136 &_uint16Traits, /* char16 */
137 &_datetimeTraits, /* datetime */
138 &_stringTraits, /* string */
139 &_instanceTraits, /* reference */
140 &_instanceTraits, /* instance */
141 };
142
143 //==============================================================================
144 //
145 // Array
146 //
147 //==============================================================================
148 mike 1.1
149 enum { CAPACITY_ALIGMENT = 16 };
150 // returns 0 - for 0; 16 for 1-6; 32 for 17-32 etc
151 inline static MI_Uint32 AlignCapacity(MI_Uint32 size) {return ((size + CAPACITY_ALIGMENT -1) / CAPACITY_ALIGMENT) * CAPACITY_ALIGMENT;}
152
153 static void* Allocate(MI_Uint32 size, const ArrayTraits* v_traits)
154 {
155 MI_Uint32 capacity = AlignCapacity(size);
156
157 // allocate new buffer
158 header* chunk = (header*)operator new(sizeof(header) + capacity * v_traits->size);
159
160 chunk->m_capacity = capacity;
161 AtomicSet(chunk->m_refCounter, 0);
162
163 return (chunk + 1);
164 }
165
166 inline static header* GetHeader(void* buf)
167 {
168 return reinterpret_cast<header*>(reinterpret_cast<char*>(buf) - sizeof(header));
169 mike 1.1 }
170
171 inline static void AddRef(void* data)
172 {
173 if ( data )
174 AtomicInc(GetHeader(data)->m_refCounter);
175 }
176
177 static void Release(void* v_this, const ArrayTraits* v_traits)
178 {
179 Array_data* v = (Array_data*)v_this;
180 if ( v->p &&
181 AtomicDec(GetHeader(v->p)->m_refCounter))
182 {
183 if (v_traits->dtor)
184 v_traits->dtor(v->p,v->size);
185
186 operator delete(GetHeader(v->p));
187 v->p = 0;
188 v->size = 0;
189 }
190 mike 1.1 }
191
192 // Array class implementation - taken out to reduce code size
193 void __ArrayCopyCtor(void* v_this, const ArrayTraits* v_traits, const void* v_obj, MI_Uint32 count)
194 {
195 Array_data* v = (Array_data*)v_this;
196
197 v->p = Allocate(count,v_traits);
198 v->size = count;
199 AddRef(v->p);
200
201 if(v_traits->copy_ctor)
202 v_traits->copy_ctor(v->p,v_obj,count);
203 else
204 memcpy(v->p,v_obj,count*v_traits->size);
205 }
206
207 void __ArrayAssign(void* v_this, const ArrayTraits* v_traits, const void* v_other)
208 {
209 Array_data* v = (Array_data*)v_this;
210 const Array_data* v_x = (const Array_data*)v_other;
211 mike 1.1
212 Release(v_this, v_traits);
213
214 if (v_x)
215 {
216 *v = *v_x;
217 AddRef(v->p);
218 }
219 }
220
221 void __ArrayCOW(void* v_this, const ArrayTraits* v_traits)
222 {
223 Array_data* v = (Array_data*)v_this;
224 if ( v->p && AtomicGet(GetHeader(v->p)->m_refCounter) != 1 )
225 {
226 void* new_data = Allocate(v->size,v_traits);
227
228 if (v_traits->copy_ctor)
229 v_traits->copy_ctor(new_data,v->p,v->size);
230 else
231 memcpy(new_data,v->p,v->size*v_traits->size);
232 mike 1.1
233 Release(v_this,v_traits);
234 v->p = new_data;
235 AddRef(v->p);
236 }
237 }
238
239 void __ArrayResize(void* v_this, const ArrayTraits* v_traits, const void* v_obj, MI_Uint32 new_size)
240 {
241 Array_data* v = (Array_data*)v_this;
242
243 // special case - remove all
244 if (!new_size)
245 {
246 Release(v_this,v_traits);
247 v->p = 0;
248 v->size = 0;
249 return;
250 }
251
252 // assumptions:
253 mike 1.1 // size > 0
254 // if size < m_size, buffer stays the same
255 // actions:
256 // cow()
257 // re-alloc
258
259 // make own copy
260 __ArrayCOW(v_this,v_traits);
261
262
263 // see if we need to re-alloc
264 if ( !v->p || GetHeader(v->p)->m_capacity < new_size)
265 {
266 void* new_data = Allocate(new_size,v_traits);
267 if (v->size)
268 memcpy(new_data,v->p,v->size * v_traits->size);
269
270 if (v->p)
271 operator delete(GetHeader(v->p));
272
273 v->p = new_data;
274 mike 1.1 AddRef(v->p);
275 }
276
277 // delete extra
278 if ( v->size > new_size && v_traits->dtor )
279 {
280 v_traits->dtor(((char*)v->p) + new_size*v_traits->size, v->size-new_size);
281 }
282
283 // create missing
284 if ( v->size < new_size )
285 {
286 // copy elements one-by-one
287 for( ;v->size < new_size; v->size++)
288 {
289 if ( v_traits->copy_ctor )
290 {
291 v_traits->copy_ctor(((char*)v->p) + v->size*v_traits->size,v_obj,1);
292 }
293 else
294 {
295 mike 1.1 memcpy(((char*)v->p) + v->size*v_traits->size,v_obj,v_traits->size);
296 }
297 }
298 }
299
300 v->size = new_size;
301 }
302
303 void __ArrayDelete(void* v_this, const ArrayTraits* v_traits, MI_Uint32 index)
304 {
305 Array_data* v = (Array_data*)v_this;
306
307 __ArrayCOW(v_this,v_traits);
308
309 // destroy item
310 if ( v_traits->dtor )
311 {
312 v_traits->dtor(((char*)v->p) + index*v_traits->size,1);
313 }
314
315 // move the rest
316 mike 1.1 memmove(((char*)v->p) +index*v_traits->size, ((char*)v->p) + (index+1)*v_traits->size, (v->size - index - 1)*v_traits->size);
317
318 // dec size
319 v->size --;
320 }
321
322
323 MI_END_NAMESPACE
|