From f36045ab0095d7a0e8c8a2cbe796fced4201d21f Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Sat, 27 Jun 2009 05:24:16 +0000 Subject: [PATCH] Fix custom memory allocation for timers. Ref #3107. [SVN r54392] --- include/boost/asio/detail/timer_queue.hpp | 10 +++-- test/deadline_timer.cpp | 53 +++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/include/boost/asio/detail/timer_queue.hpp b/include/boost/asio/detail/timer_queue.hpp index f5370e51..3b20fc48 100644 --- a/include/boost/asio/detail/timer_queue.hpp +++ b/include/boost/asio/detail/timer_queue.hpp @@ -67,8 +67,10 @@ public: heap_.reserve(heap_.size() + 1); // Create a new timer object. - std::auto_ptr > new_timer( - new timer(time, handler, token)); + typedef timer timer_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr new_timer(raw_ptr, time, handler, token); // Insert the new timer into the hash. typedef typename hash_map::iterator iterator; @@ -78,12 +80,12 @@ public: if (!result.second) { result.first->second->prev_ = new_timer.get(); - new_timer->next_ = result.first->second; + new_timer.get()->next_ = result.first->second; result.first->second = new_timer.get(); } // Put the timer at the correct position in the heap. - new_timer->heap_index_ = heap_.size(); + new_timer.get()->heap_index_ = heap_.size(); heap_.push_back(new_timer.get()); up_heap(heap_.size() - 1); bool is_first = (heap_[0] == new_timer.get()); diff --git a/test/deadline_timer.cpp b/test/deadline_timer.cpp index e48a613c..cd7e1e3f 100644 --- a/test/deadline_timer.cpp +++ b/test/deadline_timer.cpp @@ -203,10 +203,63 @@ void deadline_timer_cancel_test() BOOST_CHECK(timers[i].t.cancel() == 1); } +struct custom_allocation_timer_handler +{ + custom_allocation_timer_handler(int* count) : count_(count) {} + void operator()(const boost::system::error_code&) {} + int* count_; +}; + +void* asio_handler_allocate(std::size_t size, + custom_allocation_timer_handler* handler) +{ + ++(*handler->count_); + return ::operator new(size); +} + +void asio_handler_deallocate(void* pointer, std::size_t, + custom_allocation_timer_handler* handler) +{ + --(*handler->count_); + ::operator delete(pointer); +} + +void deadline_timer_custom_allocation_test() +{ + static boost::asio::io_service io_service; + struct timer + { + boost::asio::deadline_timer t; + timer() : t(io_service) {} + } timers[100]; + + int allocation_count = 0; + + for (int i = 0; i < 50; ++i) + { + timers[i].t.expires_at(boost::posix_time::pos_infin); + timers[i].t.async_wait(custom_allocation_timer_handler(&allocation_count)); + } + + for (int i = 50; i < 100; ++i) + { + timers[i].t.expires_at(boost::posix_time::neg_infin); + timers[i].t.async_wait(custom_allocation_timer_handler(&allocation_count)); + } + + for (int i = 0; i < 50; ++i) + timers[i].t.cancel(); + + io_service.run(); + + BOOST_CHECK(allocation_count == 0); +} + test_suite* init_unit_test_suite(int, char*[]) { test_suite* test = BOOST_TEST_SUITE("deadline_timer"); test->add(BOOST_TEST_CASE(&deadline_timer_test)); test->add(BOOST_TEST_CASE(&deadline_timer_cancel_test)); + test->add(BOOST_TEST_CASE(&deadline_timer_custom_allocation_test)); return test; }