1232922Stheraven/*
2232922Stheraven * Copyright 2010-2011 PathScale, Inc. All rights reserved.
3232922Stheraven *
4232922Stheraven * Redistribution and use in source and binary forms, with or without
5232922Stheraven * modification, are permitted provided that the following conditions are met:
6232922Stheraven *
7232922Stheraven * 1. Redistributions of source code must retain the above copyright notice,
8232922Stheraven *    this list of conditions and the following disclaimer.
9232922Stheraven *
10232922Stheraven * 2. Redistributions in binary form must reproduce the above copyright notice,
11232922Stheraven *    this list of conditions and the following disclaimer in the documentation
12232922Stheraven *    and/or other materials provided with the distribution.
13232922Stheraven *
14232922Stheraven * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
15232922Stheraven * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16232922Stheraven * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17232922Stheraven * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
18232922Stheraven * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19232922Stheraven * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20232922Stheraven * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21232922Stheraven * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22232922Stheraven * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23232922Stheraven * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24232922Stheraven * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25232922Stheraven */
26232922Stheraven
27227825Stheraven/**
28227825Stheraven * memory.cc - Contains stub definition of C++ new/delete operators.
29227825Stheraven *
30227825Stheraven * These definitions are intended to be used for testing and are weak symbols
31227825Stheraven * to allow them to be replaced by definitions from a STL implementation.
32227825Stheraven * These versions simply wrap malloc() and free(), they do not provide a
33227825Stheraven * C++-specific allocator.
34227825Stheraven */
35227825Stheraven
36227825Stheraven#include <stddef.h>
37227825Stheraven#include <stdlib.h>
38227825Stheraven#include "stdexcept.h"
39245302Stheraven#include "atomic.h"
40227825Stheraven
41232922Stheraven
42227825Stheravennamespace std
43227825Stheraven{
44227825Stheraven	struct nothrow_t {};
45227825Stheraven}
46227825Stheraven
47227825Stheraven
48227825Stheraven/// The type of the function called when allocation fails.
49227825Stheraventypedef void (*new_handler)();
50227825Stheraven/**
51227825Stheraven * The function to call when allocation fails.  By default, there is no
52227825Stheraven * handler and a bad allocation exception is thrown if an allocation fails.
53227825Stheraven */
54227825Stheravenstatic new_handler new_handl;
55227825Stheraven
56227825Stheravennamespace std
57227825Stheraven{
58227825Stheraven	/**
59227825Stheraven	 * Sets a function to be called when there is a failure in new.
60227825Stheraven	 */
61227825Stheraven	__attribute__((weak))
62227825Stheraven	new_handler set_new_handler(new_handler handler)
63227825Stheraven	{
64245302Stheraven		return ATOMIC_SWAP(&new_handl, handler);
65227825Stheraven	}
66245302Stheraven	__attribute__((weak))
67245302Stheraven	new_handler get_new_handler(void)
68245302Stheraven	{
69245302Stheraven		return ATOMIC_LOAD(&new_handl);
70245302Stheraven	}
71227825Stheraven}
72227825Stheraven
73227825Stheraven
74299144Sdim#if __cplusplus < 201103L
75299144Sdim#define NOEXCEPT throw()
76299144Sdim#define BADALLOC throw(std::bad_alloc)
77299144Sdim#else
78299144Sdim#define NOEXCEPT noexcept
79299144Sdim#define BADALLOC
80299144Sdim#endif
81299144Sdim
82299144Sdim
83227825Stheraven__attribute__((weak))
84299144Sdimvoid* operator new(size_t size) BADALLOC
85227825Stheraven{
86245302Stheraven	if (0 == size)
87245302Stheraven	{
88245302Stheraven		size = 1;
89245302Stheraven	}
90227825Stheraven	void * mem = malloc(size);
91227825Stheraven	while (0 == mem)
92227825Stheraven	{
93245302Stheraven		new_handler h = std::get_new_handler();
94245302Stheraven		if (0 != h)
95227825Stheraven		{
96245302Stheraven			h();
97227825Stheraven		}
98227825Stheraven		else
99227825Stheraven		{
100227825Stheraven			throw std::bad_alloc();
101227825Stheraven		}
102227825Stheraven		mem = malloc(size);
103227825Stheraven	}
104227825Stheraven
105227825Stheraven	return mem;
106227825Stheraven}
107227825Stheraven
108227825Stheraven__attribute__((weak))
109299144Sdimvoid* operator new(size_t size, const std::nothrow_t &) NOEXCEPT
110227825Stheraven{
111253145Stheraven	try {
112253145Stheraven		return :: operator new(size);
113253145Stheraven	} catch (...) {
114253145Stheraven		// nothrow operator new should return NULL in case of
115253145Stheraven		// std::bad_alloc exception in new handler
116253145Stheraven		return NULL;
117245302Stheraven	}
118227825Stheraven}
119227825Stheraven
120227825Stheraven
121227825Stheraven__attribute__((weak))
122299144Sdimvoid operator delete(void * ptr) NOEXCEPT
123227825Stheraven{
124227825Stheraven	free(ptr);
125227825Stheraven}
126227825Stheraven
127227825Stheraven
128227825Stheraven__attribute__((weak))
129299144Sdimvoid * operator new[](size_t size) BADALLOC
130227825Stheraven{
131227825Stheraven	return ::operator new(size);
132227825Stheraven}
133227825Stheraven
134227825Stheraven
135227825Stheraven__attribute__((weak))
136299144Sdimvoid * operator new[](size_t size, const std::nothrow_t &) NOEXCEPT
137227825Stheraven{
138253145Stheraven	try {
139253145Stheraven		return ::operator new[](size);
140253145Stheraven	} catch (...) {
141253145Stheraven		// nothrow operator new should return NULL in case of
142253145Stheraven		// std::bad_alloc exception in new handler
143253145Stheraven		return NULL;
144253145Stheraven	}
145253145Stheraven}
146253145Stheraven
147253145Stheraven
148253145Stheraven__attribute__((weak))
149299144Sdimvoid operator delete[](void * ptr) NOEXCEPT
150253145Stheraven{
151227825Stheraven	::operator delete(ptr);
152227825Stheraven}
153227825Stheraven
154350400Sdim// C++14 additional delete operators
155227825Stheraven
156350400Sdim#if __cplusplus >= 201402L
157350400Sdim
158350400Sdim__attribute__((weak))
159350400Sdimvoid operator delete(void * ptr, size_t) NOEXCEPT
160350400Sdim{
161350400Sdim	::operator delete(ptr);
162350400Sdim}
163350400Sdim
164350400Sdim
165350400Sdim__attribute__((weak))
166350400Sdimvoid operator delete[](void * ptr, size_t) NOEXCEPT
167350400Sdim{
168350400Sdim	::operator delete(ptr);
169350400Sdim}
170350400Sdim
171350400Sdim#endif
172