(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           #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

ViewCVS 0.9.2