 7175a07921
			
		
	
	7175a07921
	
	
	
		
			
			Summary: This patch adds the second revision of <experimental/any>. I've been working from the LFTS draft found at this link. https://rawgit.com/cplusplus/fundamentals-ts/v1/fundamentals-ts.html#any Reviewers: danalbert, jroelofs, K-ballo, mclow.lists Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D6762 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@243728 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			250 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef COUNT_NEW_HPP
 | |
| #define COUNT_NEW_HPP
 | |
| 
 | |
| # include <cstdlib>
 | |
| # include <cassert>
 | |
| # include <new>
 | |
| 
 | |
| #ifndef __has_feature
 | |
| #  define __has_feature(x) 0
 | |
| #endif
 | |
| 
 | |
| #if  __has_feature(address_sanitizer) \
 | |
|   || __has_feature(memory_sanitizer) \
 | |
|   || __has_feature(thread_sanitizer)
 | |
| #define DISABLE_NEW_COUNT
 | |
| #endif
 | |
| 
 | |
| class MemCounter
 | |
| {
 | |
| public:
 | |
|     // Make MemCounter super hard to accidentally construct or copy.
 | |
|     class MemCounterCtorArg_ {};
 | |
|     explicit MemCounter(MemCounterCtorArg_) { reset(); }
 | |
| 
 | |
| private:
 | |
|     MemCounter(MemCounter const &);
 | |
|     MemCounter & operator=(MemCounter const &);
 | |
| 
 | |
| public:
 | |
|     // All checks return true when disable_checking is enabled.
 | |
|     static const bool disable_checking;
 | |
| 
 | |
|     // Disallow any allocations from occurring. Useful for testing that
 | |
|     // code doesn't perform any allocations.
 | |
|     bool disable_allocations;
 | |
| 
 | |
|     int outstanding_new;
 | |
|     int new_called;
 | |
|     int delete_called;
 | |
|     int last_new_size;
 | |
| 
 | |
|     int outstanding_array_new;
 | |
|     int new_array_called;
 | |
|     int delete_array_called;
 | |
|     int last_new_array_size;
 | |
| 
 | |
| public:
 | |
|     void newCalled(std::size_t s)
 | |
|     {
 | |
|         assert(disable_allocations == false);
 | |
|         assert(s);
 | |
|         ++new_called;
 | |
|         ++outstanding_new;
 | |
|         last_new_size = s;
 | |
|     }
 | |
| 
 | |
|     void deleteCalled(void * p)
 | |
|     {
 | |
|         assert(p);
 | |
|         --outstanding_new;
 | |
|         ++delete_called;
 | |
|     }
 | |
| 
 | |
|     void newArrayCalled(std::size_t s)
 | |
|     {
 | |
|         assert(disable_allocations == false);
 | |
|         assert(s);
 | |
|         ++outstanding_array_new;
 | |
|         ++new_array_called;
 | |
|         last_new_array_size = s;
 | |
|     }
 | |
| 
 | |
|     void deleteArrayCalled(void * p)
 | |
|     {
 | |
|         assert(p);
 | |
|         --outstanding_array_new;
 | |
|         ++delete_array_called;
 | |
|     }
 | |
| 
 | |
|     void disableAllocations()
 | |
|     {
 | |
|         disable_allocations = true;
 | |
|     }
 | |
| 
 | |
|     void enableAllocations()
 | |
|     {
 | |
|         disable_allocations = false;
 | |
|     }
 | |
| 
 | |
|     void reset()
 | |
|     {
 | |
|         disable_allocations = false;
 | |
| 
 | |
|         outstanding_new = 0;
 | |
|         new_called = 0;
 | |
|         delete_called = 0;
 | |
|         last_new_size = 0;
 | |
| 
 | |
|         outstanding_array_new = 0;
 | |
|         new_array_called = 0;
 | |
|         delete_array_called = 0;
 | |
|         last_new_array_size = 0;
 | |
|     }
 | |
| 
 | |
| public:
 | |
|     bool checkOutstandingNewEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n == outstanding_new;
 | |
|     }
 | |
| 
 | |
|     bool checkOutstandingNewNotEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n != outstanding_new;
 | |
|     }
 | |
| 
 | |
|     bool checkNewCalledEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n == new_called;
 | |
|     }
 | |
| 
 | |
|     bool checkNewCalledNotEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n != new_called;
 | |
|     }
 | |
| 
 | |
|     bool checkDeleteCalledEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n == delete_called;
 | |
|     }
 | |
| 
 | |
|     bool checkDeleteCalledNotEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n != delete_called;
 | |
|     }
 | |
| 
 | |
|     bool checkLastNewSizeEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n == last_new_size;
 | |
|     }
 | |
| 
 | |
|     bool checkLastNewSizeNotEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n != last_new_size;
 | |
|     }
 | |
| 
 | |
|     bool checkOutstandingArrayNewEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n == outstanding_array_new;
 | |
|     }
 | |
| 
 | |
|     bool checkOutstandingArrayNewNotEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n != outstanding_array_new;
 | |
|     }
 | |
| 
 | |
|     bool checkNewArrayCalledEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n == new_array_called;
 | |
|     }
 | |
| 
 | |
|     bool checkNewArrayCalledNotEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n != new_array_called;
 | |
|     }
 | |
| 
 | |
|     bool checkDeleteArrayCalledEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n == delete_array_called;
 | |
|     }
 | |
| 
 | |
|     bool checkDeleteArrayCalledNotEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n != delete_array_called;
 | |
|     }
 | |
| 
 | |
|     bool checkLastNewArraySizeEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n == last_new_array_size;
 | |
|     }
 | |
| 
 | |
|     bool checkLastNewArraySizeNotEq(int n) const
 | |
|     {
 | |
|         return disable_checking || n != last_new_array_size;
 | |
|     }
 | |
| };
 | |
| 
 | |
| #ifdef DISABLE_NEW_COUNT
 | |
|   const bool MemCounter::disable_checking = true;
 | |
| #else
 | |
|   const bool MemCounter::disable_checking = false;
 | |
| #endif
 | |
| 
 | |
| MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_()));
 | |
| 
 | |
| #ifndef DISABLE_NEW_COUNT
 | |
| void* operator new(std::size_t s) throw(std::bad_alloc)
 | |
| {
 | |
|     globalMemCounter.newCalled(s);
 | |
|     return std::malloc(s);
 | |
| }
 | |
| 
 | |
| void  operator delete(void* p) throw()
 | |
| {
 | |
|     globalMemCounter.deleteCalled(p);
 | |
|     std::free(p);
 | |
| }
 | |
| 
 | |
| 
 | |
| void* operator new[](std::size_t s) throw(std::bad_alloc)
 | |
| {
 | |
|     globalMemCounter.newArrayCalled(s);
 | |
|     return operator new(s);
 | |
| }
 | |
| 
 | |
| 
 | |
| void operator delete[](void* p) throw()
 | |
| {
 | |
|     globalMemCounter.deleteArrayCalled(p);
 | |
|     operator delete(p);
 | |
| }
 | |
| 
 | |
| #endif // DISABLE_NEW_COUNT
 | |
| 
 | |
| 
 | |
| struct DisableAllocationGuard {
 | |
|     explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
 | |
|     {
 | |
|         // Don't re-disable if already disabled.
 | |
|         if (globalMemCounter.disable_allocations == true) m_disabled = false;
 | |
|         if (m_disabled) globalMemCounter.disableAllocations();
 | |
|     }
 | |
| 
 | |
|     void release() {
 | |
|         if (m_disabled) globalMemCounter.enableAllocations();
 | |
|         m_disabled = false;
 | |
|     }
 | |
| 
 | |
|     ~DisableAllocationGuard() {
 | |
|         release();
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     bool m_disabled;
 | |
| 
 | |
|     DisableAllocationGuard(DisableAllocationGuard const&);
 | |
|     DisableAllocationGuard& operator=(DisableAllocationGuard const&);
 | |
| };
 | |
| 
 | |
| #endif /* COUNT_NEW_HPP */
 |