allocexc.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 242 行
CPP
242 行
/****************************************************************************
*
* 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 "cpplib.h"
#include <string.h>
#include "rtexcept.h"
#include "exc_pr.h"
#include "rtmsgs.h"
#include "lock.h"
typedef struct free_area FREE_AREA;
struct free_area // FREE_AREA -- freed area in exception area
{
FREE_AREA *next; // - next free block -- MUST BE FIRST FIELD
size_t size; // - size of free area
#if 0 // removed since it is never used (AFS 12-19-97)
#ifdef __MT__
__lock _semaphore; // - semaphore for area
#endif
#endif
};
typedef struct exc_area EXC_AREA;
struct exc_area // ENTIRE AREA
{ size_t size; // - size of area
FREE_AREA *freed; // - freed blocks - NULL only at start
#ifdef __MT__
__lock semaphore; // - semaphore for area
#endif
};
extern "C" EXC_AREA __EXC_AREA;
#define SIZEOF_HDR (sizeof( ACTIVE_EXC ) - 1)
#define SIZEOF_SPLIT ( ( sizeof( FREE_AREA ) + 3 ) & -4 )
extern "C"
ACTIVE_EXC *CPPLIB( alloc_exc )(// ALLOCATE AN EXCEPTION
void *object, // - address of object
THROW_RO *throw_ro, // - throw R/O block
_RTCTL* rtc ) // - R/T control
{
FREE_AREA *fr; // - a freed area
FREE_AREA **owner; // - previous freed area
FREE_AREA *next; // - next freed area
RT_TYPE_SIG sig; // - type signature of thrown item
ACTIVE_EXC *active; // - active exception
unsigned size; // - size required
THREAD_CTL *thr; // - thread control
#ifdef __MT__
__EXC_AREA.semaphore.p();
#endif
if( __EXC_AREA.freed == NULL ) {
fr = (FREE_AREA*)((char*)&__EXC_AREA + sizeof( EXC_AREA )); // initial free list entry
fr->next = NULL;
fr->size = __EXC_AREA.size - sizeof( EXC_AREA );
__EXC_AREA.freed = fr;
#ifndef NDEBUG
memset( (char*)fr + sizeof(FREE_AREA)
, 0xEF
, fr->size - sizeof(FREE_AREA) );
#endif
}
sig = CPPLIB( ts_refed )( throw_ro->cnvs[0].signature );
size = CPPLIB( ts_size )( sig ) + SIZEOF_HDR + sizeof( size_t );
if( size < sizeof( FREE_AREA ) ) {
size = sizeof( FREE_AREA );
}
size = ( size + 3 ) & -4;
for( owner = &__EXC_AREA.freed; ; owner = &fr->next ) {
fr = *owner;
if( fr == NULL ) {
CPPLIB(fatal_runtime_error)( RTMSG_EXC_NO_SPACE, 1 );
}
for( ;; ) { // coalesce
next = fr->next;
if( (FREE_AREA*)((char*)fr + fr->size) != next ) break;
fr->size += next->size;
fr->next = next->next;
}
if( fr->size == size ) {
*owner = fr->next;
active = (ACTIVE_EXC*)fr;
break;
} else if( fr->size > ( size + SIZEOF_SPLIT ) ) {
fr->size -= size;
active = (ACTIVE_EXC*)( (char*)fr + fr->size );
break;
}
}
#ifdef __MT__
__EXC_AREA.semaphore.v();
#endif
*(size_t*)active = size;
active = (ACTIVE_EXC*)( (char*)active + sizeof( size_t ) );
active->exc_area = &__EXC_AREA;
thr = rtc->thr;
active->prev = thr->excepts;
thr->excepts = active;
active->sig = throw_ro->cnvs[0].signature;
active->throw_ro = throw_ro;
active->state = EXCSTATE_CTOR;
active->zero_thrown = FALSE;
active->dispatch = NULL;
active->rw = NULL;
switch( sig->hdr.type ) {
case THROBJ_SCALAR :
case THROBJ_PTR_FUN :
memcpy( active->data, object, sig->scalar.size );
break;
case THROBJ_CLASS :
{ _EXC_PR_FREE marker( rtc, 0, EXCSTATE_CTOR, active );
(*sig->clss.copyctor)( active->data, object );
marker._exc = 0;
} break;
case THROBJ_CLASS_VIRT :
{ _EXC_PR_FREE marker( rtc, 0, EXCSTATE_CTOR, active );
(*sig->clss_v.copyctor)( active->data, CTOR_NULL, object );
marker._exc = 0;
} break;
case THROBJ_PTR_CLASS :
case THROBJ_PTR_SCALAR :
case THROBJ_VOID_STAR :
memcpy( active->data, object, sizeof( void* ) );
size = sizeof( void* );
break;
default :
GOOF_EXC( "ALLOCEXC: unexpected type signature" );
}
return active;
}
extern "C"
void CPPLIB( free_exc )( // FREE AN EXCEPTION
_RTCTL* rtc, // - R/T control
ACTIVE_EXC *active ) // - exception to be freed
{
FREE_AREA *done; // - completed item
FREE_AREA *fr; // - a freed area
FREE_AREA **owner; // - previous freed area
EXC_AREA* exc_area; // - exception area for exception
THREAD_CTL *thr; // - thread control
ACTIVE_EXC** pred; // - addr[ exception ]
thr = rtc->thr;
for( pred = &thr->excepts; active != *pred; pred = &(*pred)->prev );
*pred = active->prev;
exc_area = (EXC_AREA*)active->exc_area;
#ifdef __MT__
exc_area->semaphore.p();
#endif
done = (FREE_AREA*)( (char*)active - sizeof( size_t ) );
done->size = *(size_t*)done;
#ifndef NDEBUG
memset( (char*)done + sizeof(FREE_AREA)
, 0xEF
, done->size - sizeof(FREE_AREA) );
#endif
for( owner = &exc_area->freed; ; owner = &fr->next ) {
fr = *owner;
if( fr == NULL || fr > done ) {
*owner = done;
done->next = fr;
break;
}
}
#ifdef __MT__
exc_area->semaphore.v();
#endif
}
extern "C"
ACTIVE_EXC* CPPLIB( find_active )( // FIND EXCEPTION FOR A POSITION
_RTCTL* rtc, // - R/T control
RW_DTREG* rw, // - current r/w block
DTOR_CMD* cmd ) // - command within it
{
ACTIVE_EXC* exc; // - current exception
for( exc = rtc->thr->excepts
; ( exc != NULL ) && ( rw != exc->rw || cmd != exc->cat_try )
; exc = exc->prev );
return exc;
}
extern "C"
void CPPLIB( dtor_free_exc ) // DESTRUCT AND FREE EXCEPTION
( ACTIVE_EXC* active // - exception
, _RTCTL* rtc ) // - R/T control
{
if( 0 != active ) {
RT_TYPE_SIG sig = CPPLIB( ts_refed )( active->sig );
if( sig->hdr.type == THROBJ_CLASS
|| sig->hdr.type == THROBJ_CLASS_VIRT ) {
pFUNdtor dtor = sig->clss.dtor;
if( dtor != NULL ) {
_EXC_PR_FREE marker( rtc, 0, EXCSTATE_DTOR, active );
active->state = EXCSTATE_DTOR;
(*dtor)( active->data, DTOR_NULL );
marker._exc = 0;
}
}
CPPLIB( free_exc )( rtc, active );
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?