This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] No allocation for empty unordered containers


On 25/07/14 22:53 +0200, François Dumont wrote:
Hi

I think I never get feedback regarding this patch proposal. Note

I've been trying to weigh up the pros and cons and am unsure what's
best, but I think my preference is to have a noexcept default
constructor. Unless you hear any objections in the next 48 hours
please go ahead and commit this to trunk, thanks

that if accepted the doc will have to be updated regarding the default hint value.

Good point.

Thanks


On 03/06/2014 22:44, François Dumont wrote:
Hi

Thanks to the single bucket introduced to make move semantic noexcept we can also avoid some over allocations. Here is a patch to avoid any allocation on default instantiation, on range constructor when range is empty and on construction from an initialization list when this list is empty too. I had to make all default hint value to 0 so that if this value is used the rehash policy next bucket returns 1 bucket.

I don't know if you had in mind to noexcept qualify the default constructor but it would mean to have a real default constructor and another to deal with the hint which wouldn't match the Standard so no noexcept qualification at the moment.

Tested under Linux x86_64.normal debug and profile modes.


2014-06-03  François Dumont <fdumont@gcc.gnu.org>

   * include/bits/hashtable.h: Make use of the internal single bucket to
   limit allocation as long as container remains empty.
   * include/bits/unordered_map.h: Set default bucket hint to 0 in
   constructors to avoid allocation.
   * include/bits/unordered_set.h: Likewise.
   * include/debug/unordered_map: Likewise.
   * include/debug/unordered_set: Likewise.
   * include/profile/unordered_map: Likewise.
   * include/profile/unordered_set: Likewise.
   * src/c++11/hashtable_c++0x.cc (_Prime_rehash_policy::_M_next_bkt):
   Returns 1 for hint 0.
   * testsuite/23_containers/unordered_map/allocator/
   empty_instantiation.cc:    New.
   * testsuite/23_containers/unordered_multimap/allocator/
   empty_instantiation.cc:    New.
   * testsuite/23_containers/unordered_set/allocator/
   empty_instantiation.cc: New.
   * testsuite/23_containers/unordered_multiset/allocator/
   empty_instantiation.cc: New.

Ok to commit ?

François




Index: include/bits/hashtable.h
===================================================================
--- include/bits/hashtable.h	(revision 211144)
+++ include/bits/hashtable.h	(working copy)
@@ -407,12 +407,12 @@
      // Use delegating constructors.
      explicit
      _Hashtable(const allocator_type& __a)
-      : _Hashtable(10, _H1(), _H2(), _Hash(), key_equal(),
+      : _Hashtable(0, _H1(), _H2(), _Hash(), key_equal(),
		   __key_extract(), __a)
      { }

      explicit
-      _Hashtable(size_type __n = 10,
+      _Hashtable(size_type __n = 0,
		 const _H1& __hf = _H1(),
		 const key_equal& __eql = key_equal(),
		 const allocator_type& __a = allocator_type())
@@ -792,14 +792,18 @@
	       const _Equal& __eq, const _ExtractKey& __exk,
	       const allocator_type& __a)
    : __hashtable_base(__exk, __h1, __h2, __h, __eq),
-      __map_base(),
-      __rehash_base(),
      __hashtable_alloc(__node_alloc_type(__a)),
+      _M_buckets(&_M_single_bucket),
+      _M_bucket_count(1),
      _M_element_count(0),
-      _M_rehash_policy()
+      _M_single_bucket(nullptr)
    {
-      _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
-      _M_buckets = _M_allocate_buckets(_M_bucket_count);
+      auto __bkt_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
+      if (_M_bucket_count != __bkt_count)
+	{
+	  _M_bucket_count = __bkt_count;
+	  _M_buckets = _M_allocate_buckets(_M_bucket_count);
+	}
    }

  template<typename _Key, typename _Value,
@@ -815,19 +819,24 @@
		 const _Equal& __eq, const _ExtractKey& __exk,
		 const allocator_type& __a)
      : __hashtable_base(__exk, __h1, __h2, __h, __eq),
-	__map_base(),
-	__rehash_base(),
	__hashtable_alloc(__node_alloc_type(__a)),
+	_M_buckets(&_M_single_bucket),
+	_M_bucket_count(1),
	_M_element_count(0),
-	_M_rehash_policy()
+	_M_single_bucket(nullptr)
      {
	auto __nb_elems = __detail::__distance_fw(__f, __l);
-	_M_bucket_count =
+	auto __bkt_count =
	  _M_rehash_policy._M_next_bkt(
	    std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
		     __bucket_hint));
+ + if (_M_bucket_count != __bkt_count)
+	  {
+	    _M_bucket_count = __bkt_count;
+	    _M_buckets = _M_allocate_buckets(_M_bucket_count);
+	  }

-	_M_buckets = _M_allocate_buckets(_M_bucket_count);
	__try
	  {
	    for (; __f != __l; ++__f)
@@ -864,14 +873,15 @@
	      {
		// Replacement allocator cannot free existing storage.
		this->_M_deallocate_nodes(_M_begin());
-		_M_before_begin._M_nxt = nullptr;
		_M_deallocate_buckets();
-		_M_buckets = nullptr;
+		__hashtable_base::operator=(__ht);
		std::__alloc_on_copy(__this_alloc, __that_alloc);
-		__hashtable_base::operator=(__ht);
-		_M_bucket_count = __ht._M_bucket_count;
+		_M_buckets = &_M_single_bucket;
+		_M_bucket_count = 1;
+		_M_before_begin._M_nxt = nullptr;
		_M_element_count = __ht._M_element_count;
		_M_rehash_policy = __ht._M_rehash_policy;
+		_M_single_bucket = nullptr;
		__try
		  {
		    _M_assign(__ht,
@@ -946,8 +956,14 @@
      _M_assign(const _Hashtable& __ht, const _NodeGenerator& __node_gen)
      {
	__bucket_type* __buckets = nullptr;
-	if (!_M_buckets)
-	  _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
+	if (_M_bucket_count != __ht._M_bucket_count)
+	  {
+	    // Bucket deallocation useless because per design _M_buckets
+	    // can only be pointing to _M_single_bucket.
+	    //_M_deallocate_buckets();
+	    _M_bucket_count = __ht._M_bucket_count;
+	    _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
+	  }

	__try
	  {
@@ -1101,10 +1117,11 @@
      __rehash_base(__ht),
      __hashtable_alloc(
	__node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
-      _M_buckets(),
-      _M_bucket_count(__ht._M_bucket_count),
+      _M_buckets(&_M_single_bucket),
+      _M_bucket_count(1),
      _M_element_count(__ht._M_element_count),
-      _M_rehash_policy(__ht._M_rehash_policy)
+      _M_rehash_policy(__ht._M_rehash_policy),
+      _M_single_bucket(nullptr)
    {
      _M_assign(__ht,
		[this](const __node_type* __n)
@@ -1126,14 +1143,12 @@
      _M_bucket_count(__ht._M_bucket_count),
      _M_before_begin(__ht._M_before_begin._M_nxt),
      _M_element_count(__ht._M_element_count),
-      _M_rehash_policy(__ht._M_rehash_policy)
+      _M_rehash_policy(__ht._M_rehash_policy),
+      _M_single_bucket(__ht._M_single_bucket)
    {
      // Update, if necessary, buckets if __ht is using its single bucket.
      if (__ht._M_uses_single_bucket())
-	{
-	  _M_buckets = &_M_single_bucket;
-	  _M_single_bucket = __ht._M_single_bucket;
-	}
+	_M_buckets = &_M_single_bucket;

      // Update, if necessary, bucket pointing to before begin that hasn't
      // moved.
@@ -1154,10 +1169,11 @@
      __map_base(__ht),
      __rehash_base(__ht),
      __hashtable_alloc(__node_alloc_type(__a)),
-      _M_buckets(),
-      _M_bucket_count(__ht._M_bucket_count),
+      _M_buckets(&_M_single_bucket),
+      _M_bucket_count(1),
      _M_element_count(__ht._M_element_count),
-      _M_rehash_policy(__ht._M_rehash_policy)
+      _M_rehash_policy(__ht._M_rehash_policy),
+      _M_single_bucket(nullptr)
    {
      _M_assign(__ht,
		[this](const __node_type* __n)
@@ -1175,18 +1191,17 @@
      __map_base(__ht),
      __rehash_base(__ht),
      __hashtable_alloc(__node_alloc_type(__a)),
-      _M_buckets(),
-      _M_bucket_count(__ht._M_bucket_count),
+      _M_buckets(&_M_single_bucket),
+      _M_bucket_count(1),
      _M_element_count(__ht._M_element_count),
-      _M_rehash_policy(__ht._M_rehash_policy)
+      _M_rehash_policy(__ht._M_rehash_policy),
+      _M_single_bucket(nullptr)
    {
      if (__ht._M_node_allocator() == this->_M_node_allocator())
	{
+	  _M_bucket_count = __ht._M_bucket_count;
	  if (__ht._M_uses_single_bucket())
-	    {
-	      _M_buckets = &_M_single_bucket;
-	      _M_single_bucket = __ht._M_single_bucket;
-	    }
+	    _M_single_bucket = __ht._M_single_bucket;
	  else
	    _M_buckets = __ht._M_buckets;

@@ -1195,6 +1210,7 @@
	  // moved.
	  if (_M_begin())
	    _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
+
	  __ht._M_reset();
	}
      else
@@ -1218,8 +1234,7 @@
    ~_Hashtable() noexcept
    {
      clear();
-      if (_M_buckets)
-	_M_deallocate_buckets();
+      _M_deallocate_buckets();
    }

  template<typename _Key, typename _Value,
Index: include/bits/unordered_map.h
===================================================================
--- include/bits/unordered_map.h	(revision 211144)
+++ include/bits/unordered_map.h	(working copy)
@@ -136,7 +136,7 @@
       *  @param __a  An allocator object.
       */
      explicit
-      unordered_map(size_type __n = 10,
+      unordered_map(size_type __n = 0,
		    const hasher& __hf = hasher(),
		    const key_equal& __eql = key_equal(),
		    const allocator_type& __a = allocator_type())
@@ -848,7 +848,7 @@
       *  @param __a  An allocator object.
       */
      explicit
-      unordered_multimap(size_type __n = 10,
+      unordered_multimap(size_type __n = 0,
			 const hasher& __hf = hasher(),
			 const key_equal& __eql = key_equal(),
			 const allocator_type& __a = allocator_type())
Index: include/bits/unordered_set.h
===================================================================
--- include/bits/unordered_set.h	(revision 211144)
+++ include/bits/unordered_set.h	(working copy)
@@ -129,7 +129,7 @@
       *  @param __a  An allocator object.
       */
      explicit
-      unordered_set(size_type __n = 10,
+      unordered_set(size_type __n = 0,
		    const hasher& __hf = hasher(),
		    const key_equal& __eql = key_equal(),
		    const allocator_type& __a = allocator_type())
@@ -764,7 +764,7 @@
       *  @param __a  An allocator object.
       */
      explicit
-      unordered_multiset(size_type __n = 10,
+      unordered_multiset(size_type __n = 0,
			 const hasher& __hf = hasher(),
			 const key_equal& __eql = key_equal(),
			 const allocator_type& __a = allocator_type())
Index: include/debug/unordered_map
===================================================================
--- include/debug/unordered_map	(revision 211144)
+++ include/debug/unordered_map	(working copy)
@@ -83,7 +83,7 @@
	_Base_const_local_iterator, unordered_map>	const_local_iterator;

      explicit
-      unordered_map(size_type __n = 10,
+      unordered_map(size_type __n = 0,
		    const hasher& __hf = hasher(),
		    const key_equal& __eql = key_equal(),
		    const allocator_type& __a = allocator_type())
@@ -496,7 +496,7 @@
	_Base_const_local_iterator, unordered_multimap> const_local_iterator;

      explicit
-      unordered_multimap(size_type __n = 10,
+      unordered_multimap(size_type __n = 0,
			 const hasher& __hf = hasher(),
			 const key_equal& __eql = key_equal(),
			 const allocator_type& __a = allocator_type())
Index: include/debug/unordered_set
===================================================================
--- include/debug/unordered_set	(revision 211144)
+++ include/debug/unordered_set	(working copy)
@@ -83,7 +83,7 @@
	_Base_const_local_iterator, unordered_set>	const_local_iterator;

      explicit
-      unordered_set(size_type __n = 10,
+      unordered_set(size_type __n = 0,
		    const hasher& __hf = hasher(),
		    const key_equal& __eql = key_equal(),
		    const allocator_type& __a = allocator_type())
@@ -492,7 +492,7 @@
	_Base_const_local_iterator, unordered_multiset> const_local_iterator;

      explicit
-      unordered_multiset(size_type __n = 10,
+      unordered_multiset(size_type __n = 0,
			 const hasher& __hf = hasher(),
			 const key_equal& __eql = key_equal(),
			 const allocator_type& __a = allocator_type())
Index: include/profile/unordered_map
===================================================================
--- include/profile/unordered_map	(revision 211144)
+++ include/profile/unordered_map	(working copy)
@@ -77,7 +77,7 @@
      typedef typename _Base::const_iterator	const_iterator;

      explicit
-      unordered_map(size_type __n = 10,
+      unordered_map(size_type __n = 0,
		    const hasher& __hf = hasher(),
		    const key_equal& __eql = key_equal(),
		    const allocator_type& __a = allocator_type())
@@ -322,7 +322,7 @@
      typedef typename _Base::const_iterator	const_iterator;

      explicit
-      unordered_multimap(size_type __n = 10,
+      unordered_multimap(size_type __n = 0,
			 const hasher& __hf = hasher(),
			 const key_equal& __eql = key_equal(),
			 const allocator_type& __a = allocator_type())
Index: include/profile/unordered_set
===================================================================
--- include/profile/unordered_set	(revision 211144)
+++ include/profile/unordered_set	(working copy)
@@ -76,7 +76,7 @@
      typedef typename _Base::const_iterator	const_iterator;

      explicit
-      unordered_set(size_type __n = 10,
+      unordered_set(size_type __n = 0,
		    const hasher& __hf = hasher(),
		    const key_equal& __eql = key_equal(),
		    const allocator_type& __a = allocator_type())
@@ -300,7 +300,7 @@
      typedef typename _Base::const_iterator const_iterator;

      explicit
-      unordered_multiset(size_type __n = 10,
+      unordered_multiset(size_type __n = 0,
			 const hasher& __hf = hasher(),
			 const key_equal& __eql = key_equal(),
			 const allocator_type& __a = allocator_type())
Index: src/c++11/hashtable_c++0x.cc
===================================================================
--- src/c++11/hashtable_c++0x.cc	(revision 211144)
+++ src/c++11/hashtable_c++0x.cc	(working copy)
@@ -47,7 +47,7 @@
    // Optimize lookups involving the first elements of __prime_list.
    // (useful to speed-up, eg, constructors)
    static const unsigned char __fast_bkt[12]
-      = { 2, 2, 2, 3, 5, 5, 7, 7, 11, 11, 11, 11 };
+      = { 1, 2, 2, 3, 5, 5, 7, 7, 11, 11, 11, 11 };

    if (__n <= 11)
      {
Index: testsuite/23_containers/unordered_map/allocator/empty_instantiation.cc
===================================================================
--- testsuite/23_containers/unordered_map/allocator/empty_instantiation.cc	(revision 0)
+++ testsuite/23_containers/unordered_map/allocator/empty_instantiation.cc	(working copy)
@@ -0,0 +1,98 @@
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <unordered_map>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+
+using namespace __gnu_test;
+typedef tracker_allocator<std::pair<const int, int>> alloc_type;
+typedef std::unordered_map<int, int, std::hash<int>, std::equal_to<int>,
+			   alloc_type> test_type;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    // Default constructor, in fact constructor with hint using default value.
+    test_type u;
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    test_type u(1);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    std::pair<int, int> ints[] {};
+    // Range constructor.
+    test_type u(ints + 0, ints + 0);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    std::pair<int, int> ints[] { { 1, 1 } };
+    // Range constructor.
+    test_type u(ints + 0, ints + 1);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    // Initializer list constructor.
+    test_type u({});
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    test_type u({ { 1, 1 } });
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+}
Index: testsuite/23_containers/unordered_multimap/allocator/empty_instantiation.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/allocator/empty_instantiation.cc	(revision 0)
+++ testsuite/23_containers/unordered_multimap/allocator/empty_instantiation.cc	(working copy)
@@ -0,0 +1,98 @@
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <unordered_map>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+
+using namespace __gnu_test;
+typedef tracker_allocator<std::pair<const int, int>> alloc_type;
+typedef std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>,
+				alloc_type> test_type;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    // Default constructor, in fact constructor with hint using default value.
+    test_type u;
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    test_type u(1);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    std::pair<int, int> ints[] {};
+    // Range constructor.
+    test_type u(ints + 0, ints + 0);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    std::pair<int, int> ints[] { { 1, 1 } };
+    // Range constructor.
+    test_type u(ints + 0, ints + 1);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    // Initializer list constructor.
+    test_type u({});
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    test_type u({ { 1, 1 } });
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+}
Index: testsuite/23_containers/unordered_multiset/allocator/empty_instantiation.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/allocator/empty_instantiation.cc	(revision 0)
+++ testsuite/23_containers/unordered_multiset/allocator/empty_instantiation.cc	(working copy)
@@ -0,0 +1,99 @@
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <unordered_set>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+
+using namespace __gnu_test;
+typedef tracker_allocator<int> alloc_type;
+typedef std::unordered_multiset<int, std::hash<int>, std::equal_to<int>,
+				alloc_type> test_type;
+
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    // Default constructor, in fact constructor with hint using default value.
+    test_type u;
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    test_type u(1);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    int ints[] {};
+    // Range constructor.
+    test_type u(ints + 0, ints + 0);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    int ints[] { 1 };
+    // Range constructor.
+    test_type u(ints + 0, ints + 1);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    // Initializer list constructor.
+    test_type u({});
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    test_type u({ 1 });
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+}
Index: testsuite/23_containers/unordered_set/allocator/empty_instantiation.cc
===================================================================
--- testsuite/23_containers/unordered_set/allocator/empty_instantiation.cc	(revision 0)
+++ testsuite/23_containers/unordered_set/allocator/empty_instantiation.cc	(working copy)
@@ -0,0 +1,98 @@
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <unordered_set>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+
+using namespace __gnu_test;
+typedef tracker_allocator<int> alloc_type;
+typedef std::unordered_set<int, std::hash<int>, std::equal_to<int>,
+			   alloc_type> test_type;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    // Default constructor, in fact constructor with hint using default value.
+    test_type u;
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    test_type u(1);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    int ints[] {};
+    // Range constructor.
+    test_type u(ints + 0, ints + 0);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    int ints[] { 1 };
+    // Range constructor.
+    test_type u(ints + 0, ints + 1);
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  tracker_allocator_counter::reset();
+
+  {
+    // Initializer list constructor.
+    test_type u({});
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
+
+  {
+    test_type u({ 1 });
+  }
+
+  VERIFY( tracker_allocator_counter::get_allocation_count() != 0 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]