summaryrefslogtreecommitdiff
path: root/src/memory.cc
blob: 9a40b7f08250695ea93ffb2f073314f79a2c7ee5 (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
/**
 * memory.cc - Contains stub definition of C++ new/delete operators.
 *
 * These definitions are intended to be used for testing and are weak symbols
 * to allow them to be replaced by definitions from a STL implementation.
 * These versions simply wrap malloc() and free(), they do not provide a
 * C++-specific allocator.
 */

#include <stddef.h>
#include <stdlib.h>
#include "stdexcept.h"

#ifndef __has_builtin
#define __has_builtin(x) 0
#endif

#if !__has_builtin(__sync_swap)
#define __sync_swap __sync_lock_test_and_set
#endif

namespace std
{
	struct nothrow_t {};
}


/// The type of the function called when allocation fails.
typedef void (*new_handler)();
/**
 * The function to call when allocation fails.  By default, there is no
 * handler and a bad allocation exception is thrown if an allocation fails.
 */
static new_handler new_handl;

namespace std
{
	/**
	 * Sets a function to be called when there is a failure in new.
	 */
	__attribute__((weak))
	new_handler set_new_handler(new_handler handler)
	{
		return __sync_swap(&new_handl, handler);
	}
}


__attribute__((weak))
void* operator new(size_t size)
{
	void * mem = malloc(size);
	while (0 == mem)
	{
		if (0 != new_handl)
		{
			new_handl();
		}
		else
		{
			throw std::bad_alloc();
		}
		mem = malloc(size);
	}

	return mem;
}

__attribute__((weak))
void* operator new(size_t size, const std::nothrow_t &) throw()
{
	void *mem = malloc(size);
	while (0 == mem)
	{
		if (0 != new_handl)
		{
			try
			{
				new_handl();
			}
			catch (...)
			{
				// nothrow operator new should return NULL in case of
				// std::bad_alloc exception in new handler
				return NULL;
			}
		}
		else
		{
			return NULL;
		}
		mem = malloc(size);
	}

	return mem;
}


__attribute__((weak))
void operator delete(void * ptr)
{
	free(ptr);
}


__attribute__((weak))
void * operator new[](size_t size)
{
	return ::operator new(size);
}


__attribute__((weak))
void operator delete[](void * ptr) throw()
{
	::operator delete(ptr);
}