 -- |
 -- A reference to data stored on the device. It is automatically freed.
 --
-newtype DevicePtr = DevicePtr (ForeignPtr ())
-
-withDevicePtr               :: DevicePtr -> (Ptr () -> IO b) -> IO b
-withDevicePtr (DevicePtr d) =  withForeignPtr d
-
-newDevicePtr      :: FinalizerPtr () -> Ptr () -> IO DevicePtr
-newDevicePtr fp p =  newForeignPtr fp p >>= (return.DevicePtr)
+type DevicePtr a = ForeignPtr a
+
+withDevicePtr :: DevicePtr a -> (Ptr a -> IO b) -> IO b
+withDevicePtr =  withForeignPtr
+
+newDevicePtr   :: Ptr () -> IO (DevicePtr ())
+newDevicePtr p =  (doAutoRelease free_) >>= \f -> newForeignPtr f p
 
 --
 -- Memory copy

-- requirements are met. The actual allocation pitch is returned
--
malloc3D :: (Int64,Int64,Int64)         -- ^ allocation (width,height,depth) in bytes
         -> IO (Either String (DevicePtr,Int64))
malloc3D = error "not implemented yet"



-- |
-- Initialise device memory to a given value
--
memset                  :: DevicePtr () -> Int64 -> Int -> IO (Maybe String)
memset ptr bytes symbol =  nothingIfOk `fmap` cudaMemset ptr symbol bytes

{# fun unsafe cudaMemset
    { withDevicePtr* `DevicePtr ()' ,
                     `Int'          ,
      cIntConv       `Int64'        } -> `Status' cToEnum #}


-- |
-- Initialise a matrix to a given value
--
memset2D :: DevicePtr ()                -- ^ The device memory
         -> (Int64,Int64)               -- ^ The (width,height) of the matrix in bytes
         -> Int64                       -- ^ The allocation pitch, as returned by 'malloc2D'
         -> Int                         -- ^ Value to set for each byte
