251 lines
5.8 KiB
C++
251 lines
5.8 KiB
C++
// IOQueue.h -- Definition of class CIOQueue
|
|
|
|
#ifndef _IOQUEUE_H__
|
|
|
|
#define _IOQUEUE_H__
|
|
|
|
#include "DataRing.h"
|
|
#include "UnbuffIO.h"
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#define FOREVER 5000
|
|
|
|
#else
|
|
|
|
#define FOREVER INFINITE
|
|
|
|
#endif // _DEBUG
|
|
|
|
class CIOQueue;
|
|
|
|
typedef enum _IOState { Unused, Emptied, Active, Transputting, IOCompleted,
|
|
Pending, EndOfFile, IOError
|
|
} IOState;
|
|
|
|
typedef struct _IOControl
|
|
{
|
|
PUINT pdwIOBlock;
|
|
IOState ioState;
|
|
UINT ibFileLow;
|
|
UINT ibFileHigh;
|
|
BOOL fWriting;
|
|
UINT cdwTransfer;
|
|
CIOQueue *pioq;
|
|
UINT dwLastError;
|
|
struct _IOControl *piocPendingLink;
|
|
|
|
} IOControl;
|
|
|
|
typedef IOControl *PIOControl;
|
|
|
|
class CIOQueue : public CDataRing
|
|
{
|
|
friend void BlockIOCompletion(PVOID pvEnvironment, PVOID pvTransaction,
|
|
UINT uiCompletionCode, UINT cbTransferred
|
|
);
|
|
|
|
public:
|
|
|
|
enum { C_BLOCKS= 5 };
|
|
|
|
// Destructor --
|
|
|
|
virtual ~CIOQueue();
|
|
|
|
// Queries --
|
|
|
|
UINT CbBlockSize();
|
|
UINT CBufferBlocks();
|
|
|
|
protected:
|
|
|
|
// Constructor --
|
|
|
|
CIOQueue();
|
|
|
|
// Initialing --
|
|
|
|
BOOL InitialIOQueue(CUnbufferedIO *puio);
|
|
|
|
// Gating I/O --
|
|
|
|
void EnableStream(BOOL fWritable);
|
|
|
|
// Queries --
|
|
|
|
BOOL Attached();
|
|
|
|
private:
|
|
|
|
enum { CB_BLOCKS = 0x10000,
|
|
MAX_ACTIVE_IOS = 8,
|
|
WAIT_TIMER_MS = 5000
|
|
};
|
|
|
|
#ifdef _DEBUG
|
|
|
|
BOOL m_fInCriticalSection;
|
|
|
|
#endif // _DEBUG
|
|
|
|
CUnbufferedIO *m_puio;
|
|
UINT m_cbBlock;
|
|
UINT m_cdwBlock;
|
|
IOControl m_aioc[C_BLOCKS];
|
|
|
|
BOOL m_fAwaitingIO;
|
|
HANDLE m_hevAwaitingIO;
|
|
|
|
UINT m_cdwRingBuffer;
|
|
PUINT m_pdwRingBuffer;
|
|
PUINT m_pdwBufferLimit;
|
|
PUINT m_pdwRingNext; // Note that full and empty
|
|
PUINT m_pdwRingLimit; // situations can be identical!!
|
|
UINT m_cdwReserved;
|
|
UINT m_cdwInTransit;
|
|
BOOL m_fUsed; // This flag resolves full/empty confusions.
|
|
BOOL m_fAttached;
|
|
BOOL m_fEOF;
|
|
BOOL m_fIOError;
|
|
|
|
// CDataRing Virtual Interfaces --
|
|
|
|
const UINT *RawNextDWordsIn (PUINT pcdw);
|
|
PUINT RawNextDWordsOut(PUINT pcdw);
|
|
void RawFlushOutput(BOOL fForceAll);
|
|
BOOL RawEmptyRing();
|
|
|
|
// Ring management --
|
|
|
|
void ReloadRing();
|
|
UINT CdwBuffered();
|
|
UINT CdwAvailable();
|
|
UINT CdwAvailableForReading();
|
|
UINT CdwAvailableForWriting();
|
|
|
|
// Transaction management --
|
|
|
|
void BeginCritical();
|
|
void EndCritical();
|
|
|
|
#ifdef _DEBUG
|
|
BOOL InCritical();
|
|
#endif // _DEBUG
|
|
|
|
// Transaction Control --
|
|
|
|
IOState StartBlockIO(PIOControl pioc, BOOL fFront= FALSE);
|
|
IOState DeferBlockIO(PIOControl pioc, BOOL fFront= FALSE);
|
|
void FinishBlockIO(PIOControl pioc, UINT uiCompletionCode,
|
|
UINT cbTransferred
|
|
);
|
|
void AwaitQuiescence();
|
|
void MarkCompleted(PIOControl pioc);
|
|
void DiscardPendingIOs();
|
|
void StartPendingIOs();
|
|
|
|
// Message Box Interface
|
|
|
|
BOOL AskForDiskSpace();
|
|
|
|
// Virtual routines to be defined by subclasses
|
|
|
|
virtual BOOL NextFileAddress(PUINT pibFileLow, PUINT pibFileHigh, PUINT pcdw)= 0;
|
|
virtual void ReleaseFileBlock(UINT ibFileLow, UINT ibFileHigh)= 0;
|
|
};
|
|
|
|
typedef CIOQueue *PCIOQueue;
|
|
|
|
extern CRITICAL_SECTION csBlockIOControl;
|
|
|
|
inline void CIOQueue::BeginCritical()
|
|
{
|
|
ASSERT(m_hevAwaitingIO);
|
|
|
|
EnterCriticalSection(&csBlockIOControl);
|
|
|
|
#ifdef _DEBUG
|
|
m_fInCriticalSection= TRUE;
|
|
#endif // _DEBUG
|
|
}
|
|
|
|
inline void CIOQueue::EndCritical()
|
|
{
|
|
ASSERT(InCritical());
|
|
|
|
LeaveCriticalSection(&csBlockIOControl);
|
|
|
|
#ifdef _DEBUG
|
|
m_fInCriticalSection= FALSE;
|
|
#endif // _DEBUG
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
|
|
inline BOOL CIOQueue::InCritical()
|
|
{
|
|
return m_fInCriticalSection;
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
inline UINT CIOQueue::CbBlockSize() { return m_cbBlock; }
|
|
|
|
inline UINT CIOQueue::CBufferBlocks() { return C_BLOCKS; }
|
|
|
|
inline BOOL CIOQueue::Attached() { return m_fAttached; }
|
|
|
|
inline UINT CIOQueue::CdwBuffered()
|
|
{
|
|
ASSERT(Initialed());
|
|
ASSERT(Attached());
|
|
|
|
// Ring pointers use modulo increments:
|
|
|
|
ASSERT(m_pdwRingLimit >= m_pdwRingBuffer && m_pdwRingLimit < m_pdwBufferLimit);
|
|
ASSERT(m_pdwRingNext >= m_pdwRingBuffer && m_pdwRingNext < m_pdwBufferLimit);
|
|
|
|
if (m_pdwRingNext < m_pdwRingLimit) return m_pdwRingLimit - m_pdwRingNext;
|
|
|
|
if (m_pdwRingNext > m_pdwRingLimit) return (m_pdwRingLimit - m_pdwRingBuffer)
|
|
+(m_pdwBufferLimit - m_pdwRingNext );
|
|
|
|
return (m_fUsed)? 0 : (m_pdwBufferLimit - m_pdwRingBuffer);
|
|
}
|
|
|
|
inline UINT CIOQueue::CdwAvailable()
|
|
{
|
|
ASSERT(Initialed());
|
|
ASSERT(Attached());
|
|
|
|
return m_cdwRingBuffer - CdwBuffered();
|
|
}
|
|
|
|
inline UINT CIOQueue::CdwAvailableForReading()
|
|
{
|
|
ASSERT(!Writable());
|
|
|
|
ASSERT(m_cdwInTransit <= CdwAvailable());
|
|
|
|
return CdwAvailable() - m_cdwInTransit;
|
|
}
|
|
|
|
inline UINT CIOQueue::CdwAvailableForWriting()
|
|
{
|
|
ASSERT(Writable());
|
|
|
|
ASSERT(m_cdwInTransit <= CdwBuffered());
|
|
|
|
return CdwBuffered() - m_cdwInTransit;
|
|
}
|
|
|
|
inline BOOL CIOQueue::AskForDiskSpace()
|
|
{
|
|
ASSERT(m_puio);
|
|
|
|
return m_puio->AskForDiskSpace();
|
|
}
|
|
|
|
#endif // _IOQUEUE_H__
|