/*
 * oclh_h_basetype_templates.h
 *      Author: havock
 */
#ifndef OCLH_H_BASETYPE_TEMPLATES_H_
#define OCLH_H_BASETYPE_TEMPLATES_H_ 1

#define _GHM_BASETYPE_HD_DECLARATION(__GHM_BASETYPE_ARG_DEC__)                 \
typedef struct _GHT_HOST_DEV_##__GHM_BASETYPE_ARG_DEC__##_PTR {                \
    __GHM_BASETYPE_ARG_DEC__ * hPtr;                                           \
    cl_mem   dPtr;                                                             \
    uint64_t u64NofVals;                                                       \
} _GHT_HD##__GHM_BASETYPE_ARG_DEC__ ;                                          \
_GHT_HD##__GHM_BASETYPE_ARG_DEC__ _ghf_declHD_##__GHM_BASETYPE_ARG_DEC__(void);\
int32_t _ghf_wdcAllocHD_##__GHM_BASETYPE_ARG_DEC__ (_GHT_WRKSET wSet,          \
            _GHT_HD##__GHM_BASETYPE_ARG_DEC__ * const pBaseType,               \
            const uint64_t u64NofVals);                                        \
int32_t _ghf_wdcReAllocHD_##__GHM_BASETYPE_ARG_DEC__(_GHT_WRKSET wSet,         \
            const _GHE_SYNC_TYPE SyncType,                                     \
            _GHT_HD##__GHM_BASETYPE_ARG_DEC__ * const pBaseType,               \
            const uint64_t u64NofVals);                                        \
int32_t _ghf_wdcSyncHD_##__GHM_BASETYPE_ARG_DEC__(_GHT_WRKSET wSet,            \
            const _GHE_SYNC_TYPE SyncType,                                     \
            _GHT_HD##__GHM_BASETYPE_ARG_DEC__ * const pBaseType);              \
int32_t _ghf_wdcFillHD_##__GHM_BASETYPE_ARG_DEC__(_GHT_WRKSET wSet,            \
            _GHT_HD##__GHM_BASETYPE_ARG_DEC__ * const pBaseType,               \
            const __GHM_BASETYPE_ARG_DEC__ Val);                               \
int32_t _ghf_isHD_##__GHM_BASETYPE_ARG_DEC__##_Valid(                          \
            const _GHT_HD##__GHM_BASETYPE_ARG_DEC__ BaseType);                 \
int32_t _ghf_wipeHD_##__GHM_BASETYPE_ARG_DEC__(_GHT_WRKSET wSet,               \
            _GHT_HD##__GHM_BASETYPE_ARG_DEC__ * const pBaseType);              \

#define _GHM_BASETYPE_HD_IMPLEMENTATION(__GHM_BASETYPE_ARG_IMP__)              \
_GHT_HD##__GHM_BASETYPE_ARG_IMP__ _ghf_declHD_##__GHM_BASETYPE_ARG_IMP__(void){\
    _GHT_HD##__GHM_BASETYPE_ARG_IMP__ BaseType={ .hPtr=NULL,                   \
                                                 .dPtr=NULL,.u64NofVals=0 };   \
    return(BaseType);                                                          \
}                                                                              \
int32_t _ghf_wdcAllocHD_##__GHM_BASETYPE_ARG_IMP__(_GHT_WRKSET wSet,           \
            _GHT_HD##__GHM_BASETYPE_ARG_IMP__ * const pBaseType,               \
            const uint64_t u64NofVals) {                                       \
    if(!pBaseType) return(_GHM_NULL_POINTER_RECEIVED_ERROR);                   \
    _ghf_wipeHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,pBaseType);                   \
    pBaseType->hPtr=_ghf_wdcAllocHostBuf(wSet,                                 \
                                  sizeof(__GHM_BASETYPE_ARG_IMP__)*u64NofVals);\
    if(!pBaseType->hPtr) {                                                     \
        _ghf_wipeHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,pBaseType);               \
        return(_GHM_HOST_MEMALLOC_ERROR);                                      \
    }                                                                          \
    pBaseType->dPtr=                                                           \
        _ghf_wdcAllocDevBuf(wSet,CL_MEM_READ_WRITE,                            \
            sizeof(__GHM_BASETYPE_ARG_IMP__)*u64NofVals,NULL);                 \
    if(!pBaseType->dPtr) {                                                     \
        _ghf_wipeHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,pBaseType);               \
        return(_GHM_DEVICE_MEMALLOC_ERROR);                                    \
    }                                                                          \
    pBaseType->u64NofVals=u64NofVals;                                          \
    return(_GHM_OK);                                                           \
}                                                                              \
int32_t _ghf_wdcReAllocHD_##__GHM_BASETYPE_ARG_IMP__(_GHT_WRKSET wSet,         \
            const _GHE_SYNC_TYPE SyncType,                                     \
            _GHT_HD##__GHM_BASETYPE_ARG_IMP__ * const pBaseType,               \
            const uint64_t u64NofVals) {                                       \
    __GHM_BASETYPE_ARG_IMP__ * hTmpPtr=NULL;                                   \
    if(!pBaseType) return(_GHM_NULL_POINTER_RECEIVED_ERROR);                   \
    hTmpPtr=realloc(pBaseType->hPtr,                                           \
                    sizeof(__GHM_BASETYPE_ARG_IMP__)*u64NofVals);              \
    if(!hTmpPtr) {                                                             \
        if(wSet.pvDat) wSet.pfnDatCleaner(wSet);                               \
        _ghf_wipeHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,pBaseType);               \
        return(_GHM_HOST_MEMALLOC_ERROR);                                      \
    }                                                                          \
    pBaseType->hPtr=hTmpPtr;                                                   \
    _ghf_freeDevZ(wSet, &pBaseType->dPtr);                                     \
    pBaseType->dPtr=                                                           \
        _ghf_wdcAllocDevBuf(wSet,CL_MEM_READ_WRITE,                            \
                            sizeof(__GHM_BASETYPE_ARG_IMP__)*u64NofVals,NULL); \
    if(!pBaseType->dPtr) {                                                     \
        _ghf_wipeHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,pBaseType);               \
        return(_GHM_DEVICE_MEMALLOC_ERROR);                                    \
    }                                                                          \
    pBaseType->u64NofVals=u64NofVals;                                          \
    { int32_t err=0;                                                           \
      if((err= _ghf_wdcSyncHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,                \
                                          SyncType,pBaseType))) return(err); } \
    return(_GHM_OK);                                                           \
}                                                                              \
int32_t _ghf_wdcSyncHD_##__GHM_BASETYPE_ARG_IMP__(_GHT_WRKSET wSet,            \
            const _GHE_SYNC_TYPE SyncType,                                     \
            _GHT_HD##__GHM_BASETYPE_ARG_IMP__ * const pBaseType) {             \
    int32_t err=0;                                                             \
    if(!pBaseType) return(_GHM_NULL_POINTER_RECEIVED_ERROR);                   \
    switch(SyncType) {                                                         \
        case _GHE_SYNC_HOST_TO_DEV:                                            \
            {                                                                  \
                char pcLogMsg[_GHM_MAXLEN_OF_LOGMSG];                          \
                snprintf(pcLogMsg, _GHM_MAXLEN_OF_LOGMSG,                      \
                         "%s/clEnqueueWriteBuffer", __func__);                 \
                wSet.APIErr=clEnqueueWriteBuffer(wSet.Queue,                   \
                    pBaseType->dPtr, CL_TRUE, 0ul,                             \
                    sizeof(__GHM_BASETYPE_ARG_IMP__)*pBaseType->u64NofVals,    \
                    pBaseType->hPtr, 0u, NULL, NULL);                          \
                if((err=_ghf_wdcChkWS_APIErr(wSet,pcLogMsg,_GHM_FL))) {        \
                    _ghf_wipeHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,pBaseType);   \
                    return(err);                                               \
                }                                                              \
            }                                                                  \
            break;                                                             \
        case _GHE_SYNC_DEV_TO_HOST:                                            \
            {                                                                  \
                char pcLogMsg[_GHM_MAXLEN_OF_LOGMSG];                          \
                snprintf(pcLogMsg, _GHM_MAXLEN_OF_LOGMSG,                      \
                         "%s/clEnqueueReadBuffer", __func__);                  \
                wSet.APIErr=clEnqueueReadBuffer(wSet.Queue,                    \
                    pBaseType->dPtr, CL_TRUE, 0ul,                             \
                    sizeof(__GHM_BASETYPE_ARG_IMP__)*pBaseType->u64NofVals,    \
                    pBaseType->hPtr, 0u, NULL, NULL);                          \
                if((err=_ghf_wdcChkWS_APIErr(wSet,pcLogMsg,_GHM_FL))) {        \
                    _ghf_wipeHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,pBaseType);   \
                    return(err);                                               \
                }                                                              \
            }                                                                  \
            break;                                                             \
        default:                                                               \
            return(_GHM_UNKNOWN_SYNC_TYPE_ERROR);                              \
            break;                                                             \
    }                                                                          \
    return(_GHM_OK);                                                           \
}                                                                              \
int32_t _ghf_wdcFillHD_##__GHM_BASETYPE_ARG_IMP__ (_GHT_WRKSET wSet,           \
            _GHT_HD##__GHM_BASETYPE_ARG_IMP__ * const pBaseType,               \
            const __GHM_BASETYPE_ARG_IMP__ Val) {                              \
    int32_t err=0;                                                             \
    uint64_t i=0ul;                                                            \
    if(!pBaseType) return(_GHM_NULL_POINTER_RECEIVED_ERROR);                   \
    for(i=0;i<pBaseType->u64NofVals;i++) pBaseType->hPtr[i]=Val;               \
    if((err= _ghf_wdcSyncHD_##__GHM_BASETYPE_ARG_IMP__ (wSet,                  \
        _GHE_SYNC_HOST_TO_DEV,pBaseType))) return(err);                        \
    return(_GHM_OK);                                                           \
}                                                                              \
int32_t _ghf_isHD_##__GHM_BASETYPE_ARG_IMP__##_Valid(                          \
                           const _GHT_HD##__GHM_BASETYPE_ARG_IMP__ BaseType) { \
    return(BaseType.hPtr && BaseType.dPtr && BaseType.u64NofVals);             \
}                                                                              \
int32_t _ghf_wipeHD_##__GHM_BASETYPE_ARG_IMP__ (_GHT_WRKSET wSet,              \
                        _GHT_HD##__GHM_BASETYPE_ARG_IMP__ * const pBaseType) { \
    if(pBaseType) {                                                            \
        _ghf_freeDevZ(wSet, &pBaseType->dPtr);                                 \
        _ghf_freeHostZ(&pBaseType->hPtr);                                      \
        pBaseType->u64NofVals=0ul;                                             \
    }                                                                          \
    return(_GHM_OK);                                                           \
}                                                                              \

#endif /* OCLH_H_BASETYPE_TEMPLATES_H_ */

