source: yaz/trunk/fuentes/src/nmem.c @ 255

Last change on this file since 255 was 255, checked in by mabarracus, 4 years ago

added trusty code to xenial

File size: 3.4 KB
Line 
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
5
6/**
7 * \file nmem.c
8 * \brief Implements Nibble Memory
9 *
10 * This is a simple and fairly wasteful little module for nibble memory
11 * allocation.
12 *
13 */
14#if HAVE_CONFIG_H
15#include <config.h>
16#endif
17
18#include <assert.h>
19#include <stdlib.h>
20#include <string.h>
21#include <errno.h>
22#include <stddef.h>
23#include <yaz/xmalloc.h>
24#include <yaz/nmem.h>
25#include <yaz/log.h>
26
27#define NMEM_CHUNK (4*1024)
28
29struct nmem_block
30{
31    char *buf;              /* memory allocated in this block */
32    size_t size;            /* size of buf */
33    size_t top;             /* top of buffer */
34    struct nmem_block *next;
35};
36
37struct nmem_control
38{
39    size_t total;
40    struct nmem_block *blocks;
41    struct nmem_control *next;
42};
43
44struct align {
45    char x;
46    union {
47        char c;
48        short s;
49        int i;
50        long l;
51#if HAVE_LONG_LONG
52        long long ll;
53#endif
54        float f;
55        double d;
56    } u;
57};
58
59#define NMEM_ALIGN (offsetof(struct align, u))
60
61static int log_level = 0;
62static int log_level_initialized = 0;
63
64static void free_block(struct nmem_block *p)
65{
66    xfree(p->buf);
67    xfree(p);
68    if (log_level)
69        yaz_log(log_level, "nmem free_block p=%p", p);
70}
71
72/*
73 * acquire a block with a minimum of size free bytes.
74 */
75static struct nmem_block *get_block(size_t size)
76{
77    struct nmem_block *r;
78    size_t get = NMEM_CHUNK;
79
80    if (log_level)
81        yaz_log(log_level, "nmem get_block size=%ld", (long) size);
82
83    if (get < size)
84        get = size;
85    if (log_level)
86        yaz_log(log_level, "nmem get_block alloc new block size=%ld",
87                (long) get);
88
89    r = (struct nmem_block *) xmalloc(sizeof(*r));
90    r->buf = (char *)xmalloc(r->size = get);
91    r->top = 0;
92    return r;
93}
94
95void nmem_reset(NMEM n)
96{
97    struct nmem_block *t;
98
99    yaz_log(log_level, "nmem_reset p=%p", n);
100    if (!n)
101        return;
102    while (n->blocks)
103    {
104        t = n->blocks;
105        n->blocks = n->blocks->next;
106        free_block(t);
107    }
108    n->total = 0;
109}
110
111void *nmem_malloc(NMEM n, size_t size)
112{
113    struct nmem_block *p;
114    char *r;
115
116    if (!n)
117    {
118        yaz_log(YLOG_FATAL, "calling nmem_malloc with an null pointer");
119        abort();
120    }
121    p = n->blocks;
122    if (!p || p->size < size + p->top)
123    {
124        p = get_block(size);
125        p->next = n->blocks;
126        n->blocks = p;
127    }
128    r = p->buf + p->top;
129    /* align size */
130    p->top += (size + (NMEM_ALIGN - 1)) & ~(NMEM_ALIGN - 1);
131    n->total += size;
132    return r;
133}
134
135size_t nmem_total(NMEM n)
136{
137    return n->total;
138}
139
140NMEM nmem_create(void)
141{
142    NMEM r;
143    if (!log_level_initialized)
144    {
145        log_level = yaz_log_module_level("nmem");
146        log_level_initialized = 1;
147    }
148
149    r = (struct nmem_control *)xmalloc(sizeof(*r));
150
151    r->blocks = 0;
152    r->total = 0;
153    r->next = 0;
154
155    return r;
156}
157
158void nmem_destroy(NMEM n)
159{
160    if (!n)
161        return;
162
163    nmem_reset(n);
164    xfree(n);
165}
166
167void nmem_transfer(NMEM dst, NMEM src)
168{
169    struct nmem_block *t;
170    while ((t = src->blocks))
171    {
172        src->blocks = t->next;
173        t->next = dst->blocks;
174        dst->blocks = t;
175    }
176    dst->total += src->total;
177    src->total = 0;
178}
179
180/*
181 * Local variables:
182 * c-basic-offset: 4
183 * c-file-style: "Stroustrup"
184 * indent-tabs-mode: nil
185 * End:
186 * vim: shiftwidth=4 tabstop=8 expandtab
187 */
188
Note: See TracBrowser for help on using the repository browser.