多线程DiskBuffer预读

来源:互联网 发布:知乎 李矛 编辑:程序博客网 时间:2024/05/17 19:20
//Powered by barenx
    #include <Windows.h>
#include 
<WinBase.h>

#include 
"ErrCode.h"

#define DefaultBufferCount 0x200    //512
#define SingleBufferSize 0x40000    //256KB

DWORD WINAPI ThreadBuffering(LPVOID lpParamter);

class DiskBuffer
{
private:
    
int size,front,rear,AllOver;
    
int FullWait,EmptyWait;
    HANDLE hFullEvent,hEmptyEvent;
    HANDLE hThread;
    
//CRITICAL_SECTION csFull,csEmpty;
    struct StrBuf
    
{
        
char * BufPtr;
        unsigned 
long File_No;
        size_t Buf_Size;
        size_t Buf_InUse;
    }
 *tBuf;
public:
    FILE 
*hListFile;
    DiskBuffer(
int sz=DefaultBufferCount,size_t sBufferSize=SingleBufferSize)
    
{
        rear
=0;                front=1;
        FullWait
=0;            EmptyWait=0;
        AllOver
=0;
        size
=(sz>0?sz:DefaultBufferCount)+2;
        tBuf
=new StrBuf[size];
        memset(tBuf,
0,sizeof(StrBuf)*size);
        
for (int i=0;i<size;i++)
        
{
            tBuf[i].BufPtr
=(char*)malloc(sBufferSize);
            tBuf[i].Buf_Size
=sBufferSize;
        }

        hFullEvent
=CreateEvent(NULL,NULL,NULL,NULL);
        hEmptyEvent
=CreateEvent(NULL,NULL,NULL,NULL);
        
//InitializeCriticalSection(&csEmpty);
        
//InitializeCriticalSection(&csFull);
    }


    
~DiskBuffer()
    
{
        DWORD ExitCode
=0;
        GetExitCodeThread(hThread,
&ExitCode);
        
if (STILL_ACTIVE==ExitCode)    TerminateThread(hThread,NULL);
        
for (int i=0;i<size;i++) free(tBuf[i].BufPtr);
        delete [] tBuf;
        CloseHandle(hFullEvent);
        CloseHandle(hEmptyEvent);
        CloseHandle(hThread);
        
//DeleteCriticalSection(&csEmpty);
        
//DeleteCriticalSection(&csFull);
    }


    
int _StartBuffer(char *ListFile)
    
{
        
if (NULL==(hListFile=fopen((char *)ListFile,"rbS"))){printf("error open listfile! "); return (_Error_FileOpen);}
        hThread
=CreateThread(NULL,NULL,ThreadBuffering,this,NULL,NULL);
        
if (hThread!=NULL) return NULL;
        
else return _Error_CreatThread;
    }


    
int _PopData(char ** it,unsigned long *it_Num)
    
{
        
while (_IsEmpty())
        
{
            
if (AllOver) return 0;
            EmptyWait
=1;
                #ifdef _DEBUG
                printf(
"sta emp wai  %d %d ",front,rear);
                
#endif
            WaitForSingleObject(hEmptyEvent,INFINITE);
                #ifdef _DEBUG
                printf(
"end emp wai  %d %d ",front,rear);
                
#endif
        }

        EmptyWait
=0;
            #ifdef _DEBUG
            printf(
"sta pop dat %d %d ",front,rear);
            
#endif
        
*it=tBuf[front].BufPtr;
        
*it_Num=tBuf[front].File_No;
        front
=(front+1% size;
            #ifdef _DEBUG
            printf(
"end pop dat %d %d %d ",front,rear,*it_Num);
            
#endif
        
if (FullWait)
        
{
                #ifdef _DEBUG
                printf(
"act ful wai %d %d ",front,rear);
                
#endif
            SetEvent(hFullEvent);
        }

        
return 1;        
    }


    
int _PopData(char ** it,unsigned long *it_Num,size_t *it_InUse,size_t *it_Size=NULL)
    
{
        
while (_IsEmpty())
        
{
            
if (AllOver) return 0;
            EmptyWait
=1;
                #ifdef _DEBUG
                printf(
"sta emp wai  %d %d ",front,rear);
                
#endif
            WaitForSingleObject(hEmptyEvent,INFINITE);
                #ifdef _DEBUG
                printf(
"end emp wai  %d %d ",front,rear);
                
#endif
        }

        EmptyWait
=0;
        
//EnterCriticalSection(&csFull);
            #ifdef _DEBUG
            printf(
"sta pop dat %d %d ",front,rear);
            
#endif
        
*it=tBuf[front].BufPtr;
        
*it_Num=tBuf[front].File_No;
        
*it_InUse=tBuf[front].Buf_InUse;
        
if (it_Size) *it_Size=tBuf[front].Buf_Size;
        front
=(front+1% size;
            #ifdef _DEBUG
            printf(
"end pop dat %d %d %d ",front,rear,*it_Num);
            
#endif
        
if (FullWait)
        
{
                #ifdef _DEBUG
                printf(
"act ful wai %d %d ",front,rear);
                
#endif
            SetEvent(hFullEvent);
            
//FullWait=0;
        }

        
//LeaveCriticalSection(&csFull);
        return 1;        
    }

    
int _PushData(char * it,unsigned long it_Num,const size_t it_InUse,const size_t it_Size)
    
{
        
//EnterCriticalSection(&csEmpty);
            #ifdef _DEBUG
            printf(
"sta pus dat %d %d ",front,rear);
            
#endif
        
int prerear=(rear+1% size;
        tBuf[prerear].BufPtr
=it;
        tBuf[prerear].Buf_Size
=it_Size;
        tBuf[prerear].File_No
=it_Num;
        rear
=prerear;
            #ifdef _DEBUG
            printf(
"end pus dat %d %d %d ",front,rear,it_Num);
            
#endif
        
if (EmptyWait)
        
{
                #ifdef _DEBUG
                printf(
"act emp wai %d %d ",front,rear);
                
#endif
            SetEvent(hEmptyEvent);
            
//EmptyWait=0;
        }

        
//LeaveCriticalSection(&csEmpty);
        return 1;
    }

    
int _GetBuffer(char ** it,size_t *it_Size)
    
{
        
while (_IsFull()) 
        
{
            FullWait
=1;
                #ifdef _DEBUG
                printf(
"sta ful wai %d %d ",front,rear);
                
#endif
            WaitForSingleObject(hFullEvent,INFINITE);
                #ifdef _DEBUG
                printf(
"end ful wai %d %d ",front,rear);
                
#endif
        }

        FullWait
=0;
            #ifdef _DEBUG
            printf(
"sta get BufPtr %d %d ",front,rear);
            
#endif
        
int prerear=(rear+1% size;
        
*it=tBuf[prerear].BufPtr;
        
*it_Size=tBuf[prerear].Buf_Size;
            #ifdef _DEBUG
            printf(
"end get BufPtr %d %d ",front,rear);
            
#endif
        
return 1;
    }

    
//int _GetLength(void){ return (rear+size-front+1) % size;}
    void _Finished(void){ AllOver=1;SetEvent(hEmptyEvent);}
private:
    inline 
int _IsEmpty(void)
    
{
        
//EnterCriticalSection(&csEmpty);
        
//int t=(rear+size-front+1) % size == 0?1:0;
        
//LeaveCriticalSection(&csEmpty);
        
//return t;
        return (rear+size-front+1% size == 0?1:0;;
    }

    inline 
int _IsFull(void)
    
{
        
//EnterCriticalSection(&csFull);
        
//int t=(rear+2) % size == front?1:0;
        
//LeaveCriticalSection(&csFull);
        
//return t;
        return (rear+3% size == front?1:0;
    }

}
;

DWORD WINAPI ThreadBuffering(LPVOID lpParamter)
{
    DiskBuffer 
*m_Buffer=(DiskBuffer *)lpParamter;
    FILE 
*m_ListFile=m_Buffer->hListFile;

    
char BufPtr[512]={0};
    
int _filenum=1;
    
    
while (fgets(BufPtr,512,m_ListFile))
    
{            
        
if ('*'==BufPtr[0])
        
{    
            _filenum
=atoi(BufPtr+1);                                            //识别标志*,读取文件号
            if (_filenum<=0{printf("error file number! ");exit(_Error_FileNumber); }
        }

        
else
        
{
            unsigned 
long nbufLen=(unsigned long)strlen(BufPtr)-1;
            
if (0x0A==BufPtr[nbufLen] || 0x0D==BufPtr[nbufLen]) BufPtr[nbufLen--]=NULL;        // delete char 0x0A 0x0D
            if (0x0A==BufPtr[nbufLen] || 0x0D==BufPtr[nbufLen]) BufPtr[nbufLen]=NULL;        // delete char 0x0A 0x0D
            if (*BufPtr)
            
{
                HANDLE hTextFile;
                
if(NULL==(hTextFile=CreateFile(BufPtr,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL)))
                
{
                    printf(
"Error open %s ",BufPtr);
                    exit(_Error_FileOpen);
                }

                DWORD m_TextFile_Len
=GetFileSize(hTextFile,NULL);
                
                
char *m_FileText;
                size_t Old_buf_len;
                m_Buffer
->_GetBuffer(&m_FileText,&Old_buf_len);
                
if (m_TextFile_Len>Old_buf_len)
                
{
                    m_FileText
=(char*)realloc(m_FileText,m_TextFile_Len+1);
                    Old_buf_len
=m_TextFile_Len;
                    
if (!m_FileText){printf("error memory alloc! ");exit(_Error_Malloc);}
                }

                unsigned 
long n=0;
                DWORD nRead;
                
while ((n++<=3&& (NULL==ReadFile(hTextFile,m_FileText,m_TextFile_Len,&nRead,NULL) || nRead!=m_TextFile_Len)) SetFilePointer(hTextFile,NULL,NULL,FILE_BEGIN);
                
if (n>3){printf("Error read %s ",BufPtr);exit(_Error_FileRead);}
                CloseHandle(hTextFile);    
                m_FileText[m_TextFile_Len]
=NULL;
                m_Buffer
->_PushData(m_FileText,_filenum++,m_TextFile_Len,Old_buf_len);
            }

        }

    }

    m_Buffer
->_Finished();
    
return NULL;
}