]> git.cworth.org Git - apitrace/blob - retrace/scoped_allocator.hpp
retrace: Split ScopedAllocator into its own header.
[apitrace] / retrace / scoped_allocator.hpp
1 /**************************************************************************
2  *
3  * Copyright 2011-2012 Jose Fonseca
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 #ifndef _SCOPED_ALLOCATOR_HPP_
27 #define _SCOPED_ALLOCATOR_HPP_
28
29
30 #include <assert.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33
34
35 /**
36  * Similar to alloca(), but implemented with malloc.
37  */
38 class ScopedAllocator
39 {
40 private:
41     uintptr_t next;
42
43 public:
44     inline
45     ScopedAllocator() :
46         next(0) {
47     }
48
49     inline void *
50     alloc(size_t size) {
51         /* Always return valid address, even when size is zero */
52         size = std::max(size, sizeof(uintptr_t));
53
54         uintptr_t * buf = static_cast<uintptr_t *>(malloc(sizeof(uintptr_t) + size));
55         if (!buf) {
56             return NULL;
57         }
58
59         *buf = next;
60         next = reinterpret_cast<uintptr_t>(buf);
61         assert((next & 1) == 0);
62
63         return static_cast<void *>(&buf[1]);
64     }
65     
66     template< class T >
67     inline T *
68     alloc(size_t size = 1) {
69         return static_cast<T *>(alloc(sizeof(T) * size));
70     }
71
72     /**
73      * Prevent this pointer from being automatically freed.
74      */
75     template< class T >
76     inline void
77     bind(T *ptr) {
78         if (ptr) {
79             reinterpret_cast<uintptr_t *>(ptr)[-1] |= 1;
80         }
81     }
82
83     inline
84     ~ScopedAllocator() {
85         while (next) {
86             uintptr_t temp = *reinterpret_cast<uintptr_t *>(next);
87
88             bool bind = temp & 1;
89             temp &= ~1;
90
91             if (!bind) {
92                 free(reinterpret_cast<void *>(next));
93             }
94
95             next = temp;
96         }
97     }
98 };
99
100
101 #endif /* _SCOPED_ALLOCATOR_HPP_ */