1 | /* |
---|
2 | * Copyright (C) 1997 Todd Veldhuizen <tveldhui@oonumerics.org> |
---|
3 | * All rights reserved. Please see <blitz/blitz.h> for terms and |
---|
4 | * conditions of use. |
---|
5 | * |
---|
6 | */ |
---|
7 | |
---|
8 | #ifndef BZ_MEMBLOCK_CC |
---|
9 | #define BZ_MEMBLOCK_CC |
---|
10 | |
---|
11 | #include <blitz/numtrait.h> |
---|
12 | |
---|
13 | BZ_NAMESPACE(blitz) |
---|
14 | |
---|
15 | // Null memory block for each (template) instantiation of MemoryBlockReference |
---|
16 | template<typename P_type> |
---|
17 | NullMemoryBlock<P_type> MemoryBlockReference<P_type>::nullBlock_; |
---|
18 | |
---|
19 | template<typename P_type> |
---|
20 | void MemoryBlock<P_type>::deallocate() |
---|
21 | { |
---|
22 | #ifndef BZ_ALIGN_BLOCKS_ON_CACHELINE_BOUNDARY |
---|
23 | delete [] dataBlockAddress_; |
---|
24 | #else |
---|
25 | if (!NumericTypeTraits<T_type>::hasTrivialCtor) { |
---|
26 | for (int i=0; i < length_; ++i) |
---|
27 | data_[i].~T_type(); |
---|
28 | delete [] reinterpret_cast<char*>(dataBlockAddress_); |
---|
29 | } |
---|
30 | else { |
---|
31 | delete [] dataBlockAddress_; |
---|
32 | } |
---|
33 | #endif |
---|
34 | } |
---|
35 | |
---|
36 | template<typename P_type> |
---|
37 | inline void MemoryBlock<P_type>::allocate(size_t length) |
---|
38 | { |
---|
39 | TAU_TYPE_STRING(p1, "MemoryBlock<T>::allocate() [T=" |
---|
40 | + CT(P_type) + "]"); |
---|
41 | TAU_PROFILE(p1, "void ()", TAU_BLITZ); |
---|
42 | |
---|
43 | #ifndef BZ_ALIGN_BLOCKS_ON_CACHELINE_BOUNDARY |
---|
44 | dataBlockAddress_ = new T_type[length]; |
---|
45 | data_ = dataBlockAddress_; |
---|
46 | #else |
---|
47 | size_t numBytes = length * sizeof(T_type); |
---|
48 | |
---|
49 | if (numBytes < 1024) |
---|
50 | { |
---|
51 | dataBlockAddress_ = new T_type[length]; |
---|
52 | data_ = dataBlockAddress_; |
---|
53 | } |
---|
54 | else |
---|
55 | { |
---|
56 | // We're allocating a large array. For performance reasons, |
---|
57 | // it's advantageous to force the array to start on a |
---|
58 | // cache line boundary. We do this by allocating a little |
---|
59 | // more memory than necessary, then shifting the pointer |
---|
60 | // to the next cache line boundary. |
---|
61 | |
---|
62 | // Patches by Petter Urkedal to support types with nontrivial |
---|
63 | // constructors. |
---|
64 | |
---|
65 | const int cacheBlockSize = 128; // Will work for 32, 16 also |
---|
66 | |
---|
67 | dataBlockAddress_ = reinterpret_cast<T_type*> |
---|
68 | (new char[numBytes + cacheBlockSize - 1]); |
---|
69 | |
---|
70 | // Shift to the next cache line boundary |
---|
71 | |
---|
72 | ptrdiff_t offset = ptrdiff_t(dataBlockAddress_) % cacheBlockSize; |
---|
73 | ptrdiff_t shift = (offset == 0) ? 0 : (cacheBlockSize - offset); |
---|
74 | data_ = reinterpret_cast<T_type*> |
---|
75 | (reinterpret_cast<char*>(dataBlockAddress_) + shift); |
---|
76 | |
---|
77 | // Use placement new to construct types with nontrival ctors |
---|
78 | if (!NumericTypeTraits<T_type>::hasTrivialCtor) { |
---|
79 | for (int i=0; i < length; ++i) |
---|
80 | new(&data_[i]) T_type; |
---|
81 | } |
---|
82 | } |
---|
83 | #endif |
---|
84 | } |
---|
85 | |
---|
86 | |
---|
87 | BZ_NAMESPACE_END |
---|
88 | |
---|
89 | #endif // BZ_MEMBLOCK_CC |
---|