- HandlerMinelayerData: BUILD_RTI Guards für RTI-Abhängigkeiten - svcTabCommon: Export-Header-Fix via Fallback-Target - TrainingAreaBase: Stub-Header für BUILD_RTI=OFF - ddsfts: Include-Pfad und Dependency-Fixes - BUILD_RTI=OFF Compilation vollständig unterstützt Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Entire-Checkpoint: 01M0JNZA586SACX1PRZ2DJAE5S
537 lines
20 KiB
C
537 lines
20 KiB
C
/*
|
|
* (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_table_h
|
|
#define reda_table_h
|
|
|
|
#include "osapi/osapi_type.h"
|
|
#include "reda/reda_dll.h"
|
|
#include "reda/reda_epoch.h"
|
|
#include "reda/reda_fastBuffer.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Doxygen file & module documentation ==================================*/
|
|
/*e \file
|
|
|
|
\brief Defines the REDATable
|
|
*/
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \defgroup REDATableClass REDATable
|
|
\ingroup REDAModule
|
|
|
|
@brief a data structure that allows safe and efficient
|
|
storage, iteration and search among fixed-size structures that are
|
|
entered by the application. Each such structure is referred as a
|
|
"record".
|
|
|
|
The REDA model of a table is composed of three main elements: The
|
|
table (REDATable) that holds records, cursors (REDACursor) that allow
|
|
iteration and modification of records in the table, and weakReferences
|
|
(REDAWeakReference) that allow caching a logical index to a record
|
|
in the table.
|
|
|
|
\image html Table_Overview_Public.jpg "Overview of REDATable"
|
|
|
|
Each record consists of three areas: a key, a readOnlyArea and
|
|
a readWriteArea. The format and size of these three areas is
|
|
the same for all \e records in the table and is defined by
|
|
providing REDAOrderedDataTypes when the table is created.
|
|
REDATable requires the key to be unique accross all records in
|
|
the table. The key is used to provide efficient searching, using
|
|
an underlying REDAHashedSkiplist.
|
|
The readOnlyArea is written when a new record is added to the table
|
|
and can never be modified.
|
|
The readWriteArea of a record can be modified.
|
|
|
|
REDATable is optimized for use in a multi-threaded environment where
|
|
multiple threads may need to iterate as well as enter or remove
|
|
records. These operations are done through creating a REDACursor
|
|
and binding it to a table. Once a cursor has been succesfully bound
|
|
to the table, all cursor-opertations are multi-thread safe. Through
|
|
a bound cursor, threads can modify the records and the table.
|
|
|
|
The weakReference is a reference to a record of a table. Such
|
|
a reference is "weak" because the record can
|
|
be removed even if there are weak-references to it. In that case,
|
|
dereferencing the weak-reference (with gotoWeakReference) will
|
|
return an error.
|
|
|
|
As most operations are done safely through a cursor, only three methods
|
|
can be invoked on a table: REDATable_bindCursor, REDATable_cleanup
|
|
and REDATable_delete. When calling these methods on the REDATable itself,
|
|
the caller has the responsability to make sure the table has not been
|
|
deleted. After REDATable_delete has been called, no methods can be
|
|
called on that table any more; however, cursors that might still be
|
|
bound to that table will be fine: they will refuse to start..
|
|
|
|
\image html Table_States.jpg "REDATable lifecycle"
|
|
|
|
The life-line of a table can be illustrated in the pseudo-code below:
|
|
\anchor DOXANCHOR_tableLifeline
|
|
\code
|
|
struct REDACursor *cursor;
|
|
struct REDAWorker *worker;
|
|
struct REDATable *table;
|
|
struct REDAWorkerFactory *workerFactory;
|
|
|
|
workerFactory = REDAWorkerFactory_new(...)
|
|
worker = REDAWorkerFactory_createWorker(workerFactory, ...);
|
|
// or use a pre-existing one
|
|
table = REDATable_new(...); // create table
|
|
REDATable_bindCursor(table, cursor, worker);
|
|
// initialize cursor and bind it
|
|
|
|
REDACursor_start(cursor, ...);
|
|
|
|
// find a record and read it
|
|
REDACursor_gotoKeyEqual(cursor, );
|
|
REDACursor_getReadOnlyArea(cursor, ...)
|
|
|
|
// Find a record and modify it
|
|
REDACursor_gotoKeyEqual(cursor, );
|
|
REDACursor_modifyReadWriteArea(cursor, ...)
|
|
REDACursor_finishReadWriteArea(cursor, ...)
|
|
|
|
// Lock the table
|
|
REDACursor_lockTable(cursor, ...);
|
|
|
|
// Now we can insert & remove records, etc.
|
|
REDACursor_assertAndModifyReadWriteArea(cursor, ...)
|
|
|
|
// Remove a record
|
|
REDACursor_gotoKeyEqual(cursor, );
|
|
REDACursor_removeRecord(cursor, ...);
|
|
|
|
// Indicate we are no longer using the cursor
|
|
REDACursor_finish(cursor, );
|
|
|
|
// The application can keep the cursor around and call _start()/_finish()
|
|
// again to access more records
|
|
REDACursor_start(cursor, ...);
|
|
// Access more records...
|
|
REDACursor_finish(cursor, ...);
|
|
|
|
// The cursor can remove the entire table as follows
|
|
REDACursor_start(cursor, ...);
|
|
REDACursor_lockTable(cursor, ...);
|
|
REDACursor_removeTable(cursor, ...);
|
|
REDACursor_finish(cursor, ...);
|
|
|
|
// For cleanup, the following method must be called regularly
|
|
REDATable_cleanup(table, &tableCanBeDeleted,...)
|
|
|
|
// Finally, the table can be deleted
|
|
if(tableCanBeDeleted) {
|
|
REDATable_delete(table,...)
|
|
}
|
|
|
|
// At this point: methods on the table CANNOT be invoked any more
|
|
// BUT the cursors bound to the table will still be safe
|
|
REDACursor_start(cursor, ...) // returns FALSE as the table has been deleted
|
|
|
|
\endcode
|
|
|
|
@see REDACursor REDAWeakReference
|
|
*/
|
|
|
|
/* Need to declare these so that we don't have to expose the internal
|
|
* structures */
|
|
struct REDASkiplistDescription;
|
|
struct REDAExclusiveArea;
|
|
struct REDAOrderedDataType;
|
|
struct REDAHashDefinition;
|
|
struct REDACursor;
|
|
struct REDATable;
|
|
struct REDAWorker;
|
|
struct REDAWeakReferenceManager;
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
@brief Used to indicate that a default value should be used.
|
|
|
|
Typically used
|
|
as argument to functions that expect configuration parameters and
|
|
hints such as number of records, hash-buckets, etc.
|
|
*/
|
|
#define REDA_TABLE_USE_DEFAULT_VALUE (-1)
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
@brief Used to indicate the maximum length of table name used for
|
|
creating table.
|
|
*/
|
|
#define REDA_TABLE_NAME_MAX_LENGTH (80)
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
|
|
@brief Prototypes the function that can be registered to get notification
|
|
that a table is physically removed from memory. This is the place
|
|
where any resources that where loaned to the table may be
|
|
freed. This function is specified in the \c tableFinalizeFnc
|
|
argument to the REDATable_new function.
|
|
|
|
This function will be called exactly once from the context of
|
|
a thread calling REDATable_cleanup. When the function has been
|
|
called, no cursor can access the table any more and the table
|
|
can be deleted with REDATable_delete.
|
|
|
|
@param param \b In. The \c tableFinalizeParam specified when the
|
|
table was created. See REDATable_new.
|
|
|
|
@param recordFinalizeParam\b In. The \c recordFinalizeParam
|
|
specified when the table was created. See REDATable_new.
|
|
|
|
@param tableUserData\b In. The userData that was stored in the
|
|
table on creation. See REDATable_new.
|
|
|
|
@param worker\b In. Reaper worker.
|
|
|
|
@see REDATable_new
|
|
*/
|
|
typedef void (*REDATableFinalizeFunction)(
|
|
void *param,
|
|
void *recordFinalizeParam,
|
|
void *tableUserData,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
|
|
@brief Prototypes the function that can be registered to get notification
|
|
that a record is physically removed from memory. This is the place
|
|
where any resources that where inside the record may be freed.
|
|
|
|
Prior to this function being called it may be possible for cursors
|
|
to still access a removed record if they were positioned at the record
|
|
or if there was a race condition. After this function is called, it is
|
|
guaranteed that nobody can access the record and thus it is only
|
|
now that we may finalize and release resources associated with the
|
|
record.
|
|
|
|
@param param\b In. The \c recordFinalizeParam specified when the
|
|
table was created. See REDATable_new.
|
|
|
|
@param key\b In. The record's key
|
|
|
|
@param readOnlyArea\b In. The record's readOnlyArea
|
|
|
|
@param readWriteArea\b In. The record's readWriteArea
|
|
|
|
@param worker\b In. Reaper worker.
|
|
|
|
@mtsafety Safe. It is guaranteed that no other worker is using the record
|
|
now and in future. You may destroy at will.
|
|
|
|
@see REDATable_new
|
|
*/
|
|
typedef void (*REDATableRecordFinalizeFunction)(
|
|
void *param,
|
|
void *key,
|
|
void *readOnlyArea,
|
|
void *readWriteArea,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ===================================================================== */
|
|
/*e \defgroup REDATablePropertyClass REDATableProperty
|
|
\ingroup REDATableClass
|
|
@brief A convenient way to group properties of a table
|
|
Note that this is not actually used in
|
|
*/
|
|
struct REDATableProperty {
|
|
struct REDAFastBufferPoolGrowthProperty growth;
|
|
int hashBucketCount;
|
|
};
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
|
|
@brief Creates a REDATable.
|
|
|
|
REDATable is implemented using a REDAHashedSkiplist for management
|
|
of the records. See REDAHahsedSkiplist for more information on
|
|
the performance and memory usage implications of the hashing.
|
|
|
|
@param tableName \b In. Name of table for debugging purpose. Can be NULL.
|
|
|
|
@param keyType \b In. Defines the type of keys used to identify the
|
|
records in the the table. Must have been initialized with
|
|
REDAOrderedDataType_define. The relevant contents will be copied
|
|
into the table; this structure can be deleted after the Table has
|
|
been created.
|
|
|
|
@param readOnlyAreaType \b In. Defines the type of data in the read-only
|
|
area of the records. Must have been initialized with
|
|
REDAOrderedDataType_define or can be NULL in which case the Table does
|
|
not have records with a readOnlyArea.
|
|
The relevant contents will be copied into the table; this structure
|
|
can be deleted after the Table has been created.
|
|
|
|
@param readWriteAreaType \b In. Defines the type of data in the read-write
|
|
area of the records. Must have been initialized with
|
|
REDAOrderedDataType_define OR can be NULL in which case the Table does not
|
|
have records with a readWriteArea.
|
|
The relevant contents will be copied into the table; this structure can
|
|
be deleted after the Table has been created.
|
|
|
|
@param hashDefinition \b In. Defines the hashing that will be used
|
|
on the key. See the documentation for REDAHashedSkiplist and REDAHash
|
|
for more information.
|
|
The relevant contents will be copied into the table; this structure
|
|
can be deleted after the Table has been created. In case this parameter
|
|
is NULL, no hashing will be used.
|
|
|
|
@param skiplistDesc \b In. Describes the properties of the underlying
|
|
hashedSkiplist. This description is NOT copied into the table; it
|
|
must remain in existence with the Table.
|
|
|
|
@param weakRefManager \b In. a manager for the weak references. Must
|
|
have been allocated with REDAWeakReferenceManager_new. The
|
|
WeakReferenceManager must remain in existence as long as the Table
|
|
exists or weak-references to records of the Table might still be
|
|
lying around in the application. The WeakReferenceManager typically
|
|
will be the last object to be destroyed in an application using Tables.
|
|
|
|
@param tableEA \b In. The table-level exclusive area. It is necessary
|
|
that a worker can enter the adminEA of the table, the adminEA of the
|
|
weak-reference manager and the record EA's from within the tableEA.
|
|
|
|
@param adminEA \b In. The administrative EA: the table will use this
|
|
EA for short internal protection. This EA must be such that it can
|
|
be entered from within any other EA: from within the table-EA and/or
|
|
record-EA's.
|
|
|
|
@param tableFinalizeFnc \b In. A function to be notified that the
|
|
table is physically removed from memory and nobody is able to access
|
|
it anymore. See REDATableFinalizeFunction for details.
|
|
This parameter may be NULL if no finalization function is desired.
|
|
|
|
@param tableFinalizeParam \b In. Parameter to pass to tableFinalizeFnc.
|
|
|
|
@param recordFinalizeFnc \b In. Used to notify application when a
|
|
record is about the be physically removed and nobody can access its
|
|
contents. See REDARecordFinalizeFunction for details.
|
|
May be NULL to indicate there is no notification is needed.
|
|
|
|
@param recordFinalizeParam \b In. Additional parameter to pass to
|
|
recordFinalizeFnc.
|
|
|
|
@param growthPropertyIn. This is like the table's property. Since there
|
|
are no other meaningful table property, we just use this "parent" class
|
|
directly.
|
|
|
|
@param tableUserData \b In. Table provides storage space for one
|
|
pointer, which can be retrieved safely through REDACursor_getTableUserData.
|
|
The table only provides safe read-only access; this pointer or the
|
|
structure it points cannot be modified without additional protection
|
|
on top of the Table.
|
|
|
|
@mtsafety Safe.
|
|
|
|
@see REDACursor REDAWeakReferenceManager_new REDATable_cleanup
|
|
REDATable_delete
|
|
*/
|
|
extern REDADllExport struct REDATable *REDATable_new(
|
|
const char *tableName,
|
|
const struct REDAOrderedDataType *keyType,
|
|
const struct REDAOrderedDataType *readOnlyAreaType,
|
|
const struct REDAOrderedDataType *readWriteAreaType,
|
|
const struct REDAHashDefinition *hashDefinition,
|
|
const struct REDASkiplistDescription *skiplistDesc,
|
|
const struct REDAFastBufferPoolGrowthProperty *growthPropertyIn,
|
|
struct REDAWeakReferenceManager *weakRefManager,
|
|
struct REDAExclusiveArea *tableEA,
|
|
struct REDAExclusiveArea *adminEA,
|
|
REDATableFinalizeFunction tableFinalizeFnc,
|
|
void *tableFinalizeParam,
|
|
REDATableRecordFinalizeFunction recordFinalizeFnc,
|
|
void *recordFinalizeParam,
|
|
void *tableUserData);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
|
|
@brief Get the read-only growth property of the table
|
|
@mtsafety Safe.
|
|
*/
|
|
extern REDADllExport const struct REDAFastBufferPoolGrowthProperty *
|
|
REDATable_getGrowthProperty(struct REDATable *me);
|
|
|
|
/*e \ingroup REDATableClass
|
|
|
|
@brief Get the read-only table name.
|
|
@mtsafety Safe.
|
|
*/
|
|
extern REDADllExport const char *REDATable_getName(const struct REDATable *me);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
|
|
@brief Deletes a REDATable.
|
|
|
|
It is the responsability of the application that uses tables
|
|
to ensure that after the call to REDATable_delete is made, no
|
|
other methods (bindCursor, cleanup or delete) are invoked on this
|
|
table.
|
|
When the table is deleted when the precondition (see below) is met;
|
|
the implementation guarantees that Cursors still bound to the
|
|
Table will not be allowed to use the deleted Table and WeakReferences
|
|
refering to records of the deleted Table are invalidated.
|
|
|
|
@pre A valid (undeleted) Table; the table has been removed and
|
|
REDATable_cleanup() has been called as many times as required until
|
|
it sets the parameter tableCanBeDeleted to TRUE.
|
|
|
|
@post The table is deleted.
|
|
|
|
@param table \b In. The table to delete.
|
|
|
|
@mtsafety Unsafe. Only one thread can call this method.
|
|
|
|
@see REDACursor REDATable_new REDATable_cleanup
|
|
*/
|
|
extern REDADllExport void REDATable_delete(struct REDATable *table);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
|
|
@brief Bind a new cursor to a specific table and worker.
|
|
|
|
This function initializes the cursor and binds it to a table and
|
|
worker. Cursors must be bound prior to be in used on tables. This
|
|
function must be called before calling any other functions on the
|
|
cursor, specifically REDACursor_start and any other functions that
|
|
attempt to access a table.
|
|
|
|
Refer to the \ref DOXANCHOR_CursorStates "cursor state diagram" for
|
|
the role of this function within the cursor lifeline.
|
|
|
|
This operation will fail if the table has been removed or if
|
|
pre-condition checking is enabled it is detected that they
|
|
are not met
|
|
|
|
@pre cursor must point to enough memory to hold a (struct REDACursor).
|
|
Cursor must be in state "unbound";
|
|
Table must be a valid table. It can be removed but it cannot
|
|
have benn deteted (i.e. REDATable_delete should have not been
|
|
called on that table.
|
|
|
|
@post on success (RTI_TRUE is returned): the cursor is bound to the
|
|
table and worker and is in state "inactive".
|
|
on failure (RTI_FALSE is returned) the cursor is left in the
|
|
state UNBOUND.
|
|
|
|
@param table \b In. The table to bind the cursor to
|
|
|
|
@param cursor \b In. The cursor to bind. Cannot be NULL
|
|
|
|
@param worker \b In. The worker under which context the cursor will
|
|
operate
|
|
|
|
@mtsafety unsafe. This call can only be made by one thread (worker) on any
|
|
given cursor. Once bound then only that thread/worker can use the cursor.
|
|
|
|
\code
|
|
struct REDACursor cursor;
|
|
struct *REDAWorker worker;
|
|
struct *REDATable table;
|
|
|
|
worker = REDAWorker_new(...); // or use a pre-existing one
|
|
table = REDATable_new(...); // create table
|
|
if(!REDATable_bindCursor(table, &cursor, worker)) {
|
|
// error-handling
|
|
}
|
|
|
|
// Now we can start and use the cursor:
|
|
REDACursor_start(&cursor,...); // declare intent of using the cursor
|
|
\endcode
|
|
|
|
@mtsafety Safe. As long as the table is undeleted, workers can concurrently
|
|
bind to the table without affecting each other.
|
|
|
|
@see REDACursor_start REDACursor_unbind
|
|
*/
|
|
extern REDADllExport RTIBool REDATable_bindCursor(
|
|
struct REDATable *table,
|
|
struct REDACursor *cursor,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDATableClass
|
|
|
|
@brief Cleaning up will (if possible) delete the structures (records or the
|
|
entire table) that have been removed through Cursors.
|
|
|
|
The registered record- and table-finalization methods will also be
|
|
called from this method right before the affected structures are
|
|
removed from memory.
|
|
|
|
The typical usage is to call this function at some period to "delete"
|
|
the records that have been removed until the output parameter
|
|
tableCanBeDeleted is TRUE and then, once we are sure the table will
|
|
no longer be accessed, call Table_delete.
|
|
|
|
This operation can be called in any of the table states:
|
|
If the table is in the state Alive, then it will just delete the
|
|
removed records that are no longer accessible by the bound cursors.
|
|
If the table is in the state Removed, in addition to deleting the
|
|
removed records that are innaccessible it will check whether the
|
|
table can be removed and transition to the "CanBeDeleted" state.
|
|
If the table is in the "CanBeDeleted" state, the operation will
|
|
be a NOOP. It will however return RTI_TRUE and tableCanBeDeleted=TRUE.
|
|
|
|
@pre A table in the Alive, Removed, or CanBeDeleted state.
|
|
The table cannot have been deleted (by calling Table_delete)
|
|
|
|
@invariant The logical contents of the table is not modified
|
|
|
|
@param table \b in. A valid table to clean up.
|
|
@param tableCanBeDeleted \b out. An optional parameter; if RTI_TRUE
|
|
is returned, the table is in the "CanBeDeleted" state and the
|
|
operation REDATable_delete can be called to effectively delete the table
|
|
without endangering the safety of any Cursors bound to the table.
|
|
@param worker \b in. The worker that calls this function.
|
|
|
|
@return RTI_TRUE on success, RTI_FALSE on failure
|
|
|
|
@mtsafety Safe. As long as the table is undeleted, any worker can
|
|
cleanup the table.
|
|
|
|
@see REDACursor REDATable_delete
|
|
*/
|
|
extern REDADllExport RTIBool REDATable_cleanup(
|
|
struct REDATable *table,
|
|
RTIBool *tableCanBeDeleted,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \defgroupREDATablePropertyClass
|
|
* @brief A convenient way to form a table property from individual parameters
|
|
*
|
|
* @note This functions is implemented as a macro
|
|
*/
|
|
void REDATableProperty_init(
|
|
struct REDATableProperty *me,
|
|
int initial,
|
|
int maximal,
|
|
int growthIncrement,
|
|
int hashBucketCount);
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
|
|
/* pick up hidden performance boosting macros and optimizations */
|
|
#include "reda/reda_table_impl.h"
|
|
|
|
#endif /* reda_table_h */
|