PetscErrorCode DMMeshCreateMeshFromAdjacencyHybrid(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numCorners[], PetscInt cellVertices[], PetscInt spatialDim, PetscInt numVertices, const PetscReal coordinates[], PetscBool interpolate, DM *dm) { PetscInt debug = 0; PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(numCorners, 4); PetscValidPointer(cellVertices, 5); /* PetscValidLogicalCollectiveBool(comm,interpolate,6); */ PetscValidPointer(dm, 7); if (interpolate) {SETERRQ(comm, PETSC_ERR_SUP, "Interpolation (creation of faces and edges) is not yet supported.");} ierr = PetscOptionsGetInt(PETSC_NULL, "-dmmesh_debug", &debug, PETSC_NULL);CHKERRQ(ierr); Obj<PETSC_MESH_TYPE> mesh = new PETSC_MESH_TYPE(comm, dim, debug); Obj<PETSC_MESH_TYPE::sieve_type> sieve = new PETSC_MESH_TYPE::sieve_type(comm, 0, numCells+numVertices, debug); mesh->setSieve(sieve); for(PetscInt c = 0; c < numCells; ++c) { sieve->setConeSize(c, numCorners[c]); } //sieve->symmetrizeSizes(numCells, numCorners, cellVertices); sieve->allocate(); for(PetscInt c = 0, offset = 0; c < numCells; offset += numCorners[c], ++c) { sieve->setCone(&cellVertices[offset], c); } sieve->symmetrize(); PetscFunctionReturn(0); }
/*@ DMMeshCreateMeshFromAdjacency - Create an unstrctured mesh from a list of the vertices for each cell, and the coordinates for each vertex. Collective on comm Input Parameters: + comm - An MPI communicator . dim - The dimension of the cells, e.g. triangles have dimension 2 . numCells - The number of cells in the mesh . numCorners - The number of vertices in each cell . cellVertices - An array of the vertices for each cell, numbered 0 to numVertices-1 . spatialDim - The dimension for coordinates, e.g. for a triangle in 3D this would be 3 . numVertices - The number of mesh vertices . coordinates - An array of the coordinates for each vertex - interpolate - Flag to create faces and edges Output Parameter: . dm - The DMMesh object Level: beginner .seealso DMMESH, DMMeshCreateMeshFromAdjacencyHybrid(), DMMeshCreateBoxMesh() @*/ PetscErrorCode DMMeshCreateMeshFromAdjacency(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numCorners, PetscInt cellVertices[], PetscInt spatialDim, PetscInt numVertices, const PetscReal coordinates[], PetscBool interpolate, DM *dm) { PetscInt *cone; PetscInt *coneO; PetscInt debug = 0; PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(cellVertices, 5); /* PetscValidLogicalCollectiveBool(comm,interpolate,6); */ PetscValidPointer(dm, 7); if (interpolate) {SETERRQ(comm, PETSC_ERR_SUP, "Interpolation (creation of faces and edges) is not yet supported.");} ierr = PetscOptionsGetInt(PETSC_NULL, "-dm_mesh_debug", &debug, PETSC_NULL);CHKERRQ(ierr); Obj<PETSC_MESH_TYPE> mesh = new PETSC_MESH_TYPE(comm, dim, debug); Obj<PETSC_MESH_TYPE::sieve_type> sieve = new PETSC_MESH_TYPE::sieve_type(comm, 0, numCells+numVertices, debug); mesh->setSieve(sieve); for(PetscInt c = 0; c < numCells; ++c) { sieve->setConeSize(c, numCorners); } sieve->symmetrizeSizes(numCells, numCorners, cellVertices, numCells); sieve->allocate(); ierr = PetscMalloc2(numCorners,PetscInt,&cone,numCorners,PetscInt,&coneO);CHKERRQ(ierr); for(PetscInt v = 0; v < numCorners; ++v) { coneO[v] = 1; } for(PetscInt c = 0; c < numCells; ++c) { for(PetscInt v = 0; v < numCorners; ++v) { cone[v] = cellVertices[c*numCorners+v]+numCells; } sieve->setCone(cone, c); sieve->setConeOrientation(coneO, c); } ierr = PetscFree2(cone,coneO);CHKERRQ(ierr); sieve->symmetrize(); mesh->stratify(); ALE::SieveBuilder<PETSC_MESH_TYPE>::buildCoordinates(mesh, spatialDim, coordinates, numCells); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMMESH);CHKERRQ(ierr); ierr = DMMeshSetMesh(*dm, mesh);CHKERRQ(ierr); PetscFunctionReturn(0); }
extern "C" void *workerThread(void *arg) { // Perform a series of allocate, and deallocate operations on the // 'bdlma::ConcurrentAllocatorAdapter' and verify their results. This // operation is intended to be a thread entry point. Cast the specified // 'args' to a 'WorkerArgs', and perform a series of // '(WorkerArgs *)args->d_numSizes' allocations using the corresponding // allocations sizes specified by '(WorkerARgs *)args->d_sizes'. Use the // barrier 'g_barrier' to ensure tests are performed while the allocator is // in the correct state. WorkerArgs *args = (WorkerArgs *) arg; ASSERT(0 != args); ASSERT(0 != args->d_sizes); Obj *allocator = args->d_allocator; const int *allocSizes = args->d_sizes; const int numAllocs = args->d_numSizes; bsl::vector<char *> blocks(bslma::Default::allocator(0)); blocks.resize(numAllocs); g_barrier.wait(); // Perform allocations for (int i = 0; i < numAllocs; ++i) { blocks[i] = (char *)allocator->allocate(allocSizes[i]); } // deallocate all the blocks for (int i = 0; i < numAllocs; ++i) { allocator->deallocate(blocks[i]); } g_barrier.wait(); return arg; }
int main(int argc, char *argv[]) { int test = argc > 1 ? atoi(argv[1]) : 0; int verbose = argc > 2; int veryVerbose = argc > 3; int veryVeryVerbose = argc > 4; int veryVeryVeryVerbose = argc > 5; cout << "TEST " << __FILE__ << " CASE " << test << endl; // CONCERN: In no case does memory come from the global allocator. bslma::TestAllocator globalAllocator(veryVeryVerbose); bslma::Default::setGlobalAllocator(&globalAllocator); switch (test) { case 0: case 5: { // -------------------------------------------------------------------- // USAGE EXAMPLE // Extracted from component header file. // // Concerns: //: 1 The usage example provided in the component header file compiles, //: links, and runs as shown. // // Plan: //: 1 Incorporate usage example from header into test driver, remove //: leading comment characters, and replace 'assert' with 'ASSERT'. //: (C-1) // // Testing: // USAGE EXAMPLE // -------------------------------------------------------------------- if (verbose) cout << endl << "USAGE EXAMPLE" << endl << "=============" << endl; bslma::TestAllocator oa("object", veryVeryVerbose); if (verbose) cout << "Testing 'my_StrPool'." << endl; { const int SIZE[] = { 0, 10, 127, 128, 129, 1000 }; const int NUM_DATA = sizeof SIZE / sizeof *SIZE; my_StrPool strPool(&oa); for (int ti = 0; ti < NUM_DATA; ++ti) { void *p = strPool.allocate(SIZE[ti]); if (veryVerbose) { T_; P_(SIZE[ti]); P(p); } if (SIZE[ti]) { LOOP_ASSERT(ti, p); } else { LOOP_ASSERT(ti, !p); } } } ASSERT(0 == oa.numBlocksInUse()); } break; case 4: { // -------------------------------------------------------------------- // TESTING DEALLOCATE // Ensure that 'deallocate' releases the referenced memory block to // the object allocator. // // Concerns: //: 1 The memory block at (non-null) 'address' is released to the //: object allocator. //: //: 2 A memory block at any position in the block list can be //: deallocated. //: //: 3 Calling 'deallocate' with a null address has no effect. // // Plan: //: 1 Create a 'bslma::TestAllocator' object, and install it as the //: default allocator (note that a ubiquitous test allocator is //: already installed as the global allocator). //: //: 2 Using the table-driven technique: //: //: 1 Specify a set of unique test pairs consisting of 'N', a //: positive number of allocations, and 'SEQ', the sequence in //: which the 'N' allocated blocks are to be deallocated. //: //: 3 For each row 'R' (representing a pair '(N, SEQ)') in the table //: described in P-2: (C-1..2) //: //: 1 Create a 'bslma::TestAllocator' object 'oa'. //: //: 2 Use the default constructor and 'oa' to create a modifiable //: 'Obj' 'mX'. //: //: 3 Allocate 'N' blocks from 'mX'. //: //: 4 Deallocate the 'N' blocks allocated in P-3 in the sequence //: specified by 'SEQ', and verify that each block is released to //: the object allocator. (C-1..2) //: //: 4 Perform a separate test to verify that 'mX.deallocate(0)' has no //: effect. (C-3) // // Testing: // void deallocate(void *address); // -------------------------------------------------------------------- if (verbose) cout << endl << "TESTING DEALLOCATE" << endl << "==================" << endl; if (verbose) cout << "\nTesting 'deallocate'." << endl; const int SIZE_DATA[] = { 5, 12, 32, 256, 1000 }; const int NUM_SIZE_DATA = sizeof SIZE_DATA / sizeof *SIZE_DATA; struct { int d_line; // line number int d_numAlloc; // number of allocations int d_deallocSeq[5]; // deallocation sequence } DATA[] = { //LINE # ALLOC DEALLOC SEQUENCE //---- ---------- ----------------- { L_, 1, { 0 } }, { L_, 2, { 0, 1 } }, { L_, 2, { 1, 0 } }, { L_, 3, { 0, 1, 2 } }, { L_, 3, { 0, 2, 1 } }, { L_, 3, { 1, 0, 2 } }, { L_, 3, { 1, 2, 0 } }, { L_, 3, { 2, 0, 1 } }, { L_, 3, { 2, 1, 0 } }, { L_, 4, { 1, 2, 0, 3 } }, { L_, 4, { 2, 1, 3, 0 } }, { L_, 5, { 0, 1, 2, 3, 4 } }, { L_, 5, { 4, 3, 2, 1, 0 } }, { L_, 5, { 3, 1, 4, 2, 0 } }, }; const int NUM_DATA = sizeof DATA / sizeof *DATA; bslma::TestAllocator da("default", veryVeryVeryVerbose); bslma::DefaultAllocatorGuard dag(&da); for (int ti = 0; ti < NUM_DATA; ++ti) { const int LINE = DATA[ti].d_line; const int NUM_ALLOC = DATA[ti].d_numAlloc; const int *DEALLOC_SEQ = DATA[ti].d_deallocSeq; LOOP_ASSERT(LINE, NUM_ALLOC > 0); LOOP_ASSERT(LINE, NUM_ALLOC <= NUM_SIZE_DATA); bslma::TestAllocator oa("object", veryVeryVeryVerbose); Obj mX(&oa); void *p[NUM_SIZE_DATA]; for (int i = 0; i < NUM_ALLOC; ++i) { const int SIZE = SIZE_DATA[i]; p[i] = mX.allocate(SIZE); } LOOP_ASSERT(LINE, NUM_ALLOC == oa.numBlocksInUse()); for (int i = 0; i < NUM_ALLOC; ++i) { const bsls::Types::Int64 numBlocksInUse = oa.numBlocksInUse(); mX.deallocate(p[DEALLOC_SEQ[i]]); LOOP_ASSERT(LINE, numBlocksInUse - 1 == oa.numBlocksInUse()); } LOOP_ASSERT(LINE, 0 == oa.numBlocksInUse()); } { bslma::TestAllocator oa("object", veryVeryVeryVerbose); { Obj mX(&oa); ASSERT(0 == oa.numBlocksInUse()); mX.deallocate(0); ASSERT(0 == oa.numBlocksInUse()); mX.allocate(5); ASSERT(1 == oa.numBlocksInUse()); mX.deallocate(0); ASSERT(1 == oa.numBlocksInUse()); } ASSERT(0 == oa.numBlocksInUse()); } ASSERT(0 == da.numBlocksTotal()); } break; case 3: { // -------------------------------------------------------------------- // DTOR & RELEASE // Ensure that both the destructor and the 'release' method release // all memory allocated from the object allocator. // // Concerns: //: 1 All memory allocated from the object allocator is released at //: destruction. //: //: 2 All memory allocated from the object allocator is released by //: the 'release' method. //: //: 3 Additional allocations can be made from the object following //: a call to 'release'. // // Plan: //: 1 Create a 'bslma::TestAllocator' object, and install it as the //: default allocator (note that a ubiquitous test allocator is //: already installed as the global allocator). //: //: 2 For 'N' in the range '[0 .. 4]': //: 1 Create a 'bslma::TestAllocator' object, 'oa'. //: //: 2 Use the default constructor and 'oa' to create a modifiable //: 'Obj' 'mX'. //: //: 3 Allocate 'N' blocks from 'mX' and verify that the requested //: number of blocks were allocated from 'oa'. //: //: 4 Allow 'mX' to go out of scope and verify that the destructor //: released all memory back to 'oa'. (C-1) //: //: 3 Repeat P-2 except invoke 'release' on 'mX' following P-2.3 and //: verify that 'release' released all memory back to 'oa'. (C-2) //: //: 4 Following each call to 'release', allocate 'N' additional blocks //: from 'mX' and verify that the requested number of blocks were //: allocated from 'oa'. (C-3) // // Testing: // ~bdlma::BlockList(); // void release(); // -------------------------------------------------------------------- if (verbose) cout << endl << "DTOR & RELEASE" << endl << "==============" << endl; const int DATA[] = { 1, 16, 256, 1000 }; const int NUM_DATA = sizeof DATA / sizeof *DATA; bslma::TestAllocator da("default", veryVeryVeryVerbose); bslma::DefaultAllocatorGuard dag(&da); if (verbose) cout << "\nTesting destructor." << endl; { for (int ti = 0; ti <= NUM_DATA; ++ti) { bslma::TestAllocator oa("object", veryVeryVeryVerbose); { Obj mX(&oa); for (int tj = 0; tj < ti; ++tj) { const int SIZE = DATA[tj]; void *p = mX.allocate(SIZE); if (veryVerbose) { T_; P_(SIZE); P(p); } } LOOP_ASSERT(ti, ti == oa.numBlocksInUse()); } LOOP_ASSERT(ti, 0 == oa.numBlocksInUse()); } } if (verbose) cout << "\nTesting 'release'." << endl; { for (int ti = 0; ti <= NUM_DATA; ++ti) { bslma::TestAllocator oa("object", veryVeryVeryVerbose); Obj mX(&oa); for (int tj = 0; tj < ti; ++tj) { const int SIZE = DATA[tj]; void *p = mX.allocate(SIZE); if (veryVerbose) { T_; P_(SIZE); P(p); } } LOOP_ASSERT(ti, ti == oa.numBlocksInUse()); mX.release(); LOOP_ASSERT(ti, 0 == oa.numBlocksInUse()); for (int tj = 0; tj < ti; ++tj) { const int SIZE = DATA[tj]; void *p = mX.allocate(SIZE); if (veryVerbose) { T_; P_(SIZE); P(p); } } LOOP_ASSERT(ti, ti == oa.numBlocksInUse()); } } ASSERT(0 == da.numBlocksTotal()); } break; case 2: { // -------------------------------------------------------------------- // DEFAULT CTOR & ALLOCATE // Ensure that we can use the default constructor to create an // object, and that we can 'allocate' memory from that object. // // Concerns: //: 1 If an allocator is NOT supplied to the default constructor, the //: default allocator in effect at the time of construction becomes //: the object allocator for the resulting object. //: //: 2 If an allocator IS supplied to the default constructor, that //: allocator becomes the object allocator for the resulting object. //: //: 3 Supplying a null allocator address has the same effect as not //: supplying an allocator. //: //: 4 The default constructor allocates no memory. //: //: 5 Any memory allocation is from the object allocator. //: //: 6 Memory blocks returned by 'allocate' are of at least the //: requested size (in bytes). //: //: 7 Memory blocks returned by 'allocate' are maximally aligned. //: //: 8 Calling 'allocate' with 0 returns 0 and has no effect on any //: allocator. //: //: 9 There is no temporary allocation from any allocator. //: //:10 QoI: Asserted precondition violations are detected when enabled. // // Plan: //: 1 Using a loop-based approach, default-construct three distinct //: objects, in turn, but configured differently: (a) without passing //: an allocator, (b) passing a null allocator address explicitly, //: and (c) passing the address of a test allocator distinct from the //: default. For each of these three iterations: (C-1..5, 9) //: //: 1 Create three 'bslma::TestAllocator' objects, and install one as //: as the current default allocator (note that a ubiquitous test //: allocator is already installed as the global allocator). //: //: 2 Use the default constructor to dynamically create an object //: 'mX', with its object allocator configured appropriately (see //: P-2); use a distinct test allocator for the object's footprint. //: //: 3 Use the appropriate test allocators to verify that no memory //: is allocated by the default constructor. (C-4) //: //: 4 Allocate a couple of blocks from 'mX' and verify that all //: memory is allocated from the object allocator. (C-1..3, 5) //: //: 5 Verify that no temporary memory is allocated from any //: allocator. (C-9) //: //: 6 Verify that all object memory is released when the object is //: destroyed. Note that the destructor is fully tested in case 3. //: //: 2 Create a 'bslma::TestAllocator' object and install it as the //: current default allocator. //: //: 3 Using the table-driven technique: //: //: 1 Specify a set of positive allocation request sizes. //: //: 4 For each row 'R' (representing an allocation request size, 'S') //: in the table described in P-3: (C-5..7, 9) //: //: 1 Create a 'bslma::TestAllocator' object 'oa'. //: //: 2 Use the default constructor and 'oa' to create a modifiable //: 'Obj' 'mX'. //: //: 3 Invoke 'mX.allocate(S)'. //: //: 4 Verify that the returned memory address is non-null and that //: the memory was allocated from the object allocator. (C-5) //: //: 5 Verify that the actual size of the allocated block recorded by //: the allocator is equal to the expected size, and that the //: returned memory address is properly offset to reserve room for //: the memory block header. (C-6) //: //: 6 Verify that the returned memory address is maximally aligned. //: (C-7) //: //: 7 Verify that no temporary memory is allocated from any //: allocator. (C-9) //: //: 5 Perform a separate test to verify that 'mX.allocate(0)' returns 0 //: and has no effect on any allocator. (C-8) //: //: 6 Verify that, in appropriate build modes, defensive checks are //: triggered. (C-10) // // Testing: // bdlma::BlockList(bslma::Allocator *ba = 0); // void *allocate(int size); // -------------------------------------------------------------------- if (verbose) cout << endl << "DEFAULT CTOR & ALLOCATE" << endl << "=======================" << endl; if (verbose) cout << "\nTesting constructor." << endl; for (char cfg = 'a'; cfg <= 'c'; ++cfg) { const char CONFIG = cfg; // how we specify the allocator bslma::TestAllocator da("default", veryVeryVeryVerbose); bslma::TestAllocator fa("footprint", veryVeryVeryVerbose); bslma::TestAllocator sa("supplied", veryVeryVeryVerbose); bslma::DefaultAllocatorGuard dag(&da); Obj *objPtr; bslma::TestAllocator *objAllocatorPtr; switch (CONFIG) { case 'a': { objPtr = new (fa) Obj(); objAllocatorPtr = &da; } break; case 'b': { objPtr = new (fa) Obj(0); objAllocatorPtr = &da; } break; case 'c': { objPtr = new (fa) Obj(&sa); objAllocatorPtr = &sa; } break; default: { LOOP_ASSERT(CONFIG, !"Bad allocator config."); } break; } LOOP_ASSERT(CONFIG, sizeof(Obj) == fa.numBytesInUse()); Obj& mX = *objPtr; bslma::TestAllocator& oa = *objAllocatorPtr; bslma::TestAllocator& noa = 'c' != CONFIG ? sa : da; // Verify no allocation from the object allocator. LOOP2_ASSERT(CONFIG, oa.numBlocksTotal(), 0 == oa.numBlocksTotal()); // Verify no allocation from the non-object allocator. LOOP2_ASSERT(CONFIG, noa.numBlocksTotal(), 0 == noa.numBlocksTotal()); // Verify we can allocate from the object. void *p = mX.allocate(1); LOOP2_ASSERT(CONFIG, p, p); LOOP2_ASSERT(CONFIG, oa.numBlocksTotal(), 1 == oa.numBlocksTotal()); LOOP2_ASSERT(CONFIG, noa.numBlocksTotal(), 0 == noa.numBlocksTotal()); p = mX.allocate(3001); LOOP2_ASSERT(CONFIG, p, p); LOOP2_ASSERT(CONFIG, oa.numBlocksTotal(), 2 == oa.numBlocksTotal()); LOOP2_ASSERT(CONFIG, noa.numBlocksTotal(), 0 == noa.numBlocksTotal()); // Reclaim dynamically allocated object under test. fa.deleteObject(objPtr); // Verify all memory is released on object destruction. LOOP2_ASSERT(CONFIG, fa.numBlocksInUse(), 0 == fa.numBlocksInUse()); LOOP2_ASSERT(CONFIG, oa.numBlocksInUse(), 0 == oa.numBlocksInUse()); LOOP2_ASSERT(CONFIG, noa.numBlocksTotal(), 0 == noa.numBlocksTotal()); } typedef bsls::AlignmentUtil U; const int HDRSZ = sizeof(Block) - bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT; if (veryVerbose) { T_; P_(HDRSZ); P(U::BSLS_MAX_ALIGNMENT); } struct { int d_line; // line number int d_size; // memory request size } DATA[] = { //LINE SIZE //---- --------------- { L_, 1 }, { L_, 2 }, { L_, 4 }, { L_, 8 }, { L_, 16 }, { L_, HDRSZ }, { L_, 5 * HDRSZ - 0 }, { L_, 5 * HDRSZ - 1 }, { L_, 5 * HDRSZ - 2 }, { L_, 5 * HDRSZ - 3 }, { L_, 5 * HDRSZ - 4 }, { L_, 5 * HDRSZ - 5 }, { L_, 5 * HDRSZ - 6 }, { L_, 5 * HDRSZ - 7 }, { L_, 5 * HDRSZ - 8 }, { L_, 5 * HDRSZ - 9 }, { L_, 5 * HDRSZ - 10 }, { L_, 5 * HDRSZ - 11 }, { L_, 5 * HDRSZ - 12 }, { L_, 5 * HDRSZ - 13 }, { L_, 5 * HDRSZ - 14 }, { L_, 5 * HDRSZ - 15 }, { L_, 5 * HDRSZ - 16 } }; const int NUM_DATA = sizeof DATA / sizeof *DATA; if (verbose) cout << "\nTesting 'allocate'." << endl; bslma::TestAllocator da("default", veryVeryVeryVerbose); bslma::DefaultAllocatorGuard dag(&da); for (int ti = 0; ti < NUM_DATA; ++ti) { const int LINE = DATA[ti].d_line; const int SIZE = DATA[ti].d_size; const int EXP_SZ = roundUp(SIZE + HDRSZ, U::BSLS_MAX_ALIGNMENT); bslma::TestAllocator oa("object", veryVeryVeryVerbose); Obj mX(&oa); void *p = mX.allocate(SIZE); LOOP2_ASSERT(LINE, ti, p); const void *EXP_P = (char *)oa.lastAllocatedAddress() + HDRSZ; bsls::Types::Int64 numBytes = oa.lastAllocatedNumBytes(); int offset = U::calculateAlignmentOffset(p, U::BSLS_MAX_ALIGNMENT); if (veryVerbose) { T_; P_(SIZE); P_(numBytes); P_(EXP_SZ); P_(p); P_(EXP_P); P(offset); } LOOP2_ASSERT(LINE, ti, EXP_P == p); LOOP2_ASSERT(LINE, ti, EXP_SZ == numBytes); LOOP2_ASSERT(LINE, ti, 0 == offset); LOOP2_ASSERT(LINE, ti, 0 == da.numBlocksTotal()); LOOP2_ASSERT(LINE, ti, 1 == oa.numBlocksTotal()); } if (verbose) cout << "\nTesting 'allocate(0)'." << endl; { bslma::TestAllocator oa("object", veryVeryVeryVerbose); Obj mX(&oa); void *p = mX.allocate(0); ASSERT(0 == p); ASSERT(0 == oa.numBlocksTotal()); ASSERT(0 == da.numBlocksTotal()); } if (verbose) cout << "\nNegative Testing." << endl; { bsls::AssertFailureHandlerGuard hG( bsls::AssertTest::failTestDriver); Obj mX; if (veryVerbose) cout << "\t'allocate(size < 0)'" << endl; { ASSERT_SAFE_PASS(mX.allocate( 1)); ASSERT_SAFE_PASS(mX.allocate( 0)); ASSERT_SAFE_FAIL(mX.allocate(-1)); } } } break; case 1: { // -------------------------------------------------------------------- // BREATHING TEST // This case exercises (but does not fully test) basic functionality. // // Concerns: //: 1 The class is sufficiently functional to enable comprehensive //: testing in subsequent test cases. // // Plan: //: 1 Create a modifiable object 'mX'. //: 2 Allocate a block 'b1' from 'mX'. //: 3 Deallocate block 'b1'. //: 4 Allocate blocks 'b2' and 'b3' from 'mX'. //: 5 Invoke the release method on 'mX'. //: 6 Allocate a block 'b4' from 'mX'. //: 7 Allow 'mX' to go out of scope. // // Testing: // BREATHING TEST // -------------------------------------------------------------------- if (verbose) cout << endl << "BREATHING TEST" << endl << "==============" << endl; bslma::TestAllocator oa("object", veryVeryVeryVerbose); { // 1 Obj mX(&oa); ASSERT(0 == oa.numBlocksInUse()); // 2 void *p = mX.allocate(16); ASSERT(1 == oa.numBlocksInUse()); // 3 mX.deallocate(p); ASSERT(0 == oa.numBlocksInUse()); // 4 mX.allocate(8); ASSERT(1 == oa.numBlocksInUse()); mX.allocate(32); ASSERT(2 == oa.numBlocksInUse()); // 5 mX.release(); ASSERT(0 == oa.numBlocksInUse()); // 6 mX.allocate(1); ASSERT(1 == oa.numBlocksInUse()); } // 7 ASSERT(0 == oa.numBlocksInUse()); } break; default: { cerr << "WARNING: CASE `" << test << "' NOT FOUND." << endl; testStatus = -1; } } // CONCERN: In no case does memory come from the global allocator. LOOP_ASSERT(globalAllocator.numBlocksTotal(), 0 == globalAllocator.numBlocksTotal()); if (testStatus > 0) { cerr << "Error, non-zero test status = " << testStatus << "." << endl; } return testStatus; }