//! Specifies where to acquire the data
struct access_location
{
//! The enum
enum Enum
{
host, //!< Ask to acquire the data on the host
#ifdef ENABLE_CUDA
device //!< Ask to acquire the data on the device
#endif
};
};
//! Defines where the data is currently stored
struct data_location
{
//! The enum
enum Enum
{
host, //!< Data was last updated on the host
#ifdef ENABLE_CUDA
device, //!< Data was last updated on the device
hostdevice //!< Data is up to date on both the host and device
#endif
};
};
//! Specify how the data is to be accessed
struct access_mode
{
//! The enum
enum Enum
{
read, //!< Data will be accessed read only
readwrite, //!< Data will be accessed for read and write
overwrite //!< The data is to be completely overwritten during this acquire
};
};
//! CRTP (Curiously recurring template pattern) interface for GPUArray/GlobalArray
template<class T, class Derived>
class GPUArrayBase
{
.....
protected:
//! Acquires the data pointer for use
inline ArrayHandleDispatch<T> acquire(const access_location::Enum location, const access_mode::Enum mode
#ifdef ENABLE_CUDA
, bool async = false
#endif
) const
{
return static_cast<Derived const&>(*this).acquire(location, mode
#ifdef ENABLE_CUDA
, async
#endif
);
}
//! Release the data pointer
inline void release() const
{
return static_cast<Derived const&>(*this).release();
}
//! Returns the acquire state
inline bool isAcquired() const
{
return static_cast<Derived const&>(*this).isAcquired();
}
// need to be friend of the ArrayHandle class
friend class ArrayHandle<T>;
friend class ArrayHandleAsync<T>;
private:
// Make constructor private to prevent mistakes
GPUArrayBase() {};
friend Derived;
};
//! This base class is the glue between the ArrayHandle and a generic GPUArrayBase<Derived>
template<class T>
class ArrayHandleDispatch
{
public:
//! Constructor
ArrayHandleDispatch(T* const _data)
: data(_data) {}
//! Get the data pointer
T * const get() const
{
return data;
}
//! Destructor
virtual ~ArrayHandleDispatch() = default;
private:
//! The data pointer
T* const data;
};
//! Handle to access the data pointer handled by GPUArray
/*! The data in GPUArray is only accessible via ArrayHandle. The pointer is accessible for the lifetime of the
ArrayHandle. When the ArrayHandle is destroyed, the GPUArray is notified that the data has been released. This
tracking mechanism provides for error checking that will cause code assertions to fail if the data is acquired
more than once.
ArrayHandle is intended to be used within a scope limiting its use. For example:
\code
GPUArray<int> gpu_array(100);
{
ArrayHandle<int> h_handle(gpu_array, access_location::host, access_mode::readwrite);
... use h_handle.data ...
}
\endcode
The actual raw pointer \a data should \b NOT be assumed to be the same after the handle is released.
The pointer may in fact be re-allocated somewhere else after the handle is released and before the next handle
is acquired.
\ingroup data_structs
*/
template<class T>
class ArrayHandle
{
public:
//! Aquires the data and sets \a data
/*! \tparam Derived the type of GPUArray implementation
*/
template<class Derived>
inline ArrayHandle(const GPUArrayBase<T, Derived>& gpu_array, const access_location::Enum location = access_location::host,
const access_mode::Enum mode = access_mode::readwrite);
//! Notifies the containing GPUArray that the handle has been released
virtual inline ~ArrayHandle() = default;
private:
ArrayHandleDispatch<T> dispatch; //!< Reference to the dispatch object that manages the acquire/release
public:
T* const data; //!< Pointer to data
};
沒有留言:
張貼留言