~ubuntu-branches/ubuntu/utopic/libthrust/utopic

« back to all changes in this revision

Viewing changes to system/cuda/detail/detail/cached_temporary_allocator.h

  • Committer: Package Import Robot
  • Author(s): Andreas Beckmann
  • Date: 2013-07-10 12:57:33 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20130710125733-my19jic71sqsabaj
Tags: 1.7.0-1
* New upstream release.  (Closes: #715362)
* Update watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright 2008-2012 NVIDIA Corporation
 
3
 *
 
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
 
5
 *  you may not use this file except in compliance with the License.
 
6
 *  You may obtain a copy of the License at
 
7
 *
 
8
 *      http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 *  Unless required by applicable law or agreed to in writing, software
 
11
 *  distributed under the License is distributed on an "AS IS" BASIS,
 
12
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 *  See the License for the specific language governing permissions and
 
14
 *  limitations under the License.
 
15
 */
 
16
 
 
17
#pragma once
 
18
 
 
19
#include <thrust/detail/config.h>
 
20
#include <thrust/detail/raw_pointer_cast.h>
 
21
#include <thrust/detail/allocator/allocator_traits.h>
 
22
#include <thrust/detail/allocator/temporary_allocator.h>
 
23
#include <thrust/pair.h>
 
24
#include <map>
 
25
 
 
26
namespace thrust
 
27
{
 
28
namespace system
 
29
{
 
30
namespace cuda
 
31
{
 
32
namespace detail
 
33
{
 
34
namespace detail
 
35
{
 
36
 
 
37
 
 
38
template<typename DerivedPolicy, template<typename> class BasePolicy>
 
39
  class cached_temporary_allocator
 
40
    : public BasePolicy<cached_temporary_allocator<DerivedPolicy,BasePolicy> >
 
41
{
 
42
  private:
 
43
    typedef thrust::detail::temporary_allocator<char,DerivedPolicy> base_allocator_type;
 
44
    typedef thrust::detail::allocator_traits<base_allocator_type>   traits;
 
45
    typedef typename traits::pointer                                  allocator_pointer;
 
46
    typedef std::multimap<std::ptrdiff_t, void*>                      free_blocks_type;
 
47
    typedef std::map<void *, std::ptrdiff_t>                          allocated_blocks_type;
 
48
 
 
49
    base_allocator_type   m_base_allocator;
 
50
    free_blocks_type      free_blocks;
 
51
    allocated_blocks_type allocated_blocks;
 
52
 
 
53
    void free_all()
 
54
    {
 
55
      // deallocate all outstanding blocks in both lists
 
56
      for(free_blocks_type::iterator i = free_blocks.begin();
 
57
          i != free_blocks.end();
 
58
          ++i)
 
59
      {
 
60
        // transform the pointer to allocator_pointer before calling deallocate
 
61
        traits::deallocate(m_base_allocator, allocator_pointer(reinterpret_cast<char*>(i->second)), i->first);
 
62
      }
 
63
 
 
64
      for(allocated_blocks_type::iterator i = allocated_blocks.begin();
 
65
          i != allocated_blocks.end();
 
66
          ++i)
 
67
      {
 
68
        // transform the pointer to allocator_pointer before calling deallocate
 
69
        traits::deallocate(m_base_allocator, allocator_pointer(reinterpret_cast<char*>(i->first)), i->second);
 
70
      }
 
71
    }
 
72
 
 
73
  public:
 
74
    cached_temporary_allocator(thrust::execution_policy<DerivedPolicy> &system)
 
75
      : m_base_allocator(system)
 
76
    {}
 
77
 
 
78
    ~cached_temporary_allocator()
 
79
    {
 
80
      // free all allocations when cached_allocator goes out of scope
 
81
      free_all();
 
82
    }
 
83
 
 
84
    void *allocate(std::ptrdiff_t num_bytes)
 
85
    {
 
86
      void *result = 0;
 
87
 
 
88
      // search the cache for a free block
 
89
      free_blocks_type::iterator free_block = free_blocks.find(num_bytes);
 
90
 
 
91
      if(free_block != free_blocks.end())
 
92
      {
 
93
        // get the pointer
 
94
        result = free_block->second;
 
95
 
 
96
        // erase from the free_blocks map
 
97
        free_blocks.erase(free_block);
 
98
      }
 
99
      else
 
100
      {
 
101
        // no allocation of the right size exists
 
102
        // create a new one with m_base_allocator
 
103
        // allocate memory and convert to raw pointer
 
104
        result = thrust::raw_pointer_cast(traits::allocate(m_base_allocator, num_bytes));
 
105
      }
 
106
 
 
107
      // insert the allocated pointer into the allocated_blocks map
 
108
      allocated_blocks.insert(std::make_pair(result, num_bytes));
 
109
 
 
110
      return result;
 
111
    }
 
112
 
 
113
    void deallocate(void *ptr)
 
114
    {
 
115
      // erase the allocated block from the allocated blocks map
 
116
      allocated_blocks_type::iterator iter = allocated_blocks.find(ptr);
 
117
      std::ptrdiff_t num_bytes = iter->second;
 
118
      allocated_blocks.erase(iter);
 
119
 
 
120
      // insert the block into the free blocks map
 
121
      free_blocks.insert(std::make_pair(num_bytes, ptr));
 
122
    }
 
123
};
 
124
 
 
125
 
 
126
// overload get_temporary_buffer on cached_temporary_allocator
 
127
// note that we take a reference to cached_temporary_allocator
 
128
template<typename T, typename DerivedPolicy, template<typename> class BasePolicy>
 
129
  thrust::pair<T*, std::ptrdiff_t>
 
130
    get_temporary_buffer(cached_temporary_allocator<DerivedPolicy,BasePolicy> &alloc, std::ptrdiff_t n)
 
131
{
 
132
  // ask the allocator for sizeof(T) * n bytes
 
133
  T* result = reinterpret_cast<T*>(alloc.allocate(sizeof(T) * n));
 
134
 
 
135
  // return the pointer and the number of elements allocated
 
136
  return thrust::make_pair(result,n);
 
137
}
 
138
 
 
139
 
 
140
// overload return_temporary_buffer on cached_temporary_allocator
 
141
// an overloaded return_temporary_buffer should always accompany
 
142
// an overloaded get_temporary_buffer
 
143
template<typename Pointer, typename DerivedPolicy, template<typename> class BasePolicy>
 
144
  void return_temporary_buffer(cached_temporary_allocator<DerivedPolicy,BasePolicy> &alloc, Pointer p)
 
145
{
 
146
  // return the pointer to the allocator
 
147
  alloc.deallocate(thrust::raw_pointer_cast(p));
 
148
}
 
149
 
 
150
 
 
151
} // end detail
 
152
} // end detail
 
153
} // end cuda
 
154
} // end system
 
155
} // end thrust
 
156