JX Application Framework
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Member Functions | Friends | List of all members
JMemoryManager Class Reference

#include <JMemoryManager.h>

Inheritance diagram for JMemoryManager:
[legend]

Classes

class  ArrayDeletedAsObject
 
class  MultipleAllocation
 
class  MultipleDeletion
 
class  ObjectDeletedAsArray
 
struct  RecordFilter
 
class  UnallocatedDeletion
 

Public Types

enum  {
  kRunningStatsMessage ,
  kExitStatsMessage ,
  kErrorMessage ,
  kRecordsMessage ,
  kSaveSnapshotMessage ,
  kSnapshotDiffMessage
}
 
enum  { kHistogramSlotCount = 30 }
 
using DebugLink = JMessageProtocol< ACE_LSOCK_STREAM >
 

Public Member Functions

 ~JMemoryManager () override
 
void Delete (void *memory, bool isArray)
 
bool RecordingAllocated () const
 
unsigned char GetAllocateGarbage () const
 
unsigned char GetDeallocateGarbage () const
 
void PrintMemoryStats ()
 
bool GetPrintExitStats () const
 
void SetPrintExitStats (const bool yesNo)
 
bool GetPrintLibraryStats () const
 
void SetPrintLibraryStats (const bool yesNo)
 
bool GetPrintInternalStats () const
 
void SetPrintInternalStats (const bool yesNo)
 
void PrintAllocated () const
 
bool GetBroadcastErrors () const
 
void SetBroadcastErrors (const bool broadcast)
 
bool GetCheckDoubleAllocation () const
 
void SetCheckDoubleAllocation (const bool yesNo)
 
bool GetPrintErrors () const
 
void SetPrintErrors (const bool print)
 
- Public Member Functions inherited from JBroadcaster
 JBroadcaster ()
 
virtual ~JBroadcaster ()
 
JBroadcasteroperator= (const JBroadcaster &source)
 
bool HasSenders () const
 
JSize GetSenderCount () const
 
bool HasRecipients () const
 
JSize GetRecipientCount () const
 
virtual JString ToString () const
 
template<class T >
void ListenTo (const JBroadcaster *sender, const std::function< void(const T &)> &f)
 

Static Public Member Functions

static JMemoryManagerInstance ()
 
static void * New (const size_t size, const JUtf8Byte *file, const JUInt32 line, const int type, const bool isArray, const bool assert)
 
static bool GetAbortUnknownAlloc ()
 
static void SetAbortUnknownAlloc (const bool yesNo)
 
static void SetProtocol (DebugLink *link)
 
static void SendError (const JString &msg)
 

Static Public Attributes

static const JUtf8BytekUnknownFile = "<UNKNOWN>"
 
static const JUtf8BytekObjectDeletedAsArray = "ObjectDeletedAsArray::JMemoryManager"
 
static const JUtf8BytekArrayDeletedAsObject = "ArrayDeletedAsObject::JMemoryManager"
 
static const JUtf8BytekUnallocatedDeletion = "UnallocatedDeletion::JMemoryManager"
 
static const JUtf8BytekMultipleDeletion = "MultipleDeletion::JMemoryManager"
 
static const JUtf8BytekMultipleAllocation = "MultipleAllocation::JMemoryManager"
 

Protected Member Functions

 JMemoryManager ()
 
void Receive (JBroadcaster *sender, const Message &message) override
 
void HandleObjectDeletedAsArray (const JMMRecord &record)
 
void HandleArrayDeletedAsObject (const JMMRecord &record)
 
void HandleUnallocatedDeletion (const JUtf8Byte *file, const JUInt32 line, const bool isArray)
 
void HandleMultipleDeletion (const JMMRecord &thisRecord, const JUtf8Byte *file, const JUInt32 line, const bool isArray)
 
void HandleMultipleAllocation (const JMMRecord &thisRecord, const JMMRecord &firstRecord)
 
- Protected Member Functions inherited from JBroadcaster
 JBroadcaster (const JBroadcaster &source)
 
void ListenTo (const JBroadcaster *sender)
 
void StopListening (const JBroadcaster *sender)
 
void ClearWhenGoingAway (const JBroadcaster *sender, void *pointerToMember)
 
void StopListening (const JBroadcaster *sender, const std::type_info &messageType)
 
template<class T >
void Send (JBroadcaster *recipient, const T &message)
 
template<class T >
void Broadcast (const T &message)
 
void SendWithFeedback (JBroadcaster *recipient, Message *message)
 
void BroadcastWithFeedback (Message *message)
 
virtual void ReceiveWithFeedback (JBroadcaster *sender, Message *message)
 
virtual void ReceiveGoingAway (JBroadcaster *sender)
 

Friends

class JMMTable
 
void JLocateDelete (const JUtf8Byte *file, const JUInt32 line)
 
void JMMHandleExit ()
 
void JMMHandleACEExit (void *, void *)
 

Detailed Description

JMemoryManager controls all memory allocation in a JCore/JX program,
normally through the JCore operator jnew and jdelete replacements.  It is
a singleton class (it can only be instantiated once) so that memory
allocation is consistent throughout a single program.  The unique
instance is accessed through the static member function Instance.

JMemoryManager and the JCore operator jnew present a paradox: like all
JX objects created at run time, JMemoryManager components are allocated
with the global operator jnew.  However, operator jnew uses
JMemoryManager to determine what its behavior should be; thus
JMemoryManager must exist before it is allocated!  It is not necessary
for JMemoryManager to have its own class operator jnew and jdelete to
solve this problem; JMemoryManager uses static buffering to allow
recursive calls to jnew and jdelete, and this also works when the
manager itself is created.

Most programs will interact with the memory manager indirectly through
operator jnew and jdelete and will not be aware of its existence.
However, JMemoryManager can supply a number of services for programs
which take the trouble to interact with it directly.  Currently this
ability is limited to requesting simple statistics reporting, but the
capabilities will expand in the future.

JMemoryManager cannot be used in conjunction with objects that define
their own versions of new and delete.

JMemoryManager's consistency checks depend on it controlling every jnew
and jdelete, so that if it is to record information it must begin doing
so at the moment of construction.  Because the memory manager is almost
certain to be created before execution of main even begins (any static
object whose constructor calls operator jnew will guarantee this on any
system, for example), the memory manager uses lots of environment
variables to control its operation (for all variables case is
irrelevant):

JMM_TABLE_TYPE If this environment variable is set to "array"

(case is irrelevant) the manager uses a stack

implementation for its memory block table, and

if its value is "hashtable" a hash table

implementation is used. If it does not exist,

or its value is unrecognized, the default

(currently hashtable) is used without warning.

This is mostly useful for debugging the tables

themselves; otherwise, there is little reason

to use the grossly inefficient array

implementation.

JMM_RECORD_ALLOCATED If this environment variable is set to "yes" the

manager will keep a record of all currently

allocated memory.

CancelRecordAllocated() can stop the recording

of initializations, but once canceled it cannot

be restarted.

JMM_INITIALIZE If this environment variable is set but given no

value the manager will initialize new memory blocks

to the default AllocateGarbage value. If it is

given a numerical value, that will be the value

used for initialization. If the manager cannot

understand the value given, the default is used

(setting it to "default" is the recommended way

to do this intentionally). If it does not exist

or is set to "no" memory blocks will not be

initialized.

JMM_SHRED If this environment variable is set but given no

value the manager will set deleted blocks to the

default DeallocateGarbage value. If it is given

a numerical value, that will be the value the

blocks are set to. If the manager cannot

understand the value given, the default is used

(setting it to "default" is the recommended way

to do this intentionally). If it does not exist

or is set to "no" memory blocks will not be

initialized.

This variable is meaningless if allocation records

are not being kept, because in that case the

manager cannot know the size of the block being

freed.

Keep in mind that jdelete (via free()) generally

will store information at the beginning of each

deallocated block. This information will overwrite

the JMM garbage values at those locations, so

don't expect the first few bytes to have the

JMM_SHRED value.

Generally, you'll want to use different initialize

and shred values so you can look at a piece of

memory and see at a glance whether the manager

thinks it is allocated or deallocated.

JMM_RECORD_DEALLOCATED If this environment variable is set to "yes" the

manager will keep a record of all memory which

has been deallocated. It is useless unless

JMM_RECORD_ALLOCATED is also set. Can be canceled

by CancelRecordDeallocated.

JMM_CHECK_DOUBLE_ALLOCATION If this environment variable is set to "yes"

the manager will complain if memory is allocated at

a location previously allocated (this indicates an

error in the system malloc() and so is only useful

for debugging the C memory manager itself, or more

likely for detecting a logic error in JMM). It is

useless unless JMM_RECORD_ALLOCATED is also set.

The SetCheckDoubleAllocation method overrides this

variable.

JMM_BROADCAST_ERRORS If this environment variable is set to "yes" the

manager will broadcast when errors occur. It

is overridden by the SetBroadcastErrors method.

JMM_PRINT_EXIT_STATS If this environment variable is set to "yes" the

manager will print dynamic memory usage stats

when the program finishes. The SetPrintExitStats

method overrides the environment variable setting.

JMM_PRINT_LIBRARY_STATS If this environment variable is set to "yes"

then whenever allocation stats are printed (such as

at program exit) the manager will also print stats

on the library code. The SetPrintLibraryStats

method overrides the environment variable setting.

JMM_PRINT_INTERNAL_STATS If this environment variable is set to "yes"

then whenever allocation stats are printed (such as

at program exit) the manager will also print stats

on its internal state, such as the memory it has

allocated for its own use. The SetPrintInternalStats

method overrides the environment variable setting.

JMM_ABORT_UNKNOWN_ALLOC If set to "yes", the process will abort if memory

is allocated by code that the memory manager cannot

locate. One reason to do this is to examine the

resulting core dump for the location of the offending

code. Overridden by SetAbortUnknownAlloc().

JMM_NO_PRINT_ERRORS Setting this environment variable to "yes" suppresses

all printing (the default is to print because

JMemoryManager's messages are already off by default

and if you turn them on you likely want to print error

messages).

JMM_PIPE UNIX pipe on which to receive requests. Also used

to send exit stats.

MALLOC_PERTURB_ Setting this environment variable turns on

initialization and shredding of memory in libc.

(JMM_NO_PRINT_ERRORS is actually read in the JMMErrorPrinter proxy object.)

Setting up so many variables can be a pain, and frequently writing a
few handy shell scripts is the best solution.  After you do this you'll
forget exactly what the variables do when you go to change them!  The
descriptions are commented out with the unix script comment symbol,
'#', to make it easy to paste them directly into a shell script;
self-documentation is much easier than having to find this file again
to modify the script.  The jmmenv script provides an example of this as
well as a handy summary of all the variables and their effects.

To get file/line information you must include <jNew.h>, because it must
define jnew and jdelete.  The recommended way to do this is to #include
jAssert.h, since it #include's jNew.h.

Performance:

A test involving starting and immediately quitting jcc on a project
that displays the jcore+jx inheritance tree with various JMM
environment settings produced the following results (in CPU seconds):

    baseline: 1.97
    +init: 2.05
    +hash: 3.99
    +broadcast: 4.05
    +shred: 3.94
    +dealloc: 6.32
    +double alloc: 6.54
    +array-dealloc: 616.77
    +dealloc: 611.67

Repeated runs showed the accuracy was no better than a few percent.
This suggests that there is no noticable penalty for initialization or
shredding. Clearly hash tables were at least two orders of magnitude
better than arrays. For building the tree, deallocation didn't cost much
extra with arrays, though if the program would have kept running it
eventually would have.





Base code generated by Codemill v0.1.0

Member Typedef Documentation

◆ DebugLink

using JMemoryManager::DebugLink = JMessageProtocol<ACE_LSOCK_STREAM>

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
kRunningStatsMessage 
kExitStatsMessage 
kErrorMessage 
kRecordsMessage 
kSaveSnapshotMessage 
kSnapshotDiffMessage 

◆ anonymous enum

anonymous enum
Enumerator
kHistogramSlotCount 

Constructor & Destructor Documentation

◆ ~JMemoryManager()

JMemoryManager::~JMemoryManager ( )
override

◆ JMemoryManager()

JMemoryManager::JMemoryManager ( )
protected

Member Function Documentation

◆ Delete()

void JMemoryManager::Delete ( void *  memory,
bool  isArray 
)

◆ GetAbortUnknownAlloc()

bool JMemoryManager::GetAbortUnknownAlloc ( )
inlinestatic

◆ GetAllocateGarbage()

unsigned char JMemoryManager::GetAllocateGarbage ( ) const
inline

◆ GetBroadcastErrors()

bool JMemoryManager::GetBroadcastErrors ( ) const
inline

◆ GetCheckDoubleAllocation()

bool JMemoryManager::GetCheckDoubleAllocation ( ) const
inline

◆ GetDeallocateGarbage()

unsigned char JMemoryManager::GetDeallocateGarbage ( ) const
inline

◆ GetPrintErrors()

bool JMemoryManager::GetPrintErrors ( ) const

◆ GetPrintExitStats()

bool JMemoryManager::GetPrintExitStats ( ) const
inline

◆ GetPrintInternalStats()

bool JMemoryManager::GetPrintInternalStats ( ) const
inline

◆ GetPrintLibraryStats()

bool JMemoryManager::GetPrintLibraryStats ( ) const
inline

◆ HandleArrayDeletedAsObject()

void JMemoryManager::HandleArrayDeletedAsObject ( const JMMRecord record)
protected

◆ HandleMultipleAllocation()

void JMemoryManager::HandleMultipleAllocation ( const JMMRecord thisRecord,
const JMMRecord firstRecord 
)
protected

◆ HandleMultipleDeletion()

void JMemoryManager::HandleMultipleDeletion ( const JMMRecord thisRecord,
const JUtf8Byte file,
const JUInt32  line,
const bool  isArray 
)
protected

◆ HandleObjectDeletedAsArray()

void JMemoryManager::HandleObjectDeletedAsArray ( const JMMRecord record)
protected

◆ HandleUnallocatedDeletion()

void JMemoryManager::HandleUnallocatedDeletion ( const JUtf8Byte file,
const JUInt32  line,
const bool  isArray 
)
protected

It frequently happens that we don't catch the alloc for system code.

◆ Instance()

JMemoryManager * JMemoryManager::Instance ( )
static

◆ New()

void * JMemoryManager::New ( const size_t  size,
const JUtf8Byte file,
const JUInt32  line,
const int  type,
const bool  isArray,
const bool  assert 
)
static

If assert==true, the returned pointer is guaranteed to be valid.

◆ PrintAllocated()

void JMemoryManager::PrintAllocated ( ) const

◆ PrintMemoryStats()

void JMemoryManager::PrintMemoryStats ( )

◆ Receive()

void JMemoryManager::Receive ( JBroadcaster sender,
const Message message 
)
overrideprotectedvirtual

Process the given message from the given sender. This function is not pure virtual because not all classes will want to implement it.

Reimplemented from JBroadcaster.

◆ RecordingAllocated()

bool JMemoryManager::RecordingAllocated ( ) const
inline

◆ SendError()

void JMemoryManager::SendError ( const JString msg)
static

called by JMMDebugErrorStream.

◆ SetAbortUnknownAlloc()

void JMemoryManager::SetAbortUnknownAlloc ( const bool  yesNo)
inlinestatic

Sets whether the program will abort if unknown code allocates memory. If the memory manager cannot locate an allocation, examining the core dump resulting from such an abort is one way to figure out where the memory is being allocated. This overrides the JMM_ABORT_UNKNOWN_ALLOC environment variable.

◆ SetBroadcastErrors()

void JMemoryManager::SetBroadcastErrors ( const bool  broadcast)
inline

Sets whether error notifications will be broadcast. Overrides the JMM_BROADCAST_ERRORS environment variable.

◆ SetCheckDoubleAllocation()

void JMemoryManager::SetCheckDoubleAllocation ( const bool  yesNo)
inline

Sets whether deletion of a nullptr pointer is considered an error (ANSI says no). Overrides the J_ALLOW_DELETE_NULL environment variable.

◆ SetPrintErrors()

void JMemoryManager::SetPrintErrors ( const bool  print)

Sets whether error notifications will be printed. Overrides the JMM_NO_PRINT_ERRORS environment variable.

◆ SetPrintExitStats()

void JMemoryManager::SetPrintExitStats ( const bool  yesNo)
inline

Sets whether dynamic memory usage stats will be printed when the program exists. Values set by this function override that set with the environment variable J_PRINT_EXIT_STATS.

◆ SetPrintInternalStats()

void JMemoryManager::SetPrintInternalStats ( const bool  yesNo)
inline

Sets whether memory usage stats for the memory manager itself will be printed whenever regular memory allocation stats are printed (such as at program exit). Values set by this function override that set with the environment variable J_PRINT_EXIT_STATS.

◆ SetPrintLibraryStats()

void JMemoryManager::SetPrintLibraryStats ( const bool  yesNo)
inline

Sets whether memory usage stats for the libraries will be printed whenever regular memory allocation stats are printed (such as at program exit). Values set by this function override that set with the environment variable JMM_PRINT_LIBRARY_STATS.

◆ SetProtocol()

void JMemoryManager::SetProtocol ( DebugLink link)
static

Friends And Related Symbol Documentation

◆ JLocateDelete

void JLocateDelete ( const JUtf8Byte file,
const JUInt32  line 
)
friend

◆ JMMHandleACEExit

void JMMHandleACEExit ( void *  ,
void *   
)
friend

◆ JMMHandleExit

void JMMHandleExit ( )
friend

◆ JMMTable

friend class JMMTable
friend

Member Data Documentation

◆ kArrayDeletedAsObject

const JUtf8Byte * JMemoryManager::kArrayDeletedAsObject = "ArrayDeletedAsObject::JMemoryManager"
static

◆ kMultipleAllocation

const JUtf8Byte * JMemoryManager::kMultipleAllocation = "MultipleAllocation::JMemoryManager"
static

◆ kMultipleDeletion

const JUtf8Byte * JMemoryManager::kMultipleDeletion = "MultipleDeletion::JMemoryManager"
static

◆ kObjectDeletedAsArray

const JUtf8Byte * JMemoryManager::kObjectDeletedAsArray = "ObjectDeletedAsArray::JMemoryManager"
static

◆ kUnallocatedDeletion

const JUtf8Byte * JMemoryManager::kUnallocatedDeletion = "UnallocatedDeletion::JMemoryManager"
static

◆ kUnknownFile

const JUtf8Byte * JMemoryManager::kUnknownFile = "<UNKNOWN>"
static

The documentation for this class was generated from the following files: