1//
2// Copyright (C) 2007-2015 Free Software Foundation, Inc.
3//
4// This file is part of the GNU ISO C++ Library.  This library is free
5// software; you can redistribute it and/or modify it under the
6// terms of the GNU General Public License as published by the
7// Free Software Foundation; either version 3, or (at your option)
8// any later version.
9//
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License along
16// with this library; see the file COPYING3.  If not see
17// <http://www.gnu.org/licenses/>.
18
19#include <exception>
20#include <stdexcept>
21#include <cstdlib>
22#include <cstdio>
23
24namespace __gnu_test
25{
26  struct counter_error : public std::exception { };
27
28  struct counter
29  {
30    std::size_t _M_count;
31    bool	_M_throw;
32
33    counter() : _M_count(0), _M_throw(true) { }
34
35    ~counter()
36    {
37      if (_M_throw && _M_count != 0)
38	throw counter_error();
39    }
40
41    static void
42    increment() { get()._M_count++; }
43
44    static void
45    decrement() { get()._M_count--; }
46
47    static counter&
48    get()
49    {
50      static counter g;
51      return g;
52    }
53
54    static std::size_t
55    count() { return get()._M_count; }
56
57    static void
58    exceptions(bool __b) { get()._M_throw = __b; }
59  };
60
61  template<typename Alloc, bool uses_global_new>
62    bool
63    check_new(Alloc a = Alloc())
64    {
65      __gnu_test::counter::exceptions(false);
66      a.allocate(10);
67      const bool __b((__gnu_test::counter::count() > 0) == uses_global_new);
68      if (!__b)
69	throw std::logic_error("counter not incremented");
70      return __b;
71    }
72
73  template<typename Alloc, bool uses_global_delete>
74    bool
75    check_delete(Alloc a = Alloc())
76    {
77      __gnu_test::counter::exceptions(false);
78      typename Alloc::pointer p = a.allocate(10);
79      const std::size_t count1 = __gnu_test::counter::count();
80      a.deallocate(p, 10);
81      const std::size_t count2 = __gnu_test::counter::count();
82      const bool __b((count2 < count1) == uses_global_delete);
83      if (!__b)
84	throw std::logic_error("counter not decremented");
85      return __b;
86    }
87} // namespace __gnu_test
88
89void* operator new(std::size_t size) throw(std::bad_alloc)
90{
91  std::printf("operator new is called \n");
92  void* p = std::malloc(size);
93  if (!p)
94    throw std::bad_alloc();
95  __gnu_test::counter::increment();
96  return p;
97}
98
99void operator delete(void* p) throw()
100{
101  std::printf("operator delete is called \n");
102  if (p)
103    {
104      std::free(p);
105      __gnu_test::counter::decrement();
106
107      std::size_t count = __gnu_test::counter::count();
108      if (count == 0)
109	std::printf("All memory released \n");
110      else
111	std::printf("%lu allocations to be released \n", (unsigned long)count);
112    }
113}
114