libSCALE  0.2.0
A modern C++ CUDA API
sp::RAIIObject< AllocType, CTorArgs > Class Template Reference

A generic mechanism for giving RAII semantics to C-style APIs. More...

#include <RAII.hpp>

Inheritance diagram for sp::RAIIObject< AllocType, CTorArgs >:
[legend]

Public Member Functions

 RAIIObject (const CTorArgs &... args)
 Allocate a new object and take ownership of it. More...
 
 RAIIObject (const APIType &obj, bool own=true)
 Wrap an existing object. More...
 
const APIType get () const
 Get the underlying C API object (eg. cudaStream_t) More...
 
APIType get ()
 Get the underlying C API object (eg. cudaStream_t) More...
 
APIType operator* ()
 
const APIType operator* () const
 
 operator APIType () const
 Implicitly convert to the C API type, so you can just pass this object to the C library whence it came. More...
 
 operator APIType ()
 

Protected Types

using APIType = typename AllocType::APIType
 The C API type. Something like cudaStream_t. More...
 
using UnderlyingType = std::remove_pointer_t< APIType >
 

Detailed Description

template<typename AllocType, typename... CTorArgs>
class sp::RAIIObject< AllocType, CTorArgs >

A generic mechanism for giving RAII semantics to C-style APIs.

If you have a C API that works like this:

makeThingy(Thingy** output);
destroyThingy(Thingy* input);

You can write an allocator class wrapping makeThingy() and destroyThingy() with this signature:

struct ThingyAllocator {
Thingy* create();
void destroy(const Thingy*);
}
T destroy(T... args)

You can then instantiate RAIIObject<Thingy*, ThingyAllocator> and have RAII semantics for Thingy, thus eliminating many of the nightmares associated with using C APIs which have their own allocation functions .

This class defines operators allowing implicit conversion to the underlying C API type, allowing you to directly pass an RAIIObject<...> to functions of the C library you've wrapped.

Note
C APIs that work in this fashion typically give a nice name to Thingy* and give you that as the API object for you to play with. For instance, all NVIDIA® CUDA® APIs work like this: cudaStream_t is secretly pointer to a magic internal struct, for example.
Template Parameters
AllocTypeA wrapper type around the C allocate/deallocate functions.

Member Typedef Documentation

◆ APIType

template<typename AllocType , typename... CTorArgs>
using sp::RAIIObject< AllocType, CTorArgs >::APIType = typename AllocType::APIType
protected

The C API type. Something like cudaStream_t.

Constructor & Destructor Documentation

◆ RAIIObject() [1/2]

template<typename AllocType , typename... CTorArgs>
sp::RAIIObject< AllocType, CTorArgs >::RAIIObject ( const CTorArgs &...  args)
explicit

Allocate a new object and take ownership of it.

◆ RAIIObject() [2/2]

template<typename AllocType , typename... CTorArgs>
sp::RAIIObject< AllocType, CTorArgs >::RAIIObject ( const APIType obj,
bool  own = true 
)
explicit

Wrap an existing object.

This is mostly useful for writing glue code that bridges between C and C++ APIs.

Parameters
objThe object to wrap.
ownIf true, ownership is taken of the object. This is almost always desirable.

Member Function Documentation

◆ get() [1/2]

template<typename AllocType , typename... CTorArgs>
APIType sp::RAIIObject< AllocType, CTorArgs >::get ( )

Get the underlying C API object (eg. cudaStream_t)

◆ get() [2/2]

template<typename AllocType , typename... CTorArgs>
const APIType sp::RAIIObject< AllocType, CTorArgs >::get ( ) const

Get the underlying C API object (eg. cudaStream_t)

◆ operator APIType()

template<typename AllocType , typename... CTorArgs>
sp::RAIIObject< AllocType, CTorArgs >::operator APIType ( ) const

Implicitly convert to the C API type, so you can just pass this object to the C library whence it came.