/*
* (c) Copyright, Real-Time Innovations, 2002-2026.
* All rights reserved.
* No duplications, whole or partial, manual or electronic, may be made
* without express written permission. Any such copies, or
* revisions thereof, must display this notice unaltered.
* This code contains trade secrets of Real-Time Innovations, Inc.
*/
#ifndef reda_weakReference_h
#define reda_weakReference_h
#include "osapi/osapi_type.h"
#include "reda/reda_dll.h"
#ifdef __cplusplus
extern "C" {
#endif
/*e \file
* @brief solves the dangling pointer problem
*/
/*e \defgroup REDAWeakReferenceClass REDAWeakReference
* \ingroup REDATableClass
*
* @brief WeakReferences are structures that refer to a Record of a Table.
* They are value-types and can be copied or destroyed at will.
*
* \image html Table_WeakReference_Public.jpg "WeakReference"
*
* A WeakReference can be in following states:
*
* - The weakReference can be "invalid": it does not refer to anything
*
- The weakReference can refer to a record that does not exist any more
*
- The weakReference refers to an existing record
*
* @see REDACursor_getWeakReference REDACursor_gotoWeakReference
*/
struct REDAWeakReference;
struct REDAWorker;
struct REDACursor;
struct REDAExclusiveArea;
/*e \ingroup REDADatabaseClass
* @brief Indicates the weak reference
* manager should have unlimited number of weak references. That is
* auto-grow them.
*/
#define REDA_TABLE_WEAKREF_UNLIMITED (RTI_UINT32_MAX)
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
* @brief for logging
* @see REDAOrderedDataTypePrintFunction
*/
extern REDADllExport void REDAWeakReference_print(
const void *data,
const char *desc,
int indent);
/*e \ingroup REDAWeakReferenceClass
*
* @brief Method that can be used as a comparison function when a WeakReference
* is used as an OrderedDataType in a Skiplist or Table.
*
* @param left \b In.
* @param right \b In.
*
* @mtsafety safe
* @see REDAOrderedDataTypeCompareFunction
*/
extern REDADllExport int REDAWeakReference_compare(
const void *left,
const void *right);
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
* @brief Value to initialize stack variables to.
*/
#define REDA_WEAK_REFERENCE_INVALID \
{ NULL, REDA_WEAK_REFERENCE_INDEX_INVALID, REDA_EPOCH_UNKNOWN }
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
* @brief Invalidate weak reference back to same state as
* \ref REDA_WEAK_REFERENCE_INVALID.
* @param reference \b In.
*/
void REDAWeakReference_reset(struct REDAWeakReference *reference);
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
* @brief Makes a copy of the weak reference.
*
* @note This is implemented as a macro for performance reasons.
*/
void REDAWeakReference_copy(
struct REDAWeakReference *to,
const struct REDAWeakReference *src);
/* ----------------------------------------------------------------- */
/*e
* \ingroup REDAWeakReferenceClass
*
* @brief Creates a weak reference manager with the stated number of weak
* references.
*
* This function allocates memory for a REDAWeakReferenceManager object
* capable of delivering \c uniqueWeakRefCountMax weak references
* to unique records.
*
* The value of \c uniqueWeakRefCountInit controls the initial number of
* weak references that are allocated.
*
* The actual number of weak references is allowed to grow "on demand" up
* to the value specified by \c uniqueWeakRefCountMax. This paramater can
* be set to the special value REDA_TABLE_WEAKREF_UNLIMITED to indicate
* no hard limit. In this case the implementation will limit the number
* to 2^28 referents (~256 million).
*
* Once allocated, weak referents are never freed (they're reused as the
* records they refer to are deleted, but the memory is never returned
* to the system).
*
* The number of weak referents needed by a system is hard to
* anticipate. For this reason the normal use should set
* uniqueWeakRefCountMax=REDA_TABLE_WEAKREF_UNLIMITED to let the system grow to
* the required value. A concrete maximum value should only be set if we want to
* limit the memory to some smaller number. A use-case for this would be where
* the application wants to pre-allocate the memory (so as not to risk
* doing a dynamic memory allocation when it needs a referent). See below.
*
* The number of references needed corresponds to the maximum number of
* weak references to unique records we want to have at any one
* time. This is because the REDAWeakReferenceManager only needs
* management space for each unique record independent of the number
* of weak references there are that refer to that record. Moreover, as
* soon as a record is moved into the garbage list, its weak references
* are invalidated and the weak reference referent is reclaimed so the
* number of weak reference referents will not be affected by the garbage
* collection mechanism. The special value REDA_TABLE_WEAKREF_UNLIMITED can be
* used to indicate unlimited weak references. If REDA_TABLE_WEAKREF_UNLIMITED
* is used, the maximum will be limited in software to 2^28 referents (~256
* million) but it is possible that the system will run of other resources
* before that.
*
* A worst-case upper bound for the value of \c uniqueWeakRefCountMax
* would be the sum of the maximum number of records of all tables that
* share the same weak reference manager. This is quite conservative. A
* less-conservative (but harder to estimate) bound is the maximum number
* of actual records present in all tables attached to the
* weak reference. In fact even this is too conservative, as it assumes
* that each record will have at least one weak reference and this is not
* necessarily the case.
*
* If uniqueWeakRefCountInit==uniqueWeakRefCountMax then the
* REDAWeakReferenceManager will not allocate memory after it has been
* created. Otherwise an attempt to get a weak reference can result on a
* memory allocation if there are no available weak references.
*
* @param uniqueWeakRefCountInit initial number of weak-referents to allocate.
* Should verify uniqueWeakRefCountInit >=1 and uniqueWeakRefCountInit !=
* REDA_TABLE_WEAKREF_UNLIMITED.
*
* @param uniqueWeakRefCountMax maximum number of weak-referents the
* manager can grow to. The special value REDA_TABLE_WEAKREF_UNLIMITED
* can be used to indicate no limits. Other than the aforementioned
* special value this number must verify uniqueWeakRefCountMax >=
* uniqueWeakRefCountInit
*
* @param adminEA an exclusive area that the REDAWeakReferenceManager
* will use to protect its internal state. This exclusive area is entered
* by the operations that add and remove weak referents but not by the
* operations that de-reference the referent. This translates into only
* entering the exclusive-area when we first try to get a weak reference
* to a record that had no weak references before and also when we remove
* a record.
*
* @mtsafety Safe
*/
extern REDADllExport struct REDAWeakReferenceManager *
REDAWeakReferenceManager_new(
RTI_UINT32 uniqueWeakRefCountInit,
RTI_UINT32 uniqueWeakRefCountMax,
struct REDAExclusiveArea *adminEA);
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
*
* @brief Gets the initial number of weak references.
*
* The number returned by this method may be larger than the initial number
* specified in the constructor if that specified initial count would not have
* allowed the number of weak references to grow to the maximum.
*
* @mtsafety safe.
*/
extern REDADllExport RTI_UINT32 REDAWeakReferenceManager_getWeakRefCountInit(
struct REDAWeakReferenceManager *me);
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
*
* @brief Gets the maximum number of weak references.
*
* If an infinite maximum was specified in the constructor, the actual maximum
* will be returned (i.e. the maximum finite number that can be represented
* by the implementation).
*
* @mtsafety safe.
*/
extern REDADllExport RTI_UINT32 REDAWeakReferenceManager_getWeakRefCountMax(
struct REDAWeakReferenceManager *me);
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
*
* @brief Deletes a weak reference manager.
*
* @post application must not use any weak references dispensed by this
* manager.
*
* @mtsafety unsafe. Can only be called by one thread ever.
*
*/
extern REDADllExport void REDAWeakReferenceManager_delete(
struct REDAWeakReferenceManager *manager);
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
*
* @brief Return whether a weak reference is valid
*
* @pre non NULL reference
*
* @param reference \b In.
*
* @return RTI_TRUE iff valid (meaning the weakReference refers to
* a -possibly deleted- record of a table)
*
* @mtsafety safe
*
* @note This function is implemented as a macro for performance reasons.
*/
RTIBool REDAWeakReference_isValid(const struct REDAWeakReference *reference);
#define REDAWeakReference_getValidCount(reference__) ( \
REDAWeakReference_isValid(reference__) ? 1 : 0 \
)
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
*
* @brief Return whether a weak reference refers to a record that
* still exists (has not been deleted)
*
* @pre a valid weak reference reference; the weak reference manager
* must exist
*
* @param reference \b In.
*
* @return RTI_TRUE iff reference refers to a record that still
* exists
*
* @mtsafety safe
* @see REDACursor_gotoWeakReference
*
* @note This function is implemented as a macro for performance reasons.
*/
RTIBool REDAWeakReference_refersToExistingRecord(
const struct REDAWeakReference *reference);
/* ----------------------------------------------------------------- */
/*e \ingroup REDAWeakReferenceClass
*
* @brief Compare whether 2 valid weak references refer to the same record
* (whether that record itself still exists or has been deleted does
* not affect the outcome)
*
* @pre valid weak references left and right.
*
* @param left \b In.
* @param right \b In.
*
* @return RTI_TRUE if equal, RTI_FALSE otherwise.
* @mtsafety safe
*
* @note This function is implemented as a macro for performance reasons.
*/
RTIBool REDAWeakReference_referToSameRecord(
const struct REDAWeakReference *left,
const struct REDAWeakReference *right);
#ifdef __cplusplus
} /* extern "C" */
#endif
/* pick up hidden performance boosting macros and optimizations */
#include "reda/reda_weakReference_impl.h"
#endif /* reda_weakReference_h */