/* * (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: * * @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 */