Waitsets, listeners and masks#900
Conversation
|
I agree with the changes in how the status mask works, the existing approach has always confused me somewhat. I've checked the code changes and couldn't find any issues (although I didn't look into the data-on-readers part in detail, as I don't have much experience in using this). The name of the PS: while testing the changes of this PR, I found another issue (#905) which I think is completely unrelated |
|
@mauropasse I just realised that you may have missed this PR, which I think should solve the problems with the EventsExecutor on Cyclone. I would appreciate it if you could give it a try. The default behaviour is unchanged, so to get the desired behaviour you need to change the way you configure the listeners. It is but a small change, e.g., instead of |
|
Hi @eboasson, thanks for your work! |
Signed-off-by: Erik Boasson <eb@ilities.com>
Signed-off-by: Erik Boasson <eb@ilities.com>
Signed-off-by: Erik Boasson <eb@ilities.com>
Signed-off-by: Erik Boasson <eb@ilities.com>
Used only in two places, with behaviour that is confusingly different in its side-effects from dds_entity_status_set. Signed-off-by: Erik Boasson <eb@ilities.com>
The documentation comment suggests it is allowed, though it said "NULL" and didn't say what exactly that means, but in any case 0 was a rather useless value as it would turn the operation into a no-op. The wisdom of returning an error if the mask contains status flags not relevant to the particular entity type is also doubtful, but if 0 is allowed to simply mean "everything", that is not really much of an issue. And with that change, dds_get_status_changes becomes an alias for dds_read_status with mask = 0. Deprecating should be considered, as the "get" is rather ambiguous and can just as easily be interpreted as an innocent "getter" or as a function that also reset the status. Signed-off-by: Erik Boasson <eb@ilities.com>
Signed-off-by: Erik Boasson <eb@ilities.com>
Signed-off-by: Erik Boasson <eb@ilities.com>
The vast majority of the DDS applications ignores DATA_ON_READERS, as it really is only useful for group ordered/coherent subscribers, and those weren't available in any DDS implementation for many years. Cyclone doesn't have them either. At the same time, DATA_ON_READERS is relatively costly, because the spec says it should always be raised when DATA_AVAILABLE is on any of the subscriber's readers, and reset when read/take is called on any of the same. That roughly means every single time a reader history cache is updated, the subscriber status has to be manipulated as well. It turns out that this has a significant performance impact once one allows the statuses to remain set even when invoking the listener, so that one can have listeners that monitor without any side-effects. (Significant here is 3.02MS/s -> 2.95MS/s in ddsperf -TOU pub/sub test on my laptop, and the significane is perhaps more in sinking below 3MS/s than in any absolute terms!) This commit addresses that be only materializing the DATA_ON_READERS state when the subscriber is attached to a waitset, and returning an approximation of it when querying the subscriber's status. The workaround for getting a materialized DATA_ON_READERS is to create an otherwise unused waitset with just the subscriber attached to it. Signed-off-by: Erik Boasson <eb@ilities.com>
These extend on the existing setters/getters as follows: * Provide a return value for returning BAD_PARAMETER if the "listener" argument is a null pointer. * Allow overriding the listener argument pointer specified in the dds_create_listener call. This is quite useful but the workaround for the absence of this argument was a rather convoluted procedure combining getting, setting and merging listeners. * A new boolean argument whether (true) or not (false) the status corresponding to the listener should be reset prior to invoking the listener (or more precisely: never get set) as described in the DDS specification. Setting it to false allows installing listeners without side-effects. The old functions have been re-written in terms of the extended ones. Signed-off-by: Erik Boasson <eb@ilities.com>
This provides the implementation of leaving the status flags set in the entity when invoking a listener if that listener was set with the "invoke_on_reset" flag clear (via the new, extended interface for setting listeners), and resetting it as required by the spec otherwise. Signed-off-by: Erik Boasson <eb@ilities.com>
This brings the behaviour of the status mask in line with the specification, previously masking an event (i.e., clearing its bit in the mask) would have two additional, impractical consequences: * It would prevent a listener from being invoked. If there is no need for a listener, don't set one. * It would force the corresponding status to 0 (not signalled), making it impossible to poll for events outside the status mask. E.g., with a waitset and a mask of DATA_AVAILABLE to wait for the arrival of data, it was impossible to observe any liveliness changed events on the same reader. Signed-off-by: Erik Boasson <eb@ilities.com>
This adds a test to verify that invoking a DATA_AVAILABLE listener configured not to auto-reset the status does indeed allow a waitset to trigger and that the waitset (generally, there is a short window in time during which the status can be observed) wakes up after the listener was invoked. It tests this both in the case of a listener that doesn't reset DATA_AVAILABLE internally, and in the case of a listener that does reset it by calling dds_take(). Signed-off-by: Erik Boasson <eb@ilities.com>
71bd09c to
757fc2a
Compare
This PR changes — "fixes" would be a nicer way of putting it, but there is always the possibility of mistakes ... — the way waitsets, listeners and status masks interact. Some of this met the spec but caused trouble nonetheless, some did not meet the spec but caused suprisingly little trouble.
dds_lset_..._argfunctions.Both referenced issues should be addressed by this PR.
In the process it also changes the implementation of the
DATA_ON_READERSevent because maintaining it in the subscriber in combination with the first point turned out to dramatically lower performance on an M1-based MBP (ddsperf -TOUin a throughput test dropping below 3MS/s is clearly unacceptable!). Now, for subscribers not attached to any waitset, it computes theDATA_ON_READERSstatus on demand from the subscriber's readers.DATA_ON_READERSis supposed to be raised on along withDATA_AVAILABLEon some reader (of the subscriber), and supposed to be reset by the first operation on some reader (of the subscriber) that resetsDATA_AVAILABLE. When it is attached to a waitset, this is what it does; when not attached to a waitset, it actually it returnsDATA_ON_READERSif there is some reader that hasDATA_AVAILABLEset.Either behaviour seems usable for applications, and the change in behaviour seems acceptable considering that
D_O_Ronly becomes really valuable for "group ordered" and "group coherent" data, which aren't supported yet anyway.