//#define _GNU_SOURCE
 
#include <string>
#include <stdio.h>
 
 
#define DWORD_ unsigned int
 
#ifdef WIN32
#include <Windows.h>
#include <conio.h>
#endif

#include <vector>
#include <memory>
 
#include <boost/thread.hpp>
#include <boost/multi_array.hpp>
#include<fstream>
#include<iostream>
 
#ifndef WIN32
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <pthread.h>
#include <sched.h>
#include <aio.h>
#include <signal.h>
#endif
 
 
#pragma commenct (lib, "rt.lib")

//########## samplethread.cpp 파일 #########
 
 
 

 
//void Aio_completion_handler( int signo, siginfo_t *info, void *context);
//void Aio_completion_handler2( int signo, siginfo_t *info, void *context);
void Callback_aio_completion_handler(sigval_t sigval);
 

#define df_aiocb aiocb
 
 
class CSampleThread
{
 
public:
 
 
    /// DMA thread.
    std::shared_ptr<boost::thread> m_IOThread;
 
    /// DMA thread functor.
    struct Runner;
    std::shared_ptr<Runner> m_IORunner;
 
 
    /// DMA thread.
    std::shared_ptr<boost::thread> m_IOThread2;
 
    /// DMA thread functor.
    struct Runner2;
    std::shared_ptr<Runner2> m_IORunner2;
 
 
//    static int temp;
    static char * test_buf;
    //const unsigned long long size = 8ULL * 1024ULL * 1024ULL;
 
    FILE * output;
    //fstream dataFile;
    clock_t t;
 
    bool B_Start[8];
    float time;
 
    unsigned long long WSpeed[8];
    unsigned long long second_keep;
    unsigned long long dur;
    unsigned long long start_dur;
    unsigned long long end_dur;
    unsigned long long single_buffer;
    unsigned long long v2_single_buffer;
 
    ~CSampleThread();
    static void Aio_completion_handler( int signo, siginfo_t *info, void *context );
    static void Aio_completion_handler2( int signo, siginfo_t *info, void *context );
    void Signal_aio_init();
    void Signal_aio_init2();
    void My_aio_write();
    void Init();
    void Init2();
 
 
    int hFile[8];
    int hFile__;
 
 
    std::string fname;
    std::string name;
    std::string d_name[8];
 
    int i_numBuffer;
    int i_numThread;
    int i_fileSize;
    unsigned long long  n_fileSizeByte;
    unsigned long long datasize;
    unsigned long long secdatasize;
    std::vector<char*> buffer;
 
    char* v_buffer;
    char* v2_buffer;
    void *addr = NULL;
 
 
    //void* v_buffer;
    char* c_buffer;
 
    long long m_count[8];
    long long total_count[8];
    float SLEEP;
    unsigned long long result;
 
    //bool m_flag = false;
 
    int aio_flg;
 
    char * buf;
    int retval;
    ssize_t nbytes;
    //int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
 
    struct sigaction sig_act;
    struct sigaction sig_act2;
    static struct aiocb my_aiocb;
    static struct aiocb my_aiocb2;

 //main.cpp:143:18: error: invalid use of 'struct aiocb' with a zero-size array in 'class CSampleThread' [-Wpedantic]
//     struct aiocb my_aiocb;
 
};
 
struct CSampleThread::Runner
 {
     CSampleThread* sampleThread;
     Runner(CSampleThread* r)
         : sampleThread(r)
     {
 
     }
 
     /**
     * operator() is the implementation of the device running logic.
     */
     //commit test
     void operator()()
     {
        sampleThread->Signal_aio_init();
     }
 };
 
struct CSampleThread::Runner2
 {
     CSampleThread* sampleThread2;
     Runner2(CSampleThread* r)
         : sampleThread2(r)
     {
 
     }
 
     /**
     * operator() is the implementation of the device running logic.
     */
     //commit test
     void operator()()
     {
        sampleThread2->Signal_aio_init2();
     }
 };
 
 
 
 
CSampleThread::~CSampleThread()
{
    //fclose(output);
}
 
 
void CSampleThread::Init()
{
    m_IORunner = std::shared_ptr<Runner>(new Runner(this));
    m_IOThread = std::shared_ptr<boost::thread>(new boost::thread(boost::ref(*m_IORunner)));
 
}
 
void CSampleThread::Init2()
{
    m_IORunner2 = std::shared_ptr<Runner2>(new Runner2(this));
    m_IOThread2 = std::shared_ptr<boost::thread>(new boost::thread(boost::ref(*m_IORunner2)));
}
 
 

void CSampleThread::Signal_aio_init()
{
    int fd;
//    const int temp = 1024*512;
    int ret;
    
    ret = 0;
 
    char * buf[1024*512];
    //char * buf;
    //buf = new char[512*KB];
 
    bzero((char *)&my_aiocb, sizeof(struct aiocb));
    //memset(buf, 0, 1024);
    memset(&buf[0], 0, 1024*512);
 
    //file
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    char * name = (char*)"//media/z87c/Data/AIO_test1.txt";
    fd = open(name, O_CREAT |O_APPEND | O_WRONLY | O_TRUNC | O_DIRECT , mode );
 
    /* Set up the signal handler */
    sigemptyset(&sig_act.sa_mask);
    sig_act.sa_flags = SA_SIGINFO;
    sig_act.sa_sigaction = Aio_completion_handler;
 
 
    /* Set up the AIO request */
    bzero( (char *)&my_aiocb, sizeof(struct aiocb) );
    my_aiocb.aio_fildes = fd;
    my_aiocb.aio_buf = buf;
    my_aiocb.aio_nbytes = 1024*512;
    my_aiocb.aio_offset = 0;
 
    /* Link the AIO request with the Signal Handler */
    my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    my_aiocb.aio_sigevent.sigev_signo = SIGIO;
    my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
 
    /* Map the Signal to the Signal Handler */
    ret = sigaction( SIGIO, &sig_act, NULL );
 
    ret = aio_write( &my_aiocb );
}
 
 
void CSampleThread::Signal_aio_init2()
{
    int fd;
//    const int temp = 1024*256;
    int ret;
    
    ret = 0;
 
    char * buf[1024*512];
 
    bzero((char *)&my_aiocb2, sizeof(struct aiocb));
    memset(buf, 0, 1024*512);
 
    //file
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    char * name = (char*)"//media/z87c/Data/AIO_test2.txt";
    fd = open(name, O_CREAT |O_APPEND | O_WRONLY | O_TRUNC | O_DIRECT , mode );
 
    /* Set up the signal handler */
    sigemptyset(&sig_act2.sa_mask);
    sig_act2.sa_flags = SA_SIGINFO;
    sig_act2.sa_sigaction = Aio_completion_handler2;
 
 
    /* Set up the AIO request */
    bzero( (char *)&my_aiocb2, sizeof(struct aiocb) );
    my_aiocb2.aio_fildes = fd;
    my_aiocb2.aio_buf = buf;
    my_aiocb2.aio_nbytes = 1024*512;
    my_aiocb2.aio_offset = 0;
 
    /* Link the AIO request with the Signal Handler */
    my_aiocb2.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    my_aiocb2.aio_sigevent.sigev_signo = SIGIO;
    my_aiocb2.aio_sigevent.sigev_value.sival_ptr = &my_aiocb2;
 
    /* Map the Signal to the Signal Handler */
    ret = sigaction( SIGIO, &sig_act2, NULL );
 
    ret = aio_write( &my_aiocb2 );
}
 
 
//void CSampleThread::My_aio_write()
//{
//    ret = aio_write( &my_aiocb );
//}
 
 
void CSampleThread::Aio_completion_handler( int signo, siginfo_t *info, void *context )
{
    struct aiocb *req;
    int ret = 0;
 
    /* Ensure it's our signal */
    if (info->si_signo == SIGIO)
    {
 
        req = (struct aiocb *)info->si_value.sival_ptr;
 
        /* Did the request complete? */
        if (aio_error( req ) == 0)
        {
            //req->aio_buf = buf;
            /* Request completed successfully, get the return status */
            //ret = aio_return( req );
 
            //My_aio_write();
            ret = aio_write( req );
        }
    }
 
}
 
void CSampleThread::Aio_completion_handler2( int signo, siginfo_t *info, void *context )
{
    struct aiocb *req;
    int ret = 0;
 
    /* Ensure it's our signal */
    if (info->si_signo == SIGIO)
    {
        req = (struct aiocb *)info->si_value.sival_ptr;
 
        /* Did the request complete? */
        if (aio_error( req ) == 0)
        {
            //req->aio_buf = buf;
            /* Request completed successfully, get the return status */
            //ret = aio_return( req );
            //My_aio_write();
 
            ret = aio_write( req );
        }
    }
 
}
 
//################## samplethread.h ####################
 
#ifndef SAMPLETHREAD_H
#define SAMPLETHREAD_H
 
#endif // SAMPLETHREAD_H
 
 
#include <string>
#include <stdio.h>
 
 
#define DWORD_ unsigned int
 
#ifdef WIN32
#include <Windows.h>
#include <conio.h>
#endif
#include <vector>
#include <memory>
 
#include <boost/thread.hpp>
#include <boost/multi_array.hpp>
#include<fstream>
#include<iostream>
 
#ifndef WIN32
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <pthread.h>
#include <sched.h>
#include <aio.h>
#include <signal.h>
#include<fstream>
#endif
 



int main()
{
 
    CSampleThread Cthread;
    Cthread.Init();
 
    CSampleThread Cthread2;
    Cthread.Init2();
 
 
//    int pid;
//    pid = fork();
 
//    if(pid ==0)
//    {
//        CSampleThread Cthread;
//        Cthread.Init();
//    }
//    else
//    {
//        CSampleThread2 Cthread2;
//        Cthread2.Init2();
//    }
 
 
    while(true)
        usleep(100);

    return 0;
}
 