// farheapb.cpp
//
// Copyright Singleton Systems Ltd 1994
#include "stdafx.h"
#include <new.h>
#include "mobject.h"
#include "farheapb.h"
// static pointers to the FarheapBlock structures
HGLOBAL FarHeapBlock::first_fhb = NULL;
HGLOBAL FarHeapBlock::last_fhb = NULL;
FP_FHB FarHeapBlock::GetHbFromHandle (HGLOBAL h)
{
FP_FHB p_fhb = (FP_FHB) GlobalLock (h);
ASSERT (p_fhb != NULL);
GlobalUnlock (h);
return p_fhb;
}
void FAR * FarHeapBlock::operator new
(size_t /* size */)
// We do not need to use the size parameter,
// as we always allocate a fixed size of
// FarHeapBlock::default_size bytes.
{
HGLOBAL h = GlobalAlloc
(GMEM_MOVEABLE | GMEM_ZEROINIT,
FarHeapBlock::default_size);
// The GMEM_ZEROINIT is not strictly necessary, but
// it seems a good idea to start off with the memory
// in a defined state.
// #define FHB_MEM_TEST
// For test purposes only, force a failure
// if less than 5Mb memory free
#if defined (FHB_MEM_TEST) && defined (_DEBUG)
if (GetFreeSpace (0) < 5000000L)
{
// Unable to get memory or not enough left to
// handle recovery, so take some error action
// Get current new handler
_PNH handler = _set_new_handler (0);
// and restore it as the action of getting a
// pointer to it unsets it
_set_new_handler (handler);
// Signal the failure back up the chain.
// This should raise an Exception
(* handler) (FarHeapBlock::default_size);
// Fail regardless of value returned by the
// handler
return NULL;
}
#endif
ASSERT (h != NULL);
if (h == NULL || GetFreeSpace (0) < 10000L)
{
// Unable to get memory or not enough left to
// handle recovery, so take some error action
// Get current new handler
_PNH handler = _set_new_handler (0);
// and restore it as the action of getting a
// pointer to it unsets it
_set_new_handler (handler);
// Signal the failure back up the chain.
// This should raise an Exception
(* handler) (FarHeapBlock::default_size);
// Fail regardless of value returned by the
// handler
return NULL;
}
else
{
FP_FHB p_fhb = (FP_FHB) GlobalLock (h);
p_fhb->my_hglobal = h;
p_fhb->fhb_block_size = GlobalSize (h);
// Now chain the block into the list of blocks
if (IsEmpty ())
{
ASSERT (last_fhb == NULL);
first_fhb = last_fhb = h;
}
else
{
FP_FHB p_last_fhb =
FarHeapBlock::GetHbFromHandle(last_fhb);
p_last_fhb->next_hglobal = h;
p_fhb->previous_hglobal = last_fhb;
p_fhb->next_hglobal = NULL;
last_fhb = h:
}
return p_fhb;
}
}
void FarHeapBlock::operator delete (void FAR * p_fhb)
{
ASSERT (p_fhb != NULL);
ASSERT (OFFSETOF (p_fhb) == 0);
FP_FHB current_block_pointer = (FP_FHB) p_fhb;
#if defined (_DEBUG)
FP_FHB check = FarHeapBlock::GetHbFromHandle
(current_blocK_pointer->my_hglobal);
ASSERT (check == current_block_pointer);
#endif
// Reset the pointers in the previous block
if (current_block_pointer->previous_hglobal != NULL)
{
FP_FHB prev_ptr = GetHbFromHandle
(current_block_pointer->previous_hglobal);
prev_ptr->next_hglobal =
current_block_pointer->next_hglobal;
}
else // This should be the first block in the list
{
ASSERT (current_block_pointer->my_hglobal ==
FarHeapBlock::first_fhb);
FarHeapBlock::first_fhb =
current_block_pointer->next_hglobal;
}
// Reset the pointers in the next block
if (current_block_pointer->next_hglobal)!= NULL)
{
FP_FHB next_ptr =
FarHeapBlock::GetHbFromHandle
(current_block_pointer->next_hglobal);
next_ptr->previous_hglobal =
current_block_pointer->previous_hglobal;
}
else // This should be the last block in the list
{
ASSERT (current_block_pointer->my_hglobal ==
FarHeapBlock::last_fhb);
FarHeapBlock::last_fhb =
current_block_pointer->previous_hglobal;
}
// The block has been unlinked, so return it to
// Windows
GlobalUnlock (current_block_pointer->my_hglobal);
GlobalFree (current_block_pointer->my_hglobal);
}
FarHeapBlock::FarHeapBlock ()
{
// fhb_block_size set by new!
// A FarHeapBlock is requested directly from
// Windows. Windows supplies
// a segment with offsets starting at 0.
__segment cur_seg = (__segment) SELECTOROF (this);
// Mark all of the free space in the FarHeapBlock
// as a single, free MemoryObject
free_list = end_free_list = (VP_MOBJECT) sizeof(FarHeapBlock);
in_use_list = NULL;
end_in_use_list = NULL;
(cur_seg:>free_list)->SetFirstMemoryObject
(my_hglobal,
(int) Size () - sizeof(FarHeapBlock));
}
int FarHeapBlock::GetCount ()
{
int usage_count = 0;;
HGLOBAL current_block = FarHeapBlock::first_fhb;
while (current_block != NULL)
{
FP_FHB p_fhb = GetHbFromHandle (current_block);
usage_count++;
current_block = p_fhb->next_hglobal;
}
return usage_count;
}
FP_FHB FarHeapBlock::GetNext (FHB_POSITION & p)
{
ASSERT (p != NULL);
FP_FHB p_fhb = GetHbFromHandle (p);
p = p_fhb->next_hglobal;
return p_fhb;
}
// End of File