dwiobuff.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 380 行
C
380 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "plusplus.h"
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "memmgr.h"
#include "errdefns.h"
#include "iosupp.h"
#include "dwiobuff.h"
#include "ring.h"
#include "toggle.h"
#include "dbg.h"
static DWIOBUFF *activeBufs; // active buffers
static DWIOBUFF *freeBufs; // free buffers
static DWIOBUFF *beingWritten; // buffer being written
static void deactivateBuffer( // DEACTIVATE A BUFFER FROM ACTIVE RING
DWIOBUFF *ctl ) // - buffer control
{
RingPrune( &activeBufs, ctl );
RingAppend( &freeBufs, ctl );
}
static void activateBuffer( // ACTIVATE A BUFFER FROM FREE RING
DWIOBUFF *ctl ) // - buffer control
{
RingPrune( &freeBufs, ctl );
RingAppend( &activeBufs, ctl );
}
static DWIOBUFF *allocateBuffer(// ALLOCATE A NEW BUFFER
void )
{
DWIOBUFF *ctl; // - new buffer
ctl = CMemAlloc( sizeof( *ctl ) );
ctl->next = NULL;
ctl->disk_addr = 0;
ctl->next_addr = 0;
ctl->prev_addr = 0;
ctl->current_offset = 0;
ctl->block_num = 0;
ctl->reading = 0;
ctl->written = FALSE;
ctl->writing = FALSE;
RingAppend( &activeBufs, ctl );
return ctl;
}
static void *pointXfer( // POINT AT TRANSFER POINT
DWIOBUFF *ctl ) // - buffer control
{
return (char*)ctl->data + ctl->current_offset;
}
static DWIOBUFF *findWrBuffer( // FIND A BUFFER FOR WRITING
void )
{
DWIOBUFF *ctl; // - buffer control
ctl = allocateBuffer();
ctl->disk_addr = IoSuppTempNextBlock( DWBLOCK_FACTOR );
ctl->writing = TRUE;
ctl->written = FALSE;
return ctl;
}
static DWIOBUFF *locateRdBuffer(// LOCATE A READ BUFFER IN A RING
DWIOBUFF *ring, // - ring of buffers
DISK_ADDR disk_addr ) // - disk block for buffer
{
DWIOBUFF *ctl; // - buffer control (current buffer)
DWIOBUFF *found; // - buffer control (located buffer)
found = NULL;
RingIterBeg( ring, ctl ) {
if( ctl->disk_addr == disk_addr ) {
found = ctl;
break;
}
} RingIterEnd( ctl )
return found;
}
static void savePrevNext( DWIOBUFF *ctl )
{
DWIOBUFF_EXTRA *p;
p = (DWIOBUFF_EXTRA *) ( ctl->data + DWBLOCK_BSIZE );
p->prev_addr = ctl->prev_addr;
p->next_addr = ctl->next_addr;
p->block_num = ctl->block_num;
}
static void extractPrevNext( DWIOBUFF *ctl )
{
DWIOBUFF_EXTRA *p;
p = (DWIOBUFF_EXTRA *) ( ctl->data + DWBLOCK_BSIZE );
ctl->prev_addr = p->prev_addr;
ctl->next_addr = p->next_addr;
ctl->block_num = p->block_num;
}
static DWIOBUFF *findBuffer( // FIND A SPECIFIC BUFFER
DISK_ADDR block ) // - disk block
{
DWIOBUFF *ctl; // - buffer control
ctl = locateRdBuffer( activeBufs, block );
if( ctl == NULL ) {
ctl = locateRdBuffer( freeBufs, block );
if( ctl == NULL ) {
ctl = allocateBuffer();
IoSuppTempRead( block
, TMPBLOCK_BSIZE * DWBLOCK_FACTOR
, ctl->data );
extractPrevNext( ctl );
ctl->disk_addr = block;
ctl->written = TRUE;
} else {
activateBuffer( ctl );
}
}
return ctl;
}
static DWIOBUFF *findRdBuffer( // FIND A BUFFER FOR READING
DISK_ADDR block ) // - disk block
{
DWIOBUFF *ctl;
ctl = findBuffer( block );
++ctl->reading;
ctl->current_offset = 0;
return ctl;
}
static DWIOBUFF *findReWrBuffer(// FIND BUFFER FOR RE-WRITE
DISK_ADDR block ) // - disk block
{
DWIOBUFF *ctl;
ctl = findBuffer( block );
ctl->writing = TRUE;
return ctl;
}
static void finishWrBuffer( // COMPLETE WRITE-USE OF A BUFFER
DWIOBUFF *ctl ) // - buffer control
{
ctl->writing = FALSE;
deactivateBuffer( ctl );
}
static void finishRdBuffer( // COMPLETE READ-USE OF A BUFFER
DWIOBUFF *ctl ) // - buffer control
{
-- ctl->reading;
if( ( ctl->reading == 0 ) && ! ctl->writing ) {
deactivateBuffer( ctl );
}
}
DWIOBUFF *DwioBuffWrOpen( // GET BUFFER FOR WRITING
void )
{
return findWrBuffer();
}
DWIOBUFF *DwioBuffWrite( // WRITE A RECORD
DWIOBUFF *ctl, // - buffer control
void *record, // - record to be written
size_t size ) // - record size
{
DWIOBUFF *next; // - next buffer control
size_t len; // - amount to write
for(;;) {
len = min( size, DWBLOCK_BSIZE - ctl->current_offset );
memcpy( pointXfer( ctl ), record, len );
ctl->written = FALSE;
ctl->current_offset += len;
record = (void *)((char *)record + len);
size -= len;
if( size == 0 ) break;
if( ctl->next_addr == 0 ) {
next = findWrBuffer();
ctl->next_addr = next->disk_addr;
next->prev_addr = ctl->disk_addr;
next->block_num = ctl->block_num + 1;
} else {
next = findReWrBuffer( ctl->next_addr );
}
next->current_offset = 0;
finishWrBuffer( ctl );
ctl = next;
}
return ctl;
}
DWIOBUFF *DwioBuffSeek( // POSITION TO SPECIFIED OFFSET FROM START
DWIOBUFF *ctl, // - current buffer control
DISK_ADDR block, // - starting disk address
size_t offset ) // - where to position to
{
DWIOBUFF *next; // - next buffer control
size_t required_block;
size_t required_offset;
required_block = offset / DWBLOCK_BSIZE;
required_offset = offset % DWBLOCK_BSIZE;
while( ctl->block_num != required_block ) {
if( ctl->block_num < required_block ) {
if( ctl->next_addr == 0 ) {
next = findWrBuffer();
ctl->next_addr = next->disk_addr;
next->prev_addr = ctl->disk_addr;
next->block_num = ctl->block_num + 1;
} else {
next = findReWrBuffer( ctl->next_addr );
}
} else {
if( (ctl->block_num - required_block) > required_block ) {
next = findReWrBuffer( block );
} else {
if( ctl->prev_addr == 0 ) {
#ifndef NDEBUG
CFatal( "dwiobuff: attempt to seek off start of file" );
#endif
} else {
next = findReWrBuffer( ctl->prev_addr );
}
}
}
finishWrBuffer( ctl );
ctl = next;
}
ctl->current_offset = required_offset;
return( ctl );
}
void DwioBuffWrClose( // RELEASE BUFFER AFTER WRITING
DWIOBUFF *ctl ) // - buffer control
{
finishWrBuffer( ctl );
}
DWIOBUFF *DwioBuffRdOpen( // GET BUFFER FOR READING
DISK_ADDR block ) // - disk address
{
DWIOBUFF *ctl;
ctl = findRdBuffer( block );
ctl->current_offset = 0;
return ctl;
}
DWIOBUFF *DwioBuffRead( // READ A RECORD
DWIOBUFF *ctl, // - buffer control
void **record, // - record to be read
size_t *size ) // - in -> last size consumed
// - out -> new space avail
{
char *ptr; // - current pointer
size_t new_size; // - space still available in buffer
DWIOBUFF *next; // - buffer control (next buffer)
ctl->current_offset += *size;
ptr = (char *)ctl->data + ctl->current_offset;
new_size = DWBLOCK_BSIZE - ctl->current_offset;
if( new_size == 0 ) {
next = findRdBuffer( ctl->next_addr );
ptr = (char *)next->data;
finishRdBuffer( ctl );
ctl = next;
new_size = (ctl->data+DWBLOCK_BSIZE) - ptr;
}
*size = new_size;
*record = (void *)ptr;
return ctl;
}
void DwioBuffRdClose( // RELEASE BUFFER AFTER READING
DWIOBUFF *ctl ) // - buffer control
{
finishRdBuffer( ctl );
}
static void dwioBuffReleaseMemory( // RELEASE MEMORY
void )
{
DWIOBUFF *buf; // - current buffer
for(;;) {
buf = RingPop( &freeBufs );
if( buf == NULL ) break;
if( ! buf->written
&& ! CompFlags.compile_failed ) {
savePrevNext( buf );
beingWritten = buf;
IoSuppTempWrite( buf->disk_addr
, TMPBLOCK_BSIZE * DWBLOCK_FACTOR
, buf->data );
beingWritten = NULL;
}
CMemFree( buf );
}
}
void DwioBuffInit( // BUFFERING INITIALIZATION
void )
{
beingWritten = NULL;
CMemRegisterCleanup( dwioBuffReleaseMemory );
}
void DwioBuffFini( // BUFFERING COMPLETION
void )
{
if( NULL != beingWritten ) {
CMemFree( beingWritten );
beingWritten = NULL;
}
RingFree( &freeBufs );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?