summaryrefslogtreecommitdiffstats
path: root/gst/goom/goomsl_heap.c
blob: e418a2af502ee5c4e1a0a68aa2f54c73f5ad056a (plain)
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "goomsl_heap.h"
#include <stdlib.h>

struct _GOOM_HEAP
{
  void **arrays;
  int number_of_arrays;
  int size_of_each_array;
  int consumed_in_last_array;
};

/* Constructors / Destructor */
GoomHeap *
goom_heap_new (void)
{
  return goom_heap_new_with_granularity (4096);
}

GoomHeap *
goom_heap_new_with_granularity (int granularity)
{
  GoomHeap *_this;

  _this = (GoomHeap *) malloc (sizeof (GoomHeap));
  _this->number_of_arrays = 0;
  _this->size_of_each_array = granularity;
  _this->consumed_in_last_array = 0;
  _this->arrays = (void **) malloc (sizeof (void *));
  return _this;
}

void
goom_heap_delete (GoomHeap * _this)
{
  int i;

  for (i = 0; i < _this->number_of_arrays; ++i) {
    free (_this->arrays[i]);
  }
  free (_this->arrays);
  free (_this);
}

static void
align_it (GoomHeap * _this, int alignment)
{
  if ((alignment > 1) && (_this->number_of_arrays > 0)) {
    void *last_array = _this->arrays[_this->number_of_arrays - 1];
    long last_address = (long) last_array + _this->consumed_in_last_array;
    long decal = (last_address % alignment);

    if (decal != 0) {
      _this->consumed_in_last_array += alignment - decal;
    }
  }
}

void *
goom_heap_malloc_with_alignment_prefixed (GoomHeap * _this, int nb_bytes,
    int alignment, int prefix_bytes)
{
  void *retval = NULL;

  /* d'abord on gere les problemes d'alignement */
  _this->consumed_in_last_array += prefix_bytes;
  align_it (_this, alignment);

  /* ensuite on verifie que la quantite de memoire demandee tient dans le buffer */
  if ((_this->consumed_in_last_array + nb_bytes >= _this->size_of_each_array)
      || (_this->number_of_arrays == 0)) {

    if (prefix_bytes + nb_bytes + alignment >= _this->size_of_each_array) {

      /* Si la zone demandee est plus grosse que la granularitee */
      /* On alloue un buffer plus gros que les autres */
      _this->arrays =
          (void **) realloc (_this->arrays,
          sizeof (void *) * (_this->number_of_arrays + 2));

      _this->number_of_arrays += 1;
      _this->consumed_in_last_array = prefix_bytes;

      _this->arrays[_this->number_of_arrays - 1] =
          malloc (prefix_bytes + nb_bytes + alignment);
      align_it (_this, alignment);
      retval =
          (void *) ((char *) _this->arrays[_this->number_of_arrays - 1] +
          _this->consumed_in_last_array);

      /* puis on repart sur un nouveau buffer vide */
      _this->number_of_arrays += 1;
      _this->consumed_in_last_array = 0;
      _this->arrays[_this->number_of_arrays - 1] =
          malloc (_this->size_of_each_array);
      return retval;
    } else {
      _this->number_of_arrays += 1;
      _this->consumed_in_last_array = prefix_bytes;
      _this->arrays =
          (void **) realloc (_this->arrays,
          sizeof (void *) * _this->number_of_arrays);

      _this->arrays[_this->number_of_arrays - 1] =
          malloc (_this->size_of_each_array);
      align_it (_this, alignment);
    }
  }
  retval =
      (void *) ((char *) _this->arrays[_this->number_of_arrays - 1] +
      _this->consumed_in_last_array);
  _this->consumed_in_last_array += nb_bytes;
  return retval;
}

void *
goom_heap_malloc_with_alignment (GoomHeap * _this, int nb_bytes, int alignment)
{
  return goom_heap_malloc_with_alignment_prefixed (_this, nb_bytes, alignment,
      0);
}

void *
goom_heap_malloc (GoomHeap * _this, int nb_bytes)
{
  return goom_heap_malloc_with_alignment (_this, nb_bytes, 1);
}