/* * Copyright 2008-2012 NVIDIA Corporation * * 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 * * http://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 #include #include #include #include namespace thrust { namespace detail { namespace allocator_traits_detail { // destroy_range has three cases: // if Allocator has an effectful member function destroy: // 1. destroy via the allocator // else // 2. if T has a non-trivial destructor, destroy the range without using the allocator // 3. if T has a trivial destructor, do a no-op template struct has_effectful_member_destroy : has_member_destroy {}; // std::allocator::destroy's only effect is to invoke its argument's destructor template struct has_effectful_member_destroy, T> : thrust::detail::false_type {}; // case 1: Allocator has an effectful 1-argument member function "destroy" template struct enable_if_destroy_range_case1 : thrust::detail::enable_if< has_effectful_member_destroy< Allocator, typename pointer_element::type >::value > {}; // case 2: Allocator has no member function "destroy", but T has a non-trivial destructor template struct enable_if_destroy_range_case2 : thrust::detail::enable_if< !has_effectful_member_destroy< Allocator, typename pointer_element::type >::value && !has_trivial_destructor< typename pointer_element::type >::value > {}; // case 3: Allocator has no member function "destroy", and T has a trivial destructor template struct enable_if_destroy_range_case3 : thrust::detail::enable_if< !has_effectful_member_destroy< Allocator, typename pointer_element::type >::value && has_trivial_destructor< typename pointer_element::type >::value > {}; template struct destroy_via_allocator { Allocator &a; destroy_via_allocator(Allocator &a) : a(a) {} template inline __host__ __device__ void operator()(T &x) { allocator_traits::destroy(a, &x); } }; // destroy_range case 1: destroy via allocator template typename enable_if_destroy_range_case1::type destroy_range(Allocator &a, Pointer p, Size n) { thrust::for_each_n(allocator_system::get(a), p, n, destroy_via_allocator(a)); } // we must prepare for His coming struct gozer { template inline __host__ __device__ void operator()(T &x) { x.~T(); } }; // destroy_range case 2: destroy without the allocator template typename enable_if_destroy_range_case2::type destroy_range(Allocator &a, Pointer p, Size n) { thrust::for_each_n(allocator_system::get(a), p, n, gozer()); } // destroy_range case 3: no-op template typename enable_if_destroy_range_case3::type destroy_range(Allocator &, Pointer, Size) { // no op } } // end allocator_traits_detail template void destroy_range(Allocator &a, Pointer p, Size n) { return allocator_traits_detail::destroy_range(a,p,n); } } // end detail } // end thrust