Ticket #1910: moving_function_swap.patch
File moving_function_swap.patch, 7.7 KB (added by , 14 years ago) |
---|
-
function_base.hpp
122 122 union function_buffer 123 123 { 124 124 // For pointers to function objects 125 void* obj_ptr;125 mutable void* obj_ptr; 126 126 127 127 // For pointers to std::type_info objects 128 128 // (get_functor_type_tag, check_functor_type_tag). … … 203 203 template<typename F> 204 204 struct reference_manager 205 205 { 206 // Note: the 4th argument (bool) would specify whether to move the buffer, 207 // but this is irrelevant in this case. 206 208 static inline void 207 209 get(const function_buffer& in_buffer, function_buffer& out_buffer, 208 functor_manager_operation_type op )210 functor_manager_operation_type op, bool) 209 211 { 210 212 switch (op) { 211 213 case clone_functor_tag: … … 319 321 typedef Functor functor_type; 320 322 321 323 // Function pointers 324 // Note: the 5th argument (bool) would specify whether to move the buffer, 325 // but this is irrelevant for function pointers. 322 326 static inline void 323 327 manager(const function_buffer& in_buffer, function_buffer& out_buffer, 324 functor_manager_operation_type op, function_ptr_tag )328 functor_manager_operation_type op, function_ptr_tag, bool) 325 329 { 326 330 functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); 327 331 } 328 332 329 333 // Function objects that fit in the small-object buffer. 334 // Note: the 5th argument (bool) would specify whether to move the buffer, 335 // but this is irrelevant when the small-object buffer is used. 330 336 static inline void 331 337 manager(const function_buffer& in_buffer, function_buffer& out_buffer, 332 functor_manager_operation_type op, mpl::true_ )338 functor_manager_operation_type op, mpl::true_, bool) 333 339 { 334 340 functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op); 335 341 } … … 337 343 // Function objects that require heap allocation 338 344 static inline void 339 345 manager(const function_buffer& in_buffer, function_buffer& out_buffer, 340 functor_manager_operation_type op, mpl::false_ )346 functor_manager_operation_type op, mpl::false_, bool move_buffer) 341 347 { 342 348 if (op == clone_functor_tag) { 343 // Clone the functor 344 // GCC 2.95.3 gets the CV qualifiers wrong here, so we 345 // can't do the static_cast that we should do. 346 const functor_type* f = 347 (const functor_type*)(in_buffer.obj_ptr); 348 functor_type* new_f = new functor_type(*f); 349 out_buffer.obj_ptr = new_f; 349 if (move_buffer) 350 { 351 out_buffer.obj_ptr = in_buffer.obj_ptr; 352 in_buffer.obj_ptr = 0; 353 } 354 else 355 { 356 // Clone the functor 357 // GCC 2.95.3 gets the CV qualifiers wrong here, so we 358 // can't do the static_cast that we should do. 359 const functor_type* f = 360 (const functor_type*)(in_buffer.obj_ptr); 361 functor_type* new_f = new functor_type(*f); 362 out_buffer.obj_ptr = new_f; 363 } 350 364 } else if (op == destroy_functor_tag) { 351 365 /* Cast from the void pointer to the functor pointer type */ 352 366 functor_type* f = … … 368 382 // whether we need to allocate it on the heap. 369 383 static inline void 370 384 manager(const function_buffer& in_buffer, function_buffer& out_buffer, 371 functor_manager_operation_type op, function_obj_tag )385 functor_manager_operation_type op, function_obj_tag, bool move_buffer) 372 386 { 373 387 manager(in_buffer, out_buffer, op, 374 mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>() );388 mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>(), move_buffer); 375 389 } 376 390 377 391 public: … … 379 393 function pointer or a function object pointer. */ 380 394 static inline void 381 395 manage(const function_buffer& in_buffer, function_buffer& out_buffer, 382 functor_manager_operation_type op )396 functor_manager_operation_type op, bool move_buffer) 383 397 { 384 398 typedef typename get_function_tag<functor_type>::type tag_type; 385 399 switch (op) { … … 388 402 return; 389 403 390 404 default: 391 manager(in_buffer, out_buffer, op, tag_type() );405 manager(in_buffer, out_buffer, op, tag_type(), move_buffer); 392 406 return; 393 407 } 394 408 } … … 403 417 // Function pointers 404 418 static inline void 405 419 manager(const function_buffer& in_buffer, function_buffer& out_buffer, 406 functor_manager_operation_type op, function_ptr_tag )420 functor_manager_operation_type op, function_ptr_tag, bool move_buffer) 407 421 { 408 422 functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); 409 423 } … … 559 573 vtable_base() : manager(0) { } 560 574 void (*manager)(const function_buffer& in_buffer, 561 575 function_buffer& out_buffer, 562 functor_manager_operation_type op); 576 functor_manager_operation_type op, 577 bool move_buffer); 563 578 }; 564 579 } // end namespace function 565 580 } // end namespace detail … … 585 600 if (!vtable) return typeid(void); 586 601 587 602 detail::function::function_buffer type; 588 vtable->manager(functor, type, detail::function::get_functor_type_tag );603 vtable->manager(functor, type, detail::function::get_functor_type_tag, false); 589 604 return *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(type.const_obj_ptr); 590 605 } 591 606 -
function_template.hpp
286 286 void clear(function_buffer& functor) 287 287 { 288 288 if (manager) 289 manager(functor, functor, destroy_functor_tag );289 manager(functor, functor, destroy_functor_tag, false); 290 290 } 291 291 292 292 private: … … 729 729 if (&other == this) 730 730 return; 731 731 732 BOOST_FUNCTION_FUNCTION tmp = *this; 733 *this = other; 734 other = tmp; 732 BOOST_FUNCTION_FUNCTION tmp; 733 tmp.move_assign(*this); 734 this->move_assign(other); 735 other.move_assign(tmp); 735 736 } 736 737 737 738 // Clear out a target, if there is one … … 768 769 if (!f.empty()) { 769 770 this->vtable = f.vtable; 770 771 f.vtable->manager(f.functor, this->functor, 771 boost::detail::function::clone_functor_tag );772 boost::detail::function::clone_functor_tag, false); 772 773 } 773 774 } 774 775 776 // Moves the value from the specified argument to *this. If the argument 777 // has its function object allocated on the heap, move_assign will pass 778 // its buffer to *this, and set the argument's buffer pointer to NULL. 779 void move_assign(BOOST_FUNCTION_FUNCTION& f) 780 { 781 if (&f == this) 782 return; 783 784 clear(); 785 try { 786 if (!f.empty()) { 787 this->vtable = f.vtable; 788 f.vtable->manager(f.functor, this->functor, 789 boost::detail::function::clone_functor_tag, true); 790 } 791 } catch (...) { 792 vtable = 0; 793 throw; 794 } 795 } 796 775 797 template<typename Functor> 776 798 void assign_to(Functor f) 777 799 {