#ifndef BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP
#define BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP
#include <cstddef>
#include <exception>
#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/compute/buffer.hpp>
#include <boost/compute/system.hpp>
#include <boost/compute/context.hpp>
#include <boost/compute/command_queue.hpp>
#include <boost/compute/iterator/buffer_iterator.hpp>
namespace boost {
namespace compute {
template<class T>
class mapped_view
{
public:
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef buffer_iterator<T> iterator;
typedef buffer_iterator<T> const_iterator;
mapped_view()
{
m_mapped_ptr = 0;
}
mapped_view(T *host_ptr,
size_type n,
const context &context = system::default_context())
: m_buffer(_make_mapped_buffer(host_ptr, n, context))
{
m_mapped_ptr = 0;
}
mapped_view(const T *host_ptr,
size_type n,
const context &context = system::default_context())
: m_buffer(_make_mapped_buffer(host_ptr, n, context))
{
m_mapped_ptr = 0;
}
mapped_view(const mapped_view<T> &other)
: m_buffer(other.m_buffer)
{
m_mapped_ptr = 0;
}
mapped_view<T>& operator=(const mapped_view<T> &other)
{
if(this != &other){
m_buffer = other.m_buffer;
m_mapped_ptr = 0;
}
return *this;
}
~mapped_view()
{
}
iterator begin()
{
return ::boost::compute::make_buffer_iterator<T>(m_buffer, 0);
}
const_iterator begin() const
{
return ::boost::compute::make_buffer_iterator<T>(m_buffer, 0);
}
const_iterator cbegin() const
{
return begin();
}
iterator end()
{
return ::boost::compute::make_buffer_iterator<T>(m_buffer, size());
}
const_iterator end() const
{
return ::boost::compute::make_buffer_iterator<T>(m_buffer, size());
}
const_iterator cend() const
{
return end();
}
size_type size() const
{
return m_buffer.size() / sizeof(T);
}
T* get_host_ptr()
{
return static_cast<T *>(m_buffer.get_info<void *>(CL_MEM_HOST_PTR));
}
const T* get_host_ptr() const
{
return static_cast<T *>(m_buffer.get_info<void *>(CL_MEM_HOST_PTR));
}
void resize(size_type size)
{
T *old_ptr = get_host_ptr();
m_buffer = _make_mapped_buffer(old_ptr, size, m_buffer.get_context());
}
bool empty() const
{
return size() == 0;
}
const buffer& get_buffer() const
{
return m_buffer;
}
void map(cl_map_flags flags, command_queue &queue)
{
BOOST_ASSERT(m_mapped_ptr == 0);
m_mapped_ptr = queue.enqueue_map_buffer(
m_buffer, flags, 0, m_buffer.size()
);
}
void map(command_queue &queue)
{
map(CL_MAP_READ | CL_MAP_WRITE, queue);
}
void unmap(command_queue &queue)
{
BOOST_ASSERT(m_mapped_ptr != 0);
queue.enqueue_unmap_buffer(m_buffer, m_mapped_ptr);
m_mapped_ptr = 0;
}
private:
static buffer _make_mapped_buffer(T *host_ptr,
size_t n,
const context &context)
{
return buffer(
context,
n * sizeof(T),
buffer::read_write | buffer::use_host_ptr,
host_ptr
);
}
static buffer _make_mapped_buffer(const T *host_ptr,
size_t n,
const context &context)
{
return buffer(
context,
n * sizeof(T),
buffer::read_only | buffer::use_host_ptr,
const_cast<void *>(static_cast<const void *>(host_ptr))
);
}
private:
buffer m_buffer;
void *m_mapped_ptr;
};
} }
#endif