aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/crcutil/aligned_alloc.h
blob: 57bdc91d8ae15aafebb4af2150d90f1848897238 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Copyright 2010 Google Inc.  All rights reserved. 
// 
// Licensed under the Apache License, Version 2.0 (the "License"); 
// you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at 
// 
//      http://www.apache.org/licenses/LICENSE-2.0 
// 
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
// See the License for the specific language governing permissions and 
// limitations under the License. 
// 
// Poor man's platform-independent implementation of aligned memory allocator. 
 
#ifndef CRCUTIL_ALIGNED_ALLOC_H_ 
#define CRCUTIL_ALIGNED_ALLOC_H_ 
 
#include "std_headers.h"    // size_t, ptrdiff_t 
 
namespace crcutil { 
 
// Allocates a block of memory of "size" bytes so that a field 
// at "field_offset" is aligned on "align" boundary. 
// 
// NB #1: "align" shall be exact power of two. 
// 
// NB #2: memory allocated by AlignedAlloc should be release by AlignedFree(). 
// 
inline void *AlignedAlloc(size_t size, 
                          size_t field_offset, 
                          size_t align, 
                          const void **allocated_mem) { 
  if (align == 0 || (align & (align - 1)) != 0 || align < sizeof(char *)) { 
    align = sizeof(*allocated_mem); 
  } 
  size += align - 1 + sizeof(*allocated_mem); 
  char *allocated_memory = new char[size]; 
  char *aligned_memory = allocated_memory + sizeof(*allocated_mem); 
  field_offset &= align - 1; 
  size_t actual_alignment = 
      reinterpret_cast<size_t>(aligned_memory + field_offset) & (align - 1); 
  if (actual_alignment != 0) { 
    aligned_memory += align - actual_alignment; 
  } 
  reinterpret_cast<char **>(aligned_memory)[-1] = allocated_memory; 
 
  if (allocated_mem != NULL) { 
    *allocated_mem = allocated_memory; 
  } 
 
  return aligned_memory; 
} 
 
// Frees memory allocated by AlignedAlloc(). 
inline void AlignedFree(void *aligned_memory) { 
  if (aligned_memory != NULL) { 
    char *allocated_memory = reinterpret_cast<char **>(aligned_memory)[-1]; 
    delete[] allocated_memory; 
  } 
} 
 
}  // namespace crcutil 
 
#endif  // CRCUTIL_ALIGNED_ALLOC_H_