Files
qt6-migration-pipeline/external/rti_connext_dds-7.7.0/include/ndds/event/event_jobDispatcher.h
T
torstenandCopilot 342ffd3e5c Update submodule to latest BUILD_RTI fixes
- 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
2026-08-21 19:30:20 +02:00

962 lines
41 KiB
C

/*
* (c) Copyright, Real-Time Innovations, 2002-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 event_jobDispatcher_h
#define event_jobDispatcher_h
#ifndef event_dll_h
#include "event/event_dll.h"
#endif
#ifndef event_generator_h
#include "event/event_generator.h"
#endif
#ifndef event_activeObject_h
#include "event/event_activeObject.h"
#endif
#ifndef reda_worker_h
#include "reda/reda_worker.h"
#endif
#ifndef osapi_threadFactory_h
#include "osapi/osapi_threadFactory.h"
#endif
#ifndef osapi_ntptime_h
#include "osapi/osapi_ntptime.h"
#endif
#ifndef reda_orderedDataType_h
#include "reda/reda_orderedDataType.h"
#endif
#ifndef clock_interface_h
#include "clock/clock_interface.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct REDASkiplist;
struct REDAWorkerFactory;
struct RTIEventJobDispatcher;
struct RTIEventJobDispatcherThread;
struct RTIEventJobDispatcherTokenBucket;
struct RTIEventJobDispatcherAgent;
struct RTIEventJobDispatcherGroup;
struct RTIEventJobDispatcherDefinedJob;
/*e \file
\brief Defines the RTIEventJobDispatcher.
*/
/*e \defgroup RTIEventJobDispatcherClass RTIEventJobDispatcher
\ingroup RTIEventModule
\brief Allows token bucket-based job scheduling.
RTIEventJobDispatcher is an active object. There is currently no implementation
of a passive version of the Dispatcher.
User can create any number of token buckets, execution threads, agents, job
groups, and jobs.
Each agent is associated with 1 token bucket (to receive tokens from) and 1
execution thread (to run jobs in the context of). Agents are 'workers' who
execute jobs that are dispatched to it. Jobs can have different priorities,
and the agent inherits the highest priority among its jobs. The agent priority
determines the agent's precedence in receiving tokens from its token bucket.
Agents with higher priority receive tokens first. Tokens are distributed evenly
across agents of the same priority.
All jobs belong to a certain job group. Job group is a container to hold jobs.
It does not associate with an execution thread or source token bucket directly.
Rather, its jobs are dispatched to run with a given agent. Each job can be
dispatched to run by multiple agents. Each job can have its own priority.
Agents execute dispatched jobs based on the job priorities. But jobs from the
same group are executed in a FIFO fashion based on their scheduling order.
Priority inheritance is used to avoid priority inversion. That is, if a new
high priority job is dispatched to an agent containing an existing, low priority
job from the same group, the existing job inherits the new, higher priority.
A agent's jobs can be from differnt groups. A group's jobs can also be
dispatched to multiple agents. It is a many-to-many relationship.
Job group also defines pruning behavior (job can only prune jobs from the same
group to make space for itself) and provides the group callback mechanism.
Additionally, duplicate jobs are only checked within a group.
Jobs are run as tokens are received; it may take multiple runs before
all requested tokens are received. A job dispatched to multiple agents execute
independently from each other. Jobs can also terminate early (and even return
received tokens) before receving all tokens.
JobDispatcher is a general purpose scheduling infrastructure facility, but was
designed to ease Asynchronous Publishing implementation. See the Large Data
(Asynchronous Publishing) SDD for more detailed information.
*/
/*e \ingroup RTIEventJobDispatcherClass
\brief Job definition result.
*/
typedef enum {
/*e Job is successfully defined.
*/
RTI_EVENT_JOB_DISPATCHER_JOB_DEFINE_RESULT_SUCCESS,
/*e Job could not be defined (possible that job queue limit is reached).
*/
RTI_EVENT_JOB_DISPATCHER_JOB_DEFINE_RESULT_FAILED,
/*e Job is not re-defined because an identical job already exists.
*/
RTI_EVENT_JOB_DISPATCHER_JOB_DEFINE_RESULT_EXISTS
} RTIEventJobDispatcherJobDefineResult;
/*e \ingroup RTIEventJobDispatcherClass
\brief Job schedule result.
*/
typedef enum {
/*e Job is successfully scheduled.
*/
RTI_EVENT_JOB_DISPATCHER_JOB_SCHEDULE_RESULT_SUCCESS,
/*e Job could not be scheduled (possible that job queue limit is reached).
*/
RTI_EVENT_JOB_DISPATCHER_JOB_SCHEDULE_RESULT_FAILED,
/*e Job is not re-scheduled because an identical job already exists.
*/
RTI_EVENT_JOB_DISPATCHER_JOB_SCHEDULE_RESULT_EXISTS
} RTIEventJobDispatcherJobScheduleResult;
/*e \ingroup RTIEventJobDispatcherClass
\brief Dispatcher active object listener callback.
*/
typedef void (* RTIEventJobDispatcherListenerCallback)(
struct RTIEventActiveObject *obj, void *param, struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
\brief Dispatcher active object listener.
TODO: this, ActiveObjectListener, and ActiveEventGeneratorListener should be able
to be merged as one.
*/
struct RTIEventJobDispatcherListener {
/*e Called each time when a thread is started.
*/
RTIEventJobDispatcherListenerCallback onStarted;
/*e User-defined param for onStarted.
*/
void *onStartedParam;
/*e Called each time when a thread is stopped.
*/
RTIEventJobDispatcherListenerCallback onStopped;
/*e User-defined param for onStopped.
*/
void *onStoppedParam;
};
/*e \ingroup RTIEventJobDispatcherClass
\brief Default dispatcher listener.
*/
#define RTI_EVENT_JOB_DISPATCHER_LISTENER_DEFAULT { \
NULL, NULL, NULL, NULL \
}
/*e \ingroup RTIEventJobDispatcherClass
\brief Dispatcher property.
*/
struct RTIEventJobDispatcherProperty {
/*e A passive job dispatcher can only create passive threads and buckets. */
RTIBool isPassive;
/*e Growth property of the number of jobs defined to the Dispatcher.
*/
struct REDAFastBufferPoolGrowthProperty definedJobsGrowth;
/*e Growth property of the number of jobs scheduled/dispatched to the Dispatcher.
*/
struct REDAFastBufferPoolGrowthProperty scheduledJobsGrowth;
/*e Growth property of different priority levels the job groups can belong to.
*/
struct REDAFastBufferPoolGrowthProperty agentsGrowth;
/*e Growth property of the number of agents user can create.
*/
struct REDAFastBufferPoolGrowthProperty groupsGrowth;
/*e Growth property of the number of of execution threads user can create.
*/
struct REDAFastBufferPoolGrowthProperty threadsGrowth;
/*e Growth property of the number of token buckets user can create.
*/
struct REDAFastBufferPoolGrowthProperty bucketsGrowth;
/*e @brief The thread participant identification.
Used to give a meaningful name to the thread.
*/
char threadParticipantId[RTI_OSAPI_THREAD_PARTICIPANT_ID_MAX_SIZE];
/*e
* Max. time (in seconds) we wait for the destruction of the execution
* thread upon a destroyThread() call. After this time, destroyThread() will
* return without destroying execution thread's resources. When this
* happens, we will rely on the JobDispatcher shutdown call to release these
* resources.
*/
RTI_INT32 executionThreadDestructionTimeout;
};
/*e \ingroup RTIEventJobDispatcherClass
\brief Default dispatcher property.
*/
#define RTI_EVENT_JOB_DISPATCHER_PROPERTY_DEFAULT { \
RTI_FALSE, /* isPassive */ \
{20, REDA_FAST_BUFFER_POOL_UNLIMITED, 20}, /* definedJobsGrowth */ \
{50, REDA_FAST_BUFFER_POOL_UNLIMITED, 50}, /* scheduledJobsGrowth */ \
{10, REDA_FAST_BUFFER_POOL_UNLIMITED, 10}, /* agentsGrowth */ \
{10, REDA_FAST_BUFFER_POOL_UNLIMITED, 10}, /* groupsGrowth */ \
{3, REDA_FAST_BUFFER_POOL_UNLIMITED, 3}, /* threadsGrowth */ \
{3, REDA_FAST_BUFFER_POOL_UNLIMITED, 3}, /* bucketsGrowth */ \
"#####", /* threadParticipantId */ \
10, /* executionThreadDestructionTimeout */ \
}
/*e \ingroup RTIEventJobDispatcherClass
\brief Thread property.
*/
struct RTIEventJobDispatcherThreadProperty {
/*e A passive thread is not really a thread (ie, no thread is spawned). It is
merely a collection of agents to be run. These agents are run on-demand
when RTIEventJobDispatcher_executionThreadAgents() is called, and they
run in the context of the caller. Passive threads also do not call
the dispatcher listener callbacks. */
RTIBool isPassive;
/*e Dispatcher thread is an active object. */
struct RTIEventActiveObjectProperty active;
};
/*e \ingroup RTIEventJobDispatcherClass
\brief Default thread property.
*/
#define RTI_EVENT_JOB_DISPATCHER_THREAD_PROPERTY_DEFAULT { \
RTI_FALSE, /* isPassive */ \
RTI_EVENT_ACTIVE_OBJECT_PROPERTY_DEFAULT /* active */ \
}
/*e \ingroup RTIEventJobDispatcherClass
\brief Unbounded (maximum) tokens.
*/
#define RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS (-1)
/*e \ingroup RTIEventJobDispatcherClass
\brief Token bucket property.
This is a standard token bucket implementation within an additional parameter - tokensLeakedPerPeriod.
In addition to adding tokens periodically, we also provide a means to lose historic tokens.
Interesting settings:
- where maxTokens = RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS,
tokensAddedPerPeriod = RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS,
tokensLeakedPerPeriod = 0; all agents' scheduled jobs get to run (to completion)
immediately when they are scheduled. Essentially, the agents/jobs use a slave thread
(which is always ready to run) for execution.
- where maxTokens = RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS,
tokensAddedPerPeriod = RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS,
tokensLeakedPerPeriod = RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS; all agents'
scheduled jobs get to run (to completion) at every tokenPeriod. Essentially,
the agents/jobs run at a periodic rate.
*/
struct RTIEventJobDispatcherTokenBucketProperty {
/*e A passive token bucket does not install an periodic event to add tokens.
Instead, tokens are only added when user calls RTIEventJobDispatcher_addTokens().
Passive token bucket honors all other properties, except the tokenPeriod is variable
based on the user call-rate. */
RTIBool isPassive;
/*e Units can only be given in batches of tokens; this determines the size of that batch.
Use RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS to allow a single token to serve any number
of units.
*/
int unitsPerToken;
/*e Max tokens (units) the bucket can carry (save); use RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS for unlimited.
*/
int maxTokens;
/*e The number of tokens to add to the bucket per period. Use RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS to
always have maxTokens available.
*/
int tokensAddedPerPeriod;
/*e The number of tokens to leak (lose) from the bucket per period after each periodic token distribution.
Use RTI_EVENT_JOB_DISPATCHER_UNBOUNDED_TOKENS to leak all tokens.
*/
int tokensLeakedPerPeriod;
/*e The period to add tokens.
*/
struct RTINtpTime tokenPeriod;
};
extern RTIEventDllExport
int RTIEventJobDispatcherTokenBucketProperty_compare(
const struct RTIEventJobDispatcherTokenBucketProperty *left,
const struct RTIEventJobDispatcherTokenBucketProperty *right);
/*e \ingroup RTIEventJobDispatcherClass
\brief Default token bucket property.
*/
#define RTI_EVENT_JOB_DISPATCHER_TOKEN_BUCKET_PROPERTY_DEFAULT { \
RTI_FALSE, /* isPassive */ \
2, /* unitsPerToken */ \
REDA_FAST_BUFFER_POOL_UNLIMITED, /* maxTokens */ \
5, /* tokensAddedPerPeriod */ \
0, /* tokensLeakedPerPeriod */ \
{1, 0} /* tokenPeriod */ \
}
/*e \ingroup RTIEventJobDispatcherClass
\brief Agent property.
*/
struct RTIEventJobDispatcherAgentProperty {
void *dummy;
};
/*e \ingroup RTIEventJobDispatcherClass
\brief Default agent property.
*/
#define RTI_EVENT_JOB_DISPATCHER_AGENT_PROPERTY_DEFAULT { \
NULL \
}
/*e \ingroup RTIEventJobDispatcherClass
@brief Pruning mechanisms when job queue limit is reached.
*/
typedef enum {
/*e If job queue is full, replace the oldest but unstarted job from the same group.
*/
RTI_EVENT_GROUP_PRUNING_SCHEME_OLDEST_UNSTARTED,
/*e If job queue is full, wait for the specified timeout value for available job space.
*/
RTI_EVENT_GROUP_PRUNING_SCHEME_WAIT_FOR_TIMEOUT
} RTIEventJobDispatcherGroupPruningScheme;
/*e \ingroup RTIEventJobDispatcherClass
@brief group listener callback mask
*/
typedef enum {
/*e Do not call the group callback.
RTI_EVENT_GROUP_CALLBACK_MASK_NONE = 0x0,
*/
/*e Callback whenever a job from the group has completed. This is called
only if every scheduled instance of this job is run to completion.
*/
RTI_EVENT_GROUP_CALLBACK_MASK_JOB_COMPLETED = 0x1,
/*e Callback whenever a job from the group has completed. This is called
only after every scheduled instance of this job has terminated. However,
at least one scheduled instance was interrupted - either because agent
was removed before execution, job group removed in the middle of execution,
etc.
*/
RTI_EVENT_GROUP_CALLBACK_MASK_JOB_INTERRUPTED = 0x2,
/*e Callback whenever a job from the group has been pruned.
*/
RTI_EVENT_GROUP_CALLBACK_MASK_JOB_PRUNED = 0x4,
/*e Callback when all jobs from the group has terminated (completed, interrupted, or pruned).
*/
RTI_EVENT_GROUP_CALLBACK_MASK_ALL_JOBS_TERMINATED = 0x8,
/*e Callback when all jobs from the group has terminated (completed, interrupted, or pruned)
but only if previous posting to the group has failed.
*/
RTI_EVENT_GROUP_CALLBACK_MASK_ALL_JOBS_TERMINATED_AND_FAILED = 0x16
/*e Callback when any of the conditions occur.
RTI_EVENT_GROUP_CALLBACK_MASK_ALL = 0xffffffff
*/
} RTIEventJobDispatcherGroupCallbackMask;
/*e \ingroup RTIEventJobDispatcherClass
@brief No status requested. Do not call the group callback.
*/
#define RTI_EVENT_GROUP_CALLBACK_MASK_NONE ((RTIEventJobDispatcherGroupCallbackMask) 0)
/*e \ingroup RTIEventJobDispatcherClass
@brief All statusues requested. Callback when any of the conditions occur.
*/
#define RTI_EVENT_GROUP_CALLBACK_MASK_ALL (~RTI_EVENT_GROUP_CALLBACK_MASK_NONE)
/*e \ingroup RTIEventJobDispatcherClass
\brief Job group property.
*/
struct RTIEventJobDispatcherGroupProperty {
/*e Soft limit on the number of jobs that can be defined using this group. Actual
resources are still drawn from buffer pool based on the definedJobsGrowth field
in RTIEventJobDispatcherProperty. Use REDA_FAST_BUFFER_POOL_UNLIMITED for unlimited.
*/
int maxJobs;
/*e Determines the pruning scheme used when job queue is full. Job queue can
be full when the Scheduker property values jobsGrowth or maxJobsPerGroup
limits are reached.
*/
RTIEventJobDispatcherGroupPruningScheme pruningScheme;
/*e Determines when the group callback is exercised.
*/
RTIEventJobDispatcherGroupCallbackMask callbackMask;
};
/*e \ingroup RTIEventJobDispatcherClass
\brief Default job group property.
*/
#define RTI_EVENT_JOB_DISPATCHER_GROUP_PROPERTY_DEFAULT { \
REDA_FAST_BUFFER_POOL_UNLIMITED, /* maxJobs */ \
RTI_EVENT_GROUP_PRUNING_SCHEME_WAIT_FOR_TIMEOUT, /* pruningScheme */ \
RTI_EVENT_GROUP_CALLBACK_MASK_NONE /* callbackMask */ \
}
/*e \ingroup RTIEventJobDispatcherClass
\brief Destroy a previously created Dispatcher.
@param me \b In. Dispatcher to delete.
@pre preShutdownWakeup() and shutdown() have been called successfully.
@post If success, made invalid and resource returned.
@see RTIEventJobDispatcher_preShutdownWakeup, RTIEventJobDispatcher_shutdown
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_delete(
struct RTIEventJobDispatcher *me);
extern RTIEventDllExport
/*e \ingroup RTIEventJobDispatcherClass
\brief Create a new Dispatcher.
@param clock \b In. Instance of system clock.
@param generator \b In. Instance of event generator.
@param workerFactory \b In. Instance of worker factory.
@param threadFactory \b In. Instance of thread factory.
@param bucketCompareFnc \b In. To compare whether 2 token buckets are identical (when asserting
a bucket, for instance). This compare function receives 2 instances of RTIEventJobDispatcherStorage (bucketStorage)
as specified when asserting buckets.
@param threadCompareFnc \b In. To compare whether 2 execution threads are identical (when asserting
a thread, for instance). This compare function receives 2 instances of RTIEventJobDispatcherStorage (threadStorage)
as specified when asserting threads.
@param groupCompareFnc \b In. To compare whether 2 job groups are identical (when asserting
a group, for instance). This compare function receives 2 instances of RTIEventJobDispatcherStorage (groupStorage)
as specified when asserting groups.
@param property \b In. Specifies the Dispatcher property.
@return Pointer to the newly created Dispatcher on success, NULL otherwise.
@see RTIEventJobDispatcher_delete
*/
struct RTIEventJobDispatcher *RTIEventJobDispatcher_new(
struct RTIClock *clock,
struct RTIEventGenerator *generator,
struct REDAWorkerFactory *workerFactory,
struct RTIOsapiThreadFactory *threadFactory,
REDAOrderedDataTypeCompareFunction bucketCompareFnc,
REDAOrderedDataTypeCompareFunction threadCompareFnc,
REDAOrderedDataTypeCompareFunction groupCompareFnc,
struct RTIEventJobDispatcherListener *listener,
const struct RTIEventJobDispatcherProperty *property);
/*e \ingroup RTIEventJobDispatcherClass
@brief Mark active objects for termination. This does NOT guarantee the threads
have exited (they exit the next time they get to run. */
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_preShutdownWakeup(
struct RTIEventJobDispatcher *me);
/*e \ingroup RTIEventJobDispatcherClass
@brief Make it ready for deletion. RTIEventJobDispatcher_preShutdownWakeup
must be called succesfully before shutdown function can be called. By the
time this function is called, the event generator should already have been
shutdown. Additionally, this should not be called until an equal number
of RTIEventJobDispatcherListener onStopped() has been called as onStarted().
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_shutdown(
struct RTIEventJobDispatcher *me, struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
@brief Size of storage.
*/
#define RTI_EVENT_JOB_DISPATCHER_STORAGE_LENGTH (8)
/*e
* \ingroup RTIEventJobDispatcherClass
*
* @brief Size of priority. It currently contains the sample's
* publicationPriority plus the sample's deadline. See
* COMMENDWriterServiceJobDispatcherPriorityCopyFnc.
*/
#define RTI_EVENT_JOB_DISPATCHER_PRIORITY_LENGTH ((sizeof(RTI_INT32) + sizeof(struct RTIRtpsTime)) / sizeof(RTI_INT32))
/*e \ingroup RTIEventJobDispatcherClass
@brief Storage structure used throughout the Dispatcher. The Dispatcher shallow-copies
the storage.
*/
struct RTIEventJobDispatcherStorage {
void *field[ RTI_EVENT_JOB_DISPATCHER_STORAGE_LENGTH];
};
/*e \ingroup RTIEventJobDispatcherClass
@brief Job priority for execution.
*/
struct RTIEventJobDispatcherJobPriority {
/*e The Dispatcher does not interpret job priority in any way. They are passed
as input parameters to the priorityCompareFnc defined in RTIEventJobDispatcher_assertTokenBucket.
Therefore, user is free to define and store anything in the array. However,
the contents must be shallow-copiable. That is, memcpy(dest, priority, sizeof(priority))
must work.
*/
int priority[ RTI_EVENT_JOB_DISPATCHER_PRIORITY_LENGTH];
};
/*e \ingroup RTIEventJobDispatcherClass
\brief Function to copy priority attribute from source to Job Priority.
*/
typedef void (* RTIEventJobDispatcherPriorityCopyFunction)(
struct RTIEventJobDispatcherJobPriority *dst, const void *src);
/*e \ingroup RTIEventJobDispatcherClass
@brief Job information for execution.
*/
struct RTIEventJobDispatcherJobInfo {
/*e Group storage as defined when creating the group. The pointer address is
immutable, although the user may alter the field data.
*/
struct RTIEventJobDispatcherStorage *groupStorage;
/*e Job storage as defined when defining the job. The pointer address is
immutable, although the user may alter the field data.
*/
struct RTIEventJobDispatcherStorage *jobStorage;
/*e Schedule storage as defined when scheduling the job. The pointer address is
immutable, although the user may alter the field data.
*/
struct RTIEventJobDispatcherStorage *scheduleStorage;
/*e Number of additional units the job still needs after this run. Ie, the
original units requested on the job less units received thus far.
User should decrement this value to reflect the amount of units consumed
by the job. The job continues to run until all requested units are fulfilled.
The job can also terminate the job early, prior to receiving all units,
by setting unitsRequested to 0.
*/
int unitsRequested;
};
/*e \ingroup RTIEventJobDispatcherClass
\brief Agent execution function.
@param bucketStorage \b In. Bucket storage specified when creating the bucket.
@param threadStorage \b In. Thread storage specified when creating the thread.
@param agentStorage \b In. Agent storage specified when creating the agent.
@param unitsReceived \b In. Units received by agent, to be shared (at user's discretion) by
jobs of the agent. Since units are distributed in multiples of unitsPerToken, unitsReceived
may hold more units than need by all the agents' jobs combined. In such a case, user
is free to discard or refund the unused units (via the return parameter).
@param jobInfo \b InOut. List of RTIEventJobDispatcherJobInfo structs scheduled for
this agent to execute. The list itself is
read-only, although the contents are partially mutable. User should use REDASkiplist_gotoTopNode
and REDASkiplist_gotoNextNode to traverse through the list, and REDASkiplistNode_getUserData
to retrieve the job data. The user data should be casted as a RTIEventJobDispatcherJobInfo
pointer. User is free to assign unitsReceived to any job, although the jobInfo list
is provided to the user priority-sorted (and FIFO within groups). As jobs are executed,
user should decrement unitsRequested in RTIEventJobDispatcherJobInfo (job completes
when the units reach zero).
@return The number of units unconsumed by the jobs (remaining from unitsReceived). The
refunded units are returned to the token bucket only in multiples of unitsPerToken.
Any number of return units less than unitsPerToken (or remainders) are discarded.
@see RTIEventJobDispatcher_defineJob
*/
typedef int (* RTIEventJobDispatcherAgentFunction)(
struct RTIEventJobDispatcherStorage *bucketStorage,
struct RTIEventJobDispatcherStorage *threadStorage,
struct RTIEventJobDispatcherStorage *agentStorage,
int unitsReceived, struct REDASkiplist *jobInfoList, struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
\brief Callback for group status notifications.
@param jobGroup \b In. Group handle of the said group.
@param groupStorage \b In. Group storage specified when creating group.
@param jobStorage \b In. If status is job-specific, the storage of the job.
@param status \b In. Status that triggered this callback.
@param worker \b In. Worker of the group's associated execution thread.
*/
typedef void (* RTIEventJobDispatcherGroupCallback)(
struct RTIEventJobDispatcherGroup *jobGroup,
struct RTIEventJobDispatcherStorage *groupStorage,
struct RTIEventJobDispatcherStorage *jobStorage,
RTIEventJobDispatcherGroupCallbackMask status, struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
\brief Detaches the thread from the caller. The thread will stop executing
if is not attached to any user. Note this will not release any associated
resources.
@param me \b In.
@param executionThread \b In. Thread to invalidate.
@see RTIEventJobDispatcher_removeThread
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_detachThread(
struct RTIEventJobDispatcher *me,
struct RTIEventJobDispatcherThread *executionThread);
/*e \ingroup RTIEventJobDispatcherClass
\brief Remove a previous assertion on an execution thread.
@param me \b In.
@param executionThread \b In. Thread to remove.
@pre All agents associated with the thread must be detached (removed) prior.
@post If all assertions are removed, made invalid and resource returned.
@see RTIEventJobDispatcher_assertThread
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_removeThread(
struct RTIEventJobDispatcher *me, struct RTIEventJobDispatcherThread *executionThread);
extern RTIEventDllExport
/*e \ingroup RTIEventJobDispatcherClass
\brief Assert existence of an execution thread with the specified threadStorage.
If no thread exists with the key, a new thread is created.
@param me \b In.
@param threadStorage \b In. Can be used to uniquely identify an instance of thread.
The Dispatcher shallow-copies the storage.
@param eaBeforeAgentFncs \b In. Required in product code, optional in test
code. If not NULL, the specified EA will be entered
before any agent function is exercised, and exited after all agent functions are
complete. In other words, EA is entered immediately when the thread unblocks and
exited just prior to going back to sleep. To protect against data races
when invaliding the thread, the caller of detachThread, removeThread,
shutdown, or preShutdownWakeup must take this EA before calling one of
those functions.
@param property \b In. Specifies the thread property.
@return Pointer to the thread with specified key on success, NULL otherwise.
@see RTIEventJobDispatcher_removeThread
*/
struct RTIEventJobDispatcherThread *RTIEventJobDispatcher_assertThread(
struct RTIEventJobDispatcher *me, const struct RTIEventJobDispatcherStorage *threadStorage,
struct REDAExclusiveArea *eaBeforeAgentFncs,
const struct RTIEventJobDispatcherThreadProperty *property);
/*e \ingroup RTIEventJobDispatcherClass
* @brief Run the passive execution thread. The passive execution thread is
* intended for use in testing only.
*
* @param me \b In.
* @param executionThread \b In. Thread to run.
* @param worker \b In. Worker for EA access.
*
* @pre Execution thread must be passive.
* @post All agents with tokens pending executes.
*
* @see RTIEventJobDispatcher_assertThread
*/
extern RTIEventDllExport RTIBool
RTIEventJobDispatcher_executeThreadAgentsTestOnly(
struct RTIEventJobDispatcher *me,
struct RTIEventJobDispatcherThread *executionThread,
struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
\brief Remove a previous assertion on a token bucket.
@param me \b In.
@param tokenBucket \b In. Token bucket to remove.
@pre All agents associated with the bucket must be detached (removed) prior.
@post If all assertions are removed, made invalid and resource returned.
@see RTIEventJobDispatcher_assertTokenBucket
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_removeTokenBucket(
struct RTIEventJobDispatcher *me, struct RTIEventJobDispatcherTokenBucket *tokenBucket);
extern RTIEventDllExport
/*e \ingroup RTIEventJobDispatcherClass
\brief Assert existence of an token bucket with the specified bucketStorage.
If no token bucket exists with the key, a new bucket is created.
@param me \b In.
@param agentCompareFnc \b In. To compare whether 2 agents are identical (when asserting
an agent, for instance). This compare function receives 2 instances of RTIEventJobDispatcherStorage
(agentStorage) as specified when asserting agents.
@param agentPriorityCompareFnc \b In. To compare priority levels among agents.
This compare function receives 2 instances of RTIEventJobDispatcherJobPriority
(from 2 separate agents) as specified when defining jobs.
Can be NULL (all agents have same priority).
@param jobPriorityCompareFnc \b In. To compare priority levels among jobs.
This compare function receives 2 instances of RTIEventJobDispatcherJobPriority
(from 2 separate agents) as specified when defining jobs.
Can be NULL (all jobs have same priority).
@param priorityDeriveFunc \b In. Determines agent priority from priority of
scheduled jobs. If, NULL, then agent priority is taken from priority of
the first scheduled job (which is assumed to be the highest priority job.
@param priorityCopyFunc \b In. To copy priority attribute from source data to priority.
Can be NULL
@param bucketStorage \b In. Can be used to uniquely identify an instance of token bucket.
The Dispatcher shallow-copies the storage.
@param property \b In. Specified the token bucket property.
@return Pointer to the bucket with specified key on success, NULL otherwise.
@see RTIEventJobDispatcher_removeTokenBucket
*/
struct RTIEventJobDispatcherTokenBucket *RTIEventJobDispatcher_assertTokenBucket(
struct RTIEventJobDispatcher *me,
REDAOrderedDataTypeCompareFunction agentCompareFnc,
REDAOrderedDataTypeCompareFunction agentPriorityCompareFnc,
REDAOrderedDataTypeCompareFunction jobPriorityCompareFnc,
RTIEventJobDispatcherPriorityCopyFunction priorityCopyFnc,
const struct RTIEventJobDispatcherStorage *bucketStorage,
const struct RTIEventJobDispatcherTokenBucketProperty *property);
/*e \ingroup RTIEventJobDispatcherClass
\brief Retrieve the properties of a token bucket.
@param me \b In.
@param tokenBucket \b In. Token bucket to update properties of.
@param property \b Out. The bucket's current property settings.
@return True if properties were sucessfully retrieved.
@see RTIEventJobDispatcher_assertTokenBucket, RTIEventJobDispatcher_setTokenBucketProperty
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_getTokenBucketProperty(
struct RTIEventJobDispatcher *me,
struct RTIEventJobDispatcherTokenBucket *tokenBucket,
struct RTIEventJobDispatcherTokenBucketProperty *property);
/*e \ingroup RTIEventJobDispatcherClass
\brief Update the properties of a token bucket.
@param me \b In.
@param tokenBucket \b In. Token bucket to update properties of.
@param property \b In. The bucket's new property settings.
@post Token distribution under the new properties will begin immediately.
@return True if properties were sucessfully reset.
@see RTIEventJobDispatcher_assertTokenBucket, RTIEventJobDispatcher_getTokenBucketProperty
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_setTokenBucketProperty(
struct RTIEventJobDispatcher *me,
struct RTIEventJobDispatcherTokenBucket *tokenBucket,
const struct RTIEventJobDispatcherTokenBucketProperty *property);
/*e \ingroup RTIEventJobDispatcherClass
\brief Add tokens to the passive token bucket.
@param me \b In.
@param tokenBucket \b In. Token bucket to add tokens for.
@pre Token bucket must be passive.
@post Tokens are added and distributed to pending agents/jobs.
@return True if tokens were sucessfully added/distributed.
@see RTIEventJobDispatcher_assertTokenBucket, RTIEventJobDispatcher_getTokenBucketProperty
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_addTokens(
struct RTIEventJobDispatcher *me, struct RTIEventJobDispatcherTokenBucket *tokenBucket);
/*e \ingroup RTIEventJobDispatcherClass
\brief Get the priority attribute used by the job priority compare function.
@param me \b In.
@param tokenBucket \b In. Token bucket of the job.
@post Copies the priority attribute configured with this token bucket from
src object to the jobPriority object provided in the call.
*/
extern RTIEventDllExport
void RTIEventJobDispatcher_getJobPriorityAttribute(
struct RTIEventJobDispatcher *me,
struct RTIEventJobDispatcherAgent *agent,
struct RTIEventJobDispatcherJobPriority *dst, const void *src);
/*e \ingroup RTIEventJobDispatcherClass
\brief Remove a previous assertion on an agent.
@param me \b In.
@param jobAgent \b In. Agent to remove.
@param worker \b In. Worker for EA access.
@post If all assertions are removed, made invalid and resource returned. All previously
scheduled jobs are canceled; group callbacks are exercised if applicable.
@see RTIEventJobDispatcher_assertTokenBucket
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_removeAgent(
struct RTIEventJobDispatcher *me, struct RTIEventJobDispatcherAgent *jobAgent, struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
\brief Assert existence of an agent with the specified agentKey.
If no agent exists with the key, a new agent is created.
@param me \b In.
@param tokenBucket \b In. Token bucket to receive units from.
@param executionThread \b In. Execution thread the jobs dispatched to this agent will run in the context of.
@param agentFnc \b In. Called when dispatched jobs receive units.
@param agentStorage \b In. User-defined storage, accessible during agentFnc callback.
The Dispatcher shallow-copies the storage.
@param property \b In. Specifies the agent property.
@return Pointer to the job group with specified key on success, NULL otherwise.
@see RTIEventJobDispatcher_removeAgent, RTIEventJobDispatcher_dispatchJob
*/
extern RTIEventDllExport
struct RTIEventJobDispatcherAgent *RTIEventJobDispatcher_assertAgent(
struct RTIEventJobDispatcher *me,
struct RTIEventJobDispatcherTokenBucket *tokenBucket,
struct RTIEventJobDispatcherThread *executionThread,
RTIEventJobDispatcherAgentFunction agentFnc,
const struct RTIEventJobDispatcherStorage *agentStorage,
const struct RTIEventJobDispatcherAgentProperty *property);
/*e \ingroup RTIEventJobDispatcherClass
\brief Remove a previous assertion on a job group.
@param me \b In.
@param jobGroup \b In. Group to remove.
@param worker \b In. Worker for EA access.
@post If all assertions are removed, made invalid and resource returned. All jobs
(scheduled or not) are removed as well. Group callbacks are NOT exercised.
@see RTIEventJobDispatcher_assertGroup
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_removeGroup(
struct RTIEventJobDispatcher *me, struct RTIEventJobDispatcherGroup *jobGroup, struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
\brief Assert existence of a group with the specified groupKey.
If no group exists with the key, a new group is created.
@param me \b In.
@param jobCompareFnc \b In. To compare and avoid posting identical jobs. Compare function receives 2
instances of RTIEventJobDispatcherStorage (jobStorage) as specified when posting jobs. Can be NULL (jobs are always different).
@param groupCallbackFnc \b In. Used to receive notifications of group status.
@param groupStorage \b In. User-defined storage, accessible during group callback.
The Dispatcher shallow-copies the storage.
@param property \b In. Specifies the job group property.
@return Pointer to the job group with specified key on success, NULL otherwise.
@see RTIEventJobDispatcher_removeGroup, RTIEventJobDispatcher_postJob
*/
extern RTIEventDllExport
struct RTIEventJobDispatcherGroup *RTIEventJobDispatcher_assertGroup(
struct RTIEventJobDispatcher *me,
REDAOrderedDataTypeCompareFunction jobCompareFnc,
RTIEventJobDispatcherGroupCallback groupCallbackFnc,
const struct RTIEventJobDispatcherStorage *groupStorage,
const struct RTIEventJobDispatcherGroupProperty *property);
/*e \ingroup RTIEventJobDispatcherClass
\brief Finalize job, meaning it is no longer valid to dispatch this job with any
additional agents. Job is removed after all existing agents have finished
executing the job.
@param me \b In.
@param definedJob \b In. Job to finalize.
@param worker \b In. Worker for EA access.
@return Whether job was successfully finalized. Job is removed if it is not scheduled
or when all scheduled instances of it are completed.
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_finalizeJob(
struct RTIEventJobDispatcher *me, struct RTIEventJobDispatcherDefinedJob *definedJob, struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
\brief Define a job with the specified jobStorage.
@param me \b In.
@param result \b Out. Define result.
@param jobGroup \b In. Job group the job belongs to.
@param unitsRequested \b In. Jobs request tokens in terms of work units. Units are only distributed
in multiples of unitsPerToken. jobFnc is called as units are received,
not necessarily when token request has been fully met. A continuous job (whose unitsRequested
cannot be pre-determined) can be achieved by NOT decrementing the unitsRequested field in
RTIEventJobDispatcherJobInfo when executed. In that case, unitsRequested specified here determines
how agressively the agent will request units from the token bucket.
@param pruningTimeout \b In. In the event that job queue is full, specifies the timeout used
in conjunction with the RTI_EVENT_GROUP_PRUNING_SCHEME_WAIT_FOR_TIMEOUT pruning scheme.
Can be NULL (no wait).
@param jobStorage \b In. User-defined storage, accessible during agent function.
The Dispatcher shallow-copies the storage.
@param worker \b In. Worker for EA access.
@post Jobs pruned may activate the group callback.
@return Pointer to the job with specified job storage on success, NULL otherwise.
If job has already been defined, pointer will refer to the existing job
(result conveys detailed information).
@see RTIEventJobDispatcherAgentFunction RTIEventJobDispatcher_scheduleJob
*/
extern RTIEventDllExport
struct RTIEventJobDispatcherDefinedJob *RTIEventJobDispatcher_defineJob(
struct RTIEventJobDispatcher *me, RTIEventJobDispatcherJobDefineResult *result,
struct RTIEventJobDispatcherGroup *jobGroup,
int unitsRequested, const struct RTINtpTime *pruningTimeout,
const struct RTIEventJobDispatcherStorage *jobStorage, struct REDAWorker *worker);
/*e \ingroup RTIEventJobDispatcherClass
\brief Retrieve job-specific information.
@param me \b In.
@param jobExists \b Out. Whether job with such index exists.
@param unitsRequested \b Out. The units requested specified when job was defined. Can be NULL.
@param jobStorage \b Out. The storage specified when job was defined. Can be NULL.
@param jobGroup \b In. Job group the job belongs to.
@param index \b In. Index to the job of group desired, in FIFO order (0 being the earliest).
@param inGroupCallback \b In. Whether this is called within the context of group callback function.
@post If jobExists, then interested fields (non-NULL) are populated.
@return True if no such job or successfully retrieved.
@see RTIEventJobDispatcherAgentFunction RTIEventJobDispatcher_scheduleJob
*/
extern RTIEventDllExport
RTIBool RTIEventJobDispatcher_retrieveJobInfo(
struct RTIEventJobDispatcher *me, RTIBool *jobExists,
int *unitsRequested,
struct RTIEventJobDispatcherStorage *jobStorage,
struct RTIEventJobDispatcherGroup *jobGroup, int index,
RTIBool inGroupCallback);
/*e \ingroup RTIEventJobDispatcherClass
\brief Dispatch a job to run with an agent.
@param me \b In.
@param result \b Out. Scheduling result.
@param jobAgent \b In. Agent to dispatch and execute the job with.
@param definedJob \b In. Job to dispatch.
@param jobPriority \b In. Determines the job priority (token receiving precedence). User-defined
priority interpretation, but must be shallow-copiable (see RTIEventJobDispatcherJobPriority).
The Dispatcher will store a copy of this priority value internally. Can be NULL (again,
interpreted by user's priorityCompareFnc only).
@param allowDuplicateJob \b In. If this job is already dispatched to this particular
agent and is being scheduled to run, this flag determines whether to schedule this job
for a 2nd time.
@param unitsRequested \b In. Optional. Used for setting multi-encapsulation
lengths. If NULL, uses defineJob.unitsRequested (as normal)
@param scheduleStorage \b In. User-defined storage, accessible during agent function.
The Dispatcher shallow-copies the storage.
@return Whether job was successfully scheduled with the agent.
*/
extern RTIEventDllExport
void RTIEventJobDispatcher_scheduleJob(
struct RTIEventJobDispatcher *me, RTIEventJobDispatcherJobScheduleResult *result,
struct RTIEventJobDispatcherAgent *jobAgent,
struct RTIEventJobDispatcherDefinedJob *definedJob,
const struct RTIEventJobDispatcherJobPriority *jobPriority,
RTIBool allowDuplicateJob,
int *unitsRequested,
const struct RTIEventJobDispatcherStorage *scheduleStorage);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* event_jobDispatcher_h */