1*51c0b2f7Stbbdev /* 2*51c0b2f7Stbbdev Copyright (c) 2005-2020 Intel Corporation 3*51c0b2f7Stbbdev 4*51c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License"); 5*51c0b2f7Stbbdev you may not use this file except in compliance with the License. 6*51c0b2f7Stbbdev You may obtain a copy of the License at 7*51c0b2f7Stbbdev 8*51c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0 9*51c0b2f7Stbbdev 10*51c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software 11*51c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS, 12*51c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*51c0b2f7Stbbdev See the License for the specific language governing permissions and 14*51c0b2f7Stbbdev limitations under the License. 15*51c0b2f7Stbbdev */ 16*51c0b2f7Stbbdev 17*51c0b2f7Stbbdev //! \file test_malloc_new_handler.cpp 18*51c0b2f7Stbbdev //! \brief Test for [memory_allocation] functionality 19*51c0b2f7Stbbdev 20*51c0b2f7Stbbdev #define __TBB_NO_IMPLICIT_LINKAGE 1 21*51c0b2f7Stbbdev 22*51c0b2f7Stbbdev #include "common/test.h" 23*51c0b2f7Stbbdev #include "common/utils.h" 24*51c0b2f7Stbbdev 25*51c0b2f7Stbbdev #include "common/allocator_overload.h" 26*51c0b2f7Stbbdev 27*51c0b2f7Stbbdev #if !HARNESS_SKIP_TEST && TBB_USE_EXCEPTIONS 28*51c0b2f7Stbbdev 29*51c0b2f7Stbbdev #include "../../src/tbb/tls.h" 30*51c0b2f7Stbbdev 31*51c0b2f7Stbbdev tbb::detail::r1::tls<bool> new_handler_called; 32*51c0b2f7Stbbdev void customNewHandler() { 33*51c0b2f7Stbbdev new_handler_called = true; 34*51c0b2f7Stbbdev throw std::bad_alloc(); 35*51c0b2f7Stbbdev } 36*51c0b2f7Stbbdev 37*51c0b2f7Stbbdev // Return true if operator new threw exception 38*51c0b2f7Stbbdev bool allocateWithException(size_t big_mem) { 39*51c0b2f7Stbbdev bool exception_caught = false; 40*51c0b2f7Stbbdev try { 41*51c0b2f7Stbbdev // Allocate big array (should throw exception) 42*51c0b2f7Stbbdev char* volatile big_array = new char[big_mem]; 43*51c0b2f7Stbbdev // If succeeded, double the size (unless it overflows) and recursively retry 44*51c0b2f7Stbbdev if (big_mem * 2 > big_mem) { 45*51c0b2f7Stbbdev exception_caught = allocateWithException(big_mem * 2); 46*51c0b2f7Stbbdev } 47*51c0b2f7Stbbdev delete[] big_array; 48*51c0b2f7Stbbdev } catch (const std::bad_alloc&) { 49*51c0b2f7Stbbdev bool is_called = new_handler_called; 50*51c0b2f7Stbbdev REQUIRE_MESSAGE(is_called, "User provided new_handler was not called."); 51*51c0b2f7Stbbdev exception_caught = true; 52*51c0b2f7Stbbdev } 53*51c0b2f7Stbbdev return exception_caught; 54*51c0b2f7Stbbdev } 55*51c0b2f7Stbbdev 56*51c0b2f7Stbbdev class AllocLoopBody : utils::NoAssign { 57*51c0b2f7Stbbdev public: 58*51c0b2f7Stbbdev void operator()(int) const { 59*51c0b2f7Stbbdev size_t BIG_MEM = 100 * 1024 * 1024; 60*51c0b2f7Stbbdev new_handler_called = false; 61*51c0b2f7Stbbdev REQUIRE_MESSAGE(allocateWithException(BIG_MEM), "Operator new did not throw bad_alloc."); 62*51c0b2f7Stbbdev } 63*51c0b2f7Stbbdev }; 64*51c0b2f7Stbbdev 65*51c0b2f7Stbbdev //! \brief \ref error_guessing 66*51c0b2f7Stbbdev TEST_CASE("New handler callback") { 67*51c0b2f7Stbbdev #if __TBB_CPP11_GET_NEW_HANDLER_PRESENT 68*51c0b2f7Stbbdev std::new_handler default_handler = std::get_new_handler(); 69*51c0b2f7Stbbdev REQUIRE_MESSAGE(default_handler == nullptr, "No handler should be set at this point."); 70*51c0b2f7Stbbdev #endif 71*51c0b2f7Stbbdev // Define the handler for new operations 72*51c0b2f7Stbbdev std::set_new_handler(customNewHandler); 73*51c0b2f7Stbbdev // Run the test 74*51c0b2f7Stbbdev utils::NativeParallelFor(8, AllocLoopBody()); 75*51c0b2f7Stbbdev // Undo custom handler 76*51c0b2f7Stbbdev std::set_new_handler(0); 77*51c0b2f7Stbbdev } 78*51c0b2f7Stbbdev #endif // !HARNESS_SKIP_TEST && TBB_USE_EXCEPTIONS 79