#ifndef __AMSCPPIMGLIB4_INTLUTIL_HPP__
#define __AMSCPPIMGLIB4_INTLUTIL_HPP__

namespace ams
{
namespace imglib4
{

//A template function that takes as input a function pointer and a series of arguments
//The function is executed with fptr(threadnum, nthreads, otherargs...) with a certain number of threads
//psize must be supplied to determine whether to execute in threaded mode or not.
template<typename callable, typename ... argst> int threaded_execute(callable &&fptr, int64_t psize, argst&&... args)
{
    int ret = amsimage_success;
    int nthreads;
    int I;
    std::vector<std::thread*> threads;

    if(psize<amsimage_threadpsz)
    {
        nthreads = 1;
        I = 0;
        fptr(I,nthreads,std::forward<argst>(args)...);
    }
    else
    {
        nthreads = std::thread::hardware_concurrency(); //number of cpu cores the system thinks you have
        nthreads = (nthreads<=0) ? 1 : nthreads;
        nthreads = (nthreads>amsimage_maxthreads) ? amsimage_maxthreads : nthreads;
        threads.resize(nthreads);
        for(I=0;I<nthreads;I++) threads[I] = NULL;
        for(I=0;I<nthreads;I++)
        {
            threads[I] = new(std::nothrow) std::thread
            (
                std::forward<callable>(fptr),
                I,
                nthreads,
                std::forward<argst>(args)...
            );
        }
        for(I=0;I<nthreads;I++)
        {
            if(threads[I]==NULL)
            { //null thread creation failure check
                //printf("debug check!\n");
                ret = amsimage_failure;
            }
        }
        for(I=0;I<nthreads;I++)
        {
            if(threads[I]!=NULL)
            {
                threads[I]->join();
                delete threads[I];
                threads[I] = NULL;
            }
        }
    }

    return ret;
}

void amsimage_region_copy(
    uint8_t *datato,
    int Nxto,
    int Nyto,
    const uint8_t *datafrom,
    int Nxfrom,
    int Nyfrom,
    int offsetx,
    int offsety
);

void amsimage_region_set(
    uint8_t *data,
    int Nx, int Ny,
    int x0, int y0,
    int x1, int y1,
    amspixel val
);




}; //end namespace imglib4
}; //end namespace ams

#endif

