Files
qt6-migration-pipeline/external/rti_connext_dds-7.7.0/include/ndds/osapi/osapi_context.h
T
torsten 77c67c12ca Execute the same instructions but now for tools in folders you are getti
Entire-Metadata: .entire/metadata/fb87247f-2a75-407e-b336-cbc8c20ba5a6
Entire-Session: fb87247f-2a75-407e-b336-cbc8c20ba5a6
Entire-Strategy: manual-commit
2026-09-24 16:24:51 +00:00

543 lines
21 KiB
C

/*
* (c) Copyright, Real-Time Innovations, 2019-2024.
* 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 osapi_context_h
#define osapi_context_h
#include "log/log_common.h"
#include "osapi/osapi_dll.h"
#include "osapi/osapi_type.h"
#include "osapi/osapi_thread.h"
#include "osapi/osapi_heap.h"
#include "osapi/osapi_utility.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @internal \ingroup RTIOsapiContext
* Max size for the representation of the context into a string.
*/
#define RTI_OSAPI_CONTEXT_STRING_SIZE_MAX 512
/** @internal \ingroup RTIOsapiContext
* Default max size used to initialize context stack.
*/
#define RTI_OSAPI_CONTEXT_STACK_SIZE_DEFAULT 32
/** @internal \ingroup RTIOsapiActivityContext
* The Index of the activity and heap context specializations.
*/
#define RTI_OSAPI_ACTIVITY_CONTEXT_INDEX 0
#define RTI_OSAPI_HEAP_CONTEXT_INDEX 1
/** @internal \ingroup RTIOsapiContext
* Entry of the context.
*/
struct RTIOsapiContextEntry {
void *entry;
/* If the context is cached in expansion, expansionEnd points to end */
char *expansionEnd;
/*
* Represent if an entry can be skipped from the string representation of
* the context stack.
*
* We need to cache if the entry is skipped to optimize the generation of
* the activity context string: we need to check previous entries skipped
* state to make decisions about the new entries we add.
*
* For example in the activity context the output will change (we will skip
* entries) based on the order and content of the entries:
* - For example similar activities and different resources:
* `R1|A1|R2|A1` -> `R1|A1|R2|A1`. The activities are similar but cannot
* be skipped because they belong to different resources.
* - For example similar activities and similar resources:
* `R1|A1|R1|A1` -> `R1|A1`. The activities and the resources are exactly
* the same, so both of them are skipped.
*/
RTIBool skipped;
};
/** @internal \ingroup RTIOsapiContext
* The concept of context is a queue of entries associated with a thread.
* Those entries can be pushed and popped from the list of entries.
*
* The context can be instantiate for different specialization:
* - Activity context: it will describe the activity that a resource is doing.
* - Heap context: it will represent:
* - If the allocation is from the pool and in that case the buffer size
* and the buffer count.
* - The topic and the function name.
*/
struct RTIOsapiContext {
/* List of entries */
struct RTIOsapiContextEntry *entries;
RTI_UINT32 maxEntryCount;
/* Position on the list */
RTI_UINT32 top;
/* Used to cache the context as a string */
char *expansion;
/* A bitmap used to store the categories associated with the context */
RTILogCategoryMask category;
};
/** @internal \ingroup RTIOsapiContext
* Number of type of contexts.
* Instantiate different specializations of the context:
* - Activity context: it will describe the activity that a resource is doing.
* - Heap context: it will represent: If the allocation is from the pool and in
* that case the buffer size and the buffer count. The topic and the function
*name.
*- In the future, we can have more potential context families for instance
* network capture context.
*/
#define RTI_OSAPI_NUMBER_CONTEXTS 3
/** @internal \ingroup RTIOsapiContextSupport
* Each node contains the contexts of the thread.
*/
struct RTIOsapiContextSupportNode {
struct RTIOsapiInlineListNode node;
struct RTIOsapiContext *contexts[RTI_OSAPI_NUMBER_CONTEXTS];
};
/* ========================================= */
/* ContextSupport */
/* ========================================= */
/*
* The Context feature is enabled by calling RTIOsapiContextSupport_enable() and
* it is disabled by calling RTIOsapiContextSupport_disable().
*
* The lifecycle of the context support is different depending on if using heap
* monitoring.
*
* - If using heap monitoring:
* - The Context support is enabled in RTIOsapiHeap_enableMonitoring()
* - The Context support is disabled in RTIOsapiHeap_disableMonitoring()
* - In case the “Participant Globals” are initialized or finalized,
* they will not affect the context support lifecycle.
* - If not using heap monitoring:
* - The Context support is enabled in
* DDS_DomainParticipantGlobals_initializeI()
* - The Context support is disabled in
* DDS_DomainParticipantGlobals_finalizeI()
* - In case the “Participant Globals” are initialized or finalized several
* times. The context support will be too.
* - Heap Monitoring can not interfere with it because
* RTIOsapiHeap_enableMonitoring() should be the first thing to be
* done.
*/
/** @internal \ingroup RTIOsapiContextSupport
* @brief Enable the Context feature.
* Create the tssFactory, tssKey, tssList and mutex.
* It should be called from a single thread.
* It should be called before using any functionality of the context.
* It is called in:
* - DDS_DomainParticipantGlobals_initializeI
* - RTIOsapiHeap_enableMonitoring
* Increment RTIOsapiContextSupport_g_tssInitializedRefCount, it is usd to make
* sure we disable the context support when the refCount is 1.
* @param tssFactory \b In. The TSS factory.
* In case the tssFactory is null, create a new one.
*
* @return True if the feature was enabled, False otherwise.
*/
extern RTIOsapiDllExport RTIBool
RTIOsapiContextSupport_enable(RTIOsapiThreadTssFactory *tssFactory);
/** @internal \ingroup RTIOsapiContextSupport
* @brief Disable the Context feature.
* Remove the tssKey, mutex and all the contexts nodes of all the User
* threads.
* It should be called from a single thread.
* Any functionality of the context can not be used after calling this
* method.
* Decrement RTIOsapiContextSupport_g_tssInitializedRefCount, it is usd to make
* sure we disable the context support when the refCount is 1.
* It is called in:
* - DDS_DomainParticipantGlobals_finalizeI
* - RTIOsapiHeap_disableMonitoring
*/
extern RTIOsapiDllExport void RTIOsapiContextSupport_disable(void);
/** @internal \ingroup RTIOsapiContextSupport
* @brief Create a specific context and associate with the TSS of the thread.
* - It should be called per thread.
* - It should be called after RTIOsapiContextSupport_enable.
* It is called in:
* - DDS_DomainParticipantGlobals_create_worker_per_thread_with_nameI
* - RTIOsapiThreadChild_onSpawned
* - RTIOsapiThreadFactory_onSpawned
*
* @param nodeOut \b Out. The node that we will assert for the
* thread. Can be NULL.
* @param contextIndex \b In. The index of the context.
* @param addContextTssToGlobalList \b In. If true we add the context thread
* specific storage to a global list.
* @param maxEntryCount \b In. The max size of the list of entries.
* @param allowContextExpansion \b In. If true allocate the member field to
* RTI_OSAPI_CONTEXT_STRING_SIZE_MAX.
*
* @return True if the context was initalized, False otherwise.
*/
extern RTIOsapiDllExport RTIBool RTIOsapiContextSupport_assertContextTss(
struct RTIOsapiContextSupportNode **nodeOut,
RTI_UINT32 contextIndex,
RTIBool addContextTssToGlobalList,
RTI_UINT32 maxEntryCount,
RTIBool allowContextExpansion);
/** @internal \ingroup RTIOsapiContextSupport
* @brief This function is only used to finalize the contextTss and its
* associated RTIOsapiContextSupportNode for non-RTI threads.
* Specifically, it is called from
* DDS_DomainParticipantFactory_unregister_thread. If
* DDS_DomainParticipantFactory_unregister_thread is not called by the user, the
* contextTss and associated RTIOsapiContextSupportNode will be removed in
* RTIOsapiContextSupport_disable() during RTIOsapiContextSupport_g_tssList
* destruction at the end of DDS application lifecycle.
*
* For RTI threads, this function cannot be used. Instead,
* the contextTss and RTIOsapiContextSupportNode are removed by a call to
* RTIOsapiContextSupport_finalizeNode done by the thread itself before
* finishing.
*/
extern RTIOsapiDllExport void RTIOsapiContextSupport_finalizeContextTss(void);
/** @internal \ingroup RTIOsapiContext
* @brief Return the context, of the caller thread, specified by the Id.
* @param contextIndex \b In. The index of the context.
*
* @return the context specified by the Id.
*/
extern RTIOsapiDllExport struct RTIOsapiContext *
RTIOsapiContextSupport_getContext(RTI_UINT32 contextIndex);
/* ========================================= */
/* Context */
/* ========================================= */
/*
* For the enter methods:
* In case the entries do not fit in the list of entries:
* - The value context->top will be incremented as many elements the user
* expected to enter.
* - The entries will not be saved in the queue because there is not space
* for them.
* We do this in order to keep the number of entries the user has entered.
* So, the value of context->top may be greater than context->maxEntryCount.
*
* For the leave methods:
* While the value of context->top is greater than context->maxEntryCount:
* - The value of context->top will be decremented as many entries were
* expected to be left.
* Once the context->top is smaller or equal than context->maxEntryCount:
* - The elements are removed from the list.
*
* By doing that we will solve the following scenario:
* - Initial context state before calling a function: top = 2, maxEntryCount = 4
* - Start a function:
* - Enter 3 entries into the context.
* - As the number of entries to enter plus top is greater than
* maxEntryCount. The entries will not be added into the context.
* However top will be incremented as many entries are expected to be
* entered.
* - Context state: top = 5, maxEntryCount = 4
* - Leave 3 entries from the context.
* - Decrement top, 3 elements.
* - Context state: top = 2, maxEntryCount = 4
* - End the function. Now the state of the context will be the same as when
* the function began.
*
* By keeping context->top with the expected value will ensure our developer
* finishes a function with the same value of the context as it began.
*/
/*
* Infinite loops - circular dependencies
* As we have mentioned already the context will be used in heap monitoring and
* logging.
* So, it is necessary to set up a contract/rule between the context and those
* features.
* - Logging:
* - The context feature can log messages. It is safe because nothing below
* logging is going to enter/leave entries in the context. So, there are
* not possible infinite loops.
* - Advanced logging (advlog.1.0) is using the context to generate the
* string using RTIOsapiActivityContext_getString().
* - It is safe to log in that function because logging is already
* protected from infinite loops by ADVLOGLogger_blockThreadLogging().
* - Heap monitoring:
* - In the context we cannot use our allocation function
* (RTIOsapiHeap_allocate…()) because we cannot add allocation statistics
* data to the heap monitoring.
* - Then, in the context feature we use malloc instead.
*/
/** @internal \ingroup RTIOsapiContext
* @brief Enter an entry to the context specified by the Id.
* If the context is already full, the entry will not be added.
* The entry memory is owned by the caller function.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param contextIndex \b In. The index of the context.
* @param entry \b In. The entry to add the context.
*/
extern RTIOsapiDllExport void RTIOsapiContext_enter(
struct RTIOsapiContext *self,
RTI_UINT32 contextIndex,
void *entry);
/** @internal \ingroup RTIOsapiContext
* @brief Enter two entries to the context specified by the Id.
* If the context is already full, the entries will not be added.
* The entries memory is owned by the caller function.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param contextIndex \b In. The index of the context.
* @param entry1 \b In. The entry1 to add to the context.
* @param entry2 \b In. The entry1 to add to the context.
*/
extern RTIOsapiDllExport void RTIOsapiContext_enterPair(
struct RTIOsapiContext *self,
RTI_UINT32 contextIndex,
void *entry1,
void *entry2);
/** @internal \ingroup RTIOsapiContext
* @brief Leave the last entry of the context specified by the Id.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param contextIndex \b In. The index of the context.
*/
extern RTIOsapiDllExport void RTIOsapiContext_leave(
struct RTIOsapiContext *self,
RTI_UINT32 contextIndex);
/** @internal \ingroup RTIOsapiContext
* @brief Leave the last N entries of the context specified by the Id.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param contextIndex \b In. The index of the context.
* @param groupSize \b In. Number of entries to remove from the list.
*/
extern RTIOsapiDllExport void RTIOsapiContext_leaveGroup(
struct RTIOsapiContext *self,
RTI_UINT32 contextIndex,
RTI_UINT32 groupSize);
/** @internal \ingroup RTIOsapiContext
* @brief Return the number of entries of the context specified by the Id.
*
* @param contextIndex \b In. The index of the context.
*
* @return number of entries of the context specified by the Id.
*/
extern RTIOsapiDllExport RTI_UINT32
RTIOsapiContext_getDepth(RTI_UINT32 contextIndex);
/* ========================================= */
/* Category of the Context */
/* ========================================= */
/*
* The category is used to store the current category of the codepath
* that we are in. This is used to enable filtering of log messages by
* category and labelling log messages with the current category.
*
* When entering a category codepath, you first need to set the
* category. There are three methods that allow you to do this:
* RTIOsapiActivityContext_setCategory:
* Overwrites the existing category
* RTIOsapiActivityContext_addCategory:
* Adds the new category to the existing category (but does not
* overwrite any bits that have been set to 1).
* RTIOsapiActivityContext_addAndCacheCategory:
* Adds the new category to the existing category and stores the
* existing category.
*
* It is recommended to usually use RTIOsapiActivityContext_addAndCacheCategory
* when setting the category when entering a codepath so that you are able to
* restore the category to its previous value when you are leaving the
* codepath. You can then call RTIOsapiActivityContext_setCategory to set the
* category to its previous value. You should always restore the category
* before returning from the function in which you add the category, otherwise
* the category will still be set even though we will no longer be in the
* correct codepath for that category.
*
* There is also a method RTIOsapiActivityContext_resetCategory which will
* clear the bits in the context category that are set to 1 in the input
* category. This can also be used to reset the category after setting it.
*
* RTIOspaiActivityContext_getCategory can be used to get the current value
* of the context's category mask.
*
* The following shows an example of setting the category to DISCOVERY,
* logging messages, and then resetting the category:
*
* RTICategoryMask cachedCategory = RTI_LOG_CATEGORY_NONE;
* RTIOsapiActivityContext_addAndCacheCategory(
* &cachedCategory,
* RTI_LOG_CATEGORY_DISCOVERY_BIT);
* DDSLogger_log(
* RTI_LOG_BIT_LOCAL,
* &RTI_LOG_EMPTY_TEMPLATE,
* "This is a log message in the discovery codepath!\n");
* RTIOsapiActivityContext_setCategory(cachedCategory);
*
*/
/** @internal \ingroup RTIOsapiContext
* @brief Get the current category mask of the context.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param category \b Out. Pointer to location where we will store category.
* @param contextIndex \b In. The index of the context.
*/
extern RTIOsapiDllExport void RTIOsapiContext_getCategory(
struct RTIOsapiContext *self,
RTILogCategoryMask *category,
RTI_UINT32 contextIndex);
/** @internal \ingroup RTIOsapiContext
* @brief Set the category mask of the context to the category mask passed in.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param contextIndex \b In. The index of the context.
*
* @param category \b In. The category mask to set to.
*
* @return True if the category mask is set successfully. False otherwise.
*
* This function should always be called before a "return" statement when
* using RTIOsapiActivityContext_addAndCacheCategory;
*/
extern RTIOsapiDllExport void RTIOsapiContext_setCategory(
struct RTIOsapiContext *self,
RTI_UINT32 contextIndex,
RTILogCategoryMask category);
/** @internal \ingroup RTIOsapiContext
* @brief Add the passed category to the existing category mask of the
* context. This will not clear other category masks if they are already
* set, it will just add the category mask passed in.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param contextIndex \b In. The index of the context.
*
* @param category \b In. The category mask to add.
*
* @return True if the category mask is set successfully. False otherwise.
*/
extern RTIOsapiDllExport void RTIOsapiContext_addCategory(
struct RTIOsapiContext *self,
RTI_UINT32 contextIndex,
RTILogCategoryMask category);
/** @internal \ingroup RTIOsapiContext
* @brief
*
* @param contextIndex \b In. The index of the context.
*
* @param category \b In. The category mask to add.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param cachedCategory \b Out. A pointer to a variable where we will cache
* a mask of the bits to be restored upon a call to resetCategory. This
* mask will be set to the current value of
* self->_activityContext->category;
* @param contextIndex \b In. The index of the context.
* @param category \b In. The category mask to add.
*
* @return True if the category mask is set successfully. False otherwise.
*
* When using this function, there should not be a "return" statement
* prior to calling RTIOsapiContext_setCategory to reset the category.
*/
extern RTIOsapiDllExport void RTIOsapiContext_addAndCacheCategory(
struct RTIOsapiContext *self,
RTILogCategoryMask *cachedCategory,
RTI_UINT32 contextIndex,
RTILogCategoryMask category);
/** @internal \ingroup RTIOsapiContext
* @brief Reset the category mask of a given category to all 0s.
*
* @param self \b In. The context itself. If it is NULL, it will be get
* from the TSS.
* @param contextIndex \b In. The index of the context.
*
* @param category \b In. The category mask to clear.
*
* @return True if the category mask is reset successfully. False otherwise.
*/
extern RTIOsapiDllExport void RTIOsapiContext_resetCategory(
struct RTIOsapiContext *self,
RTI_UINT32 contextIndex,
RTILogCategoryMask category);
/* ========================================= */
/* ContextScope */
/* ========================================= */
/*
* We define "scope" as a block of code which:
* - Starts with a RTIOsapiContextScope_begin call.
* This macro opens the block.
* After calling begin(), you must initialize all the stack variables needed to
* support entering/leaving contexts within the block.
* - Ends with an RTIOsapiContextScope_end call.
* Before ending a scope, you must leave any remaining entered entries.
* This macro closes the block.
*
* The general scope does not provide significant functionality,
* it just opens and closes the brackets. It is just conceptual.
* The upper layer contexts are going to rely on the concept of scope.
*
* The context scope has two rules:
* - It has to be robust to not segmentation fault nor array overflow.
* - The context should have the same status before calling "begin" and after
* calling "end".
*/
/** @internal \ingroup RTIOsapiContext
* @brief This macro opens the block. After calling begin(), you must initialize
* all the stack variables needed to support entering/leaving contexts within
* the block.
*
* Note: make sure to not add ';' after a call to this macro.
*/
extern RTIOsapiDllExport void RTIOsapiContextScope_begin(void);
/** @internal \ingroup RTIOsapiContext
* @brief Upon ending a scope, you must leave any remaining entered entries.
* Close the block.
*/
extern RTIOsapiDllExport void RTIOsapiContextScope_end(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "osapi/osapi_context_impl.h"
#endif /* osapi_context_h */