From e4360d25a0c776c2135a2577ffdfb47f6a1a0b47 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 10 Jan 2019 10:41:27 +0100 Subject: [PATCH 01/10] code cleanup: replacement of lots of function-like macros by inline functions, removal of unnecessary casts Signed-off-by: Erik Boasson --- .../ddsc/include/ddsc/dds_public_stream.h | 20 +- src/core/ddsc/src/dds__entity.h | 47 ++- src/core/ddsc/src/dds__guardcond.h | 2 + src/core/ddsc/src/dds__participant.h | 3 + src/core/ddsc/src/dds__reader.h | 6 +- src/core/ddsc/src/dds__topic.h | 4 +- src/core/ddsc/src/dds__writer.h | 3 +- src/core/ddsc/src/dds_builtin.c | 8 +- src/core/ddsc/src/dds_coherent.c | 4 +- src/core/ddsc/src/dds_domain.c | 2 +- src/core/ddsc/src/dds_entity.c | 16 +- src/core/ddsc/src/dds_guardcond.c | 32 +- src/core/ddsc/src/dds_instance.c | 70 ++--- src/core/ddsc/src/dds_listener.c | 52 ++-- src/core/ddsc/src/dds_participant.c | 4 +- src/core/ddsc/src/dds_publisher.c | 6 +- src/core/ddsc/src/dds_read.c | 100 +++---- src/core/ddsc/src/dds_readcond.c | 63 ++-- src/core/ddsc/src/dds_reader.c | 202 ++++++------- src/core/ddsc/src/dds_rhc.c | 131 +++++---- src/core/ddsc/src/dds_stream.c | 18 +- src/core/ddsc/src/dds_subscriber.c | 26 +- src/core/ddsc/src/dds_topic.c | 22 +- src/core/ddsc/src/dds_waitset.c | 37 +-- src/core/ddsc/src/dds_writer.c | 275 +++++++++--------- src/core/ddsi/CMakeLists.txt | 1 - src/core/ddsi/include/ddsi/ddsi_tran.h | 79 +++-- src/core/ddsi/include/ddsi/q_align.h | 18 -- src/core/ddsi/include/ddsi/q_bswap.h | 21 +- src/core/ddsi/include/ddsi/q_entity.h | 2 +- src/core/ddsi/src/ddsi_raweth.c | 19 +- src/core/ddsi/src/ddsi_tcp.c | 22 ++ src/core/ddsi/src/ddsi_tran.c | 80 ++--- src/core/ddsi/src/q_bswap_inlines.c | 3 + src/core/ddsi/src/q_init.c | 13 +- src/core/ddsi/src/q_plist.c | 1 - src/core/ddsi/src/q_radmin.c | 1 - src/core/ddsi/src/q_receive.c | 1 - src/core/ddsi/src/q_xmsg.c | 12 +- 39 files changed, 748 insertions(+), 678 deletions(-) delete mode 100644 src/core/ddsi/include/ddsi/q_align.h diff --git a/src/core/ddsc/include/ddsc/dds_public_stream.h b/src/core/ddsc/include/ddsc/dds_public_stream.h index ef125c8..fed0f7a 100644 --- a/src/core/ddsc/include/ddsc/dds_public_stream.h +++ b/src/core/ddsc/include/ddsc/dds_public_stream.h @@ -76,11 +76,11 @@ DDS_EXPORT double dds_stream_read_double (dds_stream_t * is); DDS_EXPORT char * dds_stream_read_string (dds_stream_t * is); DDS_EXPORT void dds_stream_read_buffer (dds_stream_t * is, uint8_t * buffer, uint32_t len); -#define dds_stream_read_char(s) ((char) dds_stream_read_uint8 (s)) -#define dds_stream_read_int8(s) ((int8_t) dds_stream_read_uint8 (s)) -#define dds_stream_read_int16(s) ((int16_t) dds_stream_read_uint16 (s)) -#define dds_stream_read_int32(s) ((int32_t) dds_stream_read_uint32 (s)) -#define dds_stream_read_int64(s) ((int64_t) dds_stream_read_uint64 (s)) +inline char dds_stream_read_char (dds_stream_t *is) { return (char) dds_stream_read_uint8 (is); } +inline int8_t dds_stream_read_int8 (dds_stream_t *is) { return (int8_t) dds_stream_read_uint8 (is); } +inline int16_t dds_stream_read_int16 (dds_stream_t *is) { return (int16_t) dds_stream_read_uint16 (is); } +inline int32_t dds_stream_read_int32 (dds_stream_t *is) { return (int32_t) dds_stream_read_uint32 (is); } +inline int64_t dds_stream_read_int64 (dds_stream_t *is) { return (int64_t) dds_stream_read_uint64 (is); } DDS_EXPORT void dds_stream_write_bool (dds_stream_t * os, bool val); DDS_EXPORT void dds_stream_write_uint8 (dds_stream_t * os, uint8_t val); @@ -94,11 +94,11 @@ DDS_EXPORT void dds_stream_write_buffer (dds_stream_t * os, uint32_t len, const DDS_EXPORT void *dds_stream_address (dds_stream_t * s); DDS_EXPORT void *dds_stream_alignto (dds_stream_t * s, uint32_t a); -#define dds_stream_write_char(s,v) (dds_stream_write_uint8 ((s), (uint8_t)(v))) -#define dds_stream_write_int8(s,v) (dds_stream_write_uint8 ((s), (uint8_t)(v))) -#define dds_stream_write_int16(s,v) (dds_stream_write_uint16 ((s), (uint16_t)(v))) -#define dds_stream_write_int32(s,v) (dds_stream_write_uint32 ((s), (uint32_t)(v))) -#define dds_stream_write_int64(s,v) (dds_stream_write_uint64 ((s), (uint64_t)(v))) +inline void dds_stream_write_char (dds_stream_t * os, char val) { dds_stream_write_uint8 (os, (uint8_t) val); } +inline void dds_stream_write_int8 (dds_stream_t * os, int8_t val) { dds_stream_write_uint8 (os, (uint8_t) val); } +inline void dds_stream_write_int16 (dds_stream_t * os, int16_t val) { dds_stream_write_uint16 (os, (uint16_t) val); } +inline void dds_stream_write_int32 (dds_stream_t * os, int32_t val) { dds_stream_write_uint32 (os, (uint32_t) val); } +inline void dds_stream_write_int64 (dds_stream_t * os, int64_t val) { dds_stream_write_uint64 (os, (uint64_t) val); } #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 872278f..62285c9 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -45,11 +45,48 @@ dds_entity_listener_propagation( _In_opt_ void *metrics, _In_ bool propagate); -#define dds_entity_is_enabled(e, k) (((dds_entity*)e)->m_flags & DDS_ENTITY_ENABLED) +#define DEFINE_ENTITY_LOCK_UNLOCK(qualifier_, type_, kind_) \ + qualifier_ dds__retcode_t type_##_lock (dds_entity_t hdl, type_ **x) \ + { \ + dds__retcode_t rc; \ + dds_entity *e; \ + if ((rc = dds_entity_lock (hdl, kind_, &e)) != DDS_RETCODE_OK) \ + return rc; \ + *x = (type_ *) e; \ + return DDS_RETCODE_OK; \ + } \ + \ + qualifier_ void type_##_unlock (type_ *x) \ + { \ + dds_entity_unlock (&x->m_entity); \ + } +#define DECL_ENTITY_LOCK_UNLOCK(qualifier_, type_) \ + qualifier_ dds__retcode_t type_##_lock (dds_entity_t hdl, type_ **x); \ + qualifier_ void type_##_unlock (type_ *x); -#define dds_entity_status_set(e, t) (((dds_entity*)e)->m_trigger |= (((dds_entity*)e)->m_status_enable & t)) -#define dds_entity_status_reset(e,t) (((dds_entity*)e)->m_trigger &= ~t) -#define dds_entity_status_match(e,t) (((dds_entity*)e)->m_trigger & t) +inline bool dds_entity_is_enabled (const dds_entity *e) { + return (e->m_flags & DDS_ENTITY_ENABLED) != 0; +} + +inline void dds_entity_status_set (dds_entity *e, uint32_t t) { + e->m_trigger |= e->m_status_enable & t; +} + +inline void dds_entity_status_reset (dds_entity *e, uint32_t t) { + e->m_trigger &= ~t; +} + +inline bool dds_entity_status_match (const dds_entity *e, uint32_t t) { + return (e->m_trigger & t) != 0; +} + +inline dds_entity_kind_t dds_entity_kind (const dds_entity *e) { + return (dds_entity_kind_t) (e->m_hdl & DDS_ENTITY_KIND_MASK); +} + +inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl) { + return (hdl > 0) ? (dds_entity_kind_t) (hdl & DDS_ENTITY_KIND_MASK) : DDS_KIND_DONTCARE; +} /* The mutex needs to be unlocked when calling this because the entity can be called * within the signal callback from other contexts. That shouldn't deadlock. */ @@ -74,8 +111,6 @@ void dds_entity_unlock( _Inout_ dds_entity *e); -#define dds_entity_kind(hdl) ((hdl > 0) ? (hdl & DDS_ENTITY_KIND_MASK) : 0) - _Check_return_ dds__retcode_t dds_entity_observer_register_nl( _In_ dds_entity* observed, diff --git a/src/core/ddsc/src/dds__guardcond.h b/src/core/ddsc/src/dds__guardcond.h index 6497f70..5f1b030 100644 --- a/src/core/ddsc/src/dds__guardcond.h +++ b/src/core/ddsc/src/dds__guardcond.h @@ -18,4 +18,6 @@ _Must_inspect_result_ dds_guardcond* dds_create_guardcond( _In_ dds_participant *pp); +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_guardcond, DDS_KIND_COND_GUARD) + #endif diff --git a/src/core/ddsc/src/dds__participant.h b/src/core/ddsc/src/dds__participant.h index 0299a7a..ef52d86 100644 --- a/src/core/ddsc/src/dds__participant.h +++ b/src/core/ddsc/src/dds__participant.h @@ -12,10 +12,13 @@ #ifndef _DDS_PPANT_H_ #define _DDS_PPANT_H_ +#include "dds__entity.h" + #if defined (__cplusplus) extern "C" { #endif +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_participant, DDS_KIND_PARTICIPANT) #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__reader.h b/src/core/ddsc/src/dds__reader.h index 85ce0a0..48b1168 100644 --- a/src/core/ddsc/src/dds__reader.h +++ b/src/core/ddsc/src/dds__reader.h @@ -13,6 +13,7 @@ #define _DDS_READER_H_ #include "dds__types.h" +#include "dds__entity.h" #if defined (__cplusplus) extern "C" { @@ -20,7 +21,7 @@ extern "C" { struct status_cb_data; -void dds_reader_status_cb (void * entity, const struct status_cb_data * data); +void dds_reader_status_cb (void *entity, const struct status_cb_data * data); /* dds_reader_lock_samples: Returns number of samples in read cache and locks the @@ -40,8 +41,7 @@ struct nn_rsample_info; struct nn_rdata; DDS_EXPORT void dds_reader_ddsi2direct (dds_entity_t entity, void (*cb) (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, void *arg), void *cbarg); -#define dds_reader_lock(hdl, obj) dds_entity_lock(hdl, DDS_KIND_READER, (dds_entity**)obj) -#define dds_reader_unlock(obj) dds_entity_unlock((dds_entity*)obj); +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_reader, DDS_KIND_READER) #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__topic.h b/src/core/ddsc/src/dds__topic.h index 32bd8ca..cb81561 100644 --- a/src/core/ddsc/src/dds__topic.h +++ b/src/core/ddsc/src/dds__topic.h @@ -13,13 +13,13 @@ #define _DDS_TOPIC_H_ #include "dds__types.h" +#include "dds__entity.h" #if defined (__cplusplus) extern "C" { #endif -#define dds_topic_lock(hdl, obj) dds_entity_lock(hdl, DDS_KIND_TOPIC, (dds_entity**)obj) -#define dds_topic_unlock(obj) dds_entity_unlock((dds_entity*)obj); +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_topic, DDS_KIND_TOPIC) extern struct ddsi_sertopic * dds_topic_lookup (dds_domain * domain, const char * name); extern void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic * st); diff --git a/src/core/ddsc/src/dds__writer.h b/src/core/ddsc/src/dds__writer.h index 25b21e8..c2c9336 100644 --- a/src/core/ddsc/src/dds__writer.h +++ b/src/core/ddsc/src/dds__writer.h @@ -18,8 +18,7 @@ extern "C" { #endif -#define dds_writer_lock(hdl, obj) dds_entity_lock(hdl, DDS_KIND_WRITER, (dds_entity**)obj) -#define dds_writer_unlock(obj) dds_entity_unlock((dds_entity*)obj); +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_writer, DDS_KIND_WRITER) #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index bff293b..d5ad2f1 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -148,19 +148,17 @@ dds_entity_t dds__get_builtin_subscriber (dds_entity_t e) dds_return_t ret; dds_entity_t pp; dds_participant *p; - dds_entity *part_entity; if ((pp = dds_get_participant (e)) <= 0) return pp; - if ((ret = dds_entity_lock (pp, DDS_KIND_PARTICIPANT, &part_entity)) < 0) + if ((ret = dds_participant_lock (pp, &p)) != DDS_RETCODE_OK) return ret; - p = (dds_participant *) part_entity; if (p->m_builtin_subscriber <= 0) { - p->m_builtin_subscriber = dds__create_builtin_subscriber (part_entity); + p->m_builtin_subscriber = dds__create_builtin_subscriber (&p->m_entity); } sub = p->m_builtin_subscriber; - dds_entity_unlock(part_entity); + dds_participant_unlock(p); return sub; } diff --git a/src/core/ddsc/src/dds_coherent.c b/src/core/ddsc/src/dds_coherent.c index bf6832d..9556776 100644 --- a/src/core/ddsc/src/dds_coherent.c +++ b/src/core/ddsc/src/dds_coherent.c @@ -27,7 +27,7 @@ dds_begin_coherent( { dds_return_t ret; - switch(dds_entity_kind(entity)) { + switch(dds_entity_kind_from_handle(entity)) { case DDS_KIND_READER: case DDS_KIND_WRITER: /* Invoking on a writer/reader behaves as if invoked on @@ -58,7 +58,7 @@ dds_end_coherent( { dds_return_t ret; - switch(dds_entity_kind(entity)) { + switch(dds_entity_kind_from_handle(entity)) { case DDS_KIND_READER: case DDS_KIND_WRITER: /* Invoking on a writer/reader behaves as if invoked on diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index 4c10db5..08613b8 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -27,7 +27,7 @@ const ut_avlTreedef_t dds_domaintree_def = UT_AVL_TREEDEF_INITIALIZER dds_domain * dds_domain_find_locked (dds_domainid_t id) { - return (dds_domain*) ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &id); + return ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &id); } dds_domain * dds_domain_create (dds_domainid_t id) diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index a18976d..7e679f7 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -25,6 +25,12 @@ #endif +extern inline bool dds_entity_is_enabled (const dds_entity *e); +extern inline void dds_entity_status_set (dds_entity *e, uint32_t t); +extern inline void dds_entity_status_reset (dds_entity *e, uint32_t t); +extern inline bool dds_entity_status_match (const dds_entity *e, uint32_t t); +extern inline dds_entity_kind_t dds_entity_kind (const dds_entity *e); +extern inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl); static void dds_entity_observers_delete( @@ -83,7 +89,7 @@ dds_entity_listener_propagation( if (e) { rc = dds_entity_lock(e->m_hdl, DDS_KIND_DONTCARE, &dummy); if (rc == DDS_RETCODE_OK) { - dds_listener_t *l = (dds_listener_t *)(&e->m_listener); + dds_listener_t *l = &e->m_listener; assert(e == dummy); @@ -360,12 +366,12 @@ dds_delete_impl( * To circumvent the problem. We ignore topics in the first loop. */ child = e->m_children; - while ((child != NULL) && (dds_entity_kind(child->m_hdl) == DDS_KIND_TOPIC)) { + while ((child != NULL) && (dds_entity_kind_from_handle(child->m_hdl) == DDS_KIND_TOPIC)) { child = child->m_next; } while ((child != NULL) && (ret == DDS_RETCODE_OK)) { next = child->m_next; - while ((next != NULL) && (dds_entity_kind(next->m_hdl) == DDS_KIND_TOPIC)) { + while ((next != NULL) && (dds_entity_kind_from_handle(next->m_hdl) == DDS_KIND_TOPIC)) { next = next->m_next; } /* This will probably delete the child entry from @@ -377,7 +383,7 @@ dds_delete_impl( child = e->m_children; while ((child != NULL) && (ret == DDS_RETCODE_OK)) { next = child->m_next; - assert(dds_entity_kind(child->m_hdl) == DDS_KIND_TOPIC); + assert(dds_entity_kind_from_handle(child->m_hdl) == DDS_KIND_TOPIC); /* This will probably delete the child entry from * the current childrens list */ ret = dds_delete(child->m_hdl); @@ -1282,7 +1288,7 @@ dds_get_topic( if (rc == DDS_RETCODE_OK) { hdl = wr->m_topic->m_entity.m_hdl; dds_writer_unlock(wr); - } else if (dds_entity_kind(entity) == DDS_KIND_COND_READ || dds_entity_kind(entity) == DDS_KIND_COND_QUERY) { + } else if (dds_entity_kind_from_handle(entity) == DDS_KIND_COND_READ || dds_entity_kind_from_handle(entity) == DDS_KIND_COND_QUERY) { hdl = dds_get_topic(dds_get_parent(entity)); rc = DDS_RETCODE_OK; } diff --git a/src/core/ddsc/src/dds_guardcond.c b/src/core/ddsc/src/dds_guardcond.c index 3262aa6..a69f650 100644 --- a/src/core/ddsc/src/dds_guardcond.c +++ b/src/core/ddsc/src/dds_guardcond.c @@ -13,18 +13,20 @@ #include #include "dds__reader.h" #include "dds__guardcond.h" -#include "dds__entity.h" +#include "dds__participant.h" #include "dds__err.h" #include "ddsi/q_ephash.h" #include "ddsi/q_entity.h" #include "ddsi/q_thread.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_guardcond) + _Must_inspect_result_ dds_guardcond* dds_create_guardcond( _In_ dds_participant *pp) { dds_guardcond * gcond = dds_alloc(sizeof(*gcond)); - gcond->m_entity.m_hdl = dds_entity_init(&gcond->m_entity, (dds_entity*)pp, DDS_KIND_COND_GUARD, NULL, NULL, 0); + gcond->m_entity.m_hdl = dds_entity_init(&gcond->m_entity, &pp->m_entity, DDS_KIND_COND_GUARD, NULL, NULL, 0); return gcond; } @@ -34,15 +36,15 @@ dds_create_guardcondition( _In_ dds_entity_t participant) { dds_entity_t hdl; - dds_entity * pp; + dds_participant * pp; dds__retcode_t rc; - rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &pp); + rc = dds_participant_lock(participant, &pp); if (rc == DDS_RETCODE_OK) { - dds_guardcond *cond = dds_create_guardcond((dds_participant *)pp); + dds_guardcond *cond = dds_create_guardcond(pp); assert(cond); hdl = cond->m_entity.m_hdl; - dds_entity_unlock(pp); + dds_participant_unlock(pp); } else { DDS_ERROR("Error occurred on locking reader\n"); hdl = DDS_ERRNO(rc); @@ -64,10 +66,10 @@ dds_set_guardcondition( rc = dds_entity_lock(condition, DDS_KIND_COND_GUARD, (dds_entity**)&gcond); if (rc == DDS_RETCODE_OK) { if (triggered) { - dds_entity_status_set(gcond, DDS_WAITSET_TRIGGER_STATUS); + dds_entity_status_set(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); dds_entity_status_signal(&gcond->m_entity); } else { - dds_entity_status_reset(gcond, DDS_WAITSET_TRIGGER_STATUS); + dds_entity_status_reset(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); } dds_entity_unlock(&gcond->m_entity); ret = DDS_RETCODE_OK; @@ -91,10 +93,10 @@ dds_read_guardcondition( if (triggered != NULL) { *triggered = false; - rc = dds_entity_lock(condition, DDS_KIND_COND_GUARD, (dds_entity**)&gcond); + rc = dds_guardcond_lock(condition, &gcond); if (rc == DDS_RETCODE_OK) { - *triggered = dds_entity_status_match(gcond, DDS_WAITSET_TRIGGER_STATUS); - dds_entity_unlock((dds_entity*)gcond); + *triggered = dds_entity_status_match(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + dds_guardcond_unlock(gcond); ret = DDS_RETCODE_OK; } else { DDS_ERROR("Argument condition is not valid\n"); @@ -120,11 +122,11 @@ dds_take_guardcondition( if (triggered != NULL) { *triggered = false; - rc = dds_entity_lock(condition, DDS_KIND_COND_GUARD, (dds_entity**)&gcond); + rc = dds_guardcond_lock(condition, &gcond); if (rc == DDS_RETCODE_OK) { - *triggered = dds_entity_status_match(gcond, DDS_WAITSET_TRIGGER_STATUS); - dds_entity_status_reset(gcond, DDS_WAITSET_TRIGGER_STATUS); - dds_entity_unlock((dds_entity*)gcond); + *triggered = dds_entity_status_match(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + dds_entity_status_reset(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + dds_guardcond_unlock (gcond); ret = DDS_RETCODE_OK; } else { DDS_ERROR("Argument condition is not valid\n"); diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index ae2e05d..7912217 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -81,21 +81,22 @@ dds_instance_remove( } } -static const dds_topic* -dds_instance_info( - _In_ dds_entity *e) +static const dds_topic *dds_instance_info (dds_entity *e) { - const dds_topic *topic = NULL; - - assert (e); - assert ((dds_entity_kind(e->m_hdl) == DDS_KIND_READER) || (dds_entity_kind(e->m_hdl) == DDS_KIND_WRITER)); - - if (dds_entity_kind(e->m_hdl) == DDS_KIND_READER) { - topic = ((dds_reader*)e)->m_topic; - } else { - topic = ((dds_writer*)e)->m_topic; - } - return topic; + const dds_topic *topic; + switch (dds_entity_kind (e)) + { + case DDS_KIND_READER: + topic = ((dds_reader*) e)->m_topic; + break; + case DDS_KIND_WRITER: + topic = ((dds_writer*) e)->m_topic; + break; + default: + assert (0); + topic = NULL; + } + return topic; } static const dds_topic * dds_instance_info_by_hdl (dds_entity_t e) @@ -127,7 +128,7 @@ dds_register_instance( struct thread_state1 * const thr = lookup_thread_state(); const bool asleep = !vtime_awake_p(thr->vtime); struct ddsi_tkmap_instance * inst; - dds_entity *wr; + dds_writer *wr; dds_return_t ret; dds__retcode_t rc; @@ -141,7 +142,7 @@ dds_register_instance( ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } - rc = dds_entity_lock(writer, DDS_KIND_WRITER, &wr); + rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); @@ -150,7 +151,7 @@ dds_register_instance( if (asleep) { thread_state_awake(thr); } - inst = dds_instance_find (((dds_writer*) wr)->m_topic, data, true); + inst = dds_instance_find (wr->m_topic, data, true); if(inst != NULL){ *handle = inst->m_iid; ret = DDS_RETCODE_OK; @@ -161,7 +162,7 @@ dds_register_instance( if (asleep) { thread_state_asleep(thr); } - dds_entity_unlock(wr); + dds_writer_unlock(wr); err: return ret; } @@ -197,8 +198,7 @@ dds_unregister_instance_ts( dds__retcode_t rc; bool autodispose = true; dds_write_action action = DDS_WR_ACTION_UNREGISTER; - void * sample = (void*) data; - dds_entity *wr; + dds_writer *wr; if (data == NULL){ DDS_ERROR("Argument data is NULL\n"); @@ -210,28 +210,28 @@ dds_unregister_instance_ts( ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } - rc = dds_entity_lock(writer, DDS_KIND_WRITER, &wr); + rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); goto err; } - if (wr->m_qos) { - dds_qget_writer_data_lifecycle (wr->m_qos, &autodispose); + if (wr->m_entity.m_qos) { + dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); } if (asleep) { thread_state_awake(thr); } if (autodispose) { - dds_instance_remove (((dds_writer*) wr)->m_topic, data, DDS_HANDLE_NIL); + dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); action |= DDS_WR_DISPOSE_BIT; } - ret = dds_write_impl ((dds_writer*)wr, sample, timestamp, action); + ret = dds_write_impl (wr, data, timestamp, action); if (asleep) { thread_state_asleep(thr); } - dds_entity_unlock(wr); + dds_writer_unlock(wr); err: return ret; } @@ -249,21 +249,21 @@ dds_unregister_instance_ih_ts( dds__retcode_t rc; bool autodispose = true; dds_write_action action = DDS_WR_ACTION_UNREGISTER; - dds_entity *wr; + dds_writer *wr; struct ddsi_tkmap_instance *tk; - rc = dds_entity_lock(writer, DDS_KIND_WRITER, &wr); + rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); goto err; } - if (wr->m_qos) { - dds_qget_writer_data_lifecycle (wr->m_qos, &autodispose); + if (wr->m_entity.m_qos) { + dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); } if (autodispose) { - dds_instance_remove (((dds_writer*) wr)->m_topic, NULL, handle); + dds_instance_remove (wr->m_topic, NULL, handle); action |= DDS_WR_DISPOSE_BIT; } @@ -272,11 +272,11 @@ dds_unregister_instance_ih_ts( } tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); if (tk) { - struct ddsi_sertopic *tp = ((dds_writer*) wr)->m_topic->m_stopic; + struct ddsi_sertopic *tp = wr->m_topic->m_stopic; void *sample = ddsi_sertopic_alloc_sample (tp); ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL); ddsi_tkmap_instance_unref (tk); - ret = dds_write_impl ((dds_writer*)wr, sample, timestamp, action); + ret = dds_write_impl (wr, sample, timestamp, action); ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); } else { DDS_ERROR("No instance related with the provided handle is found\n"); @@ -285,7 +285,7 @@ dds_unregister_instance_ih_ts( if (asleep) { thread_state_asleep(thr); } - dds_entity_unlock(wr); + dds_writer_unlock(wr); err: return ret; } @@ -392,7 +392,7 @@ dds_dispose_ih_ts( thread_state_awake(thr); } if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) != NULL) { - struct ddsi_sertopic *tp = ((dds_writer*) wr)->m_topic->m_stopic; + struct ddsi_sertopic *tp = wr->m_topic->m_stopic; void *sample = ddsi_sertopic_alloc_sample (tp); ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL); ddsi_tkmap_instance_unref (tk); diff --git a/src/core/ddsc/src/dds_listener.c b/src/core/ddsc/src/dds_listener.c index dcc26a6..f4e5e51 100644 --- a/src/core/ddsc/src/dds_listener.c +++ b/src/core/ddsc/src/dds_listener.c @@ -180,7 +180,7 @@ void dds_lset_data_available (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_data_available_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_data_available = callback; + listener->on_data_available = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -190,7 +190,7 @@ void dds_lset_data_on_readers (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_data_on_readers_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_data_on_readers = callback; + listener->on_data_on_readers = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -200,7 +200,7 @@ void dds_lset_inconsistent_topic (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_inconsistent_topic_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_inconsistent_topic = callback; + listener->on_inconsistent_topic = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -210,7 +210,7 @@ void dds_lset_liveliness_changed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_liveliness_changed_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_liveliness_changed = callback; + listener->on_liveliness_changed = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -220,7 +220,7 @@ void dds_lset_liveliness_lost (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_liveliness_lost_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_liveliness_lost = callback; + listener->on_liveliness_lost = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -230,7 +230,7 @@ void dds_lset_offered_deadline_missed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_offered_deadline_missed_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_offered_deadline_missed = callback; + listener->on_offered_deadline_missed = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -240,7 +240,7 @@ void dds_lset_offered_incompatible_qos (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_offered_incompatible_qos_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_offered_incompatible_qos = callback; + listener->on_offered_incompatible_qos = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -250,7 +250,7 @@ void dds_lset_publication_matched (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_publication_matched_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_publication_matched = callback; + listener->on_publication_matched = callback; } else { DDS_ERROR("Argument listener is NULL"); } @@ -260,7 +260,7 @@ void dds_lset_requested_deadline_missed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_requested_deadline_missed_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_requested_deadline_missed = callback; + listener->on_requested_deadline_missed = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -270,7 +270,7 @@ void dds_lset_requested_incompatible_qos (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_requested_incompatible_qos_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_requested_incompatible_qos = callback; + listener->on_requested_incompatible_qos = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -280,7 +280,7 @@ void dds_lset_sample_lost (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_sample_lost_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_sample_lost = callback; + listener->on_sample_lost = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -290,7 +290,7 @@ void dds_lset_sample_rejected (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_sample_rejected_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_sample_rejected = callback; + listener->on_sample_rejected = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -300,7 +300,7 @@ void dds_lset_subscription_matched (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_subscription_matched_fn callback) { if (listener) { - ((c_listener_t*)listener)->on_subscription_matched = callback; + listener->on_subscription_matched = callback; } else { DDS_ERROR("Argument listener is NULL\n"); } @@ -321,7 +321,7 @@ dds_lget_data_available (_In_ const dds_listener_t * __restrict listener, _Outpt DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_data_available; + *callback = listener->on_data_available; } void @@ -335,7 +335,7 @@ dds_lget_data_on_readers (_In_ const dds_listener_t * __restrict listener, _Outp DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_data_on_readers; + *callback = listener->on_data_on_readers; } void dds_lget_inconsistent_topic (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_inconsistent_topic_fn *callback) @@ -348,7 +348,7 @@ void dds_lget_inconsistent_topic (_In_ const dds_listener_t * __restrict listene DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_inconsistent_topic; + *callback = listener->on_inconsistent_topic; } void @@ -362,7 +362,7 @@ dds_lget_liveliness_changed (_In_ const dds_listener_t * __restrict listener, _O DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_liveliness_changed; + *callback = listener->on_liveliness_changed; } void @@ -376,7 +376,7 @@ dds_lget_liveliness_lost (_In_ const dds_listener_t * __restrict listener, _Outp DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_liveliness_lost; + *callback = listener->on_liveliness_lost; } void @@ -390,7 +390,7 @@ dds_lget_offered_deadline_missed (_In_ const dds_listener_t * __restrict listene DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_offered_deadline_missed; + *callback = listener->on_offered_deadline_missed; } void @@ -404,7 +404,7 @@ dds_lget_offered_incompatible_qos (_In_ const dds_listener_t * __restrict listen DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_offered_incompatible_qos; + *callback = listener->on_offered_incompatible_qos; } void @@ -418,7 +418,7 @@ dds_lget_publication_matched (_In_ const dds_listener_t * __restrict listener, _ DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_publication_matched; + *callback = listener->on_publication_matched; } void @@ -432,7 +432,7 @@ dds_lget_requested_deadline_missed (_In_ const dds_listener_t * __restrict liste DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_requested_deadline_missed; + *callback = listener->on_requested_deadline_missed; } void @@ -446,7 +446,7 @@ dds_lget_requested_incompatible_qos (_In_ const dds_listener_t * __restrict list DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_requested_incompatible_qos; + *callback = listener->on_requested_incompatible_qos; } void @@ -460,7 +460,7 @@ dds_lget_sample_lost (_In_ const dds_listener_t *__restrict listener, _Outptr_re DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_sample_lost; + *callback = listener->on_sample_lost; } void @@ -474,7 +474,7 @@ dds_lget_sample_rejected (_In_ const dds_listener_t *__restrict listener, _Outp DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_sample_rejected; + *callback = listener->on_sample_rejected; } void @@ -488,5 +488,5 @@ dds_lget_subscription_matched (_In_ const dds_listener_t * __restrict listener, DDS_ERROR("Argument listener is NULL\n"); return ; } - *callback = ((c_listener_t*)listener)->on_subscription_matched; + *callback = listener->on_subscription_matched; } diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 5daf5a5..5a56ea5 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -20,6 +20,8 @@ #include "dds__err.h" #include "dds__builtin.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_participant) + #define DDS_PARTICIPANT_STATUS_MASK 0u /* List of created participants */ @@ -51,7 +53,7 @@ dds_participant_delete( assert(e); assert(thr); - assert(dds_entity_kind(e->m_hdl) == DDS_KIND_PARTICIPANT); + assert(dds_entity_kind_from_handle(e->m_hdl) == DDS_KIND_PARTICIPANT); if (asleep) { thread_state_awake(thr); diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 807f5b7..33d10f9 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -149,7 +149,7 @@ dds_suspend( { dds_return_t ret; - if(dds_entity_kind(publisher) != DDS_KIND_PUBLISHER) { + if(dds_entity_kind_from_handle(publisher) != DDS_KIND_PUBLISHER) { DDS_ERROR("Provided entity is not a publisher kind\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; @@ -169,7 +169,7 @@ dds_resume( { dds_return_t ret = DDS_RETCODE_OK; - if(dds_entity_kind(publisher) != DDS_KIND_PUBLISHER) { + if(dds_entity_kind_from_handle(publisher) != DDS_KIND_PUBLISHER) { DDS_ERROR("Provided entity is not a publisher kind\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; @@ -194,7 +194,7 @@ dds_wait_for_acks( /* TODO: CHAM-125 Currently unsupported. */ OS_UNUSED_ARG(timeout); - switch(dds_entity_kind(publisher_or_writer)) { + switch(dds_entity_kind_from_handle(publisher_or_writer)) { case DDS_KIND_WRITER: DDS_ERROR("Wait for acknowledgments on a writer is not being supported yet\n"); ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index ef7f16f..197aa9b 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -21,59 +21,53 @@ #include "ddsi/q_entity.h" #include "ddsi/ddsi_sertopic.h" - -static _Check_return_ dds__retcode_t -dds_read_lock( - _In_ dds_entity_t hdl, - _Out_ dds_reader **reader, - _Out_ dds_readcond **condition, - _In_ bool only_reader) +static dds__retcode_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_readcond **condition, bool only_reader) { - dds__retcode_t rc = hdl; - assert(reader); - assert(condition); - *reader = NULL; - *condition = NULL; - - rc = dds_entity_lock(hdl, DDS_KIND_READER, (dds_entity**)reader); - if (rc == DDS_RETCODE_ILLEGAL_OPERATION) { - if (!only_reader) { - if ((dds_entity_kind(hdl) == DDS_KIND_COND_READ ) || (dds_entity_kind(hdl) == DDS_KIND_COND_QUERY) ){ - rc = dds_entity_lock(hdl, DDS_KIND_DONTCARE, (dds_entity**)condition); - if (rc == DDS_RETCODE_OK) { - dds_entity *parent = ((dds_entity*)*condition)->m_parent; - assert(parent); - rc = dds_entity_lock(parent->m_hdl, DDS_KIND_READER, (dds_entity**)reader); - if (rc != DDS_RETCODE_OK) { - dds_entity_unlock((dds_entity*)*condition); - DDS_ERROR("Failed to lock condition reader\n"); - } - } else { - DDS_ERROR("Failed to lock condition\n"); - } - } else { - DDS_ERROR("Given entity is not a reader nor a condition\n"); - } - } else { - DDS_ERROR("Given entity is not a reader\n"); - } - } else if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Failed to lock reader\n"); - } + dds__retcode_t rc; + dds_entity *entity, *parent_entity; + if ((rc = dds_entity_lock (hdl, DDS_KIND_DONTCARE, &entity)) != DDS_RETCODE_OK) + { return rc; + } + else if (dds_entity_kind (entity) == DDS_KIND_READER) + { + *reader = (dds_reader *) entity; + *condition = NULL; + return DDS_RETCODE_OK; + } + else if (only_reader) + { + dds_entity_unlock (entity); + DDS_ERROR ("Given entity is not a reader\n"); + return DDS_RETCODE_ILLEGAL_OPERATION; + } + else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) + { + dds_entity_unlock (entity); + DDS_ERROR ("Given entity is a reader nor a condition\n"); + return DDS_RETCODE_ILLEGAL_OPERATION; + } + else if ((rc = dds_entity_lock (entity->m_parent->m_hdl, DDS_KIND_READER, &parent_entity)) != DDS_RETCODE_OK) + { + dds_entity_unlock (entity); + DDS_ERROR ("Failed to lock condition's reader\n"); + return rc; + } + else + { + *reader = (dds_reader *) parent_entity; + *condition = (dds_readcond *) entity; + return DDS_RETCODE_OK; + } } -static void -dds_read_unlock( - _In_ dds_reader *reader, - _In_ dds_readcond *condition) +static void dds_read_unlock (dds_reader *reader, dds_readcond *condition) { - assert(reader); - dds_entity_unlock((dds_entity*)reader); - if (condition) { - dds_entity_unlock((dds_entity*)condition); - } + dds_entity_unlock (&reader->m_entity); + if (condition) + dds_entity_unlock (&condition->m_entity); } + /* dds_read_impl: Core read/take function. Usually maxs is size of buf and si into which samples/status are written, when set to zero is special case @@ -172,10 +166,10 @@ dds_read_impl( ret = (dds_return_t)dds_rhc_read(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); } /* read/take resets data available status */ - dds_entity_status_reset(rd, DDS_DATA_AVAILABLE_STATUS); + dds_entity_status_reset(&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind(((dds_entity*)rd)->m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) { - dds_entity_status_reset(((dds_entity*)rd)->m_parent, DDS_DATA_ON_READERS_STATUS); + if (dds_entity_kind_from_handle(rd->m_entity.m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) { + dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } dds_read_unlock(rd, cond); @@ -227,13 +221,13 @@ dds_readcdr_impl( ); /* read/take resets data available status */ - dds_entity_status_reset(rd, DDS_DATA_AVAILABLE_STATUS); + dds_entity_status_reset(&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind(((dds_entity*)rd)->m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) + if (dds_entity_kind_from_handle(rd->m_entity.m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) { - dds_entity_status_reset(((dds_entity*)rd)->m_parent, DDS_DATA_ON_READERS_STATUS); + dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } dds_read_unlock(rd, cond); } else { diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index f555a14..1ec86cc 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -41,7 +41,7 @@ dds_create_readcond( cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE; cond->m_view_states = mask & DDS_ANY_VIEW_STATE; cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE; - cond->m_rd_guid = ((dds_entity*)rd)->m_guid; + cond->m_rd_guid = rd->m_entity.m_guid; dds_rhc_add_readcondition (cond); return cond; } @@ -70,17 +70,13 @@ dds_create_readcondition( return hdl; } -_Pre_satisfies_(((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \ - ((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY) ) -dds_entity_t -dds_get_datareader( - _In_ dds_entity_t condition) +dds_entity_t dds_get_datareader (dds_entity_t condition) { dds_entity_t hdl; - if (dds_entity_kind(condition) == DDS_KIND_COND_READ) { + if (dds_entity_kind_from_handle(condition) == DDS_KIND_COND_READ) { hdl = dds_get_parent(condition); - } else if (dds_entity_kind(condition) == DDS_KIND_COND_QUERY) { + } else if (dds_entity_kind_from_handle(condition) == DDS_KIND_COND_QUERY) { hdl = dds_get_parent(condition); } else { DDS_ERROR("Argument condition is not valid\n"); @@ -90,39 +86,26 @@ dds_get_datareader( return hdl; } - -_Pre_satisfies_(((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \ - ((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY) ) -_Check_return_ dds_return_t -dds_get_mask( - _In_ dds_entity_t condition, - _Out_ uint32_t *mask) +dds_return_t dds_get_mask (dds_entity_t condition, uint32_t *mask) { - dds_return_t ret; - dds_readcond *cond; - dds__retcode_t rc; + dds_entity *entity; + dds__retcode_t rc; - if (mask != NULL) { - *mask = 0; - if ((dds_entity_kind(condition) == DDS_KIND_COND_READ ) || - (dds_entity_kind(condition) == DDS_KIND_COND_QUERY) ){ - rc = dds_entity_lock(condition, DDS_KIND_DONTCARE, (dds_entity**)&cond); - if (rc == DDS_RETCODE_OK) { - *mask = (cond->m_sample_states | cond->m_view_states | cond->m_instance_states); - dds_entity_unlock((dds_entity*)cond); - ret = DDS_RETCODE_OK; - } else{ - DDS_ERROR("Error occurred on locking condition\n"); - ret = DDS_ERRNO(rc); - } - } else { - DDS_ERROR("Argument condition is not valid\n"); - ret = DDS_ERRNO(dds_valid_hdl(condition, DDS_KIND_COND_READ)); - } - } else { - DDS_ERROR("Argument mask is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } + if (mask == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); - return ret; + if ((rc = dds_entity_lock (condition, DDS_KIND_DONTCARE, &entity)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) + { + dds_entity_unlock (entity); + return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_READ)); + } + else + { + dds_readcond *cond = (dds_readcond *) entity; + *mask = (cond->m_sample_states | cond->m_view_states | cond->m_instance_states); + dds_entity_unlock (entity); + return DDS_RETCODE_OK; + } } diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 87c6792..1526142 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -19,6 +19,7 @@ #include "dds__init.h" #include "dds__rhc.h" #include "dds__err.h" +#include "dds__topic.h" #include "ddsi/q_entity.h" #include "ddsi/q_thread.h" #include "dds__builtin.h" @@ -27,6 +28,7 @@ #include "os/os.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_reader) #define DDS_READER_STATUS_MASK \ DDS_SAMPLE_REJECTED_STATUS |\ @@ -162,9 +164,10 @@ dds_reader_status_validate( void dds_reader_status_cb( - void *entity, + void *ventity, const status_cb_data_t *data) { + struct dds_entity * const entity = ventity; dds_reader *rd; dds__retcode_t rc; void *metrics = NULL; @@ -173,14 +176,14 @@ dds_reader_status_cb( if (data == NULL) { /* Release the initial claim that was done during the create. This * will indicate that further API deletion is now possible. */ - ut_handle_release(((dds_entity*)entity)->m_hdl, ((dds_entity*)entity)->m_hdllink); + ut_handle_release(entity->m_hdl, ((dds_entity*)entity)->m_hdllink); return; } - if (dds_reader_lock(((dds_entity*)entity)->m_hdl, &rd) != DDS_RETCODE_OK) { + if (dds_reader_lock(entity->m_hdl, &rd) != DDS_RETCODE_OK) { return; } - assert(rd == entity); + assert(&rd->m_entity == entity); /* Reset the status for possible Listener call. * When a listener is not called, the status will be set (again). */ @@ -192,20 +195,20 @@ dds_reader_status_cb( rd->m_requested_deadline_missed_status.total_count++; rd->m_requested_deadline_missed_status.total_count_change++; rd->m_requested_deadline_missed_status.last_instance_handle = data->handle; - metrics = (void*)&(rd->m_requested_deadline_missed_status); + metrics = &rd->m_requested_deadline_missed_status; break; } case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: { rd->m_requested_incompatible_qos_status.total_count++; rd->m_requested_incompatible_qos_status.total_count_change++; rd->m_requested_incompatible_qos_status.last_policy_id = data->extra; - metrics = (void*)&(rd->m_requested_incompatible_qos_status); + metrics = &rd->m_requested_incompatible_qos_status; break; } case DDS_SAMPLE_LOST_STATUS: { rd->m_sample_lost_status.total_count++; rd->m_sample_lost_status.total_count_change++; - metrics = (void*)&(rd->m_sample_lost_status); + metrics = &rd->m_sample_lost_status; break; } case DDS_SAMPLE_REJECTED_STATUS: { @@ -213,7 +216,7 @@ dds_reader_status_cb( rd->m_sample_rejected_status.total_count_change++; rd->m_sample_rejected_status.last_reason = data->extra; rd->m_sample_rejected_status.last_instance_handle = data->handle; - metrics = (void*)&(rd->m_sample_rejected_status); + metrics = &rd->m_sample_rejected_status; break; } case DDS_DATA_AVAILABLE_STATUS: { @@ -233,7 +236,7 @@ dds_reader_status_cb( rd->m_liveliness_changed_status.not_alive_count_change++; } rd->m_liveliness_changed_status.last_publication_handle = data->handle; - metrics = (void*)&(rd->m_liveliness_changed_status); + metrics = &rd->m_liveliness_changed_status; break; } case DDS_SUBSCRIPTION_MATCHED_STATUS: { @@ -247,7 +250,7 @@ dds_reader_status_cb( rd->m_subscription_matched_status.current_count_change--; } rd->m_subscription_matched_status.last_publication_handle = data->handle; - metrics = (void*)&(rd->m_subscription_matched_status); + metrics = &rd->m_subscription_matched_status; break; } default: assert (0); @@ -283,8 +286,8 @@ dds_reader_status_cb( if (rc == DDS_RETCODE_OK) { /* Event was eaten by a listener. */ - if (dds_reader_lock(((dds_entity*)entity)->m_hdl, &rd) == DDS_RETCODE_OK) { - assert(rd == entity); + if (dds_reader_lock(entity->m_hdl, &rd) == DDS_RETCODE_OK) { + assert(&rd->m_entity == entity); /* Reset the change counts of the metrics. */ switch (data->status) { @@ -353,16 +356,16 @@ dds_create_reader( dds_entity_t subscriber; dds_reader * rd; struct rhc * rhc; - dds_entity * tp; + dds_topic * tp; dds_entity_t reader; dds_entity_t t; struct thread_state1 * const thr = lookup_thread_state (); const bool asleep = !vtime_awake_p (thr->vtime); dds_return_t ret = DDS_RETCODE_OK; - if (dds_entity_kind(topic) != DDS_KIND_INTERNAL) { + if (dds_entity_kind_from_handle(topic) != DDS_KIND_INTERNAL) { /* Try claiming a participant. If that's not working, then it could be a subscriber. */ - if (dds_entity_kind(participant_or_subscriber) == DDS_KIND_PARTICIPANT) { + if (dds_entity_kind_from_handle(participant_or_subscriber) == DDS_KIND_PARTICIPANT) { subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL); } else { subscriber = participant_or_subscriber; @@ -381,19 +384,19 @@ dds_create_reader( } if ((subscriber != participant_or_subscriber) && - (dds_entity_kind(topic) != DDS_KIND_INTERNAL)) { + (dds_entity_kind_from_handle(topic) != DDS_KIND_INTERNAL)) { /* Delete implicit subscriber if reader creation fails */ sub->m_flags |= DDS_ENTITY_IMPLICIT; } - rc = dds_entity_lock(t, DDS_KIND_TOPIC, &tp); + rc = dds_topic_lock(t, &tp); if (rc != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking topic\n"); reader = DDS_ERRNO(rc); goto err_tp_lock; } - assert (((dds_topic*)tp)->m_stopic); - assert (sub->m_domain == tp->m_domain); + assert (tp->m_stopic); + assert (sub->m_domain == tp->m_entity.m_domain); /* Merge qos from topic and subscriber */ rqos = dds_create_qos (); @@ -407,8 +410,8 @@ dds_create_reader( dds_merge_qos (rqos, sub->m_qos); } - if (tp->m_qos) { - dds_merge_qos (rqos, tp->m_qos); + if (tp->m_entity.m_qos) { + dds_merge_qos (rqos, tp->m_entity.m_qos); /* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */ rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN); @@ -423,7 +426,7 @@ dds_create_reader( } /* Additional checks required for built-in topics */ - if (dds_entity_kind(topic) == DDS_KIND_INTERNAL && !dds__validate_builtin_reader_qos(topic, qos)) { + if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL && !dds__validate_builtin_reader_qos(topic, qos)) { dds_delete_qos(rqos); DDS_ERROR("Invalid QoS specified for built-in topic reader"); reader = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); @@ -434,9 +437,9 @@ dds_create_reader( rd = dds_alloc (sizeof (*rd)); reader = dds_entity_init (&rd->m_entity, sub, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK); rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; - rd->m_topic = (dds_topic*)tp; - rhc = dds_rhc_new (rd, ((dds_topic*)tp)->m_stopic); - dds_entity_add_ref_nolock (tp); + rd->m_topic = tp; + rhc = dds_rhc_new (rd, tp->m_stopic); + dds_entity_add_ref_nolock (&tp->m_entity); rd->m_entity.m_deriver.close = dds_reader_close; rd->m_entity.m_deriver.delete = dds_reader_delete; rd->m_entity.m_deriver.set_qos = dds_reader_qos_set; @@ -449,16 +452,16 @@ dds_create_reader( assert(0); } - os_mutexUnlock(&tp->m_mutex); + os_mutexUnlock(&tp->m_entity.m_mutex); os_mutexUnlock(&sub->m_mutex); if (asleep) { thread_state_awake (thr); } - rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_participant->m_guid, ((dds_topic*)tp)->m_stopic, + rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_participant->m_guid, tp->m_stopic, rqos, rhc, dds_reader_status_cb, rd); os_mutexLock(&sub->m_mutex); - os_mutexLock(&tp->m_mutex); + os_mutexLock(&tp->m_entity.m_mutex); assert (rd->m_rd); if (asleep) { thread_state_asleep (thr); @@ -468,10 +471,10 @@ dds_create_reader( if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) { (dds_global.m_dur_reader) (rd, rhc); } - dds_entity_unlock(tp); + dds_topic_unlock(tp); dds_entity_unlock(sub); - if (dds_entity_kind(topic) == DDS_KIND_INTERNAL) { + if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL) { /* If topic is builtin, then the topic entity is local and should * be deleted because the application won't. */ dds_delete(t); @@ -480,14 +483,14 @@ dds_create_reader( return reader; err_bad_qos: - dds_entity_unlock(tp); + dds_topic_unlock(tp); err_tp_lock: dds_entity_unlock(sub); if((sub->m_flags & DDS_ENTITY_IMPLICIT) != 0){ (void)dds_delete(subscriber); } err_sub_lock: - if (dds_entity_kind(topic) == DDS_KIND_INTERNAL) { + if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL) { /* If topic is builtin, then the topic entity is local and should * be deleted because the application won't. */ dds_delete(t); @@ -495,11 +498,7 @@ err_sub_lock: return reader; } -void -dds_reader_ddsi2direct( - dds_entity_t entity, - ddsi2direct_directread_cb_t cb, - void *cbarg) +void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg) { dds_reader *dds_rd; @@ -540,77 +539,62 @@ dds_reader_ddsi2direct( os_mutexLock (&rd->e.lock); } os_mutexUnlock (&rd->e.lock); - ut_handle_release(entity, ((dds_entity*)rd)->m_hdllink); + ut_handle_release(entity, dds_rd->m_entity.m_hdllink); } } -uint32_t -dds_reader_lock_samples( - dds_entity_t reader) +uint32_t dds_reader_lock_samples (dds_entity_t reader) { - uint32_t ret = 0; - dds_reader *rd; - if (dds_reader_lock(reader, &rd) == DDS_RETCODE_OK) { - ret = dds_rhc_lock_samples(rd->m_rd->rhc); - dds_reader_unlock(rd); - } else { - ret = 0; - } - return ret; + dds_reader *rd; + uint32_t n; + if (dds_reader_lock (reader, &rd) != DDS_RETCODE_OK) + return 0; + n = dds_rhc_lock_samples (rd->m_rd->rhc); + dds_reader_unlock (rd); + return n; } -_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER) -int -dds_reader_wait_for_historical_data( - dds_entity_t reader, - dds_duration_t max_wait) +int dds_reader_wait_for_historical_data (dds_entity_t reader, dds_duration_t max_wait) { - int ret; - dds_reader *rd; - - assert (reader); - - ret = dds_reader_lock(reader, &rd); - if (ret == DDS_RETCODE_OK) { - if (((dds_entity*)rd)->m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS) { - ret = (dds_global.m_dur_wait) (rd, max_wait); - } else { - DDS_ERROR("Can not wait for historical data on a reader with volatile durability\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); - } - dds_reader_unlock(rd); - } else { - DDS_ERROR("Error occurred on locking reader\n"); - ret = DDS_ERRNO(ret); - } - - return ret; + dds_reader *rd; + int ret; + if ((ret = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK) + return DDS_ERRNO (ret); + switch (rd->m_entity.m_qos->durability.kind) + { + case DDS_DURABILITY_VOLATILE: + ret = DDS_RETCODE_OK; + break; + case DDS_DURABILITY_TRANSIENT_LOCAL: + break; + case DDS_DURABILITY_TRANSIENT: + case DDS_DURABILITY_PERSISTENT: + ret = (dds_global.m_dur_wait) (rd, max_wait); + break; + } + dds_reader_unlock(rd); + return ret; } -_Pre_satisfies_(((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) || \ - ((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \ - ((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY) ) -dds_entity_t -dds_get_subscriber( - _In_ dds_entity_t entity) +dds_entity_t dds_get_subscriber (dds_entity_t entity) { - dds_entity_t hdl; + dds_entity_t hdl; + if (dds_entity_kind_from_handle (entity) == DDS_KIND_READER) + hdl = dds_get_parent (entity); + else if (dds_entity_kind_from_handle (entity) == DDS_KIND_COND_READ || dds_entity_kind_from_handle (entity) == DDS_KIND_COND_QUERY) + { + hdl = dds_get_parent (entity); + if (hdl > 0) + hdl = dds_get_subscriber (hdl); + DDS_ERROR ("Reader of this condition is already deleted\n"); + } + else + { + DDS_ERROR ("Provided entity is not a reader nor a condition\n"); + hdl = DDS_ERRNO (dds_valid_hdl (entity, DDS_KIND_READER)); + } - if (dds_entity_kind(entity) == DDS_KIND_READER) { - hdl = dds_get_parent(entity); - } else if (dds_entity_kind(entity) == DDS_KIND_COND_READ || dds_entity_kind(entity) == DDS_KIND_COND_QUERY) { - hdl = dds_get_parent(entity); - if(hdl > 0){ - hdl = dds_get_subscriber(hdl); - } else { - DDS_ERROR("Reader of this condition is already deleted\n"); - } - } else { - DDS_ERROR("Provided entity is not a reader nor a condition\n"); - hdl = DDS_ERRNO(dds_valid_hdl(entity, DDS_KIND_READER)); - } - - return hdl; + return hdl; } _Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER) @@ -633,10 +617,10 @@ dds_get_subscription_matched_status ( if (status) { *status = rd->m_subscription_matched_status; } - if (((dds_entity*)rd)->m_status_enable & DDS_SUBSCRIPTION_MATCHED_STATUS) { + if (rd->m_entity.m_status_enable & DDS_SUBSCRIPTION_MATCHED_STATUS) { rd->m_subscription_matched_status.total_count_change = 0; rd->m_subscription_matched_status.current_count_change = 0; - dds_entity_status_reset(rd, DDS_SUBSCRIPTION_MATCHED_STATUS); + dds_entity_status_reset(&rd->m_entity, DDS_SUBSCRIPTION_MATCHED_STATUS); } dds_reader_unlock(rd); fail: @@ -663,10 +647,10 @@ dds_get_liveliness_changed_status ( if (status) { *status = rd->m_liveliness_changed_status; } - if (((dds_entity*)rd)->m_status_enable & DDS_LIVELINESS_CHANGED_STATUS) { + if (rd->m_entity.m_status_enable & DDS_LIVELINESS_CHANGED_STATUS) { rd->m_liveliness_changed_status.alive_count_change = 0; rd->m_liveliness_changed_status.not_alive_count_change = 0; - dds_entity_status_reset(rd, DDS_LIVELINESS_CHANGED_STATUS); + dds_entity_status_reset(&rd->m_entity, DDS_LIVELINESS_CHANGED_STATUS); } dds_reader_unlock(rd); fail: @@ -692,10 +676,10 @@ dds_return_t dds_get_sample_rejected_status ( if (status) { *status = rd->m_sample_rejected_status; } - if (((dds_entity*)rd)->m_status_enable & DDS_SAMPLE_REJECTED_STATUS) { + if (rd->m_entity.m_status_enable & DDS_SAMPLE_REJECTED_STATUS) { rd->m_sample_rejected_status.total_count_change = 0; rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; - dds_entity_status_reset(rd, DDS_SAMPLE_REJECTED_STATUS); + dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_REJECTED_STATUS); } dds_reader_unlock(rd); fail: @@ -721,9 +705,9 @@ dds_return_t dds_get_sample_lost_status ( if (status) { *status = rd->m_sample_lost_status; } - if (((dds_entity*)rd)->m_status_enable & DDS_SAMPLE_LOST_STATUS) { + if (rd->m_entity.m_status_enable & DDS_SAMPLE_LOST_STATUS) { rd->m_sample_lost_status.total_count_change = 0; - dds_entity_status_reset(rd, DDS_SAMPLE_LOST_STATUS); + dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_LOST_STATUS); } dds_reader_unlock(rd); fail: @@ -749,9 +733,9 @@ dds_return_t dds_get_requested_deadline_missed_status ( if (status) { *status = rd->m_requested_deadline_missed_status; } - if (((dds_entity*)rd)->m_status_enable & DDS_REQUESTED_DEADLINE_MISSED_STATUS) { + if (rd->m_entity.m_status_enable & DDS_REQUESTED_DEADLINE_MISSED_STATUS) { rd->m_requested_deadline_missed_status.total_count_change = 0; - dds_entity_status_reset(rd, DDS_REQUESTED_DEADLINE_MISSED_STATUS); + dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_DEADLINE_MISSED_STATUS); } dds_reader_unlock(rd); fail: @@ -777,9 +761,9 @@ dds_return_t dds_get_requested_incompatible_qos_status ( if (status) { *status = rd->m_requested_incompatible_qos_status; } - if (((dds_entity*)rd)->m_status_enable & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS) { + if (rd->m_entity.m_status_enable & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS) { rd->m_requested_incompatible_qos_status.total_count_change = 0; - dds_entity_status_reset(rd, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS); + dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS); } dds_reader_unlock(rd); fail: diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index d71e599..f06754a 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -310,13 +310,40 @@ struct trigger_info bool has_changed; }; -#define QMASK_OF_SAMPLE(s) ((s)->isread ? DDS_READ_SAMPLE_STATE : DDS_NOT_READ_SAMPLE_STATE) -#define QMASK_OF_INVSAMPLE(i) ((i)->inv_isread ? DDS_READ_SAMPLE_STATE : DDS_NOT_READ_SAMPLE_STATE) -#define INST_NSAMPLES(i) ((i)->nvsamples + (i)->inv_exists) -#define INST_NREAD(i) ((i)->nvread + (unsigned)((i)->inv_exists & (i)->inv_isread)) -#define INST_IS_EMPTY(i) (INST_NSAMPLES (i) == 0) -#define INST_HAS_READ(i) (INST_NREAD (i) > 0) -#define INST_HAS_UNREAD(i) (INST_NREAD (i) < INST_NSAMPLES (i)) +static unsigned qmask_of_sample (const struct rhc_sample *s) +{ + return s->isread ? DDS_READ_SAMPLE_STATE : DDS_NOT_READ_SAMPLE_STATE; +} + +static unsigned qmask_of_invsample (const struct rhc_instance *i) +{ + return i->inv_isread ? DDS_READ_SAMPLE_STATE : DDS_NOT_READ_SAMPLE_STATE; +} + +static uint32_t inst_nsamples (const struct rhc_instance *i) +{ + return i->nvsamples + i->inv_exists; +} + +static uint32_t inst_nread (const struct rhc_instance *i) +{ + return i->nvread + (uint32_t) (i->inv_exists & i->inv_isread); +} + +static bool inst_is_empty (const struct rhc_instance *i) +{ + return inst_nsamples (i) == 0; +} + +static bool inst_has_read (const struct rhc_instance *i) +{ + return inst_nread (i) > 0; +} + +static bool inst_has_unread (const struct rhc_instance *i) +{ + return inst_nread (i) < inst_nsamples (i); +} static unsigned qmask_of_inst (const struct rhc_instance *inst); static bool update_conditions_locked (struct rhc *rhc, const struct trigger_info *pre, const struct trigger_info *post, const struct ddsi_serdata *sample); @@ -363,7 +390,7 @@ static void add_inst_to_nonempty_list (_Inout_ struct rhc *rhc, _Inout_ struct r static void remove_inst_from_nonempty_list (struct rhc *rhc, struct rhc_instance *inst) { - assert (INST_IS_EMPTY (inst)); + assert (inst_is_empty (inst)); #ifndef NDEBUG { const struct rhc_instance *x = rhc->nonempty_instances; @@ -488,7 +515,7 @@ static void free_instance (void *vnode, void *varg) struct rhc *rhc = varg; struct rhc_instance *inst = vnode; struct rhc_sample *s = inst->latest; - const bool was_empty = INST_IS_EMPTY (inst); + const bool was_empty = inst_is_empty (inst); if (s) { do { @@ -559,8 +586,8 @@ static void init_trigger_info_nonmatch (struct trigger_info *info) static void get_trigger_info (struct trigger_info *info, struct rhc_instance *inst, bool pre) { info->qminst = qmask_of_inst (inst); - info->has_read = INST_HAS_READ (inst); - info->has_not_read = INST_HAS_UNREAD (inst); + info->has_read = inst_has_read (inst); + info->has_not_read = inst_has_unread (inst); /* reset instance has_changed before adding/overwriting a sample */ if (pre) { @@ -749,7 +776,7 @@ static void update_inst static void drop_instance_noupdate_no_writers (struct rhc *rhc, struct rhc_instance *inst) { int ret; - assert (INST_IS_EMPTY (inst)); + assert (inst_is_empty (inst)); rhc->n_instances--; @@ -799,7 +826,7 @@ static void dds_rhc_register (struct rhc *rhc, struct rhc_instance *inst, uint64 inst->no_writers_gen++; DDS_TRACE("new1"); - if (!INST_IS_EMPTY (inst) && !inst->isdisposed) + if (!inst_is_empty (inst) && !inst->isdisposed) rhc->n_not_alive_no_writers--; } else if (inst_wr_iid == 0 && inst->wrcount == 1) @@ -876,7 +903,7 @@ static void dds_rhc_register (struct rhc *rhc, struct rhc_instance *inst, uint64 static void account_for_empty_to_nonempty_transition (struct rhc *rhc, struct rhc_instance *inst) { - assert (INST_NSAMPLES (inst) == 1); + assert (inst_nsamples (inst) == 1); add_inst_to_nonempty_list (rhc, inst); rhc->n_new += inst->isnew; if (inst->isdisposed) @@ -953,7 +980,7 @@ static int rhc_unregister_updateinst } else { - if (!INST_IS_EMPTY (inst)) + if (!inst_is_empty (inst)) { /* Instance still has content - do not drop until application takes the last sample. Set the invalid sample if the latest @@ -985,7 +1012,7 @@ static int rhc_unregister_updateinst { /* Add invalid samples for transition to no-writers */ DDS_TRACE(",#0,empty,nowriters"); - assert (INST_IS_EMPTY (inst)); + assert (inst_is_empty (inst)); inst_set_invsample (rhc, inst); update_inst (rhc, inst, pwr_info, false, tstamp); account_for_empty_to_nonempty_transition (rhc, inst); @@ -1228,7 +1255,7 @@ bool dds_rhc_store const int not_alive = inst->wrcount == 0 || inst->isdisposed; const bool old_isdisposed = inst->isdisposed; const bool old_isnew = inst->isnew; - const bool was_empty = INST_IS_EMPTY (inst); + const bool was_empty = inst_is_empty (inst); int inst_became_disposed = 0; /* Not just an unregister, so a write and/or a dispose (possibly @@ -1314,7 +1341,7 @@ bool dds_rhc_store } else { - assert (INST_IS_EMPTY (inst) == was_empty); + assert (inst_is_empty (inst) == was_empty); } } @@ -1369,7 +1396,7 @@ bool dds_rhc_store if (rhc->reader && trigger_waitsets) { - dds_entity_status_signal((dds_entity*)(rhc->reader)); + dds_entity_status_signal(&rhc->reader->m_entity); } return delivered; @@ -1447,7 +1474,7 @@ void dds_rhc_unregister_wr } else { - const bool was_empty = INST_IS_EMPTY (inst); + const bool was_empty = inst_is_empty (inst); inst_set_invsample (rhc, inst); if (was_empty) account_for_empty_to_nonempty_transition (rhc, inst); @@ -1476,7 +1503,7 @@ void dds_rhc_unregister_wr if (trigger_waitsets) { - dds_entity_status_signal((dds_entity*)(rhc->reader)); + dds_entity_status_signal(&rhc->reader->m_entity); } } @@ -1663,11 +1690,11 @@ static int dds_rhc_read_w_qminv { if (handle == DDS_HANDLE_NIL || inst->iid == handle) { - if (!INST_IS_EMPTY (inst) && (qmask_of_inst (inst) & qminv) == 0) + if (!inst_is_empty (inst) && (qmask_of_inst (inst) & qminv) == 0) { /* samples present & instance, view state matches */ struct trigger_info pre, post; - const unsigned nread = INST_NREAD (inst); + const unsigned nread = inst_nread (inst); const uint32_t n_first = n; get_trigger_info (&pre, inst, true); @@ -1676,13 +1703,13 @@ static int dds_rhc_read_w_qminv struct rhc_sample *sample = inst->latest->next, * const end1 = sample; do { - if ((QMASK_OF_SAMPLE (sample) & qminv) == 0) + if ((qmask_of_sample (sample) & qminv) == 0) { /* sample state matches too */ set_sample_info (info_seq + n, inst, sample); ddsi_serdata_to_sample (sample->sample, values[n], 0, 0); if (cond == NULL - || (dds_entity_kind(cond->m_entity.m_hdl) != DDS_KIND_COND_QUERY) + || (dds_entity_kind_from_handle(cond->m_entity.m_hdl) != DDS_KIND_COND_QUERY) || (cond->m_query.m_filter != NULL && cond->m_query.m_filter(values[n]))) { if (!sample->isread) @@ -1709,7 +1736,7 @@ static int dds_rhc_read_w_qminv while (sample != end1); } - if (inst->inv_exists && n < max_samples && (QMASK_OF_INVSAMPLE (inst) & qminv) == 0) + if (inst->inv_exists && n < max_samples && (qmask_of_invsample (inst) & qminv) == 0) { set_sample_info_invsample (info_seq + n, inst); ddsi_serdata_topicless_to_sample (rhc->topic, inst->tk->m_sample, values[n], 0, 0); @@ -1726,7 +1753,7 @@ static int dds_rhc_read_w_qminv inst->isnew = 0; rhc->n_new--; } - if (nread != INST_NREAD (inst)) + if (nread != inst_nread (inst)) { get_trigger_info (&post, inst, false); if (update_conditions_locked (rhc, &pre, &post, NULL)) @@ -1754,7 +1781,7 @@ static int dds_rhc_read_w_qminv if (trigger_waitsets) { - dds_entity_status_signal((dds_entity*)(rhc->reader)); + dds_entity_status_signal(&rhc->reader->m_entity); } assert (n <= INT_MAX); @@ -1792,7 +1819,7 @@ static int dds_rhc_take_w_qminv iid = inst->iid; if (handle == DDS_HANDLE_NIL || iid == handle) { - if (!INST_IS_EMPTY (inst) && (qmask_of_inst (inst) & qminv) == 0) + if (!inst_is_empty (inst) && (qmask_of_inst (inst) & qminv) == 0) { struct trigger_info pre, post; unsigned nvsamples = inst->nvsamples; @@ -1807,7 +1834,7 @@ static int dds_rhc_take_w_qminv { struct rhc_sample * const sample1 = sample->next; - if ((QMASK_OF_SAMPLE (sample) & qminv) != 0) + if ((qmask_of_sample (sample) & qminv) != 0) { psample = sample; } @@ -1816,7 +1843,7 @@ static int dds_rhc_take_w_qminv set_sample_info (info_seq + n, inst, sample); ddsi_serdata_to_sample (sample->sample, values[n], 0, 0); if (cond == NULL - || (dds_entity_kind(cond->m_entity.m_hdl) != DDS_KIND_COND_QUERY) + || (dds_entity_kind_from_handle(cond->m_entity.m_hdl) != DDS_KIND_COND_QUERY) || ( cond->m_query.m_filter != NULL && cond->m_query.m_filter(values[n]))) { rhc->n_vsamples--; @@ -1855,7 +1882,7 @@ static int dds_rhc_take_w_qminv } } - if (inst->inv_exists && n < max_samples && (QMASK_OF_INVSAMPLE (inst) & qminv) == 0) + if (inst->inv_exists && n < max_samples && (qmask_of_invsample (inst) & qminv) == 0) { set_sample_info_invsample (info_seq + n, inst); ddsi_serdata_topicless_to_sample (rhc->topic, inst->tk->m_sample, values[n], 0, 0); @@ -1880,7 +1907,7 @@ static int dds_rhc_take_w_qminv } } - if (INST_IS_EMPTY (inst)) + if (inst_is_empty (inst)) { remove_inst_from_nonempty_list (rhc, inst); @@ -1918,7 +1945,7 @@ static int dds_rhc_take_w_qminv if (trigger_waitsets) { - dds_entity_status_signal((dds_entity*)(rhc->reader)); + dds_entity_status_signal(&rhc->reader->m_entity); } assert (n <= INT_MAX); @@ -1957,7 +1984,7 @@ static int dds_rhc_takecdr_w_qminv iid = inst->iid; if (handle == DDS_HANDLE_NIL || iid == handle) { - if (!INST_IS_EMPTY (inst) && (qmask_of_inst (inst) & qminv) == 0) + if (!inst_is_empty (inst) && (qmask_of_inst (inst) & qminv) == 0) { struct trigger_info pre, post; unsigned nvsamples = inst->nvsamples; @@ -1972,7 +1999,7 @@ static int dds_rhc_takecdr_w_qminv { struct rhc_sample * const sample1 = sample->next; - if ((QMASK_OF_SAMPLE (sample) & qminv) != 0) + if ((qmask_of_sample (sample) & qminv) != 0) { psample = sample; } @@ -2006,7 +2033,7 @@ static int dds_rhc_takecdr_w_qminv } } - if (inst->inv_exists && n < max_samples && (QMASK_OF_INVSAMPLE (inst) & qminv) == 0) + if (inst->inv_exists && n < max_samples && (qmask_of_invsample (inst) & qminv) == 0) { set_sample_info_invsample (info_seq + n, inst); values[n] = ddsi_serdata_ref(inst->tk->m_sample); @@ -2031,7 +2058,7 @@ static int dds_rhc_takecdr_w_qminv } } - if (INST_IS_EMPTY (inst)) + if (inst_is_empty (inst)) { remove_inst_from_nonempty_list (rhc, inst); @@ -2069,7 +2096,7 @@ static int dds_rhc_takecdr_w_qminv if (trigger_waitsets) { - dds_entity_status_signal((dds_entity*)(rhc->reader)); + dds_entity_status_signal(&rhc->reader->m_entity); } assert (n <= INT_MAX); @@ -2086,15 +2113,15 @@ static uint32_t rhc_get_cond_trigger (struct rhc_instance * const inst, const dd switch (c->m_sample_states) { case DDS_SST_READ: - m = m && INST_HAS_READ (inst); + m = m && inst_has_read (inst); break; case DDS_SST_NOT_READ: - m = m && INST_HAS_UNREAD (inst); + m = m && inst_has_unread (inst); break; case DDS_SST_READ | DDS_SST_NOT_READ: case 0: /* note: we get here only if inst not empty, so this is a no-op */ - m = m && !INST_IS_EMPTY (inst); + m = m && !inst_is_empty (inst); break; default: DDS_FATAL("update_readconditions: sample_states invalid: %x\n", c->m_sample_states); @@ -2118,11 +2145,11 @@ void dds_rhc_add_readcondition (dds_readcond * cond) os_mutexLock (&rhc->lock); for (inst = ut_hhIterFirst (rhc->instances, &iter); inst; inst = ut_hhIterNext (&iter)) { - if (dds_entity_kind(cond->m_entity.m_hdl) == DDS_KIND_COND_READ) + if (dds_entity_kind_from_handle(cond->m_entity.m_hdl) == DDS_KIND_COND_READ) { - ((dds_entity*)cond)->m_trigger += rhc_get_cond_trigger (inst, cond); - if (((dds_entity*)cond)->m_trigger) { - dds_entity_status_signal((dds_entity*)cond); + cond->m_entity.m_trigger += rhc_get_cond_trigger (inst, cond); + if (cond->m_entity.m_trigger) { + dds_entity_status_signal(&cond->m_entity); } } } @@ -2225,7 +2252,7 @@ static bool update_conditions_locked } else if (m_pre < m_post) { - if (sample && tmp == NULL && (dds_entity_kind(iter->m_entity.m_hdl) == DDS_KIND_COND_QUERY)) + if (sample && tmp == NULL && (dds_entity_kind_from_handle(iter->m_entity.m_hdl) == DDS_KIND_COND_QUERY)) { tmp = ddsi_sertopic_alloc_sample (rhc->topic); ddsi_serdata_to_sample (sample, tmp, NULL, NULL); @@ -2233,7 +2260,7 @@ static bool update_conditions_locked if ( (sample == NULL) - || (dds_entity_kind(iter->m_entity.m_hdl) != DDS_KIND_COND_QUERY) + || (dds_entity_kind_from_handle(iter->m_entity.m_hdl) != DDS_KIND_COND_QUERY) || (iter->m_query.m_filter != NULL && iter->m_query.m_filter (tmp)) ) { @@ -2335,7 +2362,7 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds) for (inst = ut_hhIterFirst (rhc->instances, &iter); inst; inst = ut_hhIterNext (&iter)) { n_instances++; - if (!INST_IS_EMPTY (inst)) + if (!inst_is_empty (inst)) { /* samples present (or an invalid sample is) */ unsigned n_vsamples_in_instance = 0, n_read_vsamples_in_instance = 0; @@ -2387,7 +2414,7 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds) dds_readcond * rciter = rhc->conds; for (i = 0; i < (rhc->nconds < CHECK_MAX_CONDS ? rhc->nconds : CHECK_MAX_CONDS); i++) { - if (dds_entity_kind(rciter->m_entity.m_hdl) == DDS_KIND_COND_READ) + if (dds_entity_kind_from_handle(rciter->m_entity.m_hdl) == DDS_KIND_COND_READ) { cond_match_count[i] += rhc_get_cond_trigger (inst, rciter); } @@ -2412,7 +2439,7 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds) dds_readcond * rciter = rhc->conds; for (i = 0; i < (rhc->nconds < CHECK_MAX_CONDS ? rhc->nconds : CHECK_MAX_CONDS); i++) { - if (dds_entity_kind(rciter->m_entity.m_hdl) == DDS_KIND_COND_READ) + if (dds_entity_kind_from_handle(rciter->m_entity.m_hdl) == DDS_KIND_COND_READ) { assert (cond_match_count[i] == rciter->m_entity.m_trigger); } @@ -2433,7 +2460,7 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds) inst = rhc->nonempty_instances; n_nonempty_instances = 0; do { - assert (!INST_IS_EMPTY (inst)); + assert (!inst_is_empty (inst)); assert (prev->next == inst); assert (inst->prev == prev); prev = inst; diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index 339a73b..0861bb0 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -40,10 +40,8 @@ static const char * stream_op_type[11] = const uint32_t dds_op_size[5] = { 0, 1u, 2u, 4u, 8u }; -static void dds_stream_write - (dds_stream_t * os, const char * data, const uint32_t * ops); -static void dds_stream_read - (dds_stream_t * is, char * data, const uint32_t * ops); +static void dds_stream_write (dds_stream_t * os, const char * data, const uint32_t * ops); +static void dds_stream_read (dds_stream_t * is, char * data, const uint32_t * ops); #define DDS_SWAP16(v) \ ((uint16_t)(((v) >> 8) | ((v) << 8))) @@ -258,6 +256,12 @@ uint64_t dds_stream_read_uint64 (dds_stream_t * is) return val; } +extern inline char dds_stream_read_char (dds_stream_t *is); +extern inline int8_t dds_stream_read_int8 (dds_stream_t *is); +extern inline int16_t dds_stream_read_int16 (dds_stream_t *is); +extern inline int32_t dds_stream_read_int32 (dds_stream_t *is); +extern inline int64_t dds_stream_read_int64 (dds_stream_t *is); + float dds_stream_read_float (dds_stream_t * is) { float val = 0.0; @@ -417,6 +421,12 @@ void dds_stream_write_uint64 (dds_stream_t * os, uint64_t val) DDS_OS_PUT8 (os, val, uint64_t); } +extern inline void dds_stream_write_char (dds_stream_t * os, char val); +extern inline void dds_stream_write_int8 (dds_stream_t * os, int8_t val); +extern inline void dds_stream_write_int16 (dds_stream_t * os, int16_t val); +extern inline void dds_stream_write_int32 (dds_stream_t * os, int32_t val); +extern inline void dds_stream_write_int64 (dds_stream_t * os, int64_t val); + void dds_stream_write_float (dds_stream_t * os, float val) { union { float f; uint32_t u; } u; diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index b11ae58..7e6cab4 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -101,22 +101,20 @@ dds_subscriber_status_validate( Set boolean on readers that indicates state of DATA_ON_READERS status on parent subscriber */ -static dds_return_t -dds_subscriber_status_propagate( - dds_entity *sub, - uint32_t mask, - bool set) +static dds_return_t dds_subscriber_status_propagate (dds_entity *sub, uint32_t mask, bool set) { - if (mask & DDS_DATA_ON_READERS_STATUS) { - dds_entity *iter = sub->m_children; - while (iter) { - os_mutexLock (&iter->m_mutex); - ((dds_reader*) iter)->m_data_on_readers = set; - os_mutexUnlock (&iter->m_mutex); - iter = iter->m_next; - } + if (mask & DDS_DATA_ON_READERS_STATUS) + { + dds_entity *iter = sub->m_children; + while (iter) { + os_mutexLock (&iter->m_mutex); + assert (dds_entity_kind (iter) == DDS_KIND_READER); + ((dds_reader*) iter)->m_data_on_readers = set; + os_mutexUnlock (&iter->m_mutex); + iter = iter->m_next; } - return DDS_RETCODE_OK; + } + return DDS_RETCODE_OK; } _Requires_exclusive_lock_held_(participant) diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 1466fde..9364199 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -26,6 +26,8 @@ #include "os/os_atomics.h" #include "ddsi/ddsi_iid.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_topic) + #define DDS_TOPIC_STATUS_MASK \ DDS_INCONSISTENT_TOPIC_STATUS @@ -97,7 +99,7 @@ dds_topic_status_cb( dds_topic *topic; dds__retcode_t rc; - if (dds_topic_lock(((dds_entity*)cb_t)->m_hdl, &topic) != DDS_RETCODE_OK) { + if (dds_topic_lock(cb_t->m_entity.m_hdl, &topic) != DDS_RETCODE_OK) { return; } assert(topic == cb_t); @@ -116,24 +118,24 @@ dds_topic_status_cb( dds_topic_unlock(topic); /* Is anybody interested within the entity hierarchy through listeners? */ - rc = dds_entity_listener_propagation((dds_entity*)topic, - (dds_entity*)topic, + rc = dds_entity_listener_propagation(&topic->m_entity, + &topic->m_entity, DDS_INCONSISTENT_TOPIC_STATUS, - (void*)&(topic->m_inconsistent_topic_status), + &topic->m_inconsistent_topic_status, true); if (rc == DDS_RETCODE_OK) { /* Event was eaten by a listener. */ - if (dds_topic_lock(((dds_entity*)cb_t)->m_hdl, &topic) == DDS_RETCODE_OK) { + if (dds_topic_lock(cb_t->m_entity.m_hdl, &topic) == DDS_RETCODE_OK) { /* Reset the change counts of the metrics. */ topic->m_inconsistent_topic_status.total_count_change = 0; dds_topic_unlock(topic); } } else if (rc == DDS_RETCODE_NO_DATA) { /* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status; consider it successful. */ - dds_entity_status_set((dds_entity*)topic, DDS_INCONSISTENT_TOPIC_STATUS); + dds_entity_status_set(&topic->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); /* Notify possible interested observers. */ - dds_entity_status_signal((dds_entity*)topic); + dds_entity_status_signal(&topic->m_entity); } else if (rc == DDS_RETCODE_ALREADY_DELETED) { /* An entity up the hierarchy is being deleted; consider it successful. */ } else { @@ -184,7 +186,7 @@ dds_topic_free( assert (st); os_mutexLock (&dds_global.m_mutex); - domain = (dds_domain*) ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); + domain = ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); if (domain != NULL) { ut_avlDelete (&dds_topictree_def, &domain->m_topics, st); } @@ -715,9 +717,9 @@ dds_get_inconsistent_topic_status( if (status) { *status = t->m_inconsistent_topic_status; } - if (((dds_entity*)t)->m_status_enable & DDS_INCONSISTENT_TOPIC_STATUS) { + if (t->m_entity.m_status_enable & DDS_INCONSISTENT_TOPIC_STATUS) { t->m_inconsistent_topic_status.total_count_change = 0; - dds_entity_status_reset(t, DDS_INCONSISTENT_TOPIC_STATUS); + dds_entity_status_reset(&t->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); } dds_topic_unlock(t); fail: diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index 3d927c5..a6c2c08 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -17,10 +17,7 @@ #include "dds__rhc.h" #include "dds__err.h" - -#define dds_waitset_lock(hdl, obj) dds_entity_lock(hdl, DDS_KIND_WAITSET, (dds_entity**)obj) -#define dds_waitset_unlock(obj) dds_entity_unlock((dds_entity*)obj); - +DEFINE_ENTITY_LOCK_UNLOCK(static, dds_waitset, DDS_KIND_WAITSET) static void dds_waitset_swap( @@ -41,18 +38,16 @@ dds_waitset_swap( *dst = idx; } -static void -dds_waitset_signal_entity( - _In_ dds_waitset *ws) +static void dds_waitset_signal_entity (dds_waitset *ws) { - dds_entity *e = (dds_entity*)ws; - /* When signaling any observers of us through the entity, - * we need to be unlocked. We still have claimed the related - * handle, so possible deletions will be delayed until we - * release it. */ - os_mutexUnlock(&(e->m_mutex)); - dds_entity_status_signal(e); - os_mutexLock(&(e->m_mutex)); + dds_entity *e = &ws->m_entity; + /* When signaling any observers of us through the entity, + * we need to be unlocked. We still have claimed the related + * handle, so possible deletions will be delayed until we + * release it. */ + os_mutexUnlock (&e->m_mutex); + dds_entity_status_signal (e); + os_mutexLock (&e->m_mutex); } static dds_return_t @@ -214,8 +209,8 @@ dds_waitset_close( { dds_waitset *ws = (dds_waitset*)e; - dds_waitset_close_list(&(ws->observed), e->m_hdl); - dds_waitset_close_list(&(ws->triggered), e->m_hdl); + dds_waitset_close_list(&ws->observed, e->m_hdl); + dds_waitset_close_list(&ws->triggered, e->m_hdl); /* Trigger waitset to wake up. */ os_condBroadcast(&e->m_cond); @@ -368,7 +363,7 @@ dds_waitset_attach( e = NULL; } } else { - e = (dds_entity*)ws; + e = &ws->m_entity; } /* This will fail if given entity is already attached (or deleted). */ @@ -421,7 +416,7 @@ dds_waitset_detach( if (rc == DDS_RETCODE_OK) { /* Possibly fails when entity was not attached. */ if (waitset == entity) { - rc = dds_entity_observer_unregister_nl((dds_entity*)ws, waitset); + rc = dds_entity_observer_unregister_nl(&ws->m_entity, waitset); } else { rc = dds_entity_observer_unregister(entity, waitset); } @@ -497,9 +492,9 @@ dds_waitset_set_trigger( goto fail; } if (trigger) { - dds_entity_status_set(ws, DDS_WAITSET_TRIGGER_STATUS); + dds_entity_status_set(&ws->m_entity, DDS_WAITSET_TRIGGER_STATUS); } else { - dds_entity_status_reset(ws, DDS_WAITSET_TRIGGER_STATUS); + dds_entity_status_reset(&ws->m_entity, DDS_WAITSET_TRIGGER_STATUS); } dds_waitset_signal_entity(ws); dds_waitset_unlock(ws); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 044f2c6..b9d7cd3 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -20,10 +20,13 @@ #include "dds__qos.h" #include "dds__err.h" #include "dds__init.h" +#include "dds__topic.h" #include "ddsi/ddsi_tkmap.h" #include "dds__whc.h" #include "ddsc/ddsc_project.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_writer) + #define DDS_WRITER_STATUS_MASK \ DDS_LIVELINESS_LOST_STATUS |\ DDS_OFFERED_DEADLINE_MISSED_STATUS |\ @@ -64,121 +67,133 @@ dds_writer_status_validate( static void dds_writer_status_cb( - void *entity, + void *ventity, const status_cb_data_t *data) { - dds_writer *wr; - dds__retcode_t rc; - void *metrics = NULL; + struct dds_entity * const entity = ventity; + dds_writer *wr; + dds__retcode_t rc; + void *metrics = NULL; - /* When data is NULL, it means that the writer is deleted. */ - if (data == NULL) { - /* Release the initial claim that was done during the create. This - * will indicate that further API deletion is now possible. */ - ut_handle_release(((dds_entity*)entity)->m_hdl, ((dds_entity*)entity)->m_hdllink); - return; + /* When data is NULL, it means that the writer is deleted. */ + if (data == NULL) + { + /* Release the initial claim that was done during the create. This + * will indicate that further API deletion is now possible. */ + ut_handle_release (entity->m_hdl, entity->m_hdllink); + return; + } + + if (dds_writer_lock (entity->m_hdl, &wr) != DDS_RETCODE_OK) { + /* There's a deletion or closing going on. */ + return; + } + assert (&wr->m_entity == entity); + + /* Reset the status for possible Listener call. + * When a listener is not called, the status will be set (again). */ + dds_entity_status_reset (entity, data->status); + + /* Update status metrics. */ + switch (data->status) + { + case DDS_OFFERED_DEADLINE_MISSED_STATUS: { + struct dds_offered_deadline_missed_status * const st = &wr->m_offered_deadline_missed_status; + st->total_count++; + st->total_count_change++; + st->last_instance_handle = data->handle; + metrics = st; + break; } - - if (dds_writer_lock(((dds_entity*)entity)->m_hdl, &wr) != DDS_RETCODE_OK) { - /* There's a deletion or closing going on. */ - return; + case DDS_LIVELINESS_LOST_STATUS: { + struct dds_liveliness_lost_status * const st = &wr->m_liveliness_lost_status; + st->total_count++; + st->total_count_change++; + metrics = st; + break; } - assert(wr == entity); - - /* Reset the status for possible Listener call. - * When a listener is not called, the status will be set (again). */ - dds_entity_status_reset(entity, data->status); - - /* Update status metrics. */ - switch (data->status) { - case DDS_OFFERED_DEADLINE_MISSED_STATUS: { - wr->m_offered_deadline_missed_status.total_count++; - wr->m_offered_deadline_missed_status.total_count_change++; - wr->m_offered_deadline_missed_status.last_instance_handle = data->handle; - metrics = (void*)&(wr->m_offered_deadline_missed_status); - break; - } - case DDS_LIVELINESS_LOST_STATUS: { - wr->m_liveliness_lost_status.total_count++; - wr->m_liveliness_lost_status.total_count_change++; - metrics = (void*)&(wr->m_liveliness_lost_status); - break; - } - case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: { - wr->m_offered_incompatible_qos_status.total_count++; - wr->m_offered_incompatible_qos_status.total_count_change++; - wr->m_offered_incompatible_qos_status.last_policy_id = data->extra; - metrics = (void*)&(wr->m_offered_incompatible_qos_status); - break; - } - case DDS_PUBLICATION_MATCHED_STATUS: { - if (data->add) { - wr->m_publication_matched_status.total_count++; - wr->m_publication_matched_status.total_count_change++; - wr->m_publication_matched_status.current_count++; - wr->m_publication_matched_status.current_count_change++; - } else { - wr->m_publication_matched_status.current_count--; - wr->m_publication_matched_status.current_count_change--; - } - wr->m_publication_matched_status.last_subscription_handle = data->handle; - metrics = (void*)&(wr->m_publication_matched_status); - break; - } - default: assert (0); + case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: { + struct dds_offered_incompatible_qos_status * const st = &wr->m_offered_incompatible_qos_status; + st->total_count++; + st->total_count_change++; + st->last_policy_id = data->extra; + metrics = st; + break; } - - /* The writer needs to be unlocked when propagating the (possible) listener - * call because the application should be able to call this writer within - * the callback function. */ - dds_writer_unlock(wr); - - /* Is anybody interested within the entity hierarchy through listeners? */ - rc = dds_entity_listener_propagation(entity, entity, data->status, metrics, true); - - if (rc == DDS_RETCODE_OK) { - /* Event was eaten by a listener. */ - if (dds_writer_lock(((dds_entity*)entity)->m_hdl, &wr) == DDS_RETCODE_OK) { - assert(wr == entity); - - /* Reset the status. */ - dds_entity_status_reset(entity, data->status); - - /* Reset the change counts of the metrics. */ - switch (data->status) { - case DDS_OFFERED_DEADLINE_MISSED_STATUS: { - wr->m_offered_deadline_missed_status.total_count_change = 0; - break; - } - case DDS_LIVELINESS_LOST_STATUS: { - wr->m_liveliness_lost_status.total_count_change = 0; - break; - } - case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: { - wr->m_offered_incompatible_qos_status.total_count_change = 0; - break; - } - case DDS_PUBLICATION_MATCHED_STATUS: { - wr->m_publication_matched_status.total_count_change = 0; - wr->m_publication_matched_status.current_count_change = 0; - break; - } - default: assert (0); - } - dds_writer_unlock(wr); - } else { - /* There's a deletion or closing going on. */ - } - } else if (rc == DDS_RETCODE_NO_DATA) { - /* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status; consider it successful. */ - dds_entity_status_set(entity, data->status); - /* Notify possible interested observers. */ - dds_entity_status_signal(entity); - } else if (rc == DDS_RETCODE_ALREADY_DELETED) { - /* An entity up the hierarchy is being deleted; consider it successful. */ - } else { - /* Something went wrong up the hierarchy. */ + case DDS_PUBLICATION_MATCHED_STATUS: { + struct dds_publication_matched_status * const st = &wr->m_publication_matched_status; + if (data->add) { + st->total_count++; + st->total_count_change++; + st->current_count++; + st->current_count_change++; + } else { + st->current_count--; + st->current_count_change--; + } + st->last_subscription_handle = data->handle; + metrics = st; + break; } + default: + assert (0); + } + + /* The writer needs to be unlocked when propagating the (possible) listener + * call because the application should be able to call this writer within + * the callback function. */ + dds_writer_unlock (wr); + + /* Is anybody interested within the entity hierarchy through listeners? */ + rc = dds_entity_listener_propagation (entity, entity, data->status, metrics, true); + + if (rc == DDS_RETCODE_OK) + { + /* Event was eaten by a listener. */ + if (dds_writer_lock (entity->m_hdl, &wr) == DDS_RETCODE_OK) + { + assert (&wr->m_entity == entity); + + /* Reset the status. */ + dds_entity_status_reset (entity, data->status); + + /* Reset the change counts of the metrics. */ + switch (data->status) + { + case DDS_OFFERED_DEADLINE_MISSED_STATUS: + wr->m_offered_deadline_missed_status.total_count_change = 0; + break; + case DDS_LIVELINESS_LOST_STATUS: + wr->m_liveliness_lost_status.total_count_change = 0; + break; + case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: + wr->m_offered_incompatible_qos_status.total_count_change = 0; + break; + case DDS_PUBLICATION_MATCHED_STATUS: + wr->m_publication_matched_status.total_count_change = 0; + wr->m_publication_matched_status.current_count_change = 0; + break; + default: + assert (0); + } + dds_writer_unlock (wr); + } + } + else if (rc == DDS_RETCODE_NO_DATA) + { + /* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status; consider it successful. */ + dds_entity_status_set (entity, data->status); + /* Notify possible interested observers. */ + dds_entity_status_signal (entity); + } + else if (rc == DDS_RETCODE_ALREADY_DELETED) + { + /* An entity up the hierarchy is being deleted; consider it successful. */ + } + else + { + /* Something went wrong up the hierarchy. */ + } } static uint32_t @@ -412,7 +427,7 @@ dds_create_writer( dds_writer * wr; dds_entity_t writer; dds_entity * pub = NULL; - dds_entity * tp; + dds_topic * tp; dds_entity_t publisher; struct thread_state1 * const thr = lookup_thread_state(); const bool asleep = !vtime_awake_p(thr->vtime); @@ -420,7 +435,7 @@ dds_create_writer( dds_return_t ret; /* Try claiming a participant. If that's not working, then it could be a subscriber. */ - if(dds_entity_kind(participant_or_publisher) == DDS_KIND_PARTICIPANT){ + if(dds_entity_kind_from_handle(participant_or_publisher) == DDS_KIND_PARTICIPANT){ publisher = dds_create_publisher(participant_or_publisher, qos, NULL); } else{ publisher = participant_or_publisher; @@ -437,14 +452,14 @@ dds_create_writer( pub->m_flags |= DDS_ENTITY_IMPLICIT; } - rc = dds_entity_lock(topic, DDS_KIND_TOPIC, &tp); + rc = dds_topic_lock(topic, &tp); if (rc != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking topic\n"); writer = DDS_ERRNO(rc); goto err_tp_lock; } - assert(((dds_topic*)tp)->m_stopic); - assert(pub->m_domain == tp->m_domain); + assert(tp->m_stopic); + assert(pub->m_domain == tp->m_entity.m_domain); /* Merge Topic & Publisher qos */ wqos = dds_create_qos(); @@ -458,9 +473,9 @@ dds_create_writer( dds_merge_qos(wqos, pub->m_qos); } - if (tp->m_qos) { + if (tp->m_entity.m_qos) { /* merge topic qos data to writer qos */ - dds_merge_qos(wqos, tp->m_qos); + dds_merge_qos(wqos, tp->m_entity.m_qos); } nn_xqos_mergein_missing(wqos, &gv.default_xqos_wr); @@ -475,8 +490,8 @@ dds_create_writer( wr = dds_alloc(sizeof (*wr)); writer = dds_entity_init(&wr->m_entity, pub, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); - wr->m_topic = (dds_topic*)tp; - dds_entity_add_ref_nolock(tp); + wr->m_topic = tp; + dds_entity_add_ref_nolock(&tp->m_entity); wr->m_xp = nn_xpack_new(conn, get_bandwidth_limit(wqos->transport_priority), config.xpack_send_async); wr->m_entity.m_deriver.close = dds_writer_close; wr->m_entity.m_deriver.delete = dds_writer_delete; @@ -491,25 +506,25 @@ dds_create_writer( assert(0); } - os_mutexUnlock(&tp->m_mutex); + os_mutexUnlock(&tp->m_entity.m_mutex); os_mutexUnlock(&pub->m_mutex); if (asleep) { thread_state_awake(thr); } - wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_participant->m_guid, ((dds_topic*)tp)->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); + wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); os_mutexLock(&pub->m_mutex); - os_mutexLock(&tp->m_mutex); + os_mutexLock(&tp->m_entity.m_mutex); assert(wr->m_wr); if (asleep) { thread_state_asleep(thr); } - dds_entity_unlock(tp); + dds_topic_unlock(tp); dds_entity_unlock(pub); return writer; err_bad_qos: - dds_entity_unlock(tp); + dds_topic_unlock(tp); err_tp_lock: dds_entity_unlock(pub); if((pub->m_flags & DDS_ENTITY_IMPLICIT) != 0){ @@ -559,10 +574,10 @@ dds_get_publication_matched_status ( if (status) { *status = wr->m_publication_matched_status; } - if (((dds_entity*)wr)->m_status_enable & DDS_PUBLICATION_MATCHED_STATUS) { + if (wr->m_entity.m_status_enable & DDS_PUBLICATION_MATCHED_STATUS) { wr->m_publication_matched_status.total_count_change = 0; wr->m_publication_matched_status.current_count_change = 0; - dds_entity_status_reset(wr, DDS_PUBLICATION_MATCHED_STATUS); + dds_entity_status_reset(&wr->m_entity, DDS_PUBLICATION_MATCHED_STATUS); } dds_writer_unlock(wr); fail: @@ -589,9 +604,9 @@ dds_get_liveliness_lost_status ( if (status) { *status = wr->m_liveliness_lost_status; } - if (((dds_entity*)wr)->m_status_enable & DDS_LIVELINESS_LOST_STATUS) { + if (wr->m_entity.m_status_enable & DDS_LIVELINESS_LOST_STATUS) { wr->m_liveliness_lost_status.total_count_change = 0; - dds_entity_status_reset(wr, DDS_LIVELINESS_LOST_STATUS); + dds_entity_status_reset(&wr->m_entity, DDS_LIVELINESS_LOST_STATUS); } dds_writer_unlock(wr); fail: @@ -618,9 +633,9 @@ dds_get_offered_deadline_missed_status( if (status) { *status = wr->m_offered_deadline_missed_status; } - if (((dds_entity*)wr)->m_status_enable & DDS_OFFERED_DEADLINE_MISSED_STATUS) { + if (wr->m_entity.m_status_enable & DDS_OFFERED_DEADLINE_MISSED_STATUS) { wr->m_offered_deadline_missed_status.total_count_change = 0; - dds_entity_status_reset(wr, DDS_OFFERED_DEADLINE_MISSED_STATUS); + dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_DEADLINE_MISSED_STATUS); } dds_writer_unlock(wr); fail: @@ -647,9 +662,9 @@ dds_get_offered_incompatible_qos_status ( if (status) { *status = wr->m_offered_incompatible_qos_status; } - if (((dds_entity*)wr)->m_status_enable & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS) { + if (wr->m_entity.m_status_enable & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS) { wr->m_offered_incompatible_qos_status.total_count_change = 0; - dds_entity_status_reset(wr, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS); + dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS); } dds_writer_unlock(wr); fail: diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 0ddb2c3..077a422 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -79,7 +79,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/ddsi" ddsi_tkmap.h probes-constants.h q_addrset.h - q_align.h q_bitset.h q_bswap.h q_config.h diff --git a/src/core/ddsi/include/ddsi/ddsi_tran.h b/src/core/ddsi/include/ddsi/ddsi_tran.h index 5f2fc89..e573591 100644 --- a/src/core/ddsi/include/ddsi/ddsi_tran.h +++ b/src/core/ddsi/include/ddsi/ddsi_tran.h @@ -178,27 +178,6 @@ struct ddsi_tran_qos int m_diffserv; }; -/* Functions and pseudo functions (macro wrappers) */ - -void ddsi_factory_conn_init (ddsi_tran_factory_t, ddsi_tran_conn_t); - -#define ddsi_tran_type(b) (((ddsi_tran_base_t) (b))->m_trantype) -#define ddsi_tran_port(b) (((ddsi_tran_base_t) (b))->m_port) -int ddsi_tran_locator (ddsi_tran_base_t base, nn_locator_t * loc); -void ddsi_tran_free (ddsi_tran_base_t base); -void ddsi_tran_free_qos (ddsi_tran_qos_t qos); -ddsi_tran_qos_t ddsi_tran_create_qos (void); -os_socket ddsi_tran_handle (ddsi_tran_base_t base); - -#define ddsi_factory_create_listener(f,p,q) (((f)->m_create_listener_fn) ((p), (q))) -#define ddsi_factory_supports(f,k) (((f)->m_supports_fn) (k)) - -ddsi_tran_conn_t ddsi_factory_create_conn -( - ddsi_tran_factory_t factory, - uint32_t port, - ddsi_tran_qos_t qos -); void ddsi_tran_factories_fini (void); void ddsi_factory_add (ddsi_tran_factory_t factory); void ddsi_factory_free (ddsi_tran_factory_t factory); @@ -206,24 +185,56 @@ ddsi_tran_factory_t ddsi_factory_find (const char * type); ddsi_tran_factory_t ddsi_factory_find_supported_kind (int32_t kind); void ddsi_factory_conn_init (ddsi_tran_factory_t factory, ddsi_tran_conn_t conn); -#define ddsi_conn_handle(c) (ddsi_tran_handle (&(c)->m_base)) -#define ddsi_conn_locator(c,l) (ddsi_tran_locator (&(c)->m_base,(l))) -OSAPI_EXPORT ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags); -ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc); +inline bool ddsi_factory_supports (ddsi_tran_factory_t factory, int32_t kind) { + return factory->m_supports_fn (kind); +} +inline ddsi_tran_conn_t ddsi_factory_create_conn (ddsi_tran_factory_t factory, uint32_t port, ddsi_tran_qos_t qos) { + return factory->m_create_conn_fn (port, qos); +} +inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, int port, ddsi_tran_qos_t qos) { + return factory->m_create_listener_fn (port, qos); +} + +void ddsi_tran_free (ddsi_tran_base_t base); +void ddsi_tran_free_qos (ddsi_tran_qos_t qos); +ddsi_tran_qos_t ddsi_tran_create_qos (void); +inline os_socket ddsi_tran_handle (ddsi_tran_base_t base) { + return base->m_handle_fn (base); +} +inline int ddsi_tran_locator (ddsi_tran_base_t base, nn_locator_t * loc) { + return base->m_locator_fn (base, loc); +} + +inline os_socket ddsi_conn_handle (ddsi_tran_conn_t conn) { + return conn->m_base.m_handle_fn (&conn->m_base); +} +inline uint32_t ddsi_conn_type (ddsi_tran_conn_t conn) { + return conn->m_base.m_trantype; +} +inline uint32_t ddsi_conn_port (ddsi_tran_conn_t conn) { + return conn->m_base.m_port; +} +inline int ddsi_conn_locator (ddsi_tran_conn_t conn, nn_locator_t * loc) { + return conn->m_base.m_locator_fn (&conn->m_base, loc); +} +inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags) { + return conn->m_closed ? -1 : (conn->m_write_fn) (conn, dst, niov, iov, flags); +} +inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) { + return conn->m_closed ? -1 : conn->m_read_fn (conn, buf, len, srcloc); +} bool ddsi_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * loc); void ddsi_conn_disable_multiplexing (ddsi_tran_conn_t conn); void ddsi_conn_add_ref (ddsi_tran_conn_t conn); void ddsi_conn_free (ddsi_tran_conn_t conn); - int ddsi_conn_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf); int ddsi_conn_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf); - void ddsi_conn_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t newconn); int ddsi_conn_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn); - int ddsi_is_mcaddr (const nn_locator_t *loc); int ddsi_is_ssm_mcaddr (const nn_locator_t *loc); enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]); + enum ddsi_locator_from_string_result ddsi_locator_from_string (nn_locator_t *loc, const char *str); /* 8 for transport/ @@ -242,9 +253,15 @@ char *ddsi_locator_to_string_no_port (char *dst, size_t sizeof_dst, const nn_loc int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, os_ifaddrs_t **interfs); -#define ddsi_listener_locator(s,l) (ddsi_tran_locator (&(s)->m_base,(l))) -ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener); -int ddsi_listener_listen (ddsi_tran_listener_t listener); +inline int ddsi_listener_locator (ddsi_tran_listener_t listener, nn_locator_t * loc) { + return listener->m_base.m_locator_fn (&listener->m_base, loc); +} +inline int ddsi_listener_listen (ddsi_tran_listener_t listener) { + return listener->m_listen_fn (listener); +} +inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener) { + return listener->m_accept_fn (listener); +} void ddsi_listener_unblock (ddsi_tran_listener_t listener); void ddsi_listener_free (ddsi_tran_listener_t listener); diff --git a/src/core/ddsi/include/ddsi/q_align.h b/src/core/ddsi/include/ddsi/q_align.h deleted file mode 100644 index 170936d..0000000 --- a/src/core/ddsi/include/ddsi/q_align.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef NN_ALIGN_H -#define NN_ALIGN_H - -#define ALIGN4(x) (((x) + 3) & -4u) -#define ALIGN8(x) (((x) + 7) & -8u) - -#endif /* NN_ALIGN_H */ diff --git a/src/core/ddsi/include/ddsi/q_bswap.h b/src/core/ddsi/include/ddsi/q_bswap.h index 33e62be..c3ae2a4 100644 --- a/src/core/ddsi/include/ddsi/q_bswap.h +++ b/src/core/ddsi/include/ddsi/q_bswap.h @@ -17,13 +17,14 @@ #include "ddsi/q_rtps.h" /* for nn_guid_t, nn_guid_prefix_t */ #include "ddsi/q_protocol.h" /* for nn_sequence_number_t */ -#define bswap2(x) ((int16_t) bswap2u ((uint16_t) (x))) -#define bswap4(x) ((int32_t) bswap4u ((uint32_t) (x))) -#define bswap8(x) ((int64_t) bswap8u ((uint64_t) (x))) - inline uint16_t bswap2u (uint16_t x) { - return (unsigned short) ((x >> 8) | (x << 8)); + return (uint16_t) ((x >> 8) | (x << 8)); +} + +inline int16_t bswap2 (int16_t x) +{ + return (int16_t) bswap2u ((uint16_t) x); } inline uint32_t bswap4u (uint32_t x) @@ -31,6 +32,11 @@ inline uint32_t bswap4u (uint32_t x) return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24); } +inline int32_t bswap4 (int32_t x) +{ + return (int32_t) bswap4u ((uint32_t) x); +} + inline uint64_t bswap8u (uint64_t x) { const uint32_t newhi = bswap4u ((uint32_t) x); @@ -38,6 +44,11 @@ inline uint64_t bswap8u (uint64_t x) return ((uint64_t) newhi << 32) | (uint64_t) newlo; } +inline int64_t bswap8 (int64_t x) +{ + return (int64_t) bswap8u ((uint64_t) x); +} + inline void bswapSN (nn_sequence_number_t *sn) { sn->high = bswap4 (sn->high); diff --git a/src/core/ddsi/include/ddsi/q_entity.h b/src/core/ddsi/include/ddsi/q_entity.h index fbf99bd..64c3c87 100644 --- a/src/core/ddsi/include/ddsi/q_entity.h +++ b/src/core/ddsi/include/ddsi/q_entity.h @@ -51,7 +51,7 @@ typedef struct status_cb_data } status_cb_data_t; -typedef void (*status_cb_t) (void * entity, const status_cb_data_t * data); +typedef void (*status_cb_t) (void *entity, const status_cb_data_t *data); struct prd_wr_match { ut_avlNode_t avlnode; diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index b538872..e68f201 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -312,6 +312,22 @@ static int ddsi_raweth_is_mcaddr (const ddsi_tran_factory_t tran, const nn_locat return (loc->address[10] & 1); } +static int ddsi_raweth_is_ssm_mcaddr (const ddsi_tran_factory_t tran, const nn_locator_t *loc) +{ + (void) tran; + (void) loc; + return 0; +} + +static enum ddsi_nearby_address_result ddsi_raweth_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]) +{ + (void) tran; + (void) loc; + (void) ninterf; + (void) interf; + return DNAR_LOCAL; +} + static enum ddsi_locator_from_string_result ddsi_raweth_address_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str) { int i = 0; @@ -371,7 +387,8 @@ int ddsi_raweth_init (void) ddsi_raweth_factory_g.m_join_mc_fn = ddsi_raweth_join_mc; ddsi_raweth_factory_g.m_leave_mc_fn = ddsi_raweth_leave_mc; ddsi_raweth_factory_g.m_is_mcaddr_fn = ddsi_raweth_is_mcaddr; - ddsi_raweth_factory_g.m_is_nearby_address_fn = ddsi_ipaddr_is_nearby_address; + ddsi_raweth_factory_g.m_is_ssm_mcaddr_fn = ddsi_raweth_is_ssm_mcaddr; + ddsi_raweth_factory_g.m_is_nearby_address_fn = ddsi_raweth_is_nearby_address; ddsi_raweth_factory_g.m_locator_from_string_fn = ddsi_raweth_address_from_string; ddsi_raweth_factory_g.m_locator_to_string_fn = ddsi_raweth_to_string; ddsi_raweth_factory_g.m_enumerate_interfaces_fn = ddsi_raweth_enumerate_interfaces; diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index c2e54b4..b922578 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -1042,6 +1042,25 @@ static enum ddsi_locator_from_string_result ddsi_tcp_address_from_string (ddsi_t return ddsi_ipaddr_from_string(tran, loc, str, ddsi_tcp_factory_g.m_kind); } +static int ddsi_tcp_is_mcaddr (const ddsi_tran_factory_t tran, const nn_locator_t *loc) +{ + (void) tran; + (void) loc; + return 0; +} + +static int ddsi_tcp_is_ssm_mcaddr (const ddsi_tran_factory_t tran, const nn_locator_t *loc) +{ + (void) tran; + (void) loc; + return 0; +} + +static enum ddsi_nearby_address_result ddsi_tcp_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]) +{ + return ddsi_ipaddr_is_nearby_address(tran, loc, ninterf, interf); +} + int ddsi_tcp_init (void) { static bool init = false; @@ -1063,6 +1082,9 @@ int ddsi_tcp_init (void) ddsi_tcp_factory_g.m_locator_from_string_fn = ddsi_tcp_address_from_string; ddsi_tcp_factory_g.m_locator_to_string_fn = ddsi_ipaddr_to_string; ddsi_tcp_factory_g.m_enumerate_interfaces_fn = ddsi_eth_enumerate_interfaces; + ddsi_tcp_factory_g.m_is_mcaddr_fn = ddsi_tcp_is_mcaddr; + ddsi_tcp_factory_g.m_is_ssm_mcaddr_fn = ddsi_tcp_is_ssm_mcaddr; + ddsi_tcp_factory_g.m_is_nearby_address_fn = ddsi_tcp_is_nearby_address; ddsi_factory_add (&ddsi_tcp_factory_g); #if OS_SOCKET_HAS_IPV6 diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index 990abaf..85c3b8e 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -19,6 +19,21 @@ static ddsi_tran_factory_t ddsi_tran_factories = NULL; +extern inline uint32_t ddsi_conn_type (ddsi_tran_conn_t conn); +extern inline uint32_t ddsi_conn_port (ddsi_tran_conn_t conn); +extern inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, int port, ddsi_tran_qos_t qos); +extern inline bool ddsi_factory_supports (ddsi_tran_factory_t factory, int32_t kind); +extern inline os_socket ddsi_conn_handle (ddsi_tran_conn_t conn); +extern inline int ddsi_conn_locator (ddsi_tran_conn_t conn, nn_locator_t * loc); +extern inline os_socket ddsi_tran_handle (ddsi_tran_base_t base); +extern inline ddsi_tran_conn_t ddsi_factory_create_conn (ddsi_tran_factory_t factory, uint32_t port, ddsi_tran_qos_t qos); +extern inline int ddsi_tran_locator (ddsi_tran_base_t base, nn_locator_t * loc); +extern inline int ddsi_listener_locator (ddsi_tran_listener_t listener, nn_locator_t * loc); +extern inline int ddsi_listener_listen (ddsi_tran_listener_t listener); +extern inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener); +extern inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc); +extern inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags); + void ddsi_factory_add (ddsi_tran_factory_t factory) { factory->m_factory = ddsi_tran_factories; @@ -144,32 +159,6 @@ void ddsi_factory_conn_init (ddsi_tran_factory_t factory, ddsi_tran_conn_t conn) conn->m_factory = factory; } -ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) -{ - return (conn->m_closed) ? -1 : (conn->m_read_fn) (conn, buf, len, srcloc); -} - -ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags) -{ - ssize_t ret = -1; - if (! conn->m_closed) - { - ret = (conn->m_write_fn) (conn, dst, niov, iov, flags); - } - - /* Check that write function is atomic (all or nothing) */ -#ifndef NDEBUG - { - size_t i, len; - for (i = 0, len = 0; i < niov; i++) { - len += iov[i].iov_len; - } - assert (ret == -1 || (size_t) ret == len); - } -#endif - return ret; -} - void ddsi_conn_disable_multiplexing (ddsi_tran_conn_t conn) { if (conn->m_disable_multiplexing_fn) { @@ -202,11 +191,6 @@ int ddsi_conn_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const return conn->m_factory->m_leave_mc_fn (conn, srcloc, mcloc, interf); } -os_socket ddsi_tran_handle (ddsi_tran_base_t base) -{ - return (base->m_handle_fn) (base); -} - ddsi_tran_qos_t ddsi_tran_create_qos (void) { ddsi_tran_qos_t qos; @@ -215,31 +199,6 @@ ddsi_tran_qos_t ddsi_tran_create_qos (void) return qos; } -ddsi_tran_conn_t ddsi_factory_create_conn -( - ddsi_tran_factory_t factory, - uint32_t port, - ddsi_tran_qos_t qos -) -{ - return factory->m_create_conn_fn (port, qos); -} - -int ddsi_tran_locator (ddsi_tran_base_t base, nn_locator_t * loc) -{ - return (base->m_locator_fn) (base, loc); -} - -int ddsi_listener_listen (ddsi_tran_listener_t listener) -{ - return (listener->m_listen_fn) (listener); -} - -ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener) -{ - return (listener->m_accept_fn) (listener); -} - void ddsi_tran_free (ddsi_tran_base_t base) { if (base) @@ -274,21 +233,20 @@ void ddsi_listener_free (ddsi_tran_listener_t listener) int ddsi_is_mcaddr (const nn_locator_t *loc) { - /* FIXME: should set m_is_mcaddr_fn to a function returning false if transport doesn't provide an implementation, and get rid of the test */ - ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(loc->kind); - return tran && tran->m_is_mcaddr_fn ? tran->m_is_mcaddr_fn (tran, loc) : 0; + ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind (loc->kind); + return tran ? tran->m_is_mcaddr_fn (tran, loc) : 0; } int ddsi_is_ssm_mcaddr (const nn_locator_t *loc) { ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(loc->kind); - return tran && tran->m_is_ssm_mcaddr_fn ? tran->m_is_ssm_mcaddr_fn (tran, loc) : 0; + return tran ? tran->m_is_ssm_mcaddr_fn (tran, loc) : 0; } enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]) { ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(loc->kind); - return tran->m_is_nearby_address_fn ? tran->m_is_nearby_address_fn (tran, loc, ninterf, interf) : DNAR_DISTANT; + return tran ? tran->m_is_nearby_address_fn (tran, loc, ninterf, interf) : DNAR_DISTANT; } enum ddsi_locator_from_string_result ddsi_locator_from_string (nn_locator_t *loc, const char *str) diff --git a/src/core/ddsi/src/q_bswap_inlines.c b/src/core/ddsi/src/q_bswap_inlines.c index ed2c5d0..1ac45d5 100644 --- a/src/core/ddsi/src/q_bswap_inlines.c +++ b/src/core/ddsi/src/q_bswap_inlines.c @@ -14,5 +14,8 @@ extern inline uint16_t bswap2u (uint16_t x); extern inline uint32_t bswap4u (uint32_t x); extern inline uint64_t bswap8u (uint64_t x); +extern inline int16_t bswap2 (int16_t x); +extern inline int32_t bswap4 (int32_t x); +extern inline int64_t bswap8 (int64_t x); extern inline void bswapSN (nn_sequence_number_t *sn); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index c0758bd..3ba7d69 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -29,7 +29,6 @@ #include "ddsi/q_lat_estim.h" #include "ddsi/q_bitset.h" #include "ddsi/q_xevent.h" -#include "ddsi/q_align.h" #include "ddsi/q_addrset.h" #include "ddsi/q_ddsi_discovery.h" #include "ddsi/q_radmin.h" @@ -680,7 +679,7 @@ int create_multicast_sockets(void) gv.disc_conn_mc = disc; gv.data_conn_mc = data; DDS_TRACE("Multicast Ports: discovery %d data %d \n", - ddsi_tran_port (gv.disc_conn_mc), ddsi_tran_port (gv.data_conn_mc)); + ddsi_conn_port (gv.disc_conn_mc), ddsi_conn_port (gv.data_conn_mc)); return 1; err_data: @@ -1113,7 +1112,7 @@ int rtps_init (void) if (gv.m_factory->m_connless) { if (!(config.many_sockets_mode == MSM_NO_UNICAST && config.allowMulticast)) - DDS_TRACE("Unicast Ports: discovery %d data %d\n", ddsi_tran_port (gv.disc_conn_uc), ddsi_tran_port (gv.data_conn_uc)); + DDS_TRACE("Unicast Ports: discovery %d data %d\n", ddsi_conn_port (gv.disc_conn_uc), ddsi_conn_port (gv.data_conn_uc)); if (config.allowMulticast) { @@ -1128,11 +1127,11 @@ int rtps_init (void) /* Set multicast locators */ if (!is_unspec_locator(&gv.loc_spdp_mc)) - gv.loc_spdp_mc.port = ddsi_tran_port (gv.disc_conn_mc); + gv.loc_spdp_mc.port = ddsi_conn_port (gv.disc_conn_mc); if (!is_unspec_locator(&gv.loc_meta_mc)) - gv.loc_meta_mc.port = ddsi_tran_port (gv.disc_conn_mc); + gv.loc_meta_mc.port = ddsi_conn_port (gv.disc_conn_mc); if (!is_unspec_locator(&gv.loc_default_mc)) - gv.loc_default_mc.port = ddsi_tran_port (gv.data_conn_mc); + gv.loc_default_mc.port = ddsi_conn_port (gv.data_conn_mc); if (joinleave_spdp_defmcip (1) < 0) goto err_mc_conn; @@ -1167,7 +1166,7 @@ int rtps_init (void) /* Create shared transmit connection */ gv.tev_conn = gv.data_conn_uc; - DDS_TRACE("Timed event transmit port: %d\n", (int) ddsi_tran_port (gv.tev_conn)); + DDS_TRACE("Timed event transmit port: %d\n", (int) ddsi_conn_port (gv.tev_conn)); #ifdef DDSI_INCLUDE_NETWORK_CHANNELS { diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 7594705..72e2da7 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -21,7 +21,6 @@ #include "ddsi/q_bswap.h" #include "ddsi/q_unused.h" -#include "ddsi/q_align.h" #include "ddsi/q_error.h" #include "ddsi/q_plist.h" #include "ddsi/q_time.h" diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 99a1869..73b8cf0 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -32,7 +32,6 @@ #include "ddsi/q_config.h" #include "ddsi/q_log.h" -#include "ddsi/q_align.h" #include "ddsi/q_plist.h" #include "ddsi/q_unused.h" #include "ddsi/q_radmin.h" diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index a9a6200..542a408 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -30,7 +30,6 @@ #include "ddsi/q_lat_estim.h" #include "ddsi/q_bitset.h" #include "ddsi/q_xevent.h" -#include "ddsi/q_align.h" #include "ddsi/q_addrset.h" #include "ddsi/q_ddsi_discovery.h" #include "ddsi/q_radmin.h" diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 9e5c232..5d1e95c 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -34,7 +34,6 @@ #include "ddsi/q_log.h" #include "ddsi/q_unused.h" #include "ddsi/q_xmsg.h" -#include "ddsi/q_align.h" #include "ddsi/q_config.h" #include "ddsi/q_entity.h" #include "ddsi/q_globals.h" @@ -1339,7 +1338,18 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg) #endif { if (!gv.mute) + { nbytes = ddsi_conn_write (xp->conn, loc, xp->niov, xp->iov, xp->call_flags); +#ifndef NDEBUG + { + size_t i, len; + for (i = 0, len = 0; i < xp->niov; i++) { + len += xp->iov[i].iov_len; + } + assert (nbytes == -1 || (size_t) nbytes == len); + } +#endif + } else { DDS_TRACE("(dropped)"); From 0057896bebe7bd9d1924cde2f064fc571d9b6ed3 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 10 Jan 2019 10:55:29 +0100 Subject: [PATCH 02/10] skip testing lookup of an invalid hostname, it times out in some configurations Signed-off-by: Erik Boasson --- src/os/tests/socket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/os/tests/socket.c b/src/os/tests/socket.c index 55abed1..7fe52c7 100644 --- a/src/os/tests/socket.c +++ b/src/os/tests/socket.c @@ -140,9 +140,9 @@ static void gethostbyname_test(char *name, int af, int ret) } CU_TheoryDataPoints(os_gethostbyname, ipv4) = { - CU_DataPoints(char *, "", "_nah", "127.0.0.1", "127.0.0.1"), - CU_DataPoints(int, AF_UNSPEC, AF_UNSPEC, AF_INET, AF_UNSPEC), - CU_DataPoints(int, OS_HOST_NOT_FOUND, OS_HOST_NOT_FOUND, 0, 0) + CU_DataPoints(char *, "", "127.0.0.1", "127.0.0.1"), + CU_DataPoints(int, AF_UNSPEC, AF_INET, AF_UNSPEC), + CU_DataPoints(int, OS_HOST_NOT_FOUND, 0, 0) }; CU_Theory((char *name, int af, int ret), os_gethostbyname, ipv4, .init=setup, .fini=teardown) From 14a80978f3b251abab2a1446c1fb78f7a79d17b1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 15 Jan 2019 09:54:02 +0100 Subject: [PATCH 03/10] enable tons of warnings in Xcode Signed-off-by: Erik Boasson --- src/CMakeLists.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6fcb572..9de5427 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -98,6 +98,38 @@ elseif(${CMAKE_C_COMPILER_ID} STREQUAL "MSVC") add_definitions(/W3) endif() +# I don't know how to enable warnings properly so that it ends up in Xcode projects as well +if(${CMAKE_GENERATOR} STREQUAL "Xcode") + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_EMPTY_BODY YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_SHADOW YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_BOOL_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_CONSTANT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_64_TO_32_BIT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_ENUM_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_FLOAT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_INT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_NON_LITERAL_NULL_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_IMPLICIT_SIGN_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_INFINITE_RECURSION YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_RETURN_TYPE YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_MISSING_PARENTHESES YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_NEWLINE YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_ASSIGN_ENUM YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_SIGN_COMPARE YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_STRICT_PROTOTYPES YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_COMMA YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNINITIALIZED_AUTOS YES_AGGRESSIVE) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_FUNCTION YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_LABEL YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_PARAMETER YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VALUE YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VARIABLE YES) +endif() + # Make it easy to enable one of Clang's/gcc's analyzers, and default to using # the address sanitizer for ordinary debug builds; gcc is giving some grief on # Travis, so don't enable it for gcc by default From 2e5ecb2e766a0aba2c1d1effba7305b2edd58092 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 15 Jan 2019 09:57:06 +0100 Subject: [PATCH 04/10] requiring checking the return value of dds_{get,set}_listener is pedantry Signed-off-by: Erik Boasson --- src/core/ddsc/include/ddsc/dds.h | 4 ++-- src/core/ddsc/src/dds_entity.c | 15 ++------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/core/ddsc/include/ddsc/dds.h b/src/core/ddsc/include/ddsc/dds.h index 65ebead..6c378a2 100644 --- a/src/core/ddsc/include/ddsc/dds.h +++ b/src/core/ddsc/include/ddsc/dds.h @@ -685,7 +685,7 @@ dds_set_qos( */ /* TODO: Link to (generic) Listener and status information. */ _Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -DDS_EXPORT _Check_return_ dds_return_t +DDS_EXPORT dds_return_t dds_get_listener( _In_ dds_entity_t entity, _Out_ dds_listener_t * listener); @@ -744,7 +744,7 @@ dds_get_listener( */ /* TODO: Link to (generic) Listener and status information. */ _Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -DDS_EXPORT _Check_return_ dds_return_t +DDS_EXPORT dds_return_t dds_set_listener( _In_ dds_entity_t entity, _In_opt_ const dds_listener_t * listener); diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 7e679f7..843405e 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -480,12 +480,7 @@ dds_get_parent( return hdl; } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_entity_t -dds_get_participant ( - _In_ dds_entity_t entity) +dds_return_t dds_get_listener (dds_entity_t entity, dds_listener_t *listener) { dds_entity *e; dds__retcode_t rc; @@ -663,13 +658,7 @@ dds_get_listener( return ret; } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_set_listener( - _In_ dds_entity_t entity, - _In_opt_ const dds_listener_t * listener) +dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listener) { dds_entity *e; dds__retcode_t rc; From ba46cb1140ea86c7e5321e27bc6a20dedb745ff4 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 15 Jan 2019 10:04:30 +0100 Subject: [PATCH 05/10] rework listener invocation and entity status flags Listener/status management invocation was rather expensive, and especially the cost of checking listeners, then setting status flags and triggering waitsets ran into severe lock contention. A major cost was the repeated use of dds_entity_lock and dds_entity_unlock, these have been eliminated. Another cost was that each time an event occurred (with DATA_AVAILABLE the most problematic one) it would walk the chain of ancestors to see if any had a relevant listener, and only if none of them had any, it would set the status flags. The locking/unlocking of the entity has been eliminated by moving the listener/status flag manipulation from the general entity lock to its m_observers_lock. That lock has a much smaller scope, and consequently contention has been significantly reduced. Instead of walking the entity hierarchy looking for listeners, an entity now inherits the ancestors' listeners. The set_listener operation has been made a little more complicated by the need to not only set the listeners for the specified entity, but to also update any inherited listeners its descendants. The commit is a bit larger than strictly needed ... I've started reformatting the code to reduce the variety of styles ... as there I haven't been able to find a single tool that does what I want, it may well end up as manual work. Signed-off-by: Erik Boasson --- .../ddsc/include/ddsc/dds_public_listener.h | 14 +- src/core/ddsc/src/dds__entity.h | 20 +- src/core/ddsc/src/dds__listener.h | 7 +- src/core/ddsc/src/dds__reader.h | 2 + src/core/ddsc/src/dds__types.h | 57 +- src/core/ddsc/src/dds_entity.c | 2044 +++++++---------- src/core/ddsc/src/dds_guardcond.c | 160 +- src/core/ddsc/src/dds_listener.c | 295 +-- src/core/ddsc/src/dds_reader.c | 342 +-- src/core/ddsc/src/dds_rhc.c | 4 +- src/core/ddsc/src/dds_subscriber.c | 21 - src/core/ddsc/src/dds_topic.c | 64 +- src/core/ddsc/src/dds_waitset.c | 56 +- src/core/ddsc/src/dds_writer.c | 110 +- 14 files changed, 1401 insertions(+), 1795 deletions(-) diff --git a/src/core/ddsc/include/ddsc/dds_public_listener.h b/src/core/ddsc/include/ddsc/dds_public_listener.h index e3aa792..bec465b 100644 --- a/src/core/ddsc/include/ddsc/dds_public_listener.h +++ b/src/core/ddsc/include/ddsc/dds_public_listener.h @@ -44,16 +44,9 @@ typedef void (*dds_on_requested_incompatible_qos_fn) (dds_entity_t reader, const typedef void (*dds_on_publication_matched_fn) (dds_entity_t writer, const dds_publication_matched_status_t status, void* arg); typedef void (*dds_on_subscription_matched_fn) (dds_entity_t reader, const dds_subscription_matched_status_t status, void* arg); -#if 0 -/* TODO: Why use (*dds_on_any_fn) (); and DDS_LUNSET? Why not just set the callbacks to NULL? */ -typedef void (*dds_on_any_fn) (); /**< Empty parameter list on purpose; should be assignable without cast to all of the above. @todo check with an actual compiler; I'm a sloppy compiler */ -#define DDS_LUNSET ((dds_on_any_fn)1) /**< Callback indicating a callback isn't set */ -#else -#define DDS_LUNSET (NULL) -#endif - -struct c_listener; -typedef struct c_listener dds_listener_t; +#define DDS_LUNSET 0 +struct dds_listener; +typedef struct dds_listener dds_listener_t; /** * @brief Allocate memory and initializes to default values (::DDS_LUNSET) of a listener @@ -104,7 +97,6 @@ DDS_DEPRECATED_EXPORT void dds_listener_copy (_Out_ dds_listener_t * __restrict DDS_EXPORT void dds_merge_listener (_Inout_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src); DDS_DEPRECATED_EXPORT void dds_listener_merge (_Inout_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src); - /************************************************************************************************ * Setters ************************************************************************************************/ diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 62285c9..ac92fee 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -37,14 +37,6 @@ void dds_entity_add_ref_nolock( _In_ dds_entity *e); -_Check_return_ dds__retcode_t -dds_entity_listener_propagation( - _Inout_opt_ dds_entity *e, - _In_ dds_entity *src, - _In_ uint32_t status, - _In_opt_ void *metrics, - _In_ bool propagate); - #define DEFINE_ENTITY_LOCK_UNLOCK(qualifier_, type_, kind_) \ qualifier_ dds__retcode_t type_##_lock (dds_entity_t hdl, type_ **x) \ { \ @@ -68,9 +60,7 @@ inline bool dds_entity_is_enabled (const dds_entity *e) { return (e->m_flags & DDS_ENTITY_ENABLED) != 0; } -inline void dds_entity_status_set (dds_entity *e, uint32_t t) { - e->m_trigger |= e->m_status_enable & t; -} +void dds_entity_status_set (dds_entity *e, uint32_t t); inline void dds_entity_status_reset (dds_entity *e, uint32_t t) { e->m_trigger &= ~t; @@ -88,11 +78,9 @@ inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl) { return (hdl > 0) ? (dds_entity_kind_t) (hdl & DDS_ENTITY_KIND_MASK) : DDS_KIND_DONTCARE; } -/* The mutex needs to be unlocked when calling this because the entity can be called - * within the signal callback from other contexts. That shouldn't deadlock. */ -void -dds_entity_status_signal( - _In_ dds_entity *e); +void dds_entity_status_signal (dds_entity *e); + +void dds_entity_invoke_listener (const dds_entity *entity, uint32_t status, const void *vst); _Check_return_ dds__retcode_t dds_valid_hdl( diff --git a/src/core/ddsc/src/dds__listener.h b/src/core/ddsc/src/dds__listener.h index b25453b..2d3ee90 100644 --- a/src/core/ddsc/src/dds__listener.h +++ b/src/core/ddsc/src/dds__listener.h @@ -19,11 +19,8 @@ extern "C" { #endif -/* - * Listener API (internal & external) are present in - * dds__types.h - * ddsc/dds_public_listener.h - */ +void dds_override_inherited_listener (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src); +void dds_inherit_listener (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src); #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__reader.h b/src/core/ddsc/src/dds__reader.h index 48b1168..5c9684b 100644 --- a/src/core/ddsc/src/dds__reader.h +++ b/src/core/ddsc/src/dds__reader.h @@ -23,6 +23,8 @@ struct status_cb_data; void dds_reader_status_cb (void *entity, const struct status_cb_data * data); +void dds_reader_data_available_cb (struct dds_reader *entity); + /* dds_reader_lock_samples: Returns number of samples in read cache and locks the reader cache to make sure that the samples content doesn't change. diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 78b4665..4b4cb03 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -59,22 +59,35 @@ typedef bool (*dds_querycondition_filter_with_ctx_fn) (const void * sample, cons /* The listener struct. */ -typedef struct c_listener { - dds_on_inconsistent_topic_fn on_inconsistent_topic; - dds_on_liveliness_lost_fn on_liveliness_lost; - dds_on_offered_deadline_missed_fn on_offered_deadline_missed; - dds_on_offered_incompatible_qos_fn on_offered_incompatible_qos; - dds_on_data_on_readers_fn on_data_on_readers; - dds_on_sample_lost_fn on_sample_lost; - dds_on_data_available_fn on_data_available; - dds_on_sample_rejected_fn on_sample_rejected; - dds_on_liveliness_changed_fn on_liveliness_changed; - dds_on_requested_deadline_missed_fn on_requested_deadline_missed; - dds_on_requested_incompatible_qos_fn on_requested_incompatible_qos; - dds_on_publication_matched_fn on_publication_matched; - dds_on_subscription_matched_fn on_subscription_matched; - void *arg; -} c_listener_t; +struct dds_listener { + uint32_t inherited; + dds_on_inconsistent_topic_fn on_inconsistent_topic; + void *on_inconsistent_topic_arg; + dds_on_liveliness_lost_fn on_liveliness_lost; + void *on_liveliness_lost_arg; + dds_on_offered_deadline_missed_fn on_offered_deadline_missed; + void *on_offered_deadline_missed_arg; + dds_on_offered_incompatible_qos_fn on_offered_incompatible_qos; + void *on_offered_incompatible_qos_arg; + dds_on_data_on_readers_fn on_data_on_readers; + void *on_data_on_readers_arg; + dds_on_sample_lost_fn on_sample_lost; + void *on_sample_lost_arg; + dds_on_data_available_fn on_data_available; + void *on_data_available_arg; + dds_on_sample_rejected_fn on_sample_rejected; + void *on_sample_rejected_arg; + dds_on_liveliness_changed_fn on_liveliness_changed; + void *on_liveliness_changed_arg; + dds_on_requested_deadline_missed_fn on_requested_deadline_missed; + void *on_requested_deadline_missed_arg; + dds_on_requested_incompatible_qos_fn on_requested_incompatible_qos; + void *on_requested_incompatible_qos_arg; + dds_on_publication_matched_fn on_publication_matched; + void *on_publication_matched_arg; + dds_on_subscription_matched_fn on_subscription_matched; + void *on_subscription_matched_arg; +}; /* Entity flag values */ @@ -98,7 +111,6 @@ typedef struct dds_entity_deriver { dds_return_t (*delete)(struct dds_entity *e); dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled); dds_return_t (*validate_status)(uint32_t mask); - dds_return_t (*propagate_status)(struct dds_entity *e, uint32_t mask, bool set); dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i); } dds_entity_deriver; @@ -126,15 +138,18 @@ typedef struct dds_entity dds_qos_t * m_qos; dds_domainid_t m_domainid; nn_guid_t m_guid; - uint32_t m_status_enable; uint32_t m_flags; - uint32_t m_cb_count; os_mutex m_mutex; os_cond m_cond; - c_listener_t m_listener; - uint32_t m_trigger; + os_mutex m_observers_lock; + os_cond m_observers_cond; + dds_listener_t m_listener; + uint32_t m_trigger; + uint32_t m_status_enable; + uint32_t m_cb_count; dds_entity_observer *m_observers; + struct ut_handlelink *m_hdllink; } dds_entity; diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 843405e..71fc819 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -24,1301 +24,1011 @@ #error "DDS_ENTITY_KIND_MASK != UT_HANDLE_KIND_MASK" #endif - extern inline bool dds_entity_is_enabled (const dds_entity *e); -extern inline void dds_entity_status_set (dds_entity *e, uint32_t t); extern inline void dds_entity_status_reset (dds_entity *e, uint32_t t); extern inline bool dds_entity_status_match (const dds_entity *e, uint32_t t); extern inline dds_entity_kind_t dds_entity_kind (const dds_entity *e); extern inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl); -static void -dds_entity_observers_delete( - _In_ dds_entity *observed); +static void dds_entity_observers_signal (dds_entity *observed, uint32_t status); +static void dds_entity_observers_delete (dds_entity *observed); -static void -dds_entity_observers_signal( - _In_ dds_entity *observed, - _In_ uint32_t status); - -void -dds_entity_add_ref(_In_ dds_entity * e) +void dds_entity_add_ref_nolock (dds_entity *e) { - assert (e); - os_mutexLock (&e->m_mutex); - e->m_refc++; - os_mutexUnlock (&e->m_mutex); + e->m_refc++; } -dds_domain * -dds__entity_domain(_In_ dds_entity* e) +void dds_entity_add_ref (dds_entity *e) { - return e->m_domain; + os_mutexLock (&e->m_mutex); + dds_entity_add_ref_nolock (e); + os_mutexUnlock (&e->m_mutex); } -static void -dds_set_explicit( - _In_ dds_entity_t entity); - -/*This function returns the parent entity of e. If e is a participant it returns NULL*/ -_Ret_maybenull_ -static dds_entity * -dds__nonself_parent( - _In_ dds_entity *e){ - return e->m_parent == e ? NULL : e->m_parent; +dds_domain *dds__entity_domain (dds_entity *e) +{ + return e->m_domain; } -void -dds_entity_add_ref_nolock(_In_ dds_entity *e) +static void dds_set_explicit (dds_entity_t entity) { - assert(e); - e->m_refc++; + dds_entity *e; + dds__retcode_t rc; + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) == DDS_RETCODE_OK) + { + e->m_flags &= ~DDS_ENTITY_IMPLICIT; + dds_entity_unlock (e); + } } -_Check_return_ dds__retcode_t -dds_entity_listener_propagation( - _Inout_opt_ dds_entity *e, - _In_ dds_entity *src, - _In_ uint32_t status, - _In_opt_ void *metrics, - _In_ bool propagate) +static dds_entity *dds__nonself_parent (dds_entity *e) { - dds__retcode_t rc = DDS_RETCODE_NO_DATA; /* Mis-use NO_DATA as NO_CALL. */ - dds_entity *dummy; - /* e will be NULL when reaching the top of the entity hierarchy. */ - if (e) { - rc = dds_entity_lock(e->m_hdl, DDS_KIND_DONTCARE, &dummy); - if (rc == DDS_RETCODE_OK) { - dds_listener_t *l = &e->m_listener; - - assert(e == dummy); - - /* Indicate that a callback will be in progress, so that a parallel - * delete/set_listener will wait. */ - e->m_cb_count++; - - /* Calling the actual listener should be done unlocked. */ - dds_entity_unlock(e); - - /* Now, perform the callback when available. */ - rc = DDS_RETCODE_NO_DATA; - switch (status) { - case DDS_INCONSISTENT_TOPIC_STATUS: - if (l->on_inconsistent_topic != DDS_LUNSET) { - assert(metrics); - l->on_inconsistent_topic(src->m_hdl, *((dds_inconsistent_topic_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_OFFERED_DEADLINE_MISSED_STATUS: - if (l->on_offered_deadline_missed != DDS_LUNSET) { - assert(metrics); - l->on_offered_deadline_missed(src->m_hdl, *((dds_offered_deadline_missed_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_REQUESTED_DEADLINE_MISSED_STATUS: - if (l->on_requested_deadline_missed != DDS_LUNSET) { - assert(metrics); - l->on_requested_deadline_missed(src->m_hdl, *((dds_requested_deadline_missed_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: - if (l->on_offered_incompatible_qos != DDS_LUNSET) { - assert(metrics); - l->on_offered_incompatible_qos(src->m_hdl, *((dds_offered_incompatible_qos_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: - if (l->on_requested_incompatible_qos != DDS_LUNSET) { - assert(metrics); - l->on_requested_incompatible_qos(src->m_hdl, *((dds_requested_incompatible_qos_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_SAMPLE_LOST_STATUS: - if (l->on_sample_lost != DDS_LUNSET) { - assert(metrics); - l->on_sample_lost(src->m_hdl, *((dds_sample_lost_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_SAMPLE_REJECTED_STATUS: - if (l->on_sample_rejected != DDS_LUNSET) { - assert(metrics); - l->on_sample_rejected(src->m_hdl, *((dds_sample_rejected_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_DATA_ON_READERS_STATUS: - if (l->on_data_on_readers != DDS_LUNSET) { - l->on_data_on_readers(src->m_hdl, l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_DATA_AVAILABLE_STATUS: - if (l->on_data_available != DDS_LUNSET) { - l->on_data_available(src->m_hdl, l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_LIVELINESS_LOST_STATUS: - if (l->on_liveliness_lost != DDS_LUNSET) { - assert(metrics); - l->on_liveliness_lost(src->m_hdl, *((dds_liveliness_lost_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_LIVELINESS_CHANGED_STATUS: - if (l->on_liveliness_changed != DDS_LUNSET) { - assert(metrics); - l->on_liveliness_changed(src->m_hdl, *((dds_liveliness_changed_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_PUBLICATION_MATCHED_STATUS: - if (l->on_publication_matched != DDS_LUNSET) { - assert(metrics); - l->on_publication_matched(src->m_hdl, *((dds_publication_matched_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - case DDS_SUBSCRIPTION_MATCHED_STATUS: - if (l->on_subscription_matched != DDS_LUNSET) { - assert(metrics); - l->on_subscription_matched(src->m_hdl, *((dds_subscription_matched_status_t*)metrics), l->arg); - rc = DDS_RETCODE_OK; - } - break; - default: assert (0); - } - if ((rc == DDS_RETCODE_NO_DATA) && propagate) { - /* See if the parent is interested. */ - rc = dds_entity_listener_propagation(dds__nonself_parent(e), src, status, metrics, propagate); - } - - os_mutexLock(&(e->m_mutex)); - /* We are done with our callback. */ - e->m_cb_count--; - /* Wake up possible waiting threads. */ - os_condBroadcast(&e->m_cond); - os_mutexUnlock(&(e->m_mutex)); - } - } - return rc; + return e->m_parent == e ? NULL : e->m_parent; } - -static void -dds_entity_cb_wait (_In_ dds_entity *e) +dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind_t kind, dds_qos_t *qos, const dds_listener_t *listener, uint32_t mask) { - while (e->m_cb_count > 0) { - os_condWait (&e->m_cond, &e->m_mutex); - } -} + assert ((kind == DDS_KIND_PARTICIPANT) == (parent == NULL)); + assert (e); + e->m_refc = 1; + e->m_qos = qos; + e->m_cb_count = 0; + e->m_observers = NULL; + e->m_trigger = 0; + /* TODO: CHAM-96: Implement dynamic enabling of entity. */ + e->m_flags |= DDS_ENTITY_ENABLED; -_Check_return_ dds_entity_t -dds_entity_init( - _In_ dds_entity * e, - _When_(kind != DDS_KIND_PARTICIPANT, _Notnull_) - _When_(kind == DDS_KIND_PARTICIPANT, _Null_) - _In_opt_ dds_entity * parent, - _In_ dds_entity_kind_t kind, - _In_opt_ dds_qos_t * qos, - _In_opt_ const dds_listener_t *listener, - _In_ uint32_t mask) -{ - assert (e); + /* set the status enable based on kind */ + e->m_status_enable = mask | DDS_INTERNAL_STATUS_MASK; - e->m_refc = 1; - e->m_qos = qos; - e->m_cb_count = 0; - e->m_observers = NULL; - e->m_trigger = 0; + os_mutexInit (&e->m_mutex); + os_mutexInit (&e->m_observers_lock); + os_condInit (&e->m_cond, &e->m_mutex); + os_condInit (&e->m_observers_cond, &e->m_observers_lock); - /* TODO: CHAM-96: Implement dynamic enabling of entity. */ - e->m_flags |= DDS_ENTITY_ENABLED; + if (parent) + { + e->m_parent = parent; + e->m_domain = parent->m_domain; + e->m_domainid = parent->m_domainid; + e->m_participant = parent->m_participant; + e->m_next = parent->m_children; + parent->m_children = e; + } + else + { + e->m_participant = e; + e->m_parent = e; + } - /* set the status enable based on kind */ - e->m_status_enable = mask | DDS_INTERNAL_STATUS_MASK; + dds_reset_listener (&e->m_listener); + if (listener) + dds_merge_listener (&e->m_listener, listener); + if (parent) + { + os_mutexLock (&e->m_observers_lock); + dds_inherit_listener (&e->m_listener, &parent->m_listener); + os_mutexUnlock (&e->m_observers_lock); + } - os_mutexInit (&e->m_mutex); - os_mutexInit (&e->m_observers_lock); - os_condInit (&e->m_cond, &e->m_mutex); - - if (parent) { - e->m_parent = parent; - e->m_domain = parent->m_domain; - e->m_domainid = parent->m_domainid; - e->m_participant = parent->m_participant; - e->m_next = parent->m_children; - parent->m_children = e; + e->m_hdllink = NULL; + e->m_hdl = ut_handle_create ((int32_t) kind, e); + if (e->m_hdl > 0) + { + e->m_hdllink = ut_handle_get_link (e->m_hdl); + assert(e->m_hdllink); + } + else + { + if (e->m_hdl == UT_HANDLE_OUT_OF_RESOURCES) { + DDS_ERROR ("Can not create new entity; too many where created previously\n"); + e->m_hdl = DDS_ERRNO (DDS_RETCODE_OUT_OF_RESOURCES); + } else if (e->m_hdl == UT_HANDLE_NOT_INITALIZED) { + DDS_ERROR (DDSC_PROJECT_NAME" is not yet initialized. Please create a participant before executing an other method\n"); + e->m_hdl = DDS_ERRNO (DDS_RETCODE_PRECONDITION_NOT_MET); } else { - assert (kind == DDS_KIND_PARTICIPANT); - e->m_participant = e; - e->m_parent = e; + DDS_ERROR ("An internal error has occurred\n"); + e->m_hdl = DDS_ERRNO (DDS_RETCODE_ERROR); } + } - if (listener) { - dds_copy_listener(&e->m_listener, listener); - } else { - dds_reset_listener(&e->m_listener); - } - - e->m_hdllink = NULL; - e->m_hdl = ut_handle_create((int32_t)kind, e); - if (e->m_hdl > 0) { - e->m_hdllink = ut_handle_get_link(e->m_hdl); - assert(e->m_hdllink); - } else{ - if (e->m_hdl == UT_HANDLE_OUT_OF_RESOURCES) { - DDS_ERROR("Can not create new entity; too many where created previously\n"); - e->m_hdl = DDS_ERRNO(DDS_RETCODE_OUT_OF_RESOURCES); - } else if (e->m_hdl == UT_HANDLE_NOT_INITALIZED) { - DDS_ERROR(DDSC_PROJECT_NAME" is not yet initialized. Please create a participant before executing an other method\n"); - e->m_hdl = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); - } else { - DDS_ERROR("An internal error has occurred\n"); - e->m_hdl = DDS_ERRNO(DDS_RETCODE_ERROR); - } - } - - /* An ut_handle_t is directly used as dds_entity_t. */ - return (dds_entity_t)(e->m_hdl); + /* An ut_handle_t is directly used as dds_entity_t. */ + return (dds_entity_t) e->m_hdl; } - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -dds_return_t -dds_delete( - _In_ dds_entity_t entity) +dds_return_t dds_delete (dds_entity_t entity) { - dds_return_t ret; - - ret = dds_delete_impl(entity, false); - - return ret; + return dds_delete_impl (entity, false); } - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -dds_return_t -dds_delete_impl( - _In_ dds_entity_t entity, - _In_ bool keep_if_explicit) +static dds_entity *next_non_topic_child (dds_entity *remaining_children) { - os_time timeout = { 10, 0 }; - dds_entity *e; - dds_entity *child; - dds_entity *parent; - dds_entity *prev = NULL; - dds_entity *next = NULL; - dds_return_t ret = DDS_RETCODE_OK; - dds__retcode_t rc; + while (remaining_children != NULL && dds_entity_kind (remaining_children) == DDS_KIND_TOPIC) + remaining_children = remaining_children->m_next; + return remaining_children; +} - rc = dds_entity_lock(entity, UT_HANDLE_DONTCARE_KIND, &e); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error on locking entity\n"); - return DDS_ERRNO(rc); - } +dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) +{ + os_time timeout = { 10, 0 }; + dds_entity *e; + dds_entity *child; + dds_entity *parent; + dds_entity *prev = NULL; + dds_entity *next = NULL; + dds_return_t ret; + dds__retcode_t rc; - if(keep_if_explicit == true && ((e->m_flags & DDS_ENTITY_IMPLICIT) == 0)){ - dds_entity_unlock(e); - return DDS_RETCODE_OK; - } - - if (--e->m_refc != 0) { - dds_entity_unlock(e); - return DDS_RETCODE_OK; - } - - dds_entity_cb_wait(e); - - ut_handle_close(e->m_hdl, e->m_hdllink); - e->m_status_enable = 0; - dds_reset_listener(&e->m_listener); - e->m_trigger |= DDS_DELETING_STATUS; + rc = dds_entity_lock (entity, UT_HANDLE_DONTCARE_KIND, &e); + if (rc != DDS_RETCODE_OK) + { + DDS_ERROR ("Error on locking entity\n"); + return DDS_ERRNO (rc); + } + if (keep_if_explicit == true && (e->m_flags & DDS_ENTITY_IMPLICIT) == 0) + { dds_entity_unlock(e); + return DDS_RETCODE_OK; + } - /* Signal observers that this entity will be deleted. */ - dds_entity_status_signal(e); + if (--e->m_refc != 0) + { + dds_entity_unlock (e); + return DDS_RETCODE_OK; + } - /* - * Recursively delete children. - * - * It is possible that a writer/reader has the last reference - * to a topic. This will mean that when deleting a writer could - * cause a topic to be deleted. - * This can cause issues when deleting the children of a participant: - * when a topic is the next child in line to be deleted, while at the - * same time it is already being deleted due to the recursive deletion - * of a publisher->writer. - * - * Another problem is that when the topic was already deleted, and - * we'd delete it here for the second time before the writer/reader - * is deleted, they will have dangling pointers. - * - * To circumvent the problem. We ignore topics in the first loop. - */ - child = e->m_children; - while ((child != NULL) && (dds_entity_kind_from_handle(child->m_hdl) == DDS_KIND_TOPIC)) { + ut_handle_close (e->m_hdl, e->m_hdllink); + os_mutexLock (&e->m_observers_lock); + while (e->m_cb_count > 0) + os_condWait (&e->m_observers_cond, &e->m_observers_lock); + e->m_status_enable = 0; + dds_reset_listener (&e->m_listener); + e->m_trigger |= DDS_DELETING_STATUS; + os_mutexUnlock (&e->m_observers_lock); + dds_entity_unlock(e); + + /* Signal observers that this entity will be deleted. */ + dds_entity_status_signal (e); + + /* + * Recursively delete children. + * + * It is possible that a writer/reader has the last reference + * to a topic. This will mean that when deleting a writer could + * cause a topic to be deleted. + * This can cause issues when deleting the children of a participant: + * when a topic is the next child in line to be deleted, while at the + * same time it is already being deleted due to the recursive deletion + * of a publisher->writer. + * + * Another problem is that when the topic was already deleted, and + * we'd delete it here for the second time before the writer/reader + * is deleted, they will have dangling pointers. + * + * To circumvent the problem. We ignore topics in the first loop. + */ + ret = DDS_RETCODE_OK; + child = next_non_topic_child (e->m_children); + while (child != NULL && ret == DDS_RETCODE_OK) + { + next = next_non_topic_child (child->m_next); + /* This will probably delete the child entry from the current children's list */ + ret = dds_delete (child->m_hdl); + child = next; + } + child = e->m_children; + while (child != NULL && ret == DDS_RETCODE_OK) + { + next = child->m_next; + assert (dds_entity_kind (child) == DDS_KIND_TOPIC); + ret = dds_delete (child->m_hdl); + child = next; + } + if (ret == DDS_RETCODE_OK && e->m_deriver.close) + { + /* Close the entity. This can terminate threads or kick of + * other destroy stuff that takes a while. */ + ret = e->m_deriver.close (e); + } + + if (ret == DDS_RETCODE_OK) + { + /* The ut_handle_delete will wait until the last active claim on that handle + * is released. It is possible that this last release will be done by a thread + * that was kicked during the close(). */ + if (ut_handle_delete (e->m_hdl, e->m_hdllink, timeout) != UT_HANDLE_OK) + return DDS_ERRNO (DDS_RETCODE_TIMEOUT); + } + + if (ret == DDS_RETCODE_OK) + { + /* Remove all possible observers. */ + dds_entity_observers_delete (e); + + /* Remove from parent */ + if ((parent = dds__nonself_parent(e)) != NULL) + { + os_mutexLock (&parent->m_mutex); + child = parent->m_children; + while (child && child != e) + { + prev = child; child = child->m_next; - } - while ((child != NULL) && (ret == DDS_RETCODE_OK)) { - next = child->m_next; - while ((next != NULL) && (dds_entity_kind_from_handle(next->m_hdl) == DDS_KIND_TOPIC)) { - next = next->m_next; - } - /* This will probably delete the child entry from - * the current childrens list */ - ret = dds_delete(child->m_hdl); - /* Next child. */ - child = next; - } - child = e->m_children; - while ((child != NULL) && (ret == DDS_RETCODE_OK)) { - next = child->m_next; - assert(dds_entity_kind_from_handle(child->m_hdl) == DDS_KIND_TOPIC); - /* This will probably delete the child entry from - * the current childrens list */ - ret = dds_delete(child->m_hdl); - /* Next child. */ - child = next; + } + assert (child != NULL); + if (prev) + prev->m_next = e->m_next; + else + parent->m_children = e->m_next; + os_mutexUnlock (&parent->m_mutex); } + /* Do some specific deletion when needed. */ + if (e->m_deriver.delete) + ret = e->m_deriver.delete(e); + } - if (ret == DDS_RETCODE_OK) { - /* Close the entity. This can terminate threads or kick of - * other destroy stuff that takes a while. */ - if (e->m_deriver.close) { - ret = e->m_deriver.close(e); - } - } - - if (ret == DDS_RETCODE_OK) { - /* The ut_handle_delete will wait until the last active claim on that handle - * is released. It is possible that this last release will be done by a thread - * that was kicked during the close(). */ - if (ut_handle_delete(e->m_hdl, e->m_hdllink, timeout) != UT_HANDLE_OK) { - DDS_ERROR("Entity deletion did not release resources\n"); - return DDS_ERRNO(DDS_RETCODE_TIMEOUT); - } - } - - if (ret == DDS_RETCODE_OK) { - /* Remove all possible observers. */ - dds_entity_observers_delete(e); - - /* Remove from parent */ - if ((parent = dds__nonself_parent(e)) != NULL) { - os_mutexLock (&parent->m_mutex); - child = parent->m_children; - while (child) { - if (child == e) { - if (prev) { - prev->m_next = e->m_next; - } else { - parent->m_children = e->m_next; - } - break; - } - prev = child; - child = child->m_next; - } - os_mutexUnlock (&parent->m_mutex); - } - - /* Do some specific deletion when needed. */ - if (e->m_deriver.delete) { - ret = e->m_deriver.delete(e); - } - } - - if (ret == DDS_RETCODE_OK) { - /* Destroy last few things. */ - dds_delete_qos (e->m_qos); - os_condDestroy (&e->m_cond); - os_mutexDestroy (&e->m_mutex); - os_mutexDestroy (&e->m_observers_lock); - dds_free (e); - } + if (ret == DDS_RETCODE_OK) + { + dds_delete_qos (e->m_qos); + os_condDestroy (&e->m_cond); + os_condDestroy (&e->m_observers_cond); + os_mutexDestroy (&e->m_mutex); + os_mutexDestroy (&e->m_observers_lock); + dds_free (e); + } return ret; + } + +dds_entity_t dds_get_parent (dds_entity_t entity) +{ + dds_entity *e; + dds__retcode_t rc; + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else + { + dds_entity *parent; + dds_entity_t hdl; + if ((parent = dds__nonself_parent(e)) == NULL) + hdl = DDS_ENTITY_NIL; + else + { + hdl = parent->m_hdl; + dds_set_explicit (hdl); + } + dds_entity_unlock (e); + return hdl; + } } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_entity_t -dds_get_parent( - _In_ dds_entity_t entity) +dds_entity_t dds_get_participant (dds_entity_t entity) { - dds_entity *e; - dds__retcode_t rc; - dds_entity_t hdl; - dds_entity *parent; - - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if ((parent = dds__nonself_parent(e)) != NULL) { - hdl = parent->m_hdl; - dds_set_explicit(hdl); - } else { - hdl = DDS_ENTITY_NIL; - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error on locking handle entity\n"); - hdl = DDS_ERRNO(rc); - } - + dds_entity *e; + dds__retcode_t rc; + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else + { + dds_entity_t hdl = e->m_participant->m_hdl; + dds_entity_unlock (e); return hdl; + } +} + +dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size_t size) +{ + dds_entity *e; + dds__retcode_t rc; + + if (children != NULL && (size <= 0 || size >= INT32_MAX)) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + if (children == NULL && size != 0) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else + { + dds_return_t n = 0; + dds_entity *iter = e->m_children; + while (iter) + { + if ((size_t) n < size) + { + children[n] = iter->m_hdl; + dds_set_explicit (iter->m_hdl); + } + n++; + iter = iter->m_next; + } + dds_entity_unlock(e); + return n; + } +} + +dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) +{ + dds_entity *e; + dds__retcode_t rc; + dds_return_t ret; + + if (qos == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + if (e->m_deriver.set_qos) + ret = dds_copy_qos (qos, e->m_qos); + else + ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); + dds_entity_unlock(e); + return ret; +} + +dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos) +{ + dds_entity *e; + dds__retcode_t rc; + dds_return_t ret; + + if (qos == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + if (e->m_deriver.set_qos == 0) + ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + else + { + if ((ret = e->m_deriver.set_qos (e, qos, e->m_flags & DDS_ENTITY_ENABLED)) == DDS_RETCODE_OK) + { + if (e->m_qos == NULL) + e->m_qos = dds_create_qos (); + rc = dds_copy_qos (e->m_qos, qos); + ret = DDS_ERRNO (rc); + } + } + dds_entity_unlock (e); + return ret; } dds_return_t dds_get_listener (dds_entity_t entity, dds_listener_t *listener) { - dds_entity *e; - dds__retcode_t rc; - dds_entity_t hdl; + dds_entity *e; + dds_return_t ret = DDS_RETCODE_OK; + dds__retcode_t rc; + if (listener != NULL) { rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); if (rc == DDS_RETCODE_OK) { - assert(e->m_participant); - hdl = e->m_participant->m_hdl; - dds_entity_unlock(e); + os_mutexLock (&e->m_observers_lock); + dds_copy_listener (listener, &e->m_listener); + os_mutexUnlock (&e->m_observers_lock); + dds_entity_unlock(e); } else { - DDS_ERROR("Error on locking handle entity\n"); - hdl = DDS_ERRNO(rc); + DDS_ERROR("Error occurred on locking entity\n"); + ret = DDS_ERRNO(rc); } + } else { + DDS_ERROR("Argument listener is NULL\n"); + ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + } - return hdl; + return ret; } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_get_children( - _In_ dds_entity_t entity, - _Out_opt_ dds_entity_t *children, - _In_ size_t size) +void dds_entity_invoke_listener (const dds_entity *entity, uint32_t status, const void *vst) { - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; - dds_entity* iter; - - if ((children != NULL) && ((size <= 0) || (size >= INT32_MAX))) { - DDS_ERROR("Array is given, but with invalid size\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto err; + struct dds_listener const * const lst = &entity->m_listener; + switch (status) + { + case DDS_INCONSISTENT_TOPIC_STATUS: { + struct dds_inconsistent_topic_status const * const st = vst; + lst->on_inconsistent_topic (entity->m_hdl, *st, lst->on_inconsistent_topic_arg); + break; } - - if ((children == NULL) && (size != 0)) { - DDS_ERROR("Size is given, but no array\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto err; + case DDS_REQUESTED_DEADLINE_MISSED_STATUS: { + struct dds_requested_deadline_missed_status const * const st = vst; + lst->on_requested_deadline_missed (entity->m_hdl, *st, lst->on_requested_deadline_missed_arg); + break; } - - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - goto err; + case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: { + struct dds_requested_incompatible_qos_status const * const st = vst; + lst->on_requested_incompatible_qos (entity->m_hdl, *st, lst->on_requested_incompatible_qos_arg); + break; } - /* Initialize first child to satisfy SAL. */ - if (children) { - children[0] = 0; + case DDS_SAMPLE_LOST_STATUS: { + struct dds_sample_lost_status const * const st = vst; + lst->on_sample_lost (entity->m_hdl, *st, lst->on_sample_lost_arg); + break; } - ret = 0; - iter = e->m_children; - while (iter) { - if ((size_t)ret < size) { /*To fix the warning of signed/unsigned mismatch, type casting is done for the variable 'ret'*/ - children[ret] = iter->m_hdl; - dds_set_explicit(iter->m_hdl); - } - ret++; - iter = iter->m_next; + case DDS_SAMPLE_REJECTED_STATUS: { + struct dds_sample_rejected_status const * const st = vst; + lst->on_sample_rejected (entity->m_hdl, *st, lst->on_sample_rejected_arg); + break; } - dds_entity_unlock(e); - -err: - return ret; + case DDS_LIVELINESS_CHANGED_STATUS: { + struct dds_liveliness_changed_status const * const st = vst; + lst->on_liveliness_changed (entity->m_hdl, *st, lst->on_liveliness_changed_arg); + break; + } + case DDS_SUBSCRIPTION_MATCHED_STATUS: { + struct dds_subscription_matched_status const * const st = vst; + lst->on_subscription_matched (entity->m_hdl, *st, lst->on_subscription_matched_arg); + break; + } + case DDS_OFFERED_DEADLINE_MISSED_STATUS: { + struct dds_offered_deadline_missed_status const * const st = vst; + lst->on_offered_deadline_missed (entity->m_hdl, *st, lst->on_offered_deadline_missed_arg); + break; + } + case DDS_LIVELINESS_LOST_STATUS: { + struct dds_liveliness_lost_status const * const st = vst; + lst->on_liveliness_lost (entity->m_hdl, *st, lst->on_liveliness_lost_arg); + break; + } + case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: { + struct dds_offered_incompatible_qos_status const * const st = vst; + lst->on_offered_incompatible_qos (entity->m_hdl, *st, lst->on_offered_incompatible_qos_arg); + break; + } + case DDS_PUBLICATION_MATCHED_STATUS: { + struct dds_publication_matched_status const * const st = vst; + lst->on_publication_matched (entity->m_hdl, *st, lst->on_publication_matched_arg); + break; + } + case DDS_DATA_AVAILABLE_STATUS: { + lst->on_data_available (entity->m_hdl, lst->on_data_available_arg); + break; + } + case DDS_DATA_ON_READERS_STATUS: { + lst->on_data_on_readers (entity->m_hdl, lst->on_data_on_readers_arg); + break; + } + } } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_get_qos( - _In_ dds_entity_t entity, - _Out_ dds_qos_t *qos) +static void clear_status_with_listener (struct dds_entity *e) { - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; - - if (qos == NULL) { - DDS_ERROR("Argument qos is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto fail; - } - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - goto fail; - } - if (e->m_deriver.set_qos) { - ret = dds_copy_qos(qos, e->m_qos); - } else { - DDS_ERROR("QoS cannot be set on this entity\n"); - ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); - } - dds_entity_unlock(e); -fail: - return ret; + const struct dds_listener *lst = &e->m_listener; + if (lst->on_inconsistent_topic) + e->m_trigger &= ~DDS_INCONSISTENT_TOPIC_STATUS; + if (lst->on_liveliness_lost) + e->m_trigger &= ~DDS_LIVELINESS_LOST_STATUS; + if (lst->on_offered_deadline_missed) + e->m_trigger &= ~DDS_OFFERED_DEADLINE_MISSED_STATUS; + if (lst->on_offered_deadline_missed_arg) + e->m_trigger &= ~DDS_OFFERED_DEADLINE_MISSED_STATUS; + if (lst->on_offered_incompatible_qos) + e->m_trigger &= ~DDS_OFFERED_INCOMPATIBLE_QOS_STATUS; + if (lst->on_data_on_readers) + e->m_trigger &= ~DDS_DATA_ON_READERS_STATUS; + if (lst->on_sample_lost) + e->m_trigger &= ~DDS_SAMPLE_LOST_STATUS; + if (lst->on_data_available) + e->m_trigger &= ~DDS_DATA_AVAILABLE_STATUS; + if (lst->on_sample_rejected) + e->m_trigger &= ~DDS_SAMPLE_REJECTED_STATUS; + if (lst->on_liveliness_changed) + e->m_trigger &= ~DDS_LIVELINESS_CHANGED_STATUS; + if (lst->on_requested_deadline_missed) + e->m_trigger &= ~DDS_REQUESTED_DEADLINE_MISSED_STATUS; + if (lst->on_requested_incompatible_qos) + e->m_trigger &= ~DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS; + if (lst->on_publication_matched) + e->m_trigger &= ~DDS_PUBLICATION_MATCHED_STATUS; + if (lst->on_subscription_matched) + e->m_trigger &= ~DDS_SUBSCRIPTION_MATCHED_STATUS; } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_set_qos( - _In_ dds_entity_t entity, - _In_ const dds_qos_t *qos) +static void pushdown_listener (dds_entity_t entity) { + dds_entity_t *cs = NULL; + int ncs, size = 0; + while ((ncs = dds_get_children (entity, cs, (size_t) size)) > size) + { + size = ncs; + cs = os_realloc (cs, (size_t) size * sizeof (*cs)); + } + for (int i = 0; i < ncs; i++) + { dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; - - if (qos != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if (e->m_deriver.set_qos) { - ret = e->m_deriver.set_qos(e, qos, e->m_flags & DDS_ENTITY_ENABLED); - } else { - DDS_ERROR("QoS cannot be set on this entity\n"); - ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); - } - if (ret == DDS_RETCODE_OK) { - /* Remember this QoS. */ - if (e->m_qos == NULL) { - e->m_qos = dds_create_qos(); - } - rc = dds_copy_qos(e->m_qos, qos); - DDS_ERROR("QoS cannot be set on this entity\n"); - ret = DDS_ERRNO(rc); - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - } else { - DDS_ERROR("Argument QoS is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + if (dds_entity_lock (cs[i], DDS_KIND_DONTCARE, &e) == DDS_RETCODE_OK) + { + dds_listener_t tmp; + os_mutexLock (&e->m_observers_lock); + while (e->m_cb_count > 0) + os_condWait (&e->m_observers_cond, &e->m_observers_lock); + dds_get_listener (entity, &tmp); + dds_override_inherited_listener (&e->m_listener, &tmp); + clear_status_with_listener (e); + os_mutexUnlock (&e->m_observers_lock); + dds_entity_unlock (e); } - - return ret; -} - - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_get_listener( - _In_ dds_entity_t entity, - _Out_ dds_listener_t *listener) -{ - dds_entity *e; - dds_return_t ret = DDS_RETCODE_OK; - dds__retcode_t rc; - - if (listener != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - dds_entity_cb_wait(e); - dds_copy_listener (listener, &e->m_listener); - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - } else { - DDS_ERROR("Argument listener is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } - - return ret; + } + os_free (cs); } dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listener) { + dds_entity *e, *x; + dds__retcode_t rc; + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + os_mutexLock (&e->m_observers_lock); + while (e->m_cb_count > 0) + os_condWait (&e->m_observers_cond, &e->m_observers_lock); + + /* new listener is constructed by combining "listener" with the ancestral listeners; + the new set of listeners is then pushed down into the descendant entities, overriding + the ones they originally inherited from */ + dds_reset_listener (&e->m_listener); + if (listener) + dds_merge_listener (&e->m_listener, listener); + x = e; + while (dds_entity_kind (x) != DDS_KIND_PARTICIPANT) + { + x = x->m_parent; + dds_inherit_listener (&e->m_listener, &x->m_listener); + } + clear_status_with_listener (e); + os_mutexUnlock (&e->m_observers_lock); + dds_entity_unlock (e); + pushdown_listener (entity); + return DDS_RETCODE_OK; +} + +dds_return_t dds_enable (dds_entity_t entity) +{ + dds_entity *e; + dds__retcode_t rc; + + if ((rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + if ((e->m_flags & DDS_ENTITY_ENABLED) == 0) + { + /* TODO: Really enable. */ + e->m_flags |= DDS_ENTITY_ENABLED; + DDS_ERROR ("Delayed entity enabling is not supported\n"); + } + dds_entity_unlock(e); + return DDS_RETCODE_OK; +} + +dds_return_t dds_get_status_changes (dds_entity_t entity, uint32_t *status) +{ + dds_entity *e; + dds__retcode_t rc; + dds_return_t ret; + + if (status == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + if (e->m_deriver.validate_status == 0) + ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + else + { + os_mutexLock (&e->m_observers_lock); + *status = e->m_trigger; + os_mutexUnlock (&e->m_observers_lock); + ret = DDS_RETCODE_OK; + } + dds_entity_unlock(e); + return ret; +} + +dds_return_t dds_get_status_mask (dds_entity_t entity, uint32_t *mask) +{ + dds_entity *e; + dds__retcode_t rc; + dds_return_t ret; + + if (mask == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + if (e->m_deriver.validate_status == 0) + ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + else + { + os_mutexLock (&e->m_observers_lock); + *mask = (e->m_status_enable & ~DDS_INTERNAL_STATUS_MASK); + os_mutexUnlock (&e->m_observers_lock); + ret = DDS_RETCODE_OK; + } + dds_entity_unlock(e); + return ret; +} + +dds_return_t dds_get_enabled_status (dds_entity_t entity, uint32_t *status) +{ + return dds_get_status_mask(entity, status); +} + +dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask) +{ + dds_entity *e; + dds__retcode_t rc; + dds_return_t ret; + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + if (e->m_deriver.validate_status == 0) + ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + else if ((ret = e->m_deriver.validate_status (mask)) == DDS_RETCODE_OK) + { + os_mutexLock (&e->m_observers_lock); + /* Don't block internal status triggers. */ + mask |= DDS_INTERNAL_STATUS_MASK; + e->m_status_enable = mask; + e->m_trigger &= mask; + os_mutexUnlock (&e->m_observers_lock); + } + dds_entity_unlock(e); + return ret; +} + +dds_return_t dds_set_enabled_status(dds_entity_t entity, uint32_t mask) +{ + return dds_set_status_mask( entity, mask); +} + +static dds_return_t dds_readtake_status (dds_entity_t entity, uint32_t *status, uint32_t mask, bool reset) +{ + dds_entity *e; + dds__retcode_t rc; + dds_return_t ret; + + if (status == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + if (e->m_deriver.validate_status == 0) + ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + else if ((ret = e->m_deriver.validate_status (mask)) == DDS_RETCODE_OK) + { + os_mutexLock (&e->m_observers_lock); + *status = e->m_trigger & mask; + if (reset) + e->m_trigger &= ~mask; + os_mutexUnlock (&e->m_observers_lock); + } + dds_entity_unlock (e); + return ret; +} + + +dds_return_t dds_read_status (dds_entity_t entity, uint32_t *status, uint32_t mask) +{ + return dds_readtake_status (entity, status, mask, false); +} + +dds_return_t dds_take_status (dds_entity_t entity, uint32_t *status, uint32_t mask) +{ + return dds_readtake_status (entity, status, mask, true); +} + +dds_return_t dds_get_domainid (dds_entity_t entity, dds_domainid_t *id) +{ + dds_entity *e; + dds__retcode_t rc; + + if (id == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + *id = e->m_domainid; + dds_entity_unlock(e); + return DDS_RETCODE_OK; +} + +dds_return_t dds_get_instance_handle (dds_entity_t entity, dds_instance_handle_t *ihdl) +{ + dds_entity *e; + dds__retcode_t rc; + dds_return_t ret; + + if (ihdl == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + if (e->m_deriver.get_instance_hdl) + ret = e->m_deriver.get_instance_hdl (e, ihdl); + else + ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + dds_entity_unlock(e); + return ret; +} + + +dds__retcode_t dds_valid_hdl (dds_entity_t hdl, dds_entity_kind_t kind) +{ + ut_handle_t utr; + if ((utr = ut_handle_status (hdl, NULL, (int32_t) kind)) == UT_HANDLE_OK) + return DDS_RETCODE_OK; + else if (hdl < 0) + return DDS_RETCODE_BAD_PARAMETER; + else + { + switch (utr) + { + case UT_HANDLE_OK: + assert (0); + /* FALLS THROUGH */ + case UT_HANDLE_UNEQUAL_KIND: + return DDS_RETCODE_ILLEGAL_OPERATION; + case UT_HANDLE_INVALID: + return DDS_RETCODE_BAD_PARAMETER; + case UT_HANDLE_DELETED: + case UT_HANDLE_CLOSED: + return DDS_RETCODE_ALREADY_DELETED; + default: + return DDS_RETCODE_ERROR; + } + } +} + +dds__retcode_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr) +{ + ut_handle_t utr; + void *raw; + + /* When the given handle already contains an error, then return that + * same error to retain the original information. */ + if ((utr = ut_handle_claim (hdl, NULL, (int32_t) kind, &raw)) == UT_HANDLE_OK) + { dds_entity *e; - dds__retcode_t rc; - dds_return_t ret = DDS_RETCODE_OK; + *eptr = e = raw; + os_mutexLock (&e->m_mutex); + /* FIXME: The handle could have been closed while we were waiting for the mutex -- that should be handled differently! - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if(rc != DDS_RETCODE_OK){ - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - goto fail; + For now, however, it is really important at two points in the logic: + (1) preventing creating new entities as children of a one that is currently being deleted, and + (2) preventing dds_delete_impl from doing anything once the entity is being deleted. + + Without (1), it would be possible to add children while trying to delete them, without (2) you're looking at crashes. */ + if (ut_handle_is_closed (hdl, e->m_hdllink)) + { + dds_entity_unlock (e); + return DDS_RETCODE_ALREADY_DELETED; } - dds_entity_cb_wait(e); - if (listener) { - dds_copy_listener(&e->m_listener, listener); - } else { - dds_reset_listener(&e->m_listener); + return DDS_RETCODE_OK; + } + else if (hdl < 0) + { + return DDS_RETCODE_BAD_PARAMETER; + } + else + { + switch (utr) + { + case UT_HANDLE_OK: + assert (0); + /* FALLS THROUGH */ + case UT_HANDLE_UNEQUAL_KIND: + return DDS_RETCODE_ILLEGAL_OPERATION; + case UT_HANDLE_INVALID: + return DDS_RETCODE_BAD_PARAMETER; + case UT_HANDLE_DELETED: + case UT_HANDLE_CLOSED: + return DDS_RETCODE_ALREADY_DELETED; + default: + return DDS_RETCODE_ERROR; } - dds_entity_unlock(e); -fail: - return ret; + } } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_enable( - _In_ dds_entity_t entity) +void dds_entity_unlock (dds_entity *e) { - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret = DDS_RETCODE_OK; - - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if ((e->m_flags & DDS_ENTITY_ENABLED) == 0) { - /* TODO: CHAM-96: Really enable. */ - e->m_flags |= DDS_ENTITY_ENABLED; - DDS_ERROR("Delayed entity enabling is not supported\n"); - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - - return ret; + os_mutexUnlock (&e->m_mutex); + ut_handle_release (e->m_hdl, e->m_hdllink); } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Must_inspect_result_ dds_return_t -dds_get_status_changes( - _In_ dds_entity_t entity, - _Out_ uint32_t *status) +dds_return_t dds_triggered (dds_entity_t entity) { - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; + dds_entity *e; + dds_return_t ret; + dds__retcode_t rc; - if (status != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if (e->m_deriver.validate_status) { - *status = e->m_trigger; - ret = DDS_RETCODE_OK; - } else { - DDS_ERROR("This entity does not maintain a status\n"); - ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - } else { - DDS_ERROR("Argument status is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } - - return ret; + if ((rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + os_mutexLock (&e->m_observers_lock); + ret = (e->m_trigger != 0); + os_mutexUnlock (&e->m_observers_lock); + dds_entity_unlock (e); + return ret; } - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_get_status_mask( - _In_ dds_entity_t entity, - _Out_ uint32_t *mask) -{ - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; - - if (mask != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if (e->m_deriver.validate_status) { - *mask = (e->m_status_enable & ~DDS_INTERNAL_STATUS_MASK); - ret = DDS_RETCODE_OK; - } else { - DDS_ERROR("This entity does not maintain a status mask\n"); - ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - } else{ - DDS_ERROR("Argument mask is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } - - return ret; -} - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_get_enabled_status( - _In_ dds_entity_t entity, - _Out_ uint32_t *status) -{ - return dds_get_status_mask(entity, status); -} - - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -DDS_EXPORT dds_return_t -dds_set_status_mask( - _In_ dds_entity_t entity, - _In_ uint32_t mask) -{ - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; - - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if (e->m_deriver.validate_status) { - ret = e->m_deriver.validate_status(mask); - if (ret == DDS_RETCODE_OK) { - /* Don't block internal status triggers. */ - mask |= DDS_INTERNAL_STATUS_MASK; - e->m_status_enable = mask; - e->m_trigger &= mask; - if (e->m_deriver.propagate_status) { - ret = e->m_deriver.propagate_status(e, mask, true); - } - } - } else { - DDS_ERROR("This entity does not maintain a status\n"); - ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - - return ret; -} - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -DDS_EXPORT dds_return_t -dds_set_enabled_status( - _In_ dds_entity_t entity, - _In_ uint32_t mask) -{ - return dds_set_status_mask(entity, mask); -} - - - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_read_status( - _In_ dds_entity_t entity, - _Out_ uint32_t *status, - _In_ uint32_t mask) -{ - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; - - if (status != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if (e->m_deriver.validate_status) { - ret = e->m_deriver.validate_status(mask); - assert(ret <= DDS_RETCODE_OK); - if (ret == DDS_RETCODE_OK) { - *status = e->m_trigger & mask; - } - } else { - DDS_ERROR("This entity does not maintain a status\n"); - ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - } else { - DDS_ERROR("Argument status is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } - - return ret; -} - - - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_take_status( - _In_ dds_entity_t entity, - _Out_ uint32_t *status, - _In_ uint32_t mask) -{ - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; - - if (status != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if (e->m_deriver.validate_status) { - ret = e->m_deriver.validate_status(mask); - assert(ret <= DDS_RETCODE_OK); - if (ret == DDS_RETCODE_OK) { - *status = e->m_trigger & mask; - if (e->m_deriver.propagate_status) { - ret = e->m_deriver.propagate_status(e, *status, false); - } - e->m_trigger &= ~mask; - } - } else { - DDS_ERROR("This entity does not maintain a status\n"); - ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - } else { - DDS_ERROR("Argument status is NUL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } - - return ret; -} - - - -void -dds_entity_status_signal( - _In_ dds_entity *e) -{ - assert(e); - /* Signal the observers in an unlocked state. - * This is safe because we use handles and the current entity - * will not be deleted while we're in this signaling state - * due to a claimed handle. */ - dds_entity_observers_signal(e, e->m_trigger); -} - - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_get_domainid( - _In_ dds_entity_t entity, - _Out_ dds_domainid_t *id) -{ - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret = DDS_RETCODE_OK; - - if (id != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - *id = e->m_domainid; - dds_entity_unlock(e); - } else{ - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - } else{ - DDS_ERROR("Argument domain id is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } - - return ret; -} - - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -_Check_return_ dds_return_t -dds_get_instance_handle( - _In_ dds_entity_t entity, - _Out_ dds_instance_handle_t *ihdl) -{ - dds_entity *e; - dds__retcode_t rc; - dds_return_t ret; - - if (ihdl != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - if (e->m_deriver.get_instance_hdl) { - ret = e->m_deriver.get_instance_hdl(e, ihdl); - } else { - DDS_ERROR("Instance handle is not valid\n"); - ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); - } - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - } else { - DDS_ERROR("Argument instance handle is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } - - return ret; -} - - -_Check_return_ dds__retcode_t -dds_valid_hdl( - _In_ dds_entity_t hdl, - _In_ dds_entity_kind_t kind) -{ - dds__retcode_t rc = hdl; - ut_handle_t utr; - - /* When the given handle already contains an error, then return that - * same error to retain the original information. */ - if (hdl >= 0) { - utr = ut_handle_status(hdl, NULL, (int32_t)kind); - if(utr == UT_HANDLE_OK){ - rc = DDS_RETCODE_OK; - } else if(utr == UT_HANDLE_UNEQUAL_KIND){ - rc = DDS_RETCODE_ILLEGAL_OPERATION; - DDS_WARNING("Given (%s) [0x%08"PRIx32"] entity type can not perform this operation\n", dds__entity_kind_str(hdl), hdl); - } else if(utr == UT_HANDLE_INVALID){ - rc = DDS_RETCODE_BAD_PARAMETER; - DDS_WARNING("Given (%s) [0x%08"PRIx32"] entity is invalid\n", dds__entity_kind_str(hdl), hdl); - } else if(utr == UT_HANDLE_DELETED){ - rc = DDS_RETCODE_ALREADY_DELETED; - DDS_WARNING("Given (%s) [0x%08"PRIx32"] entity is already deleted\n", dds__entity_kind_str(hdl), hdl); - } else if(utr == UT_HANDLE_CLOSED){ - rc = DDS_RETCODE_ALREADY_DELETED; - DDS_WARNING("Given (%s) [0x%08"PRIx32"] entity is already deleted\n", dds__entity_kind_str(hdl), hdl); - } else { - rc = DDS_RETCODE_ERROR; - DDS_WARNING("An internal error occurred\n"); - } - } else { - rc = DDS_RETCODE_BAD_PARAMETER; - DDS_WARNING("Given entity (0x%08"PRIx32") was not properly created\n", hdl); - } - return rc; -} - -_Acquires_exclusive_lock_(*e) -_Check_return_ dds__retcode_t -dds_entity_lock( - _In_ dds_entity_t hdl, - _In_ dds_entity_kind_t kind, - _Out_ dds_entity **e) -{ - dds__retcode_t rc = hdl; - ut_handle_t utr; - assert(e); - /* When the given handle already contains an error, then return that - * same error to retain the original information. */ - if (hdl >= 0) { - utr = ut_handle_claim(hdl, NULL, (int32_t)kind, (void**)e); - if (utr == UT_HANDLE_OK) { - os_mutexLock(&((*e)->m_mutex)); - /* The handle could have been closed while we were waiting for the mutex. */ - if (ut_handle_is_closed(hdl, (*e)->m_hdllink)) { - dds_entity_unlock(*e); - utr = UT_HANDLE_CLOSED; - } - } - if(utr == UT_HANDLE_OK){ - rc = DDS_RETCODE_OK; - } else if(utr == UT_HANDLE_UNEQUAL_KIND){ - rc = DDS_RETCODE_ILLEGAL_OPERATION; - DDS_WARNING("Given (%s) [0x%08"PRIx32"] entity type can not perform this operation\n", dds__entity_kind_str(hdl), hdl); - } else if(utr == UT_HANDLE_INVALID){ - rc = DDS_RETCODE_BAD_PARAMETER; - DDS_WARNING("Given (%s) [0x%08"PRIx32"] entity is invalid\n", dds__entity_kind_str(hdl), hdl); - } else if(utr == UT_HANDLE_DELETED){ - rc = DDS_RETCODE_ALREADY_DELETED; - DDS_WARNING("Given (%s) [0x%08"PRIx32"] entity is already deleted\n", dds__entity_kind_str(hdl), hdl); - } else if(utr == UT_HANDLE_CLOSED){ - rc = DDS_RETCODE_ALREADY_DELETED; - DDS_WARNING("Given (%s) [0x%08"PRIx32"] entity is already deleted\n", dds__entity_kind_str(hdl), hdl); - } else { - rc = DDS_RETCODE_ERROR; - DDS_WARNING("An internal error occurred\n"); - } - } else { - rc = DDS_RETCODE_BAD_PARAMETER; - DDS_WARNING("Given entity (0x%08"PRIx32") was not properly created\n", hdl); - } - return rc; -} - - -_Releases_exclusive_lock_(e) -void -dds_entity_unlock( - _Inout_ dds_entity *e) -{ - assert(e); - os_mutexUnlock(&e->m_mutex); - ut_handle_release(e->m_hdl, e->m_hdllink); -} - - - -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -dds_return_t -dds_triggered( - _In_ dds_entity_t entity) -{ - dds_entity *e; - dds_return_t ret; - dds__retcode_t rc; - - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - ret = (e->m_trigger != 0); - dds_entity_unlock(e); - } else { - DDS_ERROR("Error occurred on locking entity\n"); - ret = DDS_ERRNO(rc); - } - - return ret; -} - - static bool in_observer_list_p (const struct dds_entity *observed, const dds_entity_t observer) { - dds_entity_observer *cur; - for (cur = observed->m_observers; cur != NULL; cur = cur->m_next) { - if (cur->m_observer == observer) { - return true; - } - } - return false; + dds_entity_observer *cur; + for (cur = observed->m_observers; cur != NULL; cur = cur->m_next) + if (cur->m_observer == observer) + return true; + return false; } -_Check_return_ dds__retcode_t -dds_entity_observer_register_nl( - _In_ dds_entity* observed, - _In_ dds_entity_t observer, - _In_ dds_entity_callback cb) +dds__retcode_t dds_entity_observer_register_nl (dds_entity *observed, dds_entity_t observer, dds_entity_callback cb) { - dds__retcode_t rc; - dds_entity_observer *o = os_malloc(sizeof(dds_entity_observer)); - assert(observed); + dds__retcode_t rc; + assert (observed); + os_mutexLock (&observed->m_observers_lock); + if (in_observer_list_p (observed, observer)) + rc = DDS_RETCODE_PRECONDITION_NOT_MET; + else + { + dds_entity_observer *o = os_malloc (sizeof (dds_entity_observer)); o->m_cb = cb; o->m_observer = observer; - os_mutexLock(&observed->m_observers_lock); - if (in_observer_list_p (observed, observer)) { - rc = DDS_RETCODE_PRECONDITION_NOT_MET; - os_free (o); - } else { - rc = DDS_RETCODE_OK; - o->m_next = observed->m_observers; - observed->m_observers = o; - } - os_mutexUnlock(&observed->m_observers_lock); + o->m_next = observed->m_observers; + observed->m_observers = o; + rc = DDS_RETCODE_OK; + } + os_mutexUnlock (&observed->m_observers_lock); + return rc; +} + +dds__retcode_t dds_entity_observer_register (dds_entity_t observed, dds_entity_t observer, dds_entity_callback cb) +{ + dds__retcode_t rc; + dds_entity *e; + assert (cb); + if ((rc = dds_entity_lock (observed, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return rc; + rc = dds_entity_observer_register_nl (e, observer, cb); + dds_entity_unlock (e); + return rc; } - - -_Check_return_ dds__retcode_t -dds_entity_observer_register( - _In_ dds_entity_t observed, - _In_ dds_entity_t observer, - _In_ dds_entity_callback cb) +dds__retcode_t dds_entity_observer_unregister_nl (dds_entity *observed, dds_entity_t observer) { - dds__retcode_t rc; - dds_entity *e; - assert(cb); - rc = dds_entity_lock(observed, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - rc = dds_entity_observer_register_nl(e, observer, cb); - dds_entity_unlock(e); - } else{ - DDS_ERROR("Error occurred on locking observer\n"); - } + dds__retcode_t rc; + dds_entity_observer *prev, *idx; + + os_mutexLock (&observed->m_observers_lock); + prev = NULL; + idx = observed->m_observers; + while (idx != NULL && idx->m_observer != observer) + { + prev = idx; + idx = idx->m_next; + } + if (idx == NULL) + rc = DDS_RETCODE_PRECONDITION_NOT_MET; + else + { + if (prev == NULL) + observed->m_observers = idx->m_next; + else + prev->m_next = idx->m_next; + os_free (idx); + rc = DDS_RETCODE_OK; + } + os_mutexUnlock (&observed->m_observers_lock); + return rc; +} + +dds__retcode_t dds_entity_observer_unregister (dds_entity_t observed, dds_entity_t observer) +{ + dds__retcode_t rc; + dds_entity *e; + if ((rc = dds_entity_lock (observed, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return rc; + rc = dds_entity_observer_unregister_nl (e, observer); + dds_entity_unlock (e); + return rc; } - - -dds__retcode_t -dds_entity_observer_unregister_nl( - _In_ dds_entity* observed, - _In_ dds_entity_t observer) +static void dds_entity_observers_delete (dds_entity *observed) { - dds__retcode_t rc = DDS_RETCODE_PRECONDITION_NOT_MET; - dds_entity_observer *prev = NULL; - dds_entity_observer *idx; - os_mutexLock(&observed->m_observers_lock); - idx = observed->m_observers; - while (idx != NULL) { - if (idx->m_observer == observer) { - if (prev == NULL) { - observed->m_observers = idx->m_next; - } else { - prev->m_next = idx->m_next; - } - os_free(idx); - idx = NULL; - rc = DDS_RETCODE_OK; - } else { - prev = idx; - idx = idx->m_next; - } - } - os_mutexUnlock(&observed->m_observers_lock); - return rc; + dds_entity_observer *idx; + os_mutexLock (&observed->m_observers_lock); + idx = observed->m_observers; + while (idx != NULL) + { + dds_entity_observer *next = idx->m_next; + os_free (idx); + idx = next; + } + observed->m_observers = NULL; + os_mutexUnlock (&observed->m_observers_lock); } - - -dds__retcode_t -dds_entity_observer_unregister( - _In_ dds_entity_t observed, - _In_ dds_entity_t observer) +static void dds_entity_observers_signal (dds_entity *observed, uint32_t status) { - dds__retcode_t rc; - dds_entity *e; - rc = dds_entity_lock(observed, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - rc = dds_entity_observer_unregister_nl(e, observer); - dds_entity_unlock(e); - } else{ - DDS_ERROR("Error occurred on locking entity\n"); - (void)DDS_ERRNO(rc); - } - return rc; + for (dds_entity_observer *idx = observed->m_observers; idx; idx = idx->m_next) + idx->m_cb (idx->m_observer, observed->m_hdl, status); } - - -static void -dds_entity_observers_delete( - _In_ dds_entity *observed) +void dds_entity_status_signal (dds_entity *e) { - dds_entity_observer *next; - dds_entity_observer *idx; - os_mutexLock(&observed->m_observers_lock); - idx = observed->m_observers; - while (idx != NULL) { - next = idx->m_next; - os_free(idx); - idx = next; - } - observed->m_observers = NULL; - os_mutexUnlock(&observed->m_observers_lock); + os_mutexLock (&e->m_observers_lock); + dds_entity_observers_signal (e, e->m_trigger); + os_mutexUnlock (&e->m_observers_lock); } - - -static void -dds_entity_observers_signal( - _In_ dds_entity *observed, - _In_ uint32_t status) +void dds_entity_status_set (dds_entity *e, uint32_t t) { - dds_entity_observer *idx; - os_mutexLock(&observed->m_observers_lock); - idx = observed->m_observers; - while (idx != NULL) { - idx->m_cb(idx->m_observer, observed->m_hdl, status); - idx = idx->m_next; - } - os_mutexUnlock(&observed->m_observers_lock); + if (!(e->m_trigger & t)) + { + e->m_trigger |= e->m_status_enable & t; + dds_entity_observers_signal (e, e->m_trigger); + } } -_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -dds_entity_t -dds_get_topic( - _In_ dds_entity_t entity) +dds_entity_t dds_get_topic (dds_entity_t entity) { - dds__retcode_t rc; - dds_entity_t hdl = entity; - dds_reader *rd; - dds_writer *wr; + dds__retcode_t rc; + dds_entity_t hdl; + dds_entity *e; - rc = dds_reader_lock(entity, &rd); - if(rc == DDS_RETCODE_OK) { - hdl = rd->m_topic->m_entity.m_hdl; - dds_reader_unlock(rd); - } else if (rc == DDS_RETCODE_ILLEGAL_OPERATION) { - rc = dds_writer_lock(entity, &wr); - if (rc == DDS_RETCODE_OK) { - hdl = wr->m_topic->m_entity.m_hdl; - dds_writer_unlock(wr); - } else if (dds_entity_kind_from_handle(entity) == DDS_KIND_COND_READ || dds_entity_kind_from_handle(entity) == DDS_KIND_COND_QUERY) { - hdl = dds_get_topic(dds_get_parent(entity)); - rc = DDS_RETCODE_OK; - } + if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + switch (dds_entity_kind (e)) + { + case DDS_KIND_READER: { + dds_reader *rd = (dds_reader *) e; + hdl = rd->m_topic->m_entity.m_hdl; + break; } - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); - hdl = DDS_ERRNO(rc); + case DDS_KIND_WRITER: { + dds_writer *wr = (dds_writer *) e; + hdl = wr->m_topic->m_entity.m_hdl; + break; } - - return hdl; + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: { + assert (dds_entity_kind (e->m_parent) == DDS_KIND_READER); + dds_reader *rd = (dds_reader *) e->m_parent; + hdl = rd->m_topic->m_entity.m_hdl; + break; + } + default: { + hdl = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + break; + } + } + dds_entity_unlock (e); + return hdl; } -static void -dds_set_explicit( - _In_ dds_entity_t entity) +const char *dds__entity_kind_str (dds_entity_t e) { - dds_entity *e; - dds__retcode_t rc; - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if( rc == DDS_RETCODE_OK){ - e->m_flags &= ~DDS_ENTITY_IMPLICIT; - dds_entity_unlock(e); - } -} - -const char * -dds__entity_kind_str(_In_ dds_entity_t e) -{ - if(e <= 0) { - return "(ERROR)"; - } - switch(e & DDS_ENTITY_KIND_MASK) { - case DDS_KIND_TOPIC: return "Topic"; - case DDS_KIND_PARTICIPANT: return "Participant"; - case DDS_KIND_READER: return "Reader"; - case DDS_KIND_WRITER: return "Writer"; - case DDS_KIND_SUBSCRIBER: return "Subscriber"; - case DDS_KIND_PUBLISHER: return "Publisher"; - case DDS_KIND_COND_READ: return "ReadCondition"; - case DDS_KIND_COND_QUERY: return "QueryCondition"; - case DDS_KIND_WAITSET: return "WaitSet"; - default: return "(INVALID_ENTITY)"; - } + if (e <= 0) + return "(ERROR)"; + switch (e & DDS_ENTITY_KIND_MASK) + { + case DDS_KIND_TOPIC: return "Topic"; + case DDS_KIND_PARTICIPANT: return "Participant"; + case DDS_KIND_READER: return "Reader"; + case DDS_KIND_WRITER: return "Writer"; + case DDS_KIND_SUBSCRIBER: return "Subscriber"; + case DDS_KIND_PUBLISHER: return "Publisher"; + case DDS_KIND_COND_READ: return "ReadCondition"; + case DDS_KIND_COND_QUERY: return "QueryCondition"; + case DDS_KIND_WAITSET: return "WaitSet"; + default: return "(INVALID_ENTITY)"; + } } diff --git a/src/core/ddsc/src/dds_guardcond.c b/src/core/ddsc/src/dds_guardcond.c index a69f650..eadbadc 100644 --- a/src/core/ddsc/src/dds_guardcond.c +++ b/src/core/ddsc/src/dds_guardcond.c @@ -21,121 +21,81 @@ DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_guardcond) -_Must_inspect_result_ dds_guardcond* -dds_create_guardcond( - _In_ dds_participant *pp) +dds_entity_t dds_create_guardcondition (dds_entity_t participant) { - dds_guardcond * gcond = dds_alloc(sizeof(*gcond)); - gcond->m_entity.m_hdl = dds_entity_init(&gcond->m_entity, &pp->m_entity, DDS_KIND_COND_GUARD, NULL, NULL, 0); - return gcond; -} - -_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT) -_Must_inspect_result_ dds_entity_t -dds_create_guardcondition( - _In_ dds_entity_t participant) -{ - dds_entity_t hdl; - dds_participant * pp; - dds__retcode_t rc; - - rc = dds_participant_lock(participant, &pp); - if (rc == DDS_RETCODE_OK) { - dds_guardcond *cond = dds_create_guardcond(pp); - assert(cond); - hdl = cond->m_entity.m_hdl; - dds_participant_unlock(pp); - } else { - DDS_ERROR("Error occurred on locking reader\n"); - hdl = DDS_ERRNO(rc); - } + dds_participant *pp; + dds__retcode_t rc; + if ((rc = dds_participant_lock (participant, &pp)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else + { + dds_guardcond * gcond = dds_alloc (sizeof (*gcond)); + dds_entity_t hdl = dds_entity_init (&gcond->m_entity, &pp->m_entity, DDS_KIND_COND_GUARD, NULL, NULL, 0); + dds_participant_unlock (pp); return hdl; + } } -_Pre_satisfies_(((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_GUARD) ) -dds_return_t -dds_set_guardcondition( - _In_ dds_entity_t condition, - _In_ bool triggered) +dds_return_t dds_set_guardcondition (dds_entity_t condition, bool triggered) { - dds_return_t ret; - dds_guardcond *gcond; - dds__retcode_t rc; + dds_guardcond *gcond; + dds__retcode_t rc; - rc = dds_entity_lock(condition, DDS_KIND_COND_GUARD, (dds_entity**)&gcond); - if (rc == DDS_RETCODE_OK) { - if (triggered) { - dds_entity_status_set(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - dds_entity_status_signal(&gcond->m_entity); - } else { - dds_entity_status_reset(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - } - dds_entity_unlock(&gcond->m_entity); - ret = DDS_RETCODE_OK; - } else { - DDS_ERROR("Argument condition is not valid\n"); - ret = DDS_ERRNO(dds_valid_hdl(condition, DDS_KIND_COND_GUARD)); - } - - return ret; + if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) + return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + else + { + os_mutexLock (&gcond->m_entity.m_observers_lock); + if (triggered) + dds_entity_status_set (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + else + dds_entity_status_reset (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + os_mutexUnlock (&gcond->m_entity.m_observers_lock); + dds_guardcond_unlock (gcond); + return DDS_RETCODE_OK; + } } -_Pre_satisfies_(((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_GUARD) ) -dds_return_t -dds_read_guardcondition( - _In_ dds_entity_t condition, - _Out_ bool *triggered) +dds_return_t dds_read_guardcondition (dds_entity_t condition, bool *triggered) { - dds_return_t ret; - dds_guardcond *gcond; - dds__retcode_t rc; + dds_guardcond *gcond; + dds__retcode_t rc; - if (triggered != NULL) { - *triggered = false; - rc = dds_guardcond_lock(condition, &gcond); - if (rc == DDS_RETCODE_OK) { - *triggered = dds_entity_status_match(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - dds_guardcond_unlock(gcond); - ret = DDS_RETCODE_OK; - } else { - DDS_ERROR("Argument condition is not valid\n"); - ret = DDS_ERRNO(dds_valid_hdl(condition, DDS_KIND_COND_GUARD)); - } - } else { - DDS_ERROR("Argument triggered is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } + if (triggered == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); - return ret; + *triggered = false; + if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) + return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + else + { + os_mutexLock (&gcond->m_entity.m_observers_lock); + *triggered = dds_entity_status_match (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + os_mutexUnlock (&gcond->m_entity.m_observers_lock); + dds_guardcond_unlock (gcond); + return DDS_RETCODE_OK; + } } -_Pre_satisfies_(((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_GUARD) ) -dds_return_t -dds_take_guardcondition( - _In_ dds_entity_t condition, - _Out_ bool *triggered) +dds_return_t dds_take_guardcondition (dds_entity_t condition, bool *triggered) { - dds_return_t ret; - dds_guardcond *gcond; - dds__retcode_t rc; + dds_guardcond *gcond; + dds__retcode_t rc; - if (triggered != NULL) { - *triggered = false; - rc = dds_guardcond_lock(condition, &gcond); - if (rc == DDS_RETCODE_OK) { - *triggered = dds_entity_status_match(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - dds_entity_status_reset(&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - dds_guardcond_unlock (gcond); - ret = DDS_RETCODE_OK; - } else { - DDS_ERROR("Argument condition is not valid\n"); - ret = DDS_ERRNO(dds_valid_hdl(condition, DDS_KIND_COND_GUARD)); - } - } else { - DDS_ERROR("Argument triggered is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - } + if (triggered == NULL) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); - return ret; + *triggered = false; + if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) + return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + else + { + os_mutexLock (&gcond->m_entity.m_observers_lock); + *triggered = dds_entity_status_match (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + dds_entity_status_reset (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + os_mutexUnlock (&gcond->m_entity.m_observers_lock); + dds_guardcond_unlock (gcond); + return DDS_RETCODE_OK; + } } diff --git a/src/core/ddsc/src/dds_listener.c b/src/core/ddsc/src/dds_listener.c index f4e5e51..640745b 100644 --- a/src/core/ddsc/src/dds_listener.c +++ b/src/core/ddsc/src/dds_listener.c @@ -13,163 +13,200 @@ #include "ddsc/dds.h" #include "dds__listener.h" - - -_Ret_notnull_ -dds_listener_t* -dds_create_listener(_In_opt_ void* arg) +dds_listener_t *dds_create_listener (void* arg) { - c_listener_t *l = dds_alloc(sizeof(*l)); - dds_reset_listener(l); - l->arg = arg; - return l; + dds_listener_t *l = dds_alloc (sizeof (*l)); + dds_reset_listener (l); + l->on_inconsistent_topic_arg = arg; + l->on_liveliness_lost_arg = arg; + l->on_offered_deadline_missed_arg = arg; + l->on_offered_incompatible_qos_arg = arg; + l->on_data_on_readers_arg = arg; + l->on_sample_lost_arg = arg; + l->on_data_available_arg = arg; + l->on_sample_rejected_arg = arg; + l->on_liveliness_changed_arg = arg; + l->on_requested_deadline_missed_arg = arg; + l->on_requested_incompatible_qos_arg = arg; + l->on_publication_matched_arg = arg; + l->on_subscription_matched_arg = arg; + return l; } -_Ret_notnull_ -dds_listener_t* -dds_listener_create(_In_opt_ void* arg) +dds_listener_t *dds_listener_create (void* arg) { - return dds_create_listener(arg); + return dds_create_listener (arg); } -void -dds_delete_listener(_In_ _Post_invalid_ dds_listener_t * __restrict listener) +void dds_delete_listener (dds_listener_t * __restrict listener) { - if (listener) { - dds_free(listener); - } + dds_free (listener); } -void -dds_listener_delete(_In_ _Post_invalid_ dds_listener_t * __restrict listener) +void dds_listener_delete (dds_listener_t * __restrict listener) { - dds_delete_listener(listener); + dds_delete_listener (listener); } -void -dds_reset_listener(_Out_ dds_listener_t * __restrict listener) +void dds_reset_listener (dds_listener_t * __restrict listener) { - if (listener) { - c_listener_t *l = listener; - l->on_data_available = DDS_LUNSET; - l->on_data_on_readers = DDS_LUNSET; - l->on_inconsistent_topic = DDS_LUNSET; - l->on_liveliness_changed = DDS_LUNSET; - l->on_liveliness_lost = DDS_LUNSET; - l->on_offered_deadline_missed = DDS_LUNSET; - l->on_offered_incompatible_qos = DDS_LUNSET; - l->on_publication_matched = DDS_LUNSET; - l->on_requested_deadline_missed = DDS_LUNSET; - l->on_requested_incompatible_qos = DDS_LUNSET; - l->on_sample_lost = DDS_LUNSET; - l->on_sample_rejected = DDS_LUNSET; - l->on_subscription_matched = DDS_LUNSET; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + { + dds_listener_t * const l = listener; + l->inherited = 0; + l->on_data_available = 0; + l->on_data_on_readers = 0; + l->on_inconsistent_topic = 0; + l->on_liveliness_changed = 0; + l->on_liveliness_lost = 0; + l->on_offered_deadline_missed = 0; + l->on_offered_incompatible_qos = 0; + l->on_publication_matched = 0; + l->on_requested_deadline_missed = 0; + l->on_requested_incompatible_qos = 0; + l->on_sample_lost = 0; + l->on_sample_rejected = 0; + l->on_subscription_matched = 0; + } } -void -dds_listener_reset(_Out_ dds_listener_t * __restrict listener) +void dds_listener_reset (dds_listener_t * __restrict listener) { - dds_reset_listener(listener); + dds_reset_listener (listener); } -void -dds_copy_listener(_Out_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src) +void dds_copy_listener (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src) { - const c_listener_t *srcl = src; - c_listener_t *dstl = dst; - - if(!src){ - DDS_ERROR("Argument source(src) is NULL\n"); - return ; - } - if(!dst){ - DDS_ERROR("Argument destination(dst) is NULL\n"); - return ; - } - dstl->on_data_available = srcl->on_data_available; - dstl->on_data_on_readers = srcl->on_data_on_readers; - dstl->on_inconsistent_topic = srcl->on_inconsistent_topic; - dstl->on_liveliness_changed = srcl->on_liveliness_changed; - dstl->on_liveliness_lost = srcl->on_liveliness_lost; - dstl->on_offered_deadline_missed = srcl->on_offered_deadline_missed; - dstl->on_offered_incompatible_qos = srcl->on_offered_incompatible_qos; - dstl->on_publication_matched = srcl->on_publication_matched; - dstl->on_requested_deadline_missed = srcl->on_requested_deadline_missed; - dstl->on_requested_incompatible_qos = srcl->on_requested_incompatible_qos; - dstl->on_sample_lost = srcl->on_sample_lost; - dstl->on_sample_rejected = srcl->on_sample_rejected; - dstl->on_subscription_matched = srcl->on_subscription_matched; - dstl->arg = srcl->arg; + if (dst && src) + *dst = *src; } -void -dds_listener_copy(_Out_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src) +void dds_listener_copy(dds_listener_t * __restrict dst, const dds_listener_t * __restrict src) { - dds_copy_listener(dst, src); + dds_copy_listener (dst, src); } -void -dds_merge_listener (_Inout_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src) +static bool dds_combine_listener_merge (uint32_t inherited, void (*dst)(void), void (*src)(void)) { - const c_listener_t *srcl = src; - c_listener_t *dstl = dst; - - if(!src){ - DDS_ERROR("Argument source(src) is NULL\n"); - return ; - } - if(!dst){ - DDS_ERROR("Argument destination(dst) is NULL\n"); - return ; - } - if (dstl->on_data_available == DDS_LUNSET) { - dstl->on_data_available = srcl->on_data_available; - } - if (dstl->on_data_on_readers == DDS_LUNSET) { - dstl->on_data_on_readers = srcl->on_data_on_readers; - } - if (dstl->on_inconsistent_topic == DDS_LUNSET) { - dstl->on_inconsistent_topic = srcl->on_inconsistent_topic; - } - if (dstl->on_liveliness_changed == DDS_LUNSET) { - dstl->on_liveliness_changed = srcl->on_liveliness_changed; - } - if (dstl->on_liveliness_lost == DDS_LUNSET) { - dstl->on_liveliness_lost = srcl->on_liveliness_lost; - } - if (dstl->on_offered_deadline_missed == DDS_LUNSET) { - dstl->on_offered_deadline_missed = srcl->on_offered_deadline_missed; - } - if (dstl->on_offered_incompatible_qos == DDS_LUNSET) { - dstl->on_offered_incompatible_qos = srcl->on_offered_incompatible_qos; - } - if (dstl->on_publication_matched == DDS_LUNSET) { - dstl->on_publication_matched = srcl->on_publication_matched; - } - if (dstl->on_requested_deadline_missed == DDS_LUNSET) { - dstl->on_requested_deadline_missed = srcl->on_requested_deadline_missed; - } - if (dstl->on_requested_incompatible_qos == DDS_LUNSET) { - dstl->on_requested_incompatible_qos = srcl->on_requested_incompatible_qos; - } - if (dstl->on_sample_lost == DDS_LUNSET) { - dstl->on_sample_lost = srcl->on_sample_lost; - } - if (dstl->on_sample_rejected == DDS_LUNSET) { - dstl->on_sample_rejected = srcl->on_sample_rejected; - } - if (dstl->on_subscription_matched == DDS_LUNSET) { - dstl->on_subscription_matched = srcl->on_subscription_matched; - } + (void)inherited; + (void)src; + return dst == 0; } -void -dds_listener_merge (_Inout_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src) +static bool dds_combine_listener_override_inherited (uint32_t inherited, void (*dst)(void), void (*src)(void)) { - dds_merge_listener(dst, src); + (void)dst; + (void)src; + return inherited; +} + +static void dds_combine_listener (bool (*op) (uint32_t inherited, void (*)(void), void (*)(void)), dds_listener_t * __restrict dst, const dds_listener_t * __restrict src) +{ + if (op (dst->inherited & DDS_DATA_AVAILABLE_STATUS, (void (*)(void)) dst->on_data_available, (void (*)(void)) src->on_data_available)) + { + dst->inherited |= DDS_DATA_AVAILABLE_STATUS; + dst->on_data_available = src->on_data_available; + dst->on_data_available_arg = src->on_data_available_arg; + } + if (op (dst->inherited & DDS_DATA_ON_READERS_STATUS, (void (*)(void)) dst->on_data_on_readers, (void (*)(void)) src->on_data_on_readers)) + { + dst->inherited |= DDS_DATA_ON_READERS_STATUS; + dst->on_data_on_readers = src->on_data_on_readers; + dst->on_data_on_readers_arg = src->on_data_on_readers_arg; + } + if (op (dst->inherited & DDS_INCONSISTENT_TOPIC_STATUS, (void (*)(void)) dst->on_inconsistent_topic, (void (*)(void)) src->on_inconsistent_topic)) + { + dst->inherited |= DDS_INCONSISTENT_TOPIC_STATUS; + dst->on_inconsistent_topic = src->on_inconsistent_topic; + dst->on_inconsistent_topic_arg = src->on_inconsistent_topic_arg; + } + if (op (dst->inherited & DDS_LIVELINESS_CHANGED_STATUS, (void (*)(void)) dst->on_liveliness_changed, (void (*)(void)) src->on_liveliness_changed)) + { + dst->inherited |= DDS_LIVELINESS_CHANGED_STATUS; + dst->on_liveliness_changed = src->on_liveliness_changed; + dst->on_liveliness_changed_arg = src->on_liveliness_changed_arg; + } + if (op (dst->inherited & DDS_LIVELINESS_LOST_STATUS, (void (*)(void)) dst->on_liveliness_lost, (void (*)(void)) src->on_liveliness_lost)) + { + dst->inherited |= DDS_LIVELINESS_LOST_STATUS; + dst->on_liveliness_lost = src->on_liveliness_lost; + dst->on_liveliness_lost_arg = src->on_liveliness_lost_arg; + } + if (op (dst->inherited & DDS_OFFERED_DEADLINE_MISSED_STATUS, (void (*)(void)) dst->on_offered_deadline_missed, (void (*)(void)) src->on_offered_deadline_missed)) + { + dst->inherited |= DDS_OFFERED_DEADLINE_MISSED_STATUS; + dst->on_offered_deadline_missed = src->on_offered_deadline_missed; + dst->on_offered_deadline_missed_arg = src->on_offered_deadline_missed_arg; + } + if (op (dst->inherited & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS, (void (*)(void)) dst->on_offered_incompatible_qos, (void (*)(void)) src->on_offered_incompatible_qos)) + { + dst->inherited |= DDS_OFFERED_INCOMPATIBLE_QOS_STATUS; + dst->on_offered_incompatible_qos = src->on_offered_incompatible_qos; + dst->on_offered_incompatible_qos_arg = src->on_offered_incompatible_qos_arg; + } + if (op (dst->inherited & DDS_PUBLICATION_MATCHED_STATUS, (void (*)(void)) dst->on_publication_matched, (void (*)(void)) src->on_publication_matched)) + { + dst->inherited |= DDS_PUBLICATION_MATCHED_STATUS; + dst->on_publication_matched = src->on_publication_matched; + dst->on_publication_matched_arg = src->on_publication_matched_arg; + } + if (op (dst->inherited & DDS_REQUESTED_DEADLINE_MISSED_STATUS, (void (*)(void)) dst->on_requested_deadline_missed, (void (*)(void)) src->on_requested_deadline_missed)) + { + dst->inherited |= DDS_REQUESTED_DEADLINE_MISSED_STATUS; + dst->on_requested_deadline_missed = src->on_requested_deadline_missed; + dst->on_requested_deadline_missed_arg = src->on_requested_deadline_missed_arg; + } + if (op (dst->inherited & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS, (void (*)(void)) dst->on_requested_incompatible_qos, (void (*)(void)) src->on_requested_incompatible_qos)) + { + dst->inherited |= DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS; + dst->on_requested_incompatible_qos = src->on_requested_incompatible_qos; + dst->on_requested_incompatible_qos_arg = src->on_requested_incompatible_qos_arg; + } + if (op (dst->inherited & DDS_SAMPLE_LOST_STATUS, (void (*)(void)) dst->on_sample_lost, (void (*)(void)) src->on_sample_lost)) + { + dst->inherited |= DDS_SAMPLE_LOST_STATUS; + dst->on_sample_lost = src->on_sample_lost; + dst->on_sample_lost_arg = src->on_sample_lost_arg; + } + if (op (dst->inherited & DDS_SAMPLE_REJECTED_STATUS, (void (*)(void)) dst->on_sample_rejected, (void (*)(void)) src->on_sample_rejected)) + { + dst->inherited |= DDS_SAMPLE_REJECTED_STATUS; + dst->on_sample_rejected = src->on_sample_rejected; + dst->on_sample_rejected_arg = src->on_sample_rejected_arg; + } + if (op (dst->inherited & DDS_SUBSCRIPTION_MATCHED_STATUS, (void (*)(void)) dst->on_subscription_matched, (void (*)(void)) src->on_subscription_matched)) + { + dst->inherited |= DDS_SUBSCRIPTION_MATCHED_STATUS; + dst->on_subscription_matched = src->on_subscription_matched; + dst->on_subscription_matched_arg = src->on_subscription_matched_arg; + } +} + +void dds_override_inherited_listener (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src) +{ + if (dst && src) + dds_combine_listener (dds_combine_listener_override_inherited, dst, src); +} + +void dds_inherit_listener (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src) +{ + if (dst && src) + dds_combine_listener (dds_combine_listener_merge, dst, src); +} + +void dds_merge_listener (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src) +{ + if (dst && src) + { + uint32_t inherited = dst->inherited; + dds_combine_listener (dds_combine_listener_merge, dst, src); + dst->inherited = inherited; + } +} + +void dds_listener_merge (_Inout_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src) +{ + dds_merge_listener(dst, src); } /************************************************************************************************ diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 1526142..dc01549 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -162,181 +162,189 @@ dds_reader_status_validate( DDS_RETCODE_OK; } -void -dds_reader_status_cb( - void *ventity, - const status_cb_data_t *data) +void dds_reader_data_available_cb (struct dds_reader *rd) { - struct dds_entity * const entity = ventity; - dds_reader *rd; - dds__retcode_t rc; - void *metrics = NULL; + /* DATA_AVAILABLE is special in two ways: firstly, it should first try + DATA_ON_READERS on the line of ancestors, and if not consumed set the + status on the subscriber; secondly it is the only one for which + overhead really matters. Otherwise, it is pretty much like + dds_reader_status_cb. */ + struct dds_listener const * const lst = &rd->m_entity.m_listener; + dds_entity * const sub = rd->m_entity.m_parent; - /* When data is NULL, it means that the DDSI reader is deleted. */ - if (data == NULL) { - /* Release the initial claim that was done during the create. This - * will indicate that further API deletion is now possible. */ - ut_handle_release(entity->m_hdl, ((dds_entity*)entity)->m_hdllink); - return; + os_mutexLock (&rd->m_entity.m_observers_lock); + while (rd->m_entity.m_cb_count > 0) + os_condWait (&rd->m_entity.m_observers_cond, &rd->m_entity.m_observers_lock); + rd->m_entity.m_cb_count++; + + if (lst->on_data_on_readers) + { + os_mutexUnlock (&rd->m_entity.m_observers_lock); + + os_mutexLock (&sub->m_observers_lock); + while (sub->m_cb_count > 0) + os_condWait (&sub->m_observers_cond, &sub->m_observers_lock); + sub->m_cb_count++; + os_mutexUnlock (&sub->m_observers_lock); + + lst->on_data_on_readers (sub->m_hdl, lst->on_data_on_readers_arg); + + os_mutexLock (&rd->m_entity.m_observers_lock); + os_mutexLock (&sub->m_observers_lock); + sub->m_cb_count--; + os_condBroadcast (&sub->m_observers_cond); + os_mutexUnlock (&sub->m_observers_lock); + } + else if (rd->m_entity.m_listener.on_data_available) + { + os_mutexUnlock (&rd->m_entity.m_observers_lock); + lst->on_data_available (rd->m_entity.m_hdl, lst->on_data_available_arg); + os_mutexLock (&rd->m_entity.m_observers_lock); + } + else + { + dds_entity_status_set (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + + os_mutexLock (&sub->m_observers_lock); + dds_entity_status_set (sub, DDS_DATA_ON_READERS_STATUS); + os_mutexUnlock (&sub->m_observers_lock); + } + + rd->m_entity.m_cb_count--; + os_condBroadcast (&rd->m_entity.m_observers_cond); + os_mutexUnlock (&rd->m_entity.m_observers_lock); +} + +void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) +{ + struct dds_entity * const entity = ventity; + + /* When data is NULL, it means that the DDSI reader is deleted. */ + if (data == NULL) + { + /* Release the initial claim that was done during the create. This + * will indicate that further API deletion is now possible. */ + ut_handle_release (entity->m_hdl, entity->m_hdllink); + return; + } + + struct dds_listener const * const lst = &entity->m_listener; + bool invoke = false; + void *vst = NULL; + int32_t *reset[2] = { NULL, NULL }; + + /* DATA_AVAILABLE is handled by dds_reader_data_available_cb */ + assert (data->status != DDS_DATA_AVAILABLE_STATUS); + + /* Serialize listener invocations -- it is somewhat sad to do this, + but then it may also be unreasonable to expect the application to + handle concurrent invocations of a single listener. The benefit + here is that it means the counters and "change" counters + can safely be incremented and/or reset while releasing + m_observers_lock for the duration of the listener call itself, + and that similarly the listener function and argument pointers + are stable */ + os_mutexLock (&entity->m_observers_lock); + while (entity->m_cb_count > 0) + os_condWait (&entity->m_observers_cond, &entity->m_observers_lock); + entity->m_cb_count++; + + /* Update status metrics. */ + dds_reader * const rd = (dds_reader *) entity; + switch (data->status) { + case DDS_REQUESTED_DEADLINE_MISSED_STATUS: { + struct dds_requested_deadline_missed_status * const st = vst = &rd->m_requested_deadline_missed_status; + st->last_instance_handle = data->handle; + st->total_count++; + st->total_count_change++; + invoke = (lst->on_requested_deadline_missed != 0); + reset[0] = &st->total_count_change; + break; } - - if (dds_reader_lock(entity->m_hdl, &rd) != DDS_RETCODE_OK) { - return; + case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: { + struct dds_requested_incompatible_qos_status * const st = vst = &rd->m_requested_incompatible_qos_status; + st->total_count++; + st->total_count_change++; + st->last_policy_id = data->extra; + invoke = (lst->on_requested_incompatible_qos != 0); + reset[0] = &st->total_count_change; + break; } - assert(&rd->m_entity == entity); - - /* Reset the status for possible Listener call. - * When a listener is not called, the status will be set (again). */ - dds_entity_status_reset(entity, data->status); - - /* Update status metrics. */ - switch (data->status) { - case DDS_REQUESTED_DEADLINE_MISSED_STATUS: { - rd->m_requested_deadline_missed_status.total_count++; - rd->m_requested_deadline_missed_status.total_count_change++; - rd->m_requested_deadline_missed_status.last_instance_handle = data->handle; - metrics = &rd->m_requested_deadline_missed_status; - break; - } - case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: { - rd->m_requested_incompatible_qos_status.total_count++; - rd->m_requested_incompatible_qos_status.total_count_change++; - rd->m_requested_incompatible_qos_status.last_policy_id = data->extra; - metrics = &rd->m_requested_incompatible_qos_status; - break; - } - case DDS_SAMPLE_LOST_STATUS: { - rd->m_sample_lost_status.total_count++; - rd->m_sample_lost_status.total_count_change++; - metrics = &rd->m_sample_lost_status; - break; - } - case DDS_SAMPLE_REJECTED_STATUS: { - rd->m_sample_rejected_status.total_count++; - rd->m_sample_rejected_status.total_count_change++; - rd->m_sample_rejected_status.last_reason = data->extra; - rd->m_sample_rejected_status.last_instance_handle = data->handle; - metrics = &rd->m_sample_rejected_status; - break; - } - case DDS_DATA_AVAILABLE_STATUS: { - metrics = NULL; - break; - } - case DDS_LIVELINESS_CHANGED_STATUS: { - if (data->add) { - rd->m_liveliness_changed_status.alive_count++; - rd->m_liveliness_changed_status.alive_count_change++; - if (rd->m_liveliness_changed_status.not_alive_count > 0) { - rd->m_liveliness_changed_status.not_alive_count--; - } - } else { - rd->m_liveliness_changed_status.alive_count--; - rd->m_liveliness_changed_status.not_alive_count++; - rd->m_liveliness_changed_status.not_alive_count_change++; - } - rd->m_liveliness_changed_status.last_publication_handle = data->handle; - metrics = &rd->m_liveliness_changed_status; - break; - } - case DDS_SUBSCRIPTION_MATCHED_STATUS: { - if (data->add) { - rd->m_subscription_matched_status.total_count++; - rd->m_subscription_matched_status.total_count_change++; - rd->m_subscription_matched_status.current_count++; - rd->m_subscription_matched_status.current_count_change++; - } else { - rd->m_subscription_matched_status.current_count--; - rd->m_subscription_matched_status.current_count_change--; - } - rd->m_subscription_matched_status.last_publication_handle = data->handle; - metrics = &rd->m_subscription_matched_status; - break; - } - default: assert (0); + case DDS_SAMPLE_LOST_STATUS: { + struct dds_sample_lost_status * const st = vst = &rd->m_sample_lost_status; + st->total_count++; + st->total_count_change++; + invoke = (lst->on_sample_lost != 0); + reset[0] = &st->total_count_change; + break; } - - /* The reader needs to be unlocked when propagating the (possible) listener - * call because the application should be able to call this reader within - * the callback function. */ - dds_reader_unlock(rd); - - /* DATA_AVAILABLE is handled differently to normal status changes. */ - if (data->status == DDS_DATA_AVAILABLE_STATUS) { - dds_entity *parent = rd->m_entity.m_parent; - /* First, try to ship it off to its parent(s) DDS_DATA_ON_READERS_STATUS. */ - rc = dds_entity_listener_propagation(parent, parent, DDS_DATA_ON_READERS_STATUS, NULL, true); - - if (rc == DDS_RETCODE_NO_DATA) { - /* No parent was interested (NO_DATA == NO_CALL). - * What about myself with DDS_DATA_AVAILABLE_STATUS? */ - rc = dds_entity_listener_propagation(entity, entity, DDS_DATA_AVAILABLE_STATUS, NULL, false); - } - - if ( rc == DDS_RETCODE_NO_DATA ) { - /* Nobody was interested (NO_DATA == NO_CALL). Set the status on the subscriber. */ - dds_entity_status_set(parent, DDS_DATA_ON_READERS_STATUS); - /* Notify possible interested observers of the subscriber. */ - dds_entity_status_signal(parent); - } - } else { - /* Is anybody interested within the entity hierarchy through listeners? */ - rc = dds_entity_listener_propagation(entity, entity, data->status, metrics, true); + case DDS_SAMPLE_REJECTED_STATUS: { + struct dds_sample_rejected_status * const st = vst = &rd->m_sample_rejected_status; + st->total_count++; + st->total_count_change++; + st->last_reason = data->extra; + st->last_instance_handle = data->handle; + invoke = (lst->on_sample_rejected != 0); + reset[0] = &st->total_count_change; + break; } - - if (rc == DDS_RETCODE_OK) { - /* Event was eaten by a listener. */ - if (dds_reader_lock(entity->m_hdl, &rd) == DDS_RETCODE_OK) { - assert(&rd->m_entity == entity); - - /* Reset the change counts of the metrics. */ - switch (data->status) { - case DDS_REQUESTED_DEADLINE_MISSED_STATUS: { - rd->m_requested_deadline_missed_status.total_count_change = 0; - break; - } - case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: { - rd->m_requested_incompatible_qos_status.total_count_change = 0; - break; - } - case DDS_SAMPLE_LOST_STATUS: { - rd->m_sample_lost_status.total_count_change = 0; - break; - } - case DDS_SAMPLE_REJECTED_STATUS: { - rd->m_sample_rejected_status.total_count_change = 0; - break; - } - case DDS_DATA_AVAILABLE_STATUS: { - /* Nothing to reset. */; - break; - } - case DDS_LIVELINESS_CHANGED_STATUS: { - rd->m_liveliness_changed_status.alive_count_change = 0; - rd->m_liveliness_changed_status.not_alive_count_change = 0; - break; - } - case DDS_SUBSCRIPTION_MATCHED_STATUS: { - rd->m_subscription_matched_status.total_count_change = 0; - rd->m_subscription_matched_status.current_count_change = 0; - break; - } - default: assert (0); - } - dds_reader_unlock(rd); - } else { - /* There's a deletion or closing going on. */ + case DDS_LIVELINESS_CHANGED_STATUS: { + struct dds_liveliness_changed_status * const st = vst = &rd->m_liveliness_changed_status; + if (data->add) { + st->alive_count++; + st->alive_count_change++; + if (st->not_alive_count > 0) { + st->not_alive_count--; } - } else if (rc == DDS_RETCODE_NO_DATA) { - /* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status, consider successful. */ - dds_entity_status_set(entity, data->status); - /* Notify possible interested observers. */ - dds_entity_status_signal(entity); - } else if (rc == DDS_RETCODE_ALREADY_DELETED) { - /* An entity up the hierarchy is being deleted, consider successful. */ - } else { - /* Something went wrong up the hierarchy. */ + } else { + st->alive_count--; + st->not_alive_count++; + st->not_alive_count_change++; + } + st->last_publication_handle = data->handle; + invoke = (lst->on_liveliness_changed != 0); + reset[0] = &st->alive_count_change; + reset[1] = &st->not_alive_count_change; + break; } + case DDS_SUBSCRIPTION_MATCHED_STATUS: { + struct dds_subscription_matched_status * const st = vst = &rd->m_subscription_matched_status; + if (data->add) { + st->total_count++; + st->total_count_change++; + st->current_count++; + st->current_count_change++; + } else { + st->current_count--; + st->current_count_change--; + } + st->last_publication_handle = data->handle; + invoke = (lst->on_subscription_matched != 0); + reset[0] = &st->total_count_change; + reset[1] = &st->current_count_change; + break; + } + default: + assert (0); + } + + if (invoke) + { + os_mutexUnlock (&entity->m_observers_lock); + dds_entity_invoke_listener(entity, data->status, vst); + os_mutexLock (&entity->m_observers_lock); + *reset[0] = 0; + if (reset[1]) + *reset[1] = 0; + } + else + { + dds_entity_status_set (entity, data->status); + } + + entity->m_cb_count--; + os_condBroadcast (&entity->m_observers_cond); + os_mutexUnlock (&entity->m_observers_lock); } _Pre_satisfies_(((participant_or_subscriber & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER ) ||\ diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index f06754a..f931114 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -146,8 +146,6 @@ "signal_conditions" after releasing the RHC lock. */ -static const status_cb_data_t dds_rhc_data_avail_cb_data = { DDS_DATA_AVAILABLE_STATUS, 0, 0, true }; - /* FIXME: tkmap should perhaps retain data with timestamp set to invalid An invalid timestamp is (logically) unordered with respect to valid timestamps, and that would mean BY_SOURCE order could be respected @@ -1389,7 +1387,7 @@ bool dds_rhc_store if (rhc->reader && (rhc->reader->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) { os_atomic_inc32 (&rhc->n_cbs); - dds_reader_status_cb (&rhc->reader->m_entity, &dds_rhc_data_avail_cb_data); + dds_reader_data_available_cb (rhc->reader); os_atomic_dec32 (&rhc->n_cbs); } } diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 7e6cab4..a55dd93 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -97,26 +97,6 @@ dds_subscriber_status_validate( return ret; } -/* - Set boolean on readers that indicates state of DATA_ON_READERS - status on parent subscriber -*/ -static dds_return_t dds_subscriber_status_propagate (dds_entity *sub, uint32_t mask, bool set) -{ - if (mask & DDS_DATA_ON_READERS_STATUS) - { - dds_entity *iter = sub->m_children; - while (iter) { - os_mutexLock (&iter->m_mutex); - assert (dds_entity_kind (iter) == DDS_KIND_READER); - ((dds_reader*) iter)->m_data_on_readers = set; - os_mutexUnlock (&iter->m_mutex); - iter = iter->m_next; - } - } - return DDS_RETCODE_OK; -} - _Requires_exclusive_lock_held_(participant) _Check_return_ dds_entity_t dds__create_subscriber_l( @@ -147,7 +127,6 @@ dds__create_subscriber_l( subscriber = dds_entity_init(&sub->m_entity, participant, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK); sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set; sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate; - sub->m_entity.m_deriver.propagate_status = dds_subscriber_status_propagate; sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl; return subscriber; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 9364199..4027bdc 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -92,55 +92,29 @@ dds_topic_status_validate( status (only defined status on a topic). */ -static void -dds_topic_status_cb( - struct dds_topic *cb_t) +static void dds_topic_status_cb (struct dds_topic *tp) { - dds_topic *topic; - dds__retcode_t rc; + struct dds_listener const * const lst = &tp->m_entity.m_listener; - if (dds_topic_lock(cb_t->m_entity.m_hdl, &topic) != DDS_RETCODE_OK) { - return; - } - assert(topic == cb_t); + os_mutexLock (&tp->m_entity.m_observers_lock); + while (tp->m_entity.m_cb_count > 0) + os_condWait (&tp->m_entity.m_observers_cond, &tp->m_entity.m_observers_lock); + tp->m_entity.m_cb_count++; - /* Reset the status for possible Listener call. - * When a listener is not called, the status will be set (again). */ + tp->m_inconsistent_topic_status.total_count++; + tp->m_inconsistent_topic_status.total_count_change++; + if (lst->on_inconsistent_topic) + { + os_mutexUnlock (&tp->m_entity.m_observers_lock); + dds_entity_invoke_listener(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS, &tp->m_inconsistent_topic_status); + os_mutexLock (&tp->m_entity.m_observers_lock); + tp->m_inconsistent_topic_status.total_count_change = 0; + } - /* Update status metrics. */ - topic->m_inconsistent_topic_status.total_count++; - topic->m_inconsistent_topic_status.total_count_change++; - - - /* The topic needs to be unlocked when propagating the (possible) listener - * call because the application should be able to call this topic within - * the callback function. */ - dds_topic_unlock(topic); - - /* Is anybody interested within the entity hierarchy through listeners? */ - rc = dds_entity_listener_propagation(&topic->m_entity, - &topic->m_entity, - DDS_INCONSISTENT_TOPIC_STATUS, - &topic->m_inconsistent_topic_status, - true); - - if (rc == DDS_RETCODE_OK) { - /* Event was eaten by a listener. */ - if (dds_topic_lock(cb_t->m_entity.m_hdl, &topic) == DDS_RETCODE_OK) { - /* Reset the change counts of the metrics. */ - topic->m_inconsistent_topic_status.total_count_change = 0; - dds_topic_unlock(topic); - } - } else if (rc == DDS_RETCODE_NO_DATA) { - /* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status; consider it successful. */ - dds_entity_status_set(&topic->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); - /* Notify possible interested observers. */ - dds_entity_status_signal(&topic->m_entity); - } else if (rc == DDS_RETCODE_ALREADY_DELETED) { - /* An entity up the hierarchy is being deleted; consider it successful. */ - } else { - /* Something went wrong up the hierarchy. */ - } + dds_entity_status_set(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); + tp->m_entity.m_cb_count--; + os_condBroadcast (&tp->m_entity.m_observers_cond); + os_mutexUnlock (&tp->m_entity.m_observers_lock); } struct ddsi_sertopic * diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index a6c2c08..1b0782a 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -38,18 +38,6 @@ dds_waitset_swap( *dst = idx; } -static void dds_waitset_signal_entity (dds_waitset *ws) -{ - dds_entity *e = &ws->m_entity; - /* When signaling any observers of us through the entity, - * we need to be unlocked. We still have claimed the related - * handle, so possible deletions will be delayed until we - * release it. */ - os_mutexUnlock (&e->m_mutex); - dds_entity_status_signal (e); - os_mutexLock (&e->m_mutex); -} - static dds_return_t dds_waitset_wait_impl( _In_ dds_entity_t waitset, @@ -472,33 +460,25 @@ dds_waitset_wait( return ret; } -_Pre_satisfies_((waitset & DDS_ENTITY_KIND_MASK) == DDS_KIND_WAITSET) -dds_return_t -dds_waitset_set_trigger( - _In_ dds_entity_t waitset, - _In_ bool trigger) +dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger) { - dds_waitset *ws; - dds__retcode_t rc; - dds_return_t ret = DDS_RETCODE_OK; + dds_waitset *ws; + dds__retcode_t rc; - /* Locking the waitset here will delay a possible deletion until it is - * unlocked. Even when the related mutex is unlocked when we want to send - * a signal. */ - rc = dds_waitset_lock(waitset, &ws); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking waitset\n"); - ret = DDS_ERRNO(rc); - goto fail; - } - if (trigger) { - dds_entity_status_set(&ws->m_entity, DDS_WAITSET_TRIGGER_STATUS); - } else { - dds_entity_status_reset(&ws->m_entity, DDS_WAITSET_TRIGGER_STATUS); - } - dds_waitset_signal_entity(ws); - dds_waitset_unlock(ws); -fail: - return ret; + if ((rc = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + + os_mutexUnlock (&ws->m_entity.m_mutex); + + os_mutexLock (&ws->m_entity.m_observers_lock); + if (trigger) + dds_entity_status_set (&ws->m_entity, DDS_WAITSET_TRIGGER_STATUS); + else + dds_entity_status_reset (&ws->m_entity, DDS_WAITSET_TRIGGER_STATUS); + os_mutexUnlock (&ws->m_entity.m_observers_lock); + + os_mutexLock (&ws->m_entity.m_mutex); + dds_waitset_unlock (ws); + return DDS_RETCODE_OK; } diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index b9d7cd3..8ffab83 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -65,15 +65,9 @@ dds_writer_status_validate( then status conditions is not triggered. */ -static void -dds_writer_status_cb( - void *ventity, - const status_cb_data_t *data) +static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) { - struct dds_entity * const entity = ventity; - dds_writer *wr; - dds__retcode_t rc; - void *metrics = NULL; + struct dds_entity * const entity = ventity; /* When data is NULL, it means that the writer is deleted. */ if (data == NULL) @@ -84,44 +78,52 @@ dds_writer_status_cb( return; } - if (dds_writer_lock (entity->m_hdl, &wr) != DDS_RETCODE_OK) { - /* There's a deletion or closing going on. */ - return; - } - assert (&wr->m_entity == entity); + struct dds_listener const * const lst = &entity->m_listener; + bool invoke = false; + void *vst = NULL; + int32_t *reset[2] = { NULL, NULL }; + + os_mutexLock (&entity->m_observers_lock); + while (entity->m_cb_count > 0) + os_condWait (&entity->m_observers_cond, &entity->m_observers_lock); + entity->m_cb_count++; /* Reset the status for possible Listener call. * When a listener is not called, the status will be set (again). */ dds_entity_status_reset (entity, data->status); /* Update status metrics. */ + dds_writer * const wr = (dds_writer *) entity; switch (data->status) { case DDS_OFFERED_DEADLINE_MISSED_STATUS: { - struct dds_offered_deadline_missed_status * const st = &wr->m_offered_deadline_missed_status; + struct dds_offered_deadline_missed_status * const st = vst = &wr->m_offered_deadline_missed_status; st->total_count++; st->total_count_change++; st->last_instance_handle = data->handle; - metrics = st; + invoke = (lst->on_offered_deadline_missed != 0); + reset[0] = &st->total_count_change; break; } case DDS_LIVELINESS_LOST_STATUS: { - struct dds_liveliness_lost_status * const st = &wr->m_liveliness_lost_status; + struct dds_liveliness_lost_status * const st = vst = &wr->m_liveliness_lost_status; st->total_count++; st->total_count_change++; - metrics = st; + invoke = (lst->on_liveliness_lost != 0); + reset[0] = &st->total_count_change; break; } case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: { - struct dds_offered_incompatible_qos_status * const st = &wr->m_offered_incompatible_qos_status; + struct dds_offered_incompatible_qos_status * const st = vst = &wr->m_offered_incompatible_qos_status; st->total_count++; st->total_count_change++; st->last_policy_id = data->extra; - metrics = st; + invoke = (lst->on_offered_incompatible_qos != 0); + reset[0] = &st->total_count_change; break; } case DDS_PUBLICATION_MATCHED_STATUS: { - struct dds_publication_matched_status * const st = &wr->m_publication_matched_status; + struct dds_publication_matched_status * const st = vst = &wr->m_publication_matched_status; if (data->add) { st->total_count++; st->total_count_change++; @@ -131,69 +133,33 @@ dds_writer_status_cb( st->current_count--; st->current_count_change--; } - st->last_subscription_handle = data->handle; - metrics = st; + wr->m_publication_matched_status.last_subscription_handle = data->handle; + invoke = (lst->on_publication_matched != 0); + reset[0] = &st->total_count_change; + reset[1] = &st->current_count_change; break; } default: assert (0); } - /* The writer needs to be unlocked when propagating the (possible) listener - * call because the application should be able to call this writer within - * the callback function. */ - dds_writer_unlock (wr); - - /* Is anybody interested within the entity hierarchy through listeners? */ - rc = dds_entity_listener_propagation (entity, entity, data->status, metrics, true); - - if (rc == DDS_RETCODE_OK) + if (invoke) { - /* Event was eaten by a listener. */ - if (dds_writer_lock (entity->m_hdl, &wr) == DDS_RETCODE_OK) - { - assert (&wr->m_entity == entity); - - /* Reset the status. */ - dds_entity_status_reset (entity, data->status); - - /* Reset the change counts of the metrics. */ - switch (data->status) - { - case DDS_OFFERED_DEADLINE_MISSED_STATUS: - wr->m_offered_deadline_missed_status.total_count_change = 0; - break; - case DDS_LIVELINESS_LOST_STATUS: - wr->m_liveliness_lost_status.total_count_change = 0; - break; - case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: - wr->m_offered_incompatible_qos_status.total_count_change = 0; - break; - case DDS_PUBLICATION_MATCHED_STATUS: - wr->m_publication_matched_status.total_count_change = 0; - wr->m_publication_matched_status.current_count_change = 0; - break; - default: - assert (0); - } - dds_writer_unlock (wr); - } - } - else if (rc == DDS_RETCODE_NO_DATA) - { - /* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status; consider it successful. */ - dds_entity_status_set (entity, data->status); - /* Notify possible interested observers. */ - dds_entity_status_signal (entity); - } - else if (rc == DDS_RETCODE_ALREADY_DELETED) - { - /* An entity up the hierarchy is being deleted; consider it successful. */ + os_mutexUnlock (&entity->m_observers_lock); + dds_entity_invoke_listener(entity, data->status, vst); + os_mutexLock (&entity->m_observers_lock); + *reset[0] = 0; + if (reset[1]) + *reset[1] = 0; } else { - /* Something went wrong up the hierarchy. */ + dds_entity_status_set (entity, data->status); } + + entity->m_cb_count--; + os_condBroadcast (&entity->m_observers_cond); + os_mutexUnlock (&entity->m_observers_lock); } static uint32_t From 54b5bed8d22ef1dc61bc31b57e7af89b8bf31afe Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 15 Jan 2019 10:29:53 +0100 Subject: [PATCH 06/10] use enum with values log2(STATUS) for identifying status/listener Signed-off-by: Erik Boasson --- src/core/ddsc/include/ddsc/dds.h | 42 ++++++++++++++++++--------- src/core/ddsc/src/dds__entity.h | 2 +- src/core/ddsc/src/dds_entity.c | 30 +++++++++---------- src/core/ddsc/src/dds_reader.c | 29 +++++++++++------- src/core/ddsc/src/dds_rhc.c | 12 ++++---- src/core/ddsc/src/dds_topic.c | 2 +- src/core/ddsc/src/dds_writer.c | 27 +++++++++++------ src/core/ddsi/include/ddsi/q_entity.h | 2 +- src/core/ddsi/src/q_entity.c | 28 +++++++++--------- 9 files changed, 103 insertions(+), 71 deletions(-) diff --git a/src/core/ddsc/include/ddsc/dds.h b/src/core/ddsc/include/ddsc/dds.h index 6c378a2..41c04e9 100644 --- a/src/core/ddsc/include/ddsc/dds.h +++ b/src/core/ddsc/include/ddsc/dds.h @@ -81,31 +81,47 @@ extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION; /** @name Communication Status definitions @{**/ /** Another topic exists with the same name but with different characteristics. */ -#define DDS_INCONSISTENT_TOPIC_STATUS 1u +typedef enum dds_status_id { + DDS_INCONSISTENT_TOPIC_STATUS_ID, + DDS_OFFERED_DEADLINE_MISSED_STATUS_ID, + DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID, + DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID, + DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID, + DDS_SAMPLE_LOST_STATUS_ID, + DDS_SAMPLE_REJECTED_STATUS_ID, + DDS_DATA_ON_READERS_STATUS_ID, + DDS_DATA_AVAILABLE_STATUS_ID, + DDS_LIVELINESS_LOST_STATUS_ID, + DDS_LIVELINESS_CHANGED_STATUS_ID, + DDS_PUBLICATION_MATCHED_STATUS_ID, + DDS_SUBSCRIPTION_MATCHED_STATUS_ID +} +dds_status_id_t; +#define DDS_INCONSISTENT_TOPIC_STATUS (1u << DDS_INCONSISTENT_TOPIC_STATUS_ID) /** The deadline that the writer has committed through its deadline QoS policy was not respected for a specific instance. */ -#define DDS_OFFERED_DEADLINE_MISSED_STATUS 2u +#define DDS_OFFERED_DEADLINE_MISSED_STATUS (1u << DDS_OFFERED_DEADLINE_MISSED_STATUS_ID) /** The deadline that the reader was expecting through its deadline QoS policy was not respected for a specific instance. */ -#define DDS_REQUESTED_DEADLINE_MISSED_STATUS 4u +#define DDS_REQUESTED_DEADLINE_MISSED_STATUS (1u << DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID) /** A QoS policy setting was incompatible with what was requested. */ -#define DDS_OFFERED_INCOMPATIBLE_QOS_STATUS 32u +#define DDS_OFFERED_INCOMPATIBLE_QOS_STATUS (1u << DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID) /** A QoS policy setting was incompatible with what is offered. */ -#define DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS 64u +#define DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS (1u << DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID) /** A sample has been lost (never received). */ -#define DDS_SAMPLE_LOST_STATUS 128u +#define DDS_SAMPLE_LOST_STATUS (1u << DDS_SAMPLE_LOST_STATUS_ID) /** A (received) sample has been rejected. */ -#define DDS_SAMPLE_REJECTED_STATUS 256u +#define DDS_SAMPLE_REJECTED_STATUS (1u << DDS_SAMPLE_REJECTED_STATUS_ID) /** New information is available. */ -#define DDS_DATA_ON_READERS_STATUS 512u +#define DDS_DATA_ON_READERS_STATUS (1u << DDS_DATA_ON_READERS_STATUS_ID) /** New information is available. */ -#define DDS_DATA_AVAILABLE_STATUS 1024u +#define DDS_DATA_AVAILABLE_STATUS (1u << DDS_DATA_AVAILABLE_STATUS_ID) /** The liveliness that the DDS_DataWriter has committed through its liveliness QoS policy was not respected; thus readers will consider the writer as no longer "alive". */ -#define DDS_LIVELINESS_LOST_STATUS 2048u +#define DDS_LIVELINESS_LOST_STATUS (1u << DDS_LIVELINESS_LOST_STATUS_ID) /** The liveliness of one or more writers, that were writing instances read through the readers has changed. Some writers have become "alive" or "not alive". */ -#define DDS_LIVELINESS_CHANGED_STATUS 4096u +#define DDS_LIVELINESS_CHANGED_STATUS (1u << DDS_LIVELINESS_CHANGED_STATUS_ID) /** The writer has found a reader that matches the topic and has a compatible QoS. */ -#define DDS_PUBLICATION_MATCHED_STATUS 8192u +#define DDS_PUBLICATION_MATCHED_STATUS (1u << DDS_PUBLICATION_MATCHED_STATUS_ID) /** The reader has found a writer that matches the topic and has a compatible QoS. */ -#define DDS_SUBSCRIPTION_MATCHED_STATUS 16384u +#define DDS_SUBSCRIPTION_MATCHED_STATUS (1u << DDS_SUBSCRIPTION_MATCHED_STATUS_ID) /** @}*/ /** Read state for a data value */ diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index ac92fee..04967fa 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -80,7 +80,7 @@ inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl) { void dds_entity_status_signal (dds_entity *e); -void dds_entity_invoke_listener (const dds_entity *entity, uint32_t status, const void *vst); +void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst); _Check_return_ dds__retcode_t dds_valid_hdl( diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 71fc819..90097c8 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -424,71 +424,71 @@ dds_return_t dds_get_listener (dds_entity_t entity, dds_listener_t *listener) return ret; } -void dds_entity_invoke_listener (const dds_entity *entity, uint32_t status, const void *vst) +void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst) { struct dds_listener const * const lst = &entity->m_listener; - switch (status) + switch (which) { - case DDS_INCONSISTENT_TOPIC_STATUS: { + case DDS_INCONSISTENT_TOPIC_STATUS_ID: { struct dds_inconsistent_topic_status const * const st = vst; lst->on_inconsistent_topic (entity->m_hdl, *st, lst->on_inconsistent_topic_arg); break; } - case DDS_REQUESTED_DEADLINE_MISSED_STATUS: { + case DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID: { struct dds_requested_deadline_missed_status const * const st = vst; lst->on_requested_deadline_missed (entity->m_hdl, *st, lst->on_requested_deadline_missed_arg); break; } - case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: { + case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID: { struct dds_requested_incompatible_qos_status const * const st = vst; lst->on_requested_incompatible_qos (entity->m_hdl, *st, lst->on_requested_incompatible_qos_arg); break; } - case DDS_SAMPLE_LOST_STATUS: { + case DDS_SAMPLE_LOST_STATUS_ID: { struct dds_sample_lost_status const * const st = vst; lst->on_sample_lost (entity->m_hdl, *st, lst->on_sample_lost_arg); break; } - case DDS_SAMPLE_REJECTED_STATUS: { + case DDS_SAMPLE_REJECTED_STATUS_ID: { struct dds_sample_rejected_status const * const st = vst; lst->on_sample_rejected (entity->m_hdl, *st, lst->on_sample_rejected_arg); break; } - case DDS_LIVELINESS_CHANGED_STATUS: { + case DDS_LIVELINESS_CHANGED_STATUS_ID: { struct dds_liveliness_changed_status const * const st = vst; lst->on_liveliness_changed (entity->m_hdl, *st, lst->on_liveliness_changed_arg); break; } - case DDS_SUBSCRIPTION_MATCHED_STATUS: { + case DDS_SUBSCRIPTION_MATCHED_STATUS_ID: { struct dds_subscription_matched_status const * const st = vst; lst->on_subscription_matched (entity->m_hdl, *st, lst->on_subscription_matched_arg); break; } - case DDS_OFFERED_DEADLINE_MISSED_STATUS: { + case DDS_OFFERED_DEADLINE_MISSED_STATUS_ID: { struct dds_offered_deadline_missed_status const * const st = vst; lst->on_offered_deadline_missed (entity->m_hdl, *st, lst->on_offered_deadline_missed_arg); break; } - case DDS_LIVELINESS_LOST_STATUS: { + case DDS_LIVELINESS_LOST_STATUS_ID: { struct dds_liveliness_lost_status const * const st = vst; lst->on_liveliness_lost (entity->m_hdl, *st, lst->on_liveliness_lost_arg); break; } - case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: { + case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID: { struct dds_offered_incompatible_qos_status const * const st = vst; lst->on_offered_incompatible_qos (entity->m_hdl, *st, lst->on_offered_incompatible_qos_arg); break; } - case DDS_PUBLICATION_MATCHED_STATUS: { + case DDS_PUBLICATION_MATCHED_STATUS_ID: { struct dds_publication_matched_status const * const st = vst; lst->on_publication_matched (entity->m_hdl, *st, lst->on_publication_matched_arg); break; } - case DDS_DATA_AVAILABLE_STATUS: { + case DDS_DATA_AVAILABLE_STATUS_ID: { lst->on_data_available (entity->m_hdl, lst->on_data_available_arg); break; } - case DDS_DATA_ON_READERS_STATUS: { + case DDS_DATA_ON_READERS_STATUS_ID: { lst->on_data_on_readers (entity->m_hdl, lst->on_data_on_readers_arg); break; } diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index dc01549..b0e16cf 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -229,12 +229,13 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) } struct dds_listener const * const lst = &entity->m_listener; + enum dds_status_id status_id = (enum dds_status_id) data->raw_status_id; bool invoke = false; void *vst = NULL; int32_t *reset[2] = { NULL, NULL }; /* DATA_AVAILABLE is handled by dds_reader_data_available_cb */ - assert (data->status != DDS_DATA_AVAILABLE_STATUS); + assert (status_id != DDS_DATA_AVAILABLE_STATUS_ID); /* Serialize listener invocations -- it is somewhat sad to do this, but then it may also be unreasonable to expect the application to @@ -251,8 +252,8 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) /* Update status metrics. */ dds_reader * const rd = (dds_reader *) entity; - switch (data->status) { - case DDS_REQUESTED_DEADLINE_MISSED_STATUS: { + switch (status_id) { + case DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID: { struct dds_requested_deadline_missed_status * const st = vst = &rd->m_requested_deadline_missed_status; st->last_instance_handle = data->handle; st->total_count++; @@ -261,7 +262,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) reset[0] = &st->total_count_change; break; } - case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: { + case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID: { struct dds_requested_incompatible_qos_status * const st = vst = &rd->m_requested_incompatible_qos_status; st->total_count++; st->total_count_change++; @@ -270,7 +271,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) reset[0] = &st->total_count_change; break; } - case DDS_SAMPLE_LOST_STATUS: { + case DDS_SAMPLE_LOST_STATUS_ID: { struct dds_sample_lost_status * const st = vst = &rd->m_sample_lost_status; st->total_count++; st->total_count_change++; @@ -278,7 +279,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) reset[0] = &st->total_count_change; break; } - case DDS_SAMPLE_REJECTED_STATUS: { + case DDS_SAMPLE_REJECTED_STATUS_ID: { struct dds_sample_rejected_status * const st = vst = &rd->m_sample_rejected_status; st->total_count++; st->total_count_change++; @@ -288,7 +289,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) reset[0] = &st->total_count_change; break; } - case DDS_LIVELINESS_CHANGED_STATUS: { + case DDS_LIVELINESS_CHANGED_STATUS_ID: { struct dds_liveliness_changed_status * const st = vst = &rd->m_liveliness_changed_status; if (data->add) { st->alive_count++; @@ -307,7 +308,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) reset[1] = &st->not_alive_count_change; break; } - case DDS_SUBSCRIPTION_MATCHED_STATUS: { + case DDS_SUBSCRIPTION_MATCHED_STATUS_ID: { struct dds_subscription_matched_status * const st = vst = &rd->m_subscription_matched_status; if (data->add) { st->total_count++; @@ -324,14 +325,20 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) reset[1] = &st->current_count_change; break; } - default: + case DDS_DATA_ON_READERS_STATUS_ID: + case DDS_DATA_AVAILABLE_STATUS_ID: + case DDS_INCONSISTENT_TOPIC_STATUS_ID: + case DDS_LIVELINESS_LOST_STATUS_ID: + case DDS_PUBLICATION_MATCHED_STATUS_ID: + case DDS_OFFERED_DEADLINE_MISSED_STATUS_ID: + case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID: assert (0); } if (invoke) { os_mutexUnlock (&entity->m_observers_lock); - dds_entity_invoke_listener(entity, data->status, vst); + dds_entity_invoke_listener(entity, status_id, vst); os_mutexLock (&entity->m_observers_lock); *reset[0] = 0; if (reset[1]) @@ -339,7 +346,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) } else { - dds_entity_status_set (entity, data->status); + dds_entity_status_set (entity, 1u << status_id); } entity->m_cb_count--; diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index f931114..5fb3d1b 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -644,7 +644,7 @@ static bool add_sample if (rhc->reader && rhc->max_samples != DDS_LENGTH_UNLIMITED && rhc->n_vsamples >= (uint32_t) rhc->max_samples) { - cb_data->status = DDS_SAMPLE_REJECTED_STATUS; + cb_data->raw_status_id = (int) DDS_SAMPLE_REJECTED_STATUS_ID; cb_data->extra = DDS_REJECTED_BY_SAMPLES_LIMIT; cb_data->handle = inst->iid; cb_data->add = true; @@ -655,7 +655,7 @@ static bool add_sample if (rhc->reader && rhc->max_samples_per_instance != DDS_LENGTH_UNLIMITED && inst->nvsamples >= (uint32_t) rhc->max_samples_per_instance) { - cb_data->status = DDS_SAMPLE_REJECTED_STATUS; + cb_data->raw_status_id = (int) DDS_SAMPLE_REJECTED_STATUS_ID; cb_data->extra = DDS_REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT; cb_data->handle = inst->iid; cb_data->add = true; @@ -1108,7 +1108,7 @@ static rhc_store_result_t rhc_store_new_instance if (rhc->reader && rhc->max_instances != DDS_LENGTH_UNLIMITED && rhc->n_instances >= (uint32_t) rhc->max_instances) { - cb_data->status = DDS_SAMPLE_REJECTED_STATUS; + cb_data->raw_status_id = (int) DDS_SAMPLE_REJECTED_STATUS_ID; cb_data->extra = DDS_REJECTED_BY_INSTANCES_LIMIT; cb_data->handle = tk->m_iid; cb_data->add = true; @@ -1177,7 +1177,7 @@ bool dds_rhc_store dummy_instance.iid = tk->m_iid; stored = RHC_FILTERED; - cb_data.status = 0; + cb_data.raw_status_id = -1; os_mutexLock (&rhc->lock); @@ -1229,7 +1229,7 @@ bool dds_rhc_store } /* notify sample lost */ - cb_data.status = DDS_SAMPLE_LOST_STATUS; + cb_data.raw_status_id = (int) DDS_SAMPLE_LOST_STATUS_ID; cb_data.extra = 0; cb_data.handle = 0; cb_data.add = true; @@ -1411,7 +1411,7 @@ error_or_nochange: /* Make any reader status callback */ - if (cb_data.status && rhc->reader && rhc->reader->m_entity.m_status_enable) + if (cb_data.raw_status_id >= 0 && rhc->reader && rhc->reader->m_entity.m_status_enable) { os_atomic_inc32 (&rhc->n_cbs); dds_reader_status_cb (&rhc->reader->m_entity, &cb_data); diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 4027bdc..b9c193e 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -106,7 +106,7 @@ static void dds_topic_status_cb (struct dds_topic *tp) if (lst->on_inconsistent_topic) { os_mutexUnlock (&tp->m_entity.m_observers_lock); - dds_entity_invoke_listener(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS, &tp->m_inconsistent_topic_status); + dds_entity_invoke_listener(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS_ID, &tp->m_inconsistent_topic_status); os_mutexLock (&tp->m_entity.m_observers_lock); tp->m_inconsistent_topic_status.total_count_change = 0; } diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 8ffab83..85f868c 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -79,6 +79,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) } struct dds_listener const * const lst = &entity->m_listener; + enum dds_status_id status_id = (enum dds_status_id) data->raw_status_id; bool invoke = false; void *vst = NULL; int32_t *reset[2] = { NULL, NULL }; @@ -90,13 +91,13 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) /* Reset the status for possible Listener call. * When a listener is not called, the status will be set (again). */ - dds_entity_status_reset (entity, data->status); + dds_entity_status_reset (entity, 1u << status_id); /* Update status metrics. */ dds_writer * const wr = (dds_writer *) entity; - switch (data->status) + switch (status_id) { - case DDS_OFFERED_DEADLINE_MISSED_STATUS: { + case DDS_OFFERED_DEADLINE_MISSED_STATUS_ID: { struct dds_offered_deadline_missed_status * const st = vst = &wr->m_offered_deadline_missed_status; st->total_count++; st->total_count_change++; @@ -105,7 +106,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) reset[0] = &st->total_count_change; break; } - case DDS_LIVELINESS_LOST_STATUS: { + case DDS_LIVELINESS_LOST_STATUS_ID: { struct dds_liveliness_lost_status * const st = vst = &wr->m_liveliness_lost_status; st->total_count++; st->total_count_change++; @@ -113,7 +114,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) reset[0] = &st->total_count_change; break; } - case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: { + case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID: { struct dds_offered_incompatible_qos_status * const st = vst = &wr->m_offered_incompatible_qos_status; st->total_count++; st->total_count_change++; @@ -122,7 +123,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) reset[0] = &st->total_count_change; break; } - case DDS_PUBLICATION_MATCHED_STATUS: { + case DDS_PUBLICATION_MATCHED_STATUS_ID: { struct dds_publication_matched_status * const st = vst = &wr->m_publication_matched_status; if (data->add) { st->total_count++; @@ -139,14 +140,22 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) reset[1] = &st->current_count_change; break; } - default: + case DDS_DATA_AVAILABLE_STATUS_ID: + case DDS_INCONSISTENT_TOPIC_STATUS_ID: + case DDS_SAMPLE_LOST_STATUS_ID: + case DDS_DATA_ON_READERS_STATUS_ID: + case DDS_SAMPLE_REJECTED_STATUS_ID: + case DDS_LIVELINESS_CHANGED_STATUS_ID: + case DDS_SUBSCRIPTION_MATCHED_STATUS_ID: + case DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID: + case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID: assert (0); } if (invoke) { os_mutexUnlock (&entity->m_observers_lock); - dds_entity_invoke_listener(entity, data->status, vst); + dds_entity_invoke_listener(entity, status_id, vst); os_mutexLock (&entity->m_observers_lock); *reset[0] = 0; if (reset[1]) @@ -154,7 +163,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) } else { - dds_entity_status_set (entity, data->status); + dds_entity_status_set (entity, 1u << status_id); } entity->m_cb_count--; diff --git a/src/core/ddsi/include/ddsi/q_entity.h b/src/core/ddsi/include/ddsi/q_entity.h index 64c3c87..6840643 100644 --- a/src/core/ddsi/include/ddsi/q_entity.h +++ b/src/core/ddsi/include/ddsi/q_entity.h @@ -44,7 +44,7 @@ typedef void (*ddsi2direct_directread_cb_t) (const struct nn_rsample_info *sampl typedef struct status_cb_data { - uint32_t status; + int raw_status_id; uint32_t extra; uint64_t handle; bool add; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 36eaffb..44b76ff 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -1350,7 +1350,7 @@ static void writer_drop_connection (const struct nn_guid * wr_guid, const struct if (m != NULL && wr->status_cb) { status_cb_data_t data; - data.status = DDS_PUBLICATION_MATCHED_STATUS; + data.raw_status_id = (int) DDS_PUBLICATION_MATCHED_STATUS_ID; data.add = false; data.handle = prd->e.iid; (wr->status_cb) (wr->status_cb_entity, &data); @@ -1378,7 +1378,7 @@ static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct if (m != NULL && wr->status_cb) { status_cb_data_t data; - data.status = DDS_PUBLICATION_MATCHED_STATUS; + data.raw_status_id = (int) DDS_PUBLICATION_MATCHED_STATUS_ID; data.add = false; data.handle = rd->e.iid; (wr->status_cb) (wr->status_cb_entity, &data); @@ -1412,10 +1412,10 @@ static void reader_drop_connection (const struct nn_guid *rd_guid, const struct data.add = false; data.handle = pwr->e.iid; - data.status = DDS_LIVELINESS_CHANGED_STATUS; + data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID; (rd->status_cb) (rd->status_cb_entity, &data); - data.status = DDS_SUBSCRIPTION_MATCHED_STATUS; + data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID; (rd->status_cb) (rd->status_cb_entity, &data); } } @@ -1447,10 +1447,10 @@ static void reader_drop_local_connection (const struct nn_guid *rd_guid, const s data.add = false; data.handle = wr->e.iid; - data.status = DDS_LIVELINESS_CHANGED_STATUS; + data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID; (rd->status_cb) (rd->status_cb_entity, &data); - data.status = DDS_SUBSCRIPTION_MATCHED_STATUS; + data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID; (rd->status_cb) (rd->status_cb_entity, &data); } } @@ -1587,7 +1587,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) if (wr->status_cb) { status_cb_data_t data; - data.status = DDS_PUBLICATION_MATCHED_STATUS; + data.raw_status_id = (int) DDS_PUBLICATION_MATCHED_STATUS_ID; data.add = true; data.handle = prd->e.iid; (wr->status_cb) (wr->status_cb_entity, &data); @@ -1667,7 +1667,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) if (wr->status_cb) { status_cb_data_t data; - data.status = DDS_PUBLICATION_MATCHED_STATUS; + data.raw_status_id = (int) DDS_PUBLICATION_MATCHED_STATUS_ID; data.add = true; data.handle = rd->e.iid; (wr->status_cb) (wr->status_cb_entity, &data); @@ -1730,7 +1730,7 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, if (rd->status_cb) { status_cb_data_t data; - data.status = DDS_SUBSCRIPTION_MATCHED_STATUS; + data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID; data.add = true; data.handle = pwr->e.iid; (rd->status_cb) (rd->status_cb_entity, &data); @@ -1765,10 +1765,10 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr) data.add = true; data.handle = wr->e.iid; - data.status = DDS_LIVELINESS_CHANGED_STATUS; + data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID; (rd->status_cb) (rd->status_cb_entity, &data); - data.status = DDS_SUBSCRIPTION_MATCHED_STATUS; + data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID; (rd->status_cb) (rd->status_cb_entity, &data); } } @@ -1875,7 +1875,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader if (rd->status_cb) { status_cb_data_t data; - data.status = DDS_LIVELINESS_CHANGED_STATUS; + data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID; data.add = true; data.handle = pwr->e.iid; (rd->status_cb) (rd->status_cb_entity, &data); @@ -1997,7 +1997,7 @@ static void writer_qos_mismatch (struct writer * wr, uint32_t reason) if (wr->status_cb) { status_cb_data_t data; - data.status = DDS_OFFERED_INCOMPATIBLE_QOS_STATUS; + data.raw_status_id = (int) DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID; data.extra = reason; (wr->status_cb) (wr->status_cb_entity, &data); } @@ -2018,7 +2018,7 @@ static void reader_qos_mismatch (struct reader * rd, uint32_t reason) if (rd->status_cb) { status_cb_data_t data; - data.status = DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS; + data.raw_status_id = (int) DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID; data.extra = reason; (rd->status_cb) (rd->status_cb_entity, &data); } From cd02110af0bb956d703392380a413a6d4e6b7c96 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 15 Jan 2019 11:11:43 +0100 Subject: [PATCH 07/10] add listener-, waitset- and polling-mode to thorughput subscriber Signed-off-by: Erik Boasson --- src/examples/throughput/subscriber.c | 107 ++++++++++++--------------- 1 file changed, 48 insertions(+), 59 deletions(-) diff --git a/src/examples/throughput/subscriber.c b/src/examples/throughput/subscriber.c index a50db5e..4ea5422 100644 --- a/src/examples/throughput/subscriber.c +++ b/src/examples/throughput/subscriber.c @@ -17,7 +17,7 @@ */ #define BYTES_PER_SEC_TO_MEGABITS_PER_SEC 125000 -#define MAX_SAMPLES 100 +#define MAX_SAMPLES 1000 typedef struct HandleEntry { @@ -31,7 +31,7 @@ typedef struct HandleMap HandleEntry *entries; } HandleMap; -static long pollingDelay = 0; +static long pollingDelay = -1; /* i.e. use a listener */ static HandleMap * imap; static unsigned long long outOfOrder = 0; @@ -39,8 +39,6 @@ static unsigned long long total_bytes = 0; static unsigned long long total_samples = 0; static dds_time_t startTime = 0; -static dds_time_t time_now = 0; -static dds_time_t prev_time = 0; static unsigned long payloadSize = 0; @@ -48,9 +46,8 @@ static ThroughputModule_DataType data [MAX_SAMPLES]; static void * samples[MAX_SAMPLES]; static dds_entity_t waitSet; -static dds_entity_t pollingWaitset; -static bool done = false; +static volatile sig_atomic_t done = false; /* Forward declarations */ static HandleMap * HandleMap__alloc (void); @@ -60,7 +57,7 @@ static HandleEntry * retrieve_handle (HandleMap *map, dds_instance_handle_t key) static void data_available_handler (dds_entity_t reader, void *arg); static int parse_args(int argc, char **argv, unsigned long long *maxCycles, char **partitionName); -static void process_samples(unsigned long long maxCycles); +static void process_samples(dds_entity_t reader, unsigned long long maxCycles); static dds_entity_t prepare_dds(dds_entity_t *reader, const char *partitionName); static void finalize_dds(dds_entity_t participant); @@ -91,9 +88,6 @@ int main (int argc, char **argv) dds_entity_t participant; dds_entity_t reader; - time_now = dds_time (); - prev_time = time_now; - /* Register handler for Ctrl-C */ #ifdef _WIN32 SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, true); @@ -110,8 +104,7 @@ int main (int argc, char **argv) return EXIT_FAILURE; } - printf ("Cycles: %llu | PollingDelay: %lu | Partition: %s\n", - maxCycles, pollingDelay, partitionName); + printf ("Cycles: %llu | PollingDelay: %ld | Partition: %s\n", maxCycles, pollingDelay, partitionName); participant = prepare_dds(&reader, partitionName); @@ -119,7 +112,7 @@ int main (int argc, char **argv) /* Process samples until Ctrl-C is pressed or until maxCycles */ /* has been reached (0 = infinite) */ - process_samples(maxCycles); + process_samples(reader, maxCycles); /* Finished, disable callbacks */ dds_set_status_mask (reader, 0); @@ -189,13 +182,12 @@ static HandleEntry * retrieve_handle (HandleMap *map, dds_instance_handle_t key) return entry; } -static void data_available_handler (dds_entity_t reader, void *arg) +static int do_take (dds_entity_t reader) { int samples_received; dds_sample_info_t info [MAX_SAMPLES]; dds_instance_handle_t ph = 0; HandleEntry * current = NULL; - (void)arg; if (startTime == 0) { @@ -234,11 +226,13 @@ static void data_available_handler (dds_entity_t reader, void *arg) total_samples++; } } - time_now = dds_time (); - if ((pollingDelay == 0) && (time_now > (prev_time + DDS_SECS (1)))) - { - dds_waitset_set_trigger (pollingWaitset, true); - } + return samples_received; +} + +static void data_available_handler (dds_entity_t reader, void *arg) +{ + (void)arg; + do_take (reader); } static int parse_args(int argc, char **argv, unsigned long long *maxCycles, char **partitionName) @@ -250,7 +244,7 @@ static int parse_args(int argc, char **argv, unsigned long long *maxCycles, char if (argc == 2 && (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0)) { printf ("Usage (parameters must be supplied in order):\n"); - printf ("./subscriber [maxCycles (0 = infinite)] [pollingDelay (ms, 0 = event based)] [partitionName]\n"); + printf ("./subscriber [maxCycles (0 = infinite)] [pollingDelay (ms, 0 = waitset, -1 = listener)] [partitionName]\n"); printf ("Defaults:\n"); printf ("./subscriber 0 0 \"Throughput example\"\n"); return EXIT_FAILURE; @@ -262,7 +256,7 @@ static int parse_args(int argc, char **argv, unsigned long long *maxCycles, char } if (argc > 2) { - pollingDelay = atoi (argv[2]); /* The number of ms to wait between reads (0 = event based) */ + pollingDelay = atoi (argv[2]); /* The number of ms to wait between reads (0 = waitset, -1 = listener) */ } if (argc > 3) { @@ -271,61 +265,59 @@ static int parse_args(int argc, char **argv, unsigned long long *maxCycles, char return EXIT_SUCCESS; } -static void process_samples(unsigned long long maxCycles) +static void process_samples(dds_entity_t reader, unsigned long long maxCycles) { dds_return_t status; unsigned long long prev_bytes = 0; unsigned long long prev_samples = 0; - dds_attach_t wsresults[1]; - size_t wsresultsize = 1U; + dds_attach_t wsresults[2]; dds_time_t deltaTv; bool first_batch = true; unsigned long cycles = 0; double deltaTime = 0; + dds_time_t prev_time = 0; + dds_time_t time_now = 0; while (!done && (maxCycles == 0 || cycles < maxCycles)) { - if (pollingDelay) + if (pollingDelay > 0) { dds_sleepfor (DDS_MSECS (pollingDelay)); + while (do_take (reader)) + ; } else { - status = dds_waitset_wait (waitSet, wsresults, wsresultsize, DDS_INFINITY); + status = dds_waitset_wait (waitSet, wsresults, sizeof(wsresults)/sizeof(wsresults[0]), DDS_SECS(1)); DDS_ERR_CHECK (status, DDS_CHECK_REPORT | DDS_CHECK_EXIT); - - if ((status > 0 ) && (dds_triggered (pollingWaitset))) - { - dds_waitset_set_trigger (pollingWaitset, false); - } + while (do_take (reader)) + ; } + time_now = dds_time(); if (!first_batch) { deltaTv = time_now - prev_time; deltaTime = (double) deltaTv / DDS_NSECS_IN_SEC; - prev_time = time_now; - printf - ( - "=== [Subscriber] Payload size: %lu | Total received: %llu samples, %llu bytes | Out of order: %llu samples " - "Transfer rate: %.2lf samples/s, %.2lf Mbit/s\n", - payloadSize, total_samples, total_bytes, outOfOrder, - (deltaTime != 0.0) ? ((double)(total_samples - prev_samples) / deltaTime) : 0, - (deltaTime != 0.0) ? ((double)((total_bytes - prev_bytes) / BYTES_PER_SEC_TO_MEGABITS_PER_SEC) / deltaTime) : 0 - ); - cycles++; + if (deltaTime >= 1.0 && total_samples != prev_samples) + { + printf ("=== [Subscriber] %5.3f Payload size: %lu | Total received: %llu samples, %llu bytes | Out of order: %llu samples " + "Transfer rate: %.2lf samples/s, %.2lf Mbit/s\n", + deltaTime, payloadSize, total_samples, total_bytes, outOfOrder, + (deltaTime != 0.0) ? ((double)(total_samples - prev_samples) / deltaTime) : 0, + (deltaTime != 0.0) ? ((double)((total_bytes - prev_bytes) / BYTES_PER_SEC_TO_MEGABITS_PER_SEC) / deltaTime) : 0); + cycles++; + prev_time = time_now; + prev_bytes = total_bytes; + prev_samples = total_samples; + } } else { prev_time = time_now; first_batch = false; } - - /* Update the previous values for next iteration */ - - prev_bytes = total_bytes; - prev_samples = total_samples; } /* Output totals and averages */ @@ -345,7 +337,7 @@ static dds_entity_t prepare_dds(dds_entity_t *reader, const char *partitionName) dds_listener_t *rd_listener; dds_entity_t participant; - int32_t maxSamples = 400; + int32_t maxSamples = 4000; const char *subParts[1]; dds_qos_t *subQos = dds_create_qos (); dds_qos_t *drQos = dds_create_qos (); @@ -381,12 +373,6 @@ static dds_entity_t prepare_dds(dds_entity_t *reader, const char *partitionName) waitSet = dds_create_waitset (participant); DDS_ERR_CHECK (waitSet, DDS_CHECK_REPORT | DDS_CHECK_EXIT); - pollingWaitset = dds_create_waitset (participant); - DDS_ERR_CHECK (pollingWaitset, DDS_CHECK_REPORT | DDS_CHECK_EXIT); - - status = dds_waitset_attach (waitSet, pollingWaitset, pollingWaitset); - DDS_ERR_CHECK (status, DDS_CHECK_REPORT | DDS_CHECK_EXIT); - status = dds_waitset_attach (waitSet, waitSet, waitSet); DDS_ERR_CHECK (status, DDS_CHECK_REPORT | DDS_CHECK_EXIT); @@ -398,8 +384,15 @@ static dds_entity_t prepare_dds(dds_entity_t *reader, const char *partitionName) samples[i] = &data[i]; } - *reader = dds_create_reader (subscriber, topic, drQos, rd_listener); + *reader = dds_create_reader (subscriber, topic, drQos, pollingDelay < 0 ? rd_listener : NULL); DDS_ERR_CHECK (*reader, DDS_CHECK_REPORT | DDS_CHECK_EXIT); + + if (pollingDelay == 0) + { + status = dds_waitset_attach (waitSet, *reader, *reader); + DDS_ERR_CHECK (status, DDS_CHECK_REPORT | DDS_CHECK_EXIT); + } + dds_delete_qos (drQos); dds_delete_listener(rd_listener); @@ -417,10 +410,6 @@ static void finalize_dds(dds_entity_t participant) status = dds_waitset_detach (waitSet, waitSet); DDS_ERR_CHECK (status, DDS_CHECK_REPORT | DDS_CHECK_EXIT); - status = dds_waitset_detach (waitSet, pollingWaitset); - DDS_ERR_CHECK (status, DDS_CHECK_REPORT | DDS_CHECK_EXIT); - status = dds_delete (pollingWaitset); - DDS_ERR_CHECK (status, DDS_CHECK_REPORT | DDS_CHECK_EXIT); status = dds_delete (waitSet); DDS_ERR_CHECK (status, DDS_CHECK_REPORT | DDS_CHECK_EXIT); status = dds_delete (participant); From b864c8387924dc6155d72f88e6475fa04a7f042d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 15 Jan 2019 11:14:57 +0100 Subject: [PATCH 08/10] fix de-initialisation of tcp support code Stopping and restarting the DDSI stack in a single process would not re-initialise the TCP support code properly Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_tcp.c | 21 ++++++++++++--------- src/core/ddsi/src/ddsi_tran.c | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index b922578..b8123c8 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -27,6 +27,7 @@ #define INVALID_PORT (~0u) typedef struct ddsi_tran_factory * ddsi_tcp_factory_g_t; +static os_atomic_uint32_t ddsi_tcp_init_g = OS_ATOMIC_UINT32_INIT(0); #ifdef DDSI_INCLUDE_SSL struct ddsi_ssl_plugins ddsi_tcp_ssl_plugin = @@ -1027,14 +1028,17 @@ static void ddsi_tcp_release_listener (ddsi_tran_listener_t listener) static void ddsi_tcp_release_factory (void) { - ut_avlFree (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, ddsi_tcp_node_free); - os_mutexDestroy (&ddsi_tcp_cache_lock_g); + if (os_atomic_dec32_nv (&ddsi_tcp_init_g) == 0) { + ut_avlFree (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, ddsi_tcp_node_free); + os_mutexDestroy (&ddsi_tcp_cache_lock_g); #ifdef DDSI_INCLUDE_SSL - if (ddsi_tcp_ssl_plugin.fini) - { - (ddsi_tcp_ssl_plugin.fini) (); - } + if (ddsi_tcp_ssl_plugin.fini) + { + (ddsi_tcp_ssl_plugin.fini) (); + } #endif + DDS_LOG(DDS_LC_INFO | DDS_LC_CONFIG, "tcp de-initialized\n"); + } } static enum ddsi_locator_from_string_result ddsi_tcp_address_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str) @@ -1063,10 +1067,9 @@ static enum ddsi_nearby_address_result ddsi_tcp_is_nearby_address (ddsi_tran_fac int ddsi_tcp_init (void) { - static bool init = false; - if (!init) + if (os_atomic_inc32_nv (&ddsi_tcp_init_g) == 1) { - init = true; + memset (&ddsi_tcp_factory_g, 0, sizeof (ddsi_tcp_factory_g)); ddsi_tcp_factory_g.m_kind = NN_LOCATOR_KIND_TCPv4; ddsi_tcp_factory_g.m_typename = "tcp"; ddsi_tcp_factory_g.m_stream = true; diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index 85c3b8e..eef0616 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -62,8 +62,8 @@ void ddsi_tran_factories_fini (void) ddsi_tran_factory_t factory; while ((factory = ddsi_tran_factories) != NULL) { + ddsi_tran_factories = factory->m_factory; ddsi_factory_free(factory); - ddsi_tran_factories = ddsi_tran_factories->m_factory; } } From 102e657d455bc89fc8c948f36fd5c7aeee8b4df1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 15 Jan 2019 11:15:38 +0100 Subject: [PATCH 09/10] minor cleanup to address some compiler warnings Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_ddsi_discovery.c | 2 +- src/core/ddsi/src/q_entity.c | 4 ---- src/core/ddsi/src/q_nwif.c | 23 ----------------------- src/tools/pubsub/pubsub.c | 1 - 4 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 655a31b..730d2b1 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -1016,7 +1016,7 @@ static const char *durability_to_string (nn_durability_kind_t k) case NN_TRANSIENT_DURABILITY_QOS: return "transient"; case NN_PERSISTENT_DURABILITY_QOS: return "persistent"; } - abort (); return 0; + return "undefined-durability"; } static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 44b76ff..78009c8 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -248,16 +248,12 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e) case EK_READER: case EK_WRITER: return (nn_vendorid_t) MY_VENDOR_ID; - break; case EK_PROXY_PARTICIPANT: return ((const struct proxy_participant *) e)->vendor; - break; case EK_PROXY_READER: return ((const struct proxy_reader *) e)->c.vendor; - break; case EK_PROXY_WRITER: return ((const struct proxy_writer *) e)->c.vendor; - break; } assert (0); return (nn_vendorid_t) NN_VENDORID_UNKNOWN; diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 0db1e12..605858b 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -56,29 +56,6 @@ unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src) return id; } -unsigned short get_socket_port (os_socket socket) -{ - os_sockaddr_storage addr; - socklen_t addrlen = sizeof (addr); - if (getsockname (socket, (os_sockaddr *) &addr, &addrlen) < 0) - { - print_sockerror ("getsockname"); - return 0; - } - switch (addr.ss_family) - { - case AF_INET: - return ntohs (((os_sockaddr_in *) &addr)->sin_port); -#if OS_SOCKET_HAS_IPV6 - case AF_INET6: - return ntohs (((os_sockaddr_in6 *) &addr)->sin6_port); -#endif - default: - abort (); - return 0; - } -} - #ifdef DDSI_INCLUDE_NETWORK_CHANNELS void set_socket_diffserv (os_socket sock, int diffserv) { diff --git a/src/tools/pubsub/pubsub.c b/src/tools/pubsub/pubsub.c index 7f52f58..1b460c2 100644 --- a/src/tools/pubsub/pubsub.c +++ b/src/tools/pubsub/pubsub.c @@ -2308,7 +2308,6 @@ int MAIN(int argc, char *argv[]) { qpublisher[nqpublisher++] = q; qsubscriber[nqsubscriber++] = q; break; - break; default: assert(0); } From 98f757a5ab995e7c45e2de937d1281a5b8ceac9b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 17 Jan 2019 12:34:37 +0100 Subject: [PATCH 10/10] let dds_get_qos reset the input qos first Getting a QoS from an entity is akin to reading, and all read/take operations reuse or free/reallocate memory to avoid memory leaks, and so it is a reasonable assumption that calling dds_get_qos repeatedly without intervening calls to dds_reset_qos would not leak any memory either. (This was actually an assumption in the builtin topics test.) Therefore, it is reasonable to first call dds_reset_qos in dds_get_qos. All operations in the API that yield or modify a QoS object result in a properly initialised one, therefore the input to dds_get_qos is necessarily initialised, and so this is safe. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_entity.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 90097c8..7781875 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -363,10 +363,13 @@ dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return DDS_ERRNO (rc); - if (e->m_deriver.set_qos) - ret = dds_copy_qos (qos, e->m_qos); - else + if (e->m_deriver.set_qos == 0) ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); + else + { + dds_reset_qos (qos); + ret = dds_copy_qos (qos, e->m_qos); + } dds_entity_unlock(e); return ret; }