-- f34cd235a12ad0ee1fea3a1ee5a427272dc2b285 by Abseil Team <absl-team@google.com>: Migrates uses of deprecated map types to recommended types. PiperOrigin-RevId: 309945156 -- e3410a47ad32c0775b6911610bc47b22938decad by Matthew Brown <matthewbr@google.com>: Internal Change PiperOrigin-RevId: 309856021 -- a58cfa25e0bb59e7fa9647ac1aae65eaccff0086 by Greg Falcon <gfalcon@google.com>: Internal change. PiperOrigin-RevId: 309804612 -- cdc5ec310035fbe25f496bda283fe655d94d7769 by Mark Barolak <mbar@google.com>: Standardize the header comments for friend functions in cord.h PiperOrigin-RevId: 309779073 -- fe61602701be795e54477b0fdbf5ffc1df12a6b7 by Samuel Benzaquen <sbenza@google.com>: Implement %f natively for any input. It evaluates the input at runtime and allocates stack space accordingly. This removes a potential fallback into snprintf, improves performance, and removes all memory allocations in this formatting path. PiperOrigin-RevId: 309752501 -- 79e2a24f3f959e8b06ddf1d440bbabbd5f89b5b7 by Greg Falcon <gfalcon@google.com>: Add a Cord::swap() method. Many other Abseil types already provide this, but it was missing here. We already provided a two-argument free function form of `swap()`, but that API is better suited for generic code. The swap member function is a better API when the types are known. PiperOrigin-RevId: 309751740 -- 85cdf60024f153fb4fcb7fe68ed2b14b9faf119d by Derek Mauro <dmauro@google.com>: Cleanup uses of "linker initialized" SpinLocks PiperOrigin-RevId: 309581867 -- 9e5443bfcec4b94056b13c75326576e987ab88fb by Matt Kulukundis <kfm@google.com>: Clarify intended mixing properties of `absl::Hash` PiperOrigin-RevId: 309520174 -- a0630f0827b67f217aaeae68a448fe4c1101e17d by Greg Falcon <gfalcon@google.com>: Comment out a test in Emscripten to sidestep `long double` issues. PiperOrigin-RevId: 309482953 GitOrigin-RevId: f34cd235a12ad0ee1fea3a1ee5a427272dc2b285 Change-Id: Icce0c9d547117374d596b9d684e4054ddd118669
		
			
				
	
	
		
			162 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2017 The Abseil Authors.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //      https://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| #include "absl/base/internal/low_level_alloc.h"
 | |
| 
 | |
| #include <stdint.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <thread>  // NOLINT(build/c++11)
 | |
| #include <unordered_map>
 | |
| #include <utility>
 | |
| 
 | |
| #include "absl/container/node_hash_map.h"
 | |
| 
 | |
| namespace absl {
 | |
| ABSL_NAMESPACE_BEGIN
 | |
| namespace base_internal {
 | |
| namespace {
 | |
| 
 | |
| // This test doesn't use gtest since it needs to test that everything
 | |
| // works before main().
 | |
| #define TEST_ASSERT(x)                                           \
 | |
|   if (!(x)) {                                                    \
 | |
|     printf("TEST_ASSERT(%s) FAILED ON LINE %d\n", #x, __LINE__); \
 | |
|     abort();                                                     \
 | |
|   }
 | |
| 
 | |
| // a block of memory obtained from the allocator
 | |
| struct BlockDesc {
 | |
|   char *ptr;      // pointer to memory
 | |
|   int len;        // number of bytes
 | |
|   int fill;       // filled with data starting with this
 | |
| };
 | |
| 
 | |
| // Check that the pattern placed in the block d
 | |
| // by RandomizeBlockDesc is still there.
 | |
| static void CheckBlockDesc(const BlockDesc &d) {
 | |
|   for (int i = 0; i != d.len; i++) {
 | |
|     TEST_ASSERT((d.ptr[i] & 0xff) == ((d.fill + i) & 0xff));
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Fill the block "*d" with a pattern
 | |
| // starting with a random byte.
 | |
| static void RandomizeBlockDesc(BlockDesc *d) {
 | |
|   d->fill = rand() & 0xff;
 | |
|   for (int i = 0; i != d->len; i++) {
 | |
|     d->ptr[i] = (d->fill + i) & 0xff;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Use to indicate to the malloc hooks that
 | |
| // this calls is from LowLevelAlloc.
 | |
| static bool using_low_level_alloc = false;
 | |
| 
 | |
| // n times, toss a coin, and based on the outcome
 | |
| // either allocate a new block or deallocate an old block.
 | |
| // New blocks are placed in a std::unordered_map with a random key
 | |
| // and initialized with RandomizeBlockDesc().
 | |
| // If keys conflict, the older block is freed.
 | |
| // Old blocks are always checked with CheckBlockDesc()
 | |
| // before being freed.  At the end of the run,
 | |
| // all remaining allocated blocks are freed.
 | |
| // If use_new_arena is true, use a fresh arena, and then delete it.
 | |
| // If call_malloc_hook is true and user_arena is true,
 | |
| // allocations and deallocations are reported via the MallocHook
 | |
| // interface.
 | |
| static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
 | |
|   typedef absl::node_hash_map<int, BlockDesc> AllocMap;
 | |
|   AllocMap allocated;
 | |
|   AllocMap::iterator it;
 | |
|   BlockDesc block_desc;
 | |
|   int rnd;
 | |
|   LowLevelAlloc::Arena *arena = 0;
 | |
|   if (use_new_arena) {
 | |
|     int32_t flags = call_malloc_hook ? LowLevelAlloc::kCallMallocHook : 0;
 | |
|     arena = LowLevelAlloc::NewArena(flags);
 | |
|   }
 | |
|   for (int i = 0; i != n; i++) {
 | |
|     if (i != 0 && i % 10000 == 0) {
 | |
|       printf(".");
 | |
|       fflush(stdout);
 | |
|     }
 | |
| 
 | |
|     switch (rand() & 1) {      // toss a coin
 | |
|     case 0:     // coin came up heads: add a block
 | |
|       using_low_level_alloc = true;
 | |
|       block_desc.len = rand() & 0x3fff;
 | |
|       block_desc.ptr =
 | |
|         reinterpret_cast<char *>(
 | |
|                         arena == 0
 | |
|                         ? LowLevelAlloc::Alloc(block_desc.len)
 | |
|                         : LowLevelAlloc::AllocWithArena(block_desc.len, arena));
 | |
|       using_low_level_alloc = false;
 | |
|       RandomizeBlockDesc(&block_desc);
 | |
|       rnd = rand();
 | |
|       it = allocated.find(rnd);
 | |
|       if (it != allocated.end()) {
 | |
|         CheckBlockDesc(it->second);
 | |
|         using_low_level_alloc = true;
 | |
|         LowLevelAlloc::Free(it->second.ptr);
 | |
|         using_low_level_alloc = false;
 | |
|         it->second = block_desc;
 | |
|       } else {
 | |
|         allocated[rnd] = block_desc;
 | |
|       }
 | |
|       break;
 | |
|     case 1:     // coin came up tails: remove a block
 | |
|       it = allocated.begin();
 | |
|       if (it != allocated.end()) {
 | |
|         CheckBlockDesc(it->second);
 | |
|         using_low_level_alloc = true;
 | |
|         LowLevelAlloc::Free(it->second.ptr);
 | |
|         using_low_level_alloc = false;
 | |
|         allocated.erase(it);
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   // remove all remaining blocks
 | |
|   while ((it = allocated.begin()) != allocated.end()) {
 | |
|     CheckBlockDesc(it->second);
 | |
|     using_low_level_alloc = true;
 | |
|     LowLevelAlloc::Free(it->second.ptr);
 | |
|     using_low_level_alloc = false;
 | |
|     allocated.erase(it);
 | |
|   }
 | |
|   if (use_new_arena) {
 | |
|     TEST_ASSERT(LowLevelAlloc::DeleteArena(arena));
 | |
|   }
 | |
| }
 | |
| 
 | |
| // LowLevelAlloc is designed to be safe to call before main().
 | |
| static struct BeforeMain {
 | |
|   BeforeMain() {
 | |
|     Test(false, false, 50000);
 | |
|     Test(true, false, 50000);
 | |
|     Test(true, true, 50000);
 | |
|   }
 | |
| } before_main;
 | |
| 
 | |
| }  // namespace
 | |
| }  // namespace base_internal
 | |
| ABSL_NAMESPACE_END
 | |
| }  // namespace absl
 | |
| 
 | |
| int main(int argc, char *argv[]) {
 | |
|   // The actual test runs in the global constructor of `before_main`.
 | |
|   printf("PASS\n");
 | |
|   return 0;
 | |
| }
 |