1 karl 1.9 //%2005////////////////////////////////////////////////////////////////////////
|
2 kumpf 1.1 //
|
3 karl 1.8 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.6 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.8 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 kumpf 1.1 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 kumpf 1.2 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16 kumpf 1.1 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
|
19 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
22 kumpf 1.2 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
25 kumpf 1.1 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Mike Brasher (mbrasher@bmc.com)
31 //
32 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
33 mike 1.11 // Mike Brasher, Inova Europe (mike-brasher@austin.rr.com)
|
34 kumpf 1.1 //
35 //%/////////////////////////////////////////////////////////////////////////////
36
37 #ifndef Pegasus_ArrayRep_h
38 #define Pegasus_ArrayRep_h
39
|
40 humberto 1.7 #ifdef PEGASUS_OS_OS400
41 #include <stdlib.h>
42 #endif
43
|
44 kumpf 1.1 #include <new>
45 #include <Pegasus/Common/Config.h>
46 #include <Pegasus/Common/Memory.h>
|
47 mike 1.11 #include <Pegasus/Common/AtomicInt.h>
48 #include <Pegasus/Common/Linkage.h>
49
50 #define Array_rep (static_cast<ArrayRep<PEGASUS_ARRAY_T>*>(_rep))
51 #define Array_size (Array_rep)->size
52 #define Array_data (Array_rep)->data()
53 #define Array_capacity (Array_rep)->capacity
54 #define Array_refs (Array_rep)->refs
|
55 kumpf 1.1
|
56 mike 1.13 // The OS400 platform uses this aligment directive to ensure that
57 // ArrayRepBase is aligned an a 16 byte boundary.
58 #ifdef PEGASUS_OS_OS400
59 # define PEGASUS_ALIGN16 __align(16)
60 #else
61 # define PEGASUS_ALIGN16 /* not necessary on other platforms */
62 #endif
63
|
64 kumpf 1.1 PEGASUS_NAMESPACE_BEGIN
65
|
66 mike 1.13 PEGASUS_ALIGN16
|
67 mike 1.11 struct PEGASUS_COMMON_LINKAGE ArrayRepBase
68 {
69 // We put this first to avoid gaps in this structure. Some compilers may
70 // align it on a large boundary.
71 AtomicInt refs;
72
73 Uint32 size;
74
75 union
76 {
77 Uint32 capacity;
78 Uint64 alignment;
79 };
80
81 // Called only only _empty_rep object. We set the reference count to
82 // two and it will remain two for the lifetime of the process. Anything
83 // other than one will do. If the _empty_rep.refs were one, an Array
84 // object may think it is the sole owner and attempt to modify it.
85
86 ArrayRepBase() : refs(2), size(0), capacity(0) { }
87
88 mike 1.11 static ArrayRepBase _empty_rep;
89 };
90
|
91 kumpf 1.1 /* ArrayRep<T>
92 The ArrayRep object represents the array size, capacity,
93 and elements in one contiguous chunk of memory. The elements
94 follow immediately after the end of the ArrayRep structure in memory.
95 The union is used to force 64 bit alignment of these elements. This is
96 a private class and should not be accessed directly by the user.
97 */
98 template<class T>
|
99 mike 1.11 struct ArrayRep : public ArrayRepBase
|
100 kumpf 1.1 {
101 // Obtains a pointer to the first element in the array.
102 T* data() { return (T*)(void*)(this + 1); }
103
104 // Same as method above but returns a constant pointer.
105 const T* data() const { return (const T*)(void*)(this + 1); }
106
|
107 mike 1.11 /* Make a new copy */
108 static ArrayRep<T>* copy_on_write(ArrayRep<T>* rep);
|
109 kumpf 1.1
110 /* Create and initialize a ArrayRep instance. Note that the
111 memory for the elements is unitialized and must be initialized by
112 the caller.
113 */
|
114 mike 1.11 static ArrayRep<T>* PEGASUS_STATIC_CDECL alloc(Uint32 size);
115
116 static void ref(const ArrayRep<T>* rep);
|
117 kumpf 1.1
|
118 mike 1.11 static void unref(const ArrayRep<T>* rep);
|
119 kumpf 1.1 };
120
121 template<class T>
|
122 mike 1.11 ArrayRep<T>* PEGASUS_STATIC_CDECL ArrayRep<T>::alloc(Uint32 size)
|
123 kumpf 1.1 {
|
124 mike 1.11 // ATTN-MEB: throw out raising to next power of two (put this
125 // logic in reserveCapacity().
126
127 if (!size)
128 return (ArrayRep<T>*)&ArrayRepBase::_empty_rep;
|
129 kumpf 1.1
130 // Calculate capacity (size rounded to the next power of two).
131
|
132 keith.petley 1.4 Uint32 initialCapacity = 8;
|
133 kumpf 1.1
|
134 kumpf 1.5 while ((initialCapacity != 0) && (initialCapacity < size))
135 {
|
136 keith.petley 1.4 initialCapacity <<= 1;
|
137 kumpf 1.5 }
138
139 // Test for Uint32 overflow in the capacity
140 if (initialCapacity == 0)
141 {
142 initialCapacity = size;
143 }
144
145 // Test for Uint32 overflow in the memory allocation size
146 if (initialCapacity > (Uint32(0xffffffff)-sizeof(ArrayRep<T>))/sizeof(T))
147 {
148 return 0;
149 }
|
150 kumpf 1.1
151 // Create object:
152
|
153 kumpf 1.5 ArrayRep<T>* rep = (ArrayRep<T>*)operator new(
154 sizeof(ArrayRep<T>) + sizeof(T) * initialCapacity);
|
155 david 1.10
|
156 kumpf 1.1 rep->size = size;
|
157 keith.petley 1.4 rep->capacity = initialCapacity;
|
158 mike 1.11 new(&rep->refs) AtomicInt(1);
|
159 kumpf 1.1
160 return rep;
161 }
162
163 template<class T>
|
164 mike 1.11 inline void ArrayRep<T>::ref(const ArrayRep<T>* rep)
|
165 kumpf 1.1 {
|
166 mike 1.12 if ((void*)rep != (void*)&ArrayRepBase::_empty_rep)
|
167 mike 1.11 ((ArrayRep<T>*)rep)->refs.inc();
168 }
169
170 template<class T>
171 inline void ArrayRep<T>::unref(const ArrayRep<T>* rep_)
172 {
173 ArrayRep<T>* rep = (ArrayRep<T>*)rep_;
174
175 if (rep != &ArrayRepBase::_empty_rep && rep->refs.decAndTestIfZero())
|
176 kumpf 1.1 {
177 Destroy(rep->data(), rep->size);
|
178 mike 1.11 rep->refs.~AtomicInt();
179 ::operator delete(rep);
180 }
181 }
|
182 david 1.10
|
183 mike 1.11 template<class T>
184 ArrayRep<T>* ArrayRep<T>::copy_on_write(ArrayRep<T>* rep)
185 {
186 ArrayRep<T>* new_rep = ArrayRep<T>::alloc(rep->size);
187 new_rep->size = rep->size;
188 CopyToRaw(new_rep->data(), rep->data(), rep->size);
189 unref(rep);
190 return new_rep;
|
191 kumpf 1.1 }
192
193 PEGASUS_NAMESPACE_END
194
195 #endif /* Pegasus_ArrayRep_h */
|