/****************************************************************************

Author : Gabriele 'matrix' Gristina <gabriele.gristina@gmail.com>
Date   : Sun Jan 10 13:59:37 CET 2021
Version: 0.1beta
License: GNU General Public License v3 or any later version (see LICENSE.txt)

*****************************************************************************
    Copyright (C) 2020-2021  <Gabriele Gristina>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/


// trust me...i'm a dolphin :P
// too many allocations, too many free to manage, I need dolphin macros :)
// they could be buggy, but if you know how to fix them, do it

#define MEMORY_FREE_ADD(a)      { \
    freeList[freeListIdx++] = (void *)(a); \
}

#define MEMORY_FREE_ALL         { \
    int t = freeListIdx; \
    while (t-- > 0) { \
        if (freeList[t] != NULL) { \
            free (freeList[t]); \
            freeList[t] = NULL; \
        }\
    } \
    if (freeList != NULL) { \
        free (freeList); \
        freeList = NULL; \
    } \
}

#define MEMORY_FREE_DEL(a)      { \
    for (int i = 0; i < freeListIdx; i++) { \
        if (freeList[i] && a == freeList[i]) { \
            free(freeList[i]); \
            freeList[i] = NULL; \
            break; \
        } \
    } \
}

#define MEMORY_FREE_LIST(a,i)   { \
    if (i > 0) { \
        int t=(int)i; \
        do { \
            if (a[t] != NULL) { \
                free(a[t]); \
                a[t]=NULL; \
            } \
        } while (--t >= 0); \
        MEMORY_FREE_DEL(a) \
    } \
}

#define MEMORY_FREE_LIST_Z(a,i) { \
    int t = (int)i; \
    do { \
        if (a[t] != NULL) { \
            free(a[t]); \
            a[t] = NULL; \
        } \
    } while (--t >= 0); \
    MEMORY_FREE_DEL(a) \
}

#define MEMORY_FREE_OPENCL(c,i) { \
    int t = (int)i; \
    do { \
        if (c.contexts[t]) \
            clReleaseContext (c.contexts[t]); \
        if (c.keystreams[t]) \
            clReleaseMemObject (c.keystreams[t]); \
        if (c.candidates[t]) \
            clReleaseMemObject (c.candidates[t]); \
        if (c.matches[t]) \
            clReleaseMemObject (c.matches[t]); \
        if (c.matches_found[t]) \
            clReleaseMemObject (c.matches_found[t]); \
        if (c.commands[t]) \
            clReleaseCommandQueue (c.commands[t]); \
        if (c.kernels[t]) \
            clReleaseKernel (c.kernels[t]); \
        if (c.programs[t]) \
            clReleaseProgram (c.programs[t]); \
    } while (--t >= 0); \
 }
