(file) Return to array.cpp CVS log (file) (dir) Up to [OMI] / omi / micxx

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

ViewCVS 0.9.2