diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a307c08..89abc81 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -76,3 +76,5 @@ install( LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib ) + +add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/xtests") diff --git a/src/core/ddsc/src/dds__domain.h b/src/core/ddsc/src/dds__domain.h index feaf014..d136184 100644 --- a/src/core/ddsc/src/dds__domain.h +++ b/src/core/ddsc/src/dds__domain.h @@ -18,11 +18,11 @@ extern "C" { #endif -extern const ut_avlTreedef_t dds_domaintree_def; +extern DDS_EXPORT const ut_avlTreedef_t dds_domaintree_def; -extern dds_domain * dds_domain_create (dds_domainid_t id); -extern void dds_domain_free (dds_domain * domain); -extern dds_domain * dds_domain_find_locked (dds_domainid_t id); +DDS_EXPORT dds_domain * dds_domain_create (dds_domainid_t id); +DDS_EXPORT void dds_domain_free (dds_domain * domain); +DDS_EXPORT dds_domain * dds_domain_find_locked (dds_domainid_t id); #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 04967fa..5154504 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -19,7 +19,8 @@ extern "C" { #endif -_Check_return_ dds_entity_t +_Check_return_ +DDS_EXPORT dds_entity_t dds_entity_init( _In_ dds_entity * e, _When_(kind != DDS_KIND_PARTICIPANT, _Notnull_) @@ -30,10 +31,10 @@ dds_entity_init( _In_opt_ const dds_listener_t *listener, _In_ uint32_t mask); -void +DDS_EXPORT void dds_entity_add_ref( _In_ dds_entity *e); -void +DDS_EXPORT void dds_entity_add_ref_nolock( _In_ dds_entity *e); @@ -56,82 +57,82 @@ dds_entity_add_ref_nolock( qualifier_ dds__retcode_t type_##_lock (dds_entity_t hdl, type_ **x); \ qualifier_ void type_##_unlock (type_ *x); -inline bool dds_entity_is_enabled (const dds_entity *e) { +DDS_EXPORT inline bool dds_entity_is_enabled (const dds_entity *e) { return (e->m_flags & DDS_ENTITY_ENABLED) != 0; } -void dds_entity_status_set (dds_entity *e, uint32_t t); +DDS_EXPORT void dds_entity_status_set (dds_entity *e, uint32_t t); -inline void dds_entity_status_reset (dds_entity *e, uint32_t t) { +DDS_EXPORT 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) { +DDS_EXPORT 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) { +DDS_EXPORT 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) { +DDS_EXPORT 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; } -void dds_entity_status_signal (dds_entity *e); +DDS_EXPORT void dds_entity_status_signal (dds_entity *e); -void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst); +DDS_EXPORT void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst); -_Check_return_ dds__retcode_t +_Check_return_ DDS_EXPORT dds__retcode_t dds_valid_hdl( _In_ dds_entity_t hdl, _In_ dds_entity_kind_t kind); _Acquires_exclusive_lock_(*e) -_Check_return_ dds__retcode_t +_Check_return_ DDS_EXPORT dds__retcode_t dds_entity_lock( _In_ dds_entity_t hdl, _In_ dds_entity_kind_t kind, _Out_ dds_entity **e); _Releases_exclusive_lock_(e) -void +DDS_EXPORT void dds_entity_unlock( _Inout_ dds_entity *e); -_Check_return_ dds__retcode_t +_Check_return_ DDS_EXPORT dds__retcode_t dds_entity_observer_register_nl( _In_ dds_entity* observed, _In_ dds_entity_t observer, _In_ dds_entity_callback cb); -_Check_return_ dds__retcode_t +_Check_return_ DDS_EXPORT 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_EXPORT dds__retcode_t dds_entity_observer_unregister_nl( _In_ dds_entity* observed, _In_ dds_entity_t observer); -dds__retcode_t +DDS_EXPORT dds__retcode_t dds_entity_observer_unregister( _In_ dds_entity_t observed, _In_ dds_entity_t observer); _Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK) -dds_return_t +DDS_EXPORT dds_return_t dds_delete_impl( _In_ dds_entity_t entity, _In_ bool keep_if_explicit); -const char * +DDS_EXPORT const char * dds__entity_kind_str( _In_ dds_entity_t e); -dds_domain * +DDS_EXPORT dds_domain * dds__entity_domain( _In_ dds_entity* e); diff --git a/src/core/ddsc/src/dds__rhc.h b/src/core/ddsc/src/dds__rhc.h index a3b3cb7..21106bc 100644 --- a/src/core/ddsc/src/dds__rhc.h +++ b/src/core/ddsc/src/dds__rhc.h @@ -27,21 +27,17 @@ struct ddsi_serdata; struct ddsi_tkmap_instance; struct proxy_writer_info; -struct rhc * dds_rhc_new (dds_reader * reader, const struct ddsi_sertopic * topic); -void dds_rhc_free (struct rhc * rhc); -void dds_rhc_fini (struct rhc * rhc); +DDS_EXPORT struct rhc *dds_rhc_new (dds_reader *reader, const struct ddsi_sertopic *topic); +DDS_EXPORT void dds_rhc_free (struct rhc *rhc); +DDS_EXPORT void dds_rhc_fini (struct rhc *rhc); -uint32_t dds_rhc_lock_samples (struct rhc * rhc); +DDS_EXPORT uint32_t dds_rhc_lock_samples (struct rhc *rhc); -DDS_EXPORT bool dds_rhc_store -( - struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, - struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk -); -void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info); -void dds_rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid); +DDS_EXPORT bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk); +DDS_EXPORT void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info); +DDS_EXPORT void dds_rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid); -int +DDS_EXPORT int dds_rhc_read( struct rhc *rhc, bool lock, @@ -51,7 +47,7 @@ dds_rhc_read( uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); -int +DDS_EXPORT int dds_rhc_take( struct rhc *rhc, bool lock, @@ -62,15 +58,12 @@ dds_rhc_take( dds_instance_handle_t handle, dds_readcond *cond); -void dds_rhc_set_qos (struct rhc * rhc, const struct nn_xqos * qos); +DDS_EXPORT void dds_rhc_set_qos (struct rhc * rhc, const struct nn_xqos * qos); -bool dds_rhc_add_readcondition (dds_readcond * cond); -void dds_rhc_remove_readcondition (dds_readcond * cond); +DDS_EXPORT bool dds_rhc_add_readcondition (dds_readcond * cond); +DDS_EXPORT void dds_rhc_remove_readcondition (dds_readcond * cond); -bool dds_rhc_add_waitset (dds_readcond * cond, dds_waitset * waitset, dds_attach_t x); -int dds_rhc_remove_waitset (dds_readcond * cond, dds_waitset * waitset); - -int dds_rhc_takecdr +DDS_EXPORT int dds_rhc_takecdr ( struct rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, unsigned sample_states, diff --git a/src/core/ddsc/src/dds__topic.h b/src/core/ddsc/src/dds__topic.h index cb81561..7cba5a5 100644 --- a/src/core/ddsc/src/dds__topic.h +++ b/src/core/ddsc/src/dds__topic.h @@ -21,8 +21,8 @@ extern "C" { 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); +DDS_EXPORT struct ddsi_sertopic * dds_topic_lookup (dds_domain * domain, const char * name); +DDS_EXPORT void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic * st); #ifndef DDS_TOPIC_INTERN_FILTER_FN_DEFINED #define DDS_TOPIC_INTERN_FILTER_FN_DEFINED diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index bcc7923..4a1f232 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -303,7 +303,7 @@ char * dds_stream_reuse_string } else { - if ((str == NULL) || (strlen (str) < length)) + if ((str == NULL) || (strlen (str) + 1 < length)) { str = dds_realloc (str, length); } diff --git a/src/core/ddsc/tests/CMakeLists.txt b/src/core/ddsc/tests/CMakeLists.txt index 10cd2bb..5e00360 100644 --- a/src/core/ddsc/tests/CMakeLists.txt +++ b/src/core/ddsc/tests/CMakeLists.txt @@ -50,8 +50,9 @@ set(ddsc_test_sources "writer.c") add_cunit_executable(cunit_ddsc ${ddsc_test_sources}) -target_include_directories(cunit_ddsc PRIVATE - "$") +target_include_directories( + cunit_ddsc PRIVATE + "$") target_link_libraries(cunit_ddsc RoundTrip Space TypesArrayKey ddsc OSAPI) # Setup environment for config-tests diff --git a/src/core/ddsi/include/ddsi/ddsi_iid.h b/src/core/ddsi/include/ddsi/ddsi_iid.h index a5b9528..8ca925d 100644 --- a/src/core/ddsi/include/ddsi/ddsi_iid.h +++ b/src/core/ddsi/include/ddsi/ddsi_iid.h @@ -13,6 +13,7 @@ #define _DDS_IID_H_ #include "os/os.h" +#include "ddsc/dds_export.h" #if defined (__cplusplus) extern "C" { @@ -28,9 +29,9 @@ struct ddsi_iid { uint32_t key[4]; }; -void ddsi_iid_init (void); -void ddsi_iid_fini (void); -uint64_t ddsi_iid_gen (void); +DDS_EXPORT void ddsi_iid_init (void); +DDS_EXPORT void ddsi_iid_fini (void); +DDS_EXPORT uint64_t ddsi_iid_gen (void); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h b/src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h index 0516e89..7f884fa 100644 --- a/src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h +++ b/src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h @@ -41,6 +41,6 @@ struct ddsi_rhc_plugin void (*rhc_set_qos_fn) (struct rhc * rhc, const struct nn_xqos * qos); }; -void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos); +DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos); #endif diff --git a/src/core/ddsi/include/ddsi/ddsi_serdata.h b/src/core/ddsi/include/ddsi/ddsi_serdata.h index 9037980..6d23a2f 100644 --- a/src/core/ddsi/include/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/ddsi/ddsi_serdata.h @@ -108,60 +108,60 @@ struct ddsi_serdata_ops { ddsi_serdata_free_t free; }; -void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertopic *tp, enum ddsi_serdata_kind kind); +DDS_EXPORT void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertopic *tp, enum ddsi_serdata_kind kind); -inline struct ddsi_serdata *ddsi_serdata_ref (const struct ddsi_serdata *serdata_const) { +DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_ref (const struct ddsi_serdata *serdata_const) { struct ddsi_serdata *serdata = (struct ddsi_serdata *)serdata_const; os_atomic_inc32 (&serdata->refc); return serdata; } -inline void ddsi_serdata_unref (struct ddsi_serdata *serdata) { +DDS_EXPORT inline void ddsi_serdata_unref (struct ddsi_serdata *serdata) { if (os_atomic_dec32_ov (&serdata->refc) == 1) serdata->ops->free (serdata); } -inline uint32_t ddsi_serdata_size (const struct ddsi_serdata *d) { +DDS_EXPORT inline uint32_t ddsi_serdata_size (const struct ddsi_serdata *d) { return d->ops->get_size (d); } -inline struct ddsi_serdata *ddsi_serdata_from_ser (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size) { +DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size) { return topic->serdata_ops->from_ser (topic, kind, fragchain, size); } -inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash) { +DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash) { return topic->serdata_ops->from_keyhash (topic, keyhash); } -inline struct ddsi_serdata *ddsi_serdata_from_sample (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const void *sample) { +DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_sample (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const void *sample) { return topic->serdata_ops->from_sample (topic, kind, sample); } -inline struct ddsi_serdata *ddsi_serdata_to_topicless (const struct ddsi_serdata *d) { +DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_to_topicless (const struct ddsi_serdata *d) { return d->ops->to_topicless (d); } -inline void ddsi_serdata_to_ser (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf) { +DDS_EXPORT inline void ddsi_serdata_to_ser (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf) { d->ops->to_ser (d, off, sz, buf); } -inline struct ddsi_serdata *ddsi_serdata_to_ser_ref (const struct ddsi_serdata *d, size_t off, size_t sz, os_iovec_t *ref) { +DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_to_ser_ref (const struct ddsi_serdata *d, size_t off, size_t sz, os_iovec_t *ref) { return d->ops->to_ser_ref (d, off, sz, ref); } -inline void ddsi_serdata_to_ser_unref (struct ddsi_serdata *d, const os_iovec_t *ref) { +DDS_EXPORT inline void ddsi_serdata_to_ser_unref (struct ddsi_serdata *d, const os_iovec_t *ref) { d->ops->to_ser_unref (d, ref); } -inline bool ddsi_serdata_to_sample (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { +DDS_EXPORT inline bool ddsi_serdata_to_sample (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { return d->ops->to_sample (d, sample, bufptr, buflim); } -inline bool ddsi_serdata_topicless_to_sample (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { +DDS_EXPORT inline bool ddsi_serdata_topicless_to_sample (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { return d->ops->topicless_to_sample (topic, d, sample, bufptr, buflim); } -inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const struct ddsi_serdata *b) { +DDS_EXPORT inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const struct ddsi_serdata *b) { return a->ops->eqkey (a, b); } diff --git a/src/core/ddsi/include/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/ddsi/ddsi_serdata_default.h index ad6c080..bb80fa2 100644 --- a/src/core/ddsi/include/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/ddsi/ddsi_serdata_default.h @@ -125,12 +125,12 @@ struct ddsi_rawcdr_sample { size_t keysize; }; -extern const struct ddsi_sertopic_ops ddsi_sertopic_ops_default; +extern DDS_EXPORT const struct ddsi_sertopic_ops ddsi_sertopic_ops_default; -extern const struct ddsi_serdata_ops ddsi_serdata_ops_cdr; -extern const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey; -extern const struct ddsi_serdata_ops ddsi_serdata_ops_plist; -extern const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr; +extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_cdr; +extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey; +extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_plist; +extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr; struct serdatapool * ddsi_serdatapool_new (void); void ddsi_serdatapool_free (struct serdatapool * pool); diff --git a/src/core/ddsi/include/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/ddsi/ddsi_sertopic.h index d400245..3bd8dd8 100644 --- a/src/core/ddsi/include/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/ddsi/ddsi_sertopic.h @@ -56,32 +56,32 @@ struct ddsi_sertopic_ops { ddsi_sertopic_free_samples_t free_samples; }; -struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *tp); -void ddsi_sertopic_unref (struct ddsi_sertopic *tp); -uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops *ops); +DDS_EXPORT struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *tp); +DDS_EXPORT void ddsi_sertopic_unref (struct ddsi_sertopic *tp); +DDS_EXPORT uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops *ops); -inline void ddsi_sertopic_deinit (struct ddsi_sertopic *tp) { +DDS_EXPORT inline void ddsi_sertopic_deinit (struct ddsi_sertopic *tp) { tp->ops->deinit (tp); } -inline void ddsi_sertopic_zero_samples (const struct ddsi_sertopic *tp, void *samples, size_t count) { +DDS_EXPORT inline void ddsi_sertopic_zero_samples (const struct ddsi_sertopic *tp, void *samples, size_t count) { tp->ops->zero_samples (tp, samples, count); } -inline void ddsi_sertopic_realloc_samples (void **ptrs, const struct ddsi_sertopic *tp, void *old, size_t oldcount, size_t count) +DDS_EXPORT inline void ddsi_sertopic_realloc_samples (void **ptrs, const struct ddsi_sertopic *tp, void *old, size_t oldcount, size_t count) { tp->ops->realloc_samples (ptrs, tp, old, oldcount, count); } -inline void ddsi_sertopic_free_samples (const struct ddsi_sertopic *tp, void **ptrs, size_t count, dds_free_op_t op) { +DDS_EXPORT inline void ddsi_sertopic_free_samples (const struct ddsi_sertopic *tp, void **ptrs, size_t count, dds_free_op_t op) { tp->ops->free_samples (tp, ptrs, count, op); } -inline void ddsi_sertopic_zero_sample (const struct ddsi_sertopic *tp, void *sample) { +DDS_EXPORT inline void ddsi_sertopic_zero_sample (const struct ddsi_sertopic *tp, void *sample) { ddsi_sertopic_zero_samples (tp, sample, 1); } -inline void *ddsi_sertopic_alloc_sample (const struct ddsi_sertopic *tp) { +DDS_EXPORT inline void *ddsi_sertopic_alloc_sample (const struct ddsi_sertopic *tp) { void *ptr; ddsi_sertopic_realloc_samples (&ptr, tp, NULL, 0, 1); return ptr; } -inline void ddsi_sertopic_free_sample (const struct ddsi_sertopic *tp, void *sample, dds_free_op_t op) { +DDS_EXPORT inline void ddsi_sertopic_free_sample (const struct ddsi_sertopic *tp, void *sample, dds_free_op_t op) { ddsi_sertopic_free_samples (tp, &sample, 1, op); } diff --git a/src/core/ddsi/include/ddsi/ddsi_tkmap.h b/src/core/ddsi/include/ddsi/ddsi_tkmap.h index 225db9f..8c124d1 100644 --- a/src/core/ddsi/include/ddsi/ddsi_tkmap.h +++ b/src/core/ddsi/include/ddsi/ddsi_tkmap.h @@ -30,19 +30,14 @@ struct ddsi_tkmap_instance os_atomic_uint32_t m_refc; }; - -struct ddsi_tkmap * ddsi_tkmap_new (void); -void ddsi_tkmap_free (_Inout_ _Post_invalid_ struct ddsi_tkmap *tkmap); -void ddsi_tkmap_instance_ref (_In_ struct ddsi_tkmap_instance *tk); -uint64_t ddsi_tkmap_lookup (_In_ struct ddsi_tkmap *tkmap, _In_ const struct ddsi_serdata *serdata); -_Check_return_ struct ddsi_tkmap_instance * ddsi_tkmap_find( - _In_ struct ddsi_serdata * sd, - _In_ const bool rd, - _In_ const bool create); -_Check_return_ struct ddsi_tkmap_instance * ddsi_tkmap_find_by_id (_In_ struct ddsi_tkmap * map, _In_ uint64_t iid); - -DDS_EXPORT _Check_return_ struct ddsi_tkmap_instance * ddsi_tkmap_lookup_instance_ref (_In_ struct ddsi_serdata * sd); -DDS_EXPORT void ddsi_tkmap_instance_unref (_In_ struct ddsi_tkmap_instance * tk); +DDS_EXPORT struct ddsi_tkmap * ddsi_tkmap_new (void); +DDS_EXPORT void ddsi_tkmap_free (_Inout_ _Post_invalid_ struct ddsi_tkmap *tkmap); +DDS_EXPORT void ddsi_tkmap_instance_ref (_In_ struct ddsi_tkmap_instance *tk); +DDS_EXPORT uint64_t ddsi_tkmap_lookup (_In_ struct ddsi_tkmap *tkmap, _In_ const struct ddsi_serdata *serdata); +DDS_EXPORT struct ddsi_tkmap_instance * ddsi_tkmap_find(struct ddsi_serdata *sd, const bool rd, const bool create); +DDS_EXPORT struct ddsi_tkmap_instance * ddsi_tkmap_find_by_id (struct ddsi_tkmap *map, uint64_t iid); +DDS_EXPORT struct ddsi_tkmap_instance * ddsi_tkmap_lookup_instance_ref (struct ddsi_serdata * sd); +DDS_EXPORT void ddsi_tkmap_instance_unref (struct ddsi_tkmap_instance *tk); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/ddsi/q_gc.h b/src/core/ddsi/include/ddsi/q_gc.h index e46cd66..4bbea29 100644 --- a/src/core/ddsi/include/ddsi/q_gc.h +++ b/src/core/ddsi/include/ddsi/q_gc.h @@ -12,6 +12,7 @@ #ifndef Q_GC_H #define Q_GC_H +#include "ddsc/dds_export.h" #include "ddsi/q_thread.h" #if defined (__cplusplus) @@ -42,14 +43,14 @@ struct gcreq { struct idx_vtime vtimes[1 /* really a flex ary */]; }; -struct gcreq_queue *gcreq_queue_new (void); -void gcreq_queue_drain (struct gcreq_queue *q); -void gcreq_queue_free (struct gcreq_queue *q); +DDS_EXPORT struct gcreq_queue *gcreq_queue_new (void); +DDS_EXPORT void gcreq_queue_drain (struct gcreq_queue *q); +DDS_EXPORT void gcreq_queue_free (struct gcreq_queue *q); -struct gcreq *gcreq_new (struct gcreq_queue *gcreq_queue, gcreq_cb_t cb); -void gcreq_free (struct gcreq *gcreq); -void gcreq_enqueue (struct gcreq *gcreq); -int gcreq_requeue (struct gcreq *gcreq, gcreq_cb_t cb); +DDS_EXPORT struct gcreq *gcreq_new (struct gcreq_queue *gcreq_queue, gcreq_cb_t cb); +DDS_EXPORT void gcreq_free (struct gcreq *gcreq); +DDS_EXPORT void gcreq_enqueue (struct gcreq *gcreq); +DDS_EXPORT int gcreq_requeue (struct gcreq *gcreq, gcreq_cb_t cb); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/ddsi/q_globals.h b/src/core/ddsi/include/ddsi/q_globals.h index 7c19652..70e0317 100644 --- a/src/core/ddsi/include/ddsi/q_globals.h +++ b/src/core/ddsi/include/ddsi/q_globals.h @@ -18,6 +18,8 @@ #include "util/ut_fibheap.h" +#include "ddsc/dds_export.h" + #include "ddsi/q_plist.h" #include "ddsi/q_protocol.h" #include "ddsi/q_nwif.h" @@ -311,7 +313,7 @@ struct q_globals { struct nn_group_membership *mship; }; -extern struct q_globals OSAPI_EXPORT gv; +extern struct q_globals DDS_EXPORT gv; #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/ddsi/q_plist.h b/src/core/ddsi/include/ddsi/q_plist.h index f97d44f..8975724 100644 --- a/src/core/ddsi/include/ddsi/q_plist.h +++ b/src/core/ddsi/include/ddsi/q_plist.h @@ -204,36 +204,36 @@ typedef struct nn_plist_src { size_t bufsz; } nn_plist_src_t; -void nn_plist_init_empty (nn_plist_t *dest); -void nn_plist_mergein_missing (nn_plist_t *a, const nn_plist_t *b); -void nn_plist_copy (nn_plist_t *dst, const nn_plist_t *src); -nn_plist_t *nn_plist_dup (const nn_plist_t *src); -int nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const nn_plist_src_t *src); -void nn_plist_fini (nn_plist_t *ps); -void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted); -int nn_plist_init_default_participant (nn_plist_t *plist); +DDS_EXPORT void nn_plist_init_empty (nn_plist_t *dest); +DDS_EXPORT void nn_plist_mergein_missing (nn_plist_t *a, const nn_plist_t *b); +DDS_EXPORT void nn_plist_copy (nn_plist_t *dst, const nn_plist_t *src); +DDS_EXPORT nn_plist_t *nn_plist_dup (const nn_plist_t *src); +DDS_EXPORT int nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const nn_plist_src_t *src); +DDS_EXPORT void nn_plist_fini (nn_plist_t *ps); +DDS_EXPORT void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted); +DDS_EXPORT int nn_plist_init_default_participant (nn_plist_t *plist); -int validate_history_qospolicy (const nn_history_qospolicy_t *q); -int validate_durability_qospolicy (const nn_durability_qospolicy_t *q); -int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q); -int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr); -int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q); -int validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q); -int validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q); -int validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q); -int validate_ownership_strength_qospolicy (const nn_ownership_strength_qospolicy_t *q); -int validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q); -int validate_transport_priority_qospolicy (const nn_transport_priority_qospolicy_t *q); -int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q); -int validate_duration (const nn_duration_t *d); +DDS_EXPORT int validate_history_qospolicy (const nn_history_qospolicy_t *q); +DDS_EXPORT int validate_durability_qospolicy (const nn_durability_qospolicy_t *q); +DDS_EXPORT int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q); +DDS_EXPORT int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr); +DDS_EXPORT int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q); +DDS_EXPORT int validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q); +DDS_EXPORT int validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q); +DDS_EXPORT int validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q); +DDS_EXPORT int validate_ownership_strength_qospolicy (const nn_ownership_strength_qospolicy_t *q); +DDS_EXPORT int validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q); +DDS_EXPORT int validate_transport_priority_qospolicy (const nn_transport_priority_qospolicy_t *q); +DDS_EXPORT int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q); +DDS_EXPORT int validate_duration (const nn_duration_t *d); struct nn_rmsg; struct nn_rsample_info; struct nn_rdata; -unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const nn_plist_src_t *src); -const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid); +DDS_EXPORT unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const nn_plist_src_t *src); +DDS_EXPORT const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/ddsi/q_thread.h b/src/core/ddsi/include/ddsi/q_thread.h index d68efe3..cefa3b1 100644 --- a/src/core/ddsi/include/ddsi/q_thread.h +++ b/src/core/ddsi/include/ddsi/q_thread.h @@ -13,6 +13,7 @@ #define Q_THREAD_H #include "os/os.h" +#include "ddsc/dds_export.h" #include "ddsi/q_static_assert.h" #if defined (__cplusplus) @@ -81,43 +82,43 @@ struct thread_states { struct thread_state1 *ts; /* [nthreads] */ }; -extern struct thread_states thread_states; +extern DDS_EXPORT struct thread_states thread_states; extern os_threadLocal struct thread_state1 *tsd_thread_state; -void thread_states_init_static (void); -void thread_states_init (_In_ unsigned maxthreads); -void thread_states_fini (void); +DDS_EXPORT void thread_states_init_static (void); +DDS_EXPORT void thread_states_init (_In_ unsigned maxthreads); +DDS_EXPORT void thread_states_fini (void); -void upgrade_main_thread (void); -void downgrade_main_thread (void); -const struct config_thread_properties_listelem *lookup_thread_properties (_In_z_ const char *name); -_Success_(return != NULL) _Ret_maybenull_ struct thread_state1 *create_thread (_In_z_ const char *name, _In_ uint32_t (*f) (void *arg), _In_opt_ void *arg); -_Ret_valid_ struct thread_state1 *lookup_thread_state (void); -_Success_(return != NULL) _Ret_maybenull_ struct thread_state1 *lookup_thread_state_real (void); -_Success_(return == 0) int join_thread (_Inout_ struct thread_state1 *ts1); -void log_stack_traces (void); -struct thread_state1 *get_thread_state (_In_ os_threadId id); -struct thread_state1 * init_thread_state (_In_z_ const char *tname); -void reset_thread_state (_Inout_opt_ struct thread_state1 *ts1); -int thread_exists (_In_z_ const char *name); +DDS_EXPORT void upgrade_main_thread (void); +DDS_EXPORT void downgrade_main_thread (void); +DDS_EXPORT const struct config_thread_properties_listelem *lookup_thread_properties (const char *name); +DDS_EXPORT struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg), void *arg); +DDS_EXPORT struct thread_state1 *lookup_thread_state (void); +DDS_EXPORT struct thread_state1 *lookup_thread_state_real (void); +DDS_EXPORT int join_thread (_Inout_ struct thread_state1 *ts1); +DDS_EXPORT void log_stack_traces (void); +DDS_EXPORT struct thread_state1 *get_thread_state (_In_ os_threadId id); +DDS_EXPORT struct thread_state1 * init_thread_state (_In_z_ const char *tname); +DDS_EXPORT void reset_thread_state (_Inout_opt_ struct thread_state1 *ts1); +DDS_EXPORT int thread_exists (_In_z_ const char *name); -inline int vtime_awake_p (_In_ vtime_t vtime) +DDS_EXPORT inline int vtime_awake_p (_In_ vtime_t vtime) { return (vtime % 2) == 0; } -inline int vtime_asleep_p (_In_ vtime_t vtime) +DDS_EXPORT inline int vtime_asleep_p (_In_ vtime_t vtime) { return (vtime % 2) == 1; } -inline int vtime_gt (_In_ vtime_t vtime1, _In_ vtime_t vtime0) +DDS_EXPORT inline int vtime_gt (_In_ vtime_t vtime1, _In_ vtime_t vtime0) { Q_STATIC_ASSERT_CODE (sizeof (vtime_t) == sizeof (svtime_t)); return (svtime_t) (vtime1 - vtime0) > 0; } -inline void thread_state_asleep (_Inout_ struct thread_state1 *ts1) +DDS_EXPORT inline void thread_state_asleep (_Inout_ struct thread_state1 *ts1) { vtime_t vt = ts1->vtime; vtime_t wd = ts1->watchdog; @@ -138,9 +139,9 @@ inline void thread_state_asleep (_Inout_ struct thread_state1 *ts1) } else { ts1->watchdog = wd + 1; } - } +} -inline void thread_state_awake (_Inout_ struct thread_state1 *ts1) +DDS_EXPORT inline void thread_state_awake (_Inout_ struct thread_state1 *ts1) { vtime_t vt = ts1->vtime; vtime_t wd = ts1->watchdog; @@ -158,10 +159,9 @@ inline void thread_state_awake (_Inout_ struct thread_state1 *ts1) } else { ts1->watchdog = wd + 2; } - } -inline void thread_state_blocked (_Inout_ struct thread_state1 *ts1) +DDS_EXPORT inline void thread_state_blocked (_Inout_ struct thread_state1 *ts1) { vtime_t wd = ts1->watchdog; if ( wd % 2 ){ @@ -171,7 +171,7 @@ inline void thread_state_blocked (_Inout_ struct thread_state1 *ts1) } } -inline void thread_state_unblocked (_Inout_ struct thread_state1 *ts1) +DDS_EXPORT inline void thread_state_unblocked (_Inout_ struct thread_state1 *ts1) { vtime_t wd = ts1->watchdog; if ( wd % 2 ){ diff --git a/src/core/ddsi/include/ddsi/q_time.h b/src/core/ddsi/include/ddsi/q_time.h index e36f7af..bbe79c9 100644 --- a/src/core/ddsi/include/ddsi/q_time.h +++ b/src/core/ddsi/include/ddsi/q_time.h @@ -13,6 +13,7 @@ #define NN_TIME_H #include "os/os.h" +#include "ddsc/dds_export.h" #if defined (__cplusplus) extern "C" { @@ -55,21 +56,21 @@ extern const nn_duration_t duration_infinite; int valid_ddsi_timestamp (nn_ddsi_time_t t); -OSAPI_EXPORT nn_wctime_t now (void); /* wall clock time */ -nn_mtime_t now_mt (void); /* monotonic time */ -nn_etime_t now_et (void); /* elapsed time */ -void mtime_to_sec_usec (_Out_ int * __restrict sec, _Out_ int * __restrict usec, _In_ nn_mtime_t t); -void wctime_to_sec_usec (_Out_ int * __restrict sec, _Out_ int * __restrict usec, _In_ nn_wctime_t t); -void etime_to_sec_usec (_Out_ int * __restrict sec, _Out_ int * __restrict usec, _In_ nn_etime_t t); -nn_mtime_t mtime_round_up (nn_mtime_t t, int64_t round); -nn_mtime_t add_duration_to_mtime (nn_mtime_t t, int64_t d); -nn_wctime_t add_duration_to_wctime (nn_wctime_t t, int64_t d); -nn_etime_t add_duration_to_etime (nn_etime_t t, int64_t d); +DDS_EXPORT nn_wctime_t now (void); /* wall clock time */ +DDS_EXPORT nn_mtime_t now_mt (void); /* monotonic time */ +DDS_EXPORT nn_etime_t now_et (void); /* elapsed time */ +DDS_EXPORT void mtime_to_sec_usec (_Out_ int * __restrict sec, _Out_ int * __restrict usec, _In_ nn_mtime_t t); +DDS_EXPORT void wctime_to_sec_usec (_Out_ int * __restrict sec, _Out_ int * __restrict usec, _In_ nn_wctime_t t); +DDS_EXPORT void etime_to_sec_usec (_Out_ int * __restrict sec, _Out_ int * __restrict usec, _In_ nn_etime_t t); +DDS_EXPORT nn_mtime_t mtime_round_up (nn_mtime_t t, int64_t round); +DDS_EXPORT nn_mtime_t add_duration_to_mtime (nn_mtime_t t, int64_t d); +DDS_EXPORT nn_wctime_t add_duration_to_wctime (nn_wctime_t t, int64_t d); +DDS_EXPORT nn_etime_t add_duration_to_etime (nn_etime_t t, int64_t d); -nn_ddsi_time_t nn_wctime_to_ddsi_time (nn_wctime_t t); -OSAPI_EXPORT nn_wctime_t nn_wctime_from_ddsi_time (nn_ddsi_time_t x); -OSAPI_EXPORT nn_duration_t nn_to_ddsi_duration (int64_t t); -OSAPI_EXPORT int64_t nn_from_ddsi_duration (nn_duration_t x); +DDS_EXPORT nn_ddsi_time_t nn_wctime_to_ddsi_time (nn_wctime_t t); +DDS_EXPORT nn_wctime_t nn_wctime_from_ddsi_time (nn_ddsi_time_t x); +DDS_EXPORT nn_duration_t nn_to_ddsi_duration (int64_t t); +DDS_EXPORT int64_t nn_from_ddsi_duration (nn_duration_t x); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/ddsi/q_xevent.h b/src/core/ddsi/include/ddsi/q_xevent.h index 497b8eb..3ab7242 100644 --- a/src/core/ddsi/include/ddsi/q_xevent.h +++ b/src/core/ddsi/include/ddsi/q_xevent.h @@ -41,31 +41,31 @@ struct xeventq *xeventq_new /* xeventq_free calls callback handlers with t = T_NEVER, at which point they are required to free whatever memory is claimed for the argument and call delete_xevent. */ -void xeventq_free (struct xeventq *evq); -int xeventq_start (struct xeventq *evq, const char *name); /* <0 => error, =0 => ok */ -void xeventq_stop (struct xeventq *evq); +DDS_EXPORT void xeventq_free (struct xeventq *evq); +DDS_EXPORT int xeventq_start (struct xeventq *evq, const char *name); /* <0 => error, =0 => ok */ +DDS_EXPORT void xeventq_stop (struct xeventq *evq); -void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg); -void qxev_pwr_entityid (struct proxy_writer * pwr, nn_guid_prefix_t * id); -void qxev_prd_entityid (struct proxy_reader * prd, nn_guid_prefix_t * id); +DDS_EXPORT void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg); +DDS_EXPORT void qxev_pwr_entityid (struct proxy_writer * pwr, nn_guid_prefix_t * id); +DDS_EXPORT void qxev_prd_entityid (struct proxy_reader * prd, nn_guid_prefix_t * id); /* Returns 1 if queued, 0 otherwise (no point in returning the event, you can't do anything with it anyway) */ -int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg *msg, int force); +DDS_EXPORT int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg *msg, int force); /* All of the following lock EVQ for the duration of the operation */ -void delete_xevent (struct xevent *ev); -int resched_xevent_if_earlier (struct xevent *ev, nn_mtime_t tsched); +DDS_EXPORT void delete_xevent (struct xevent *ev); +DDS_EXPORT int resched_xevent_if_earlier (struct xevent *ev, nn_mtime_t tsched); -struct xevent *qxev_heartbeat (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *wr_guid); -struct xevent *qxev_acknack (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pwr_guid, const nn_guid_t *rd_guid); -struct xevent *qxev_spdp (nn_mtime_t tsched, const nn_guid_t *pp_guid, const nn_guid_t *proxypp_guid); -struct xevent *qxev_pmd_update (nn_mtime_t tsched, const nn_guid_t *pp_guid); -struct xevent *qxev_end_startup_mode (nn_mtime_t tsched); -struct xevent *qxev_delete_writer (nn_mtime_t tsched, const nn_guid_t *guid); +DDS_EXPORT struct xevent *qxev_heartbeat (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *wr_guid); +DDS_EXPORT struct xevent *qxev_acknack (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pwr_guid, const nn_guid_t *rd_guid); +DDS_EXPORT struct xevent *qxev_spdp (nn_mtime_t tsched, const nn_guid_t *pp_guid, const nn_guid_t *proxypp_guid); +DDS_EXPORT struct xevent *qxev_pmd_update (nn_mtime_t tsched, const nn_guid_t *pp_guid); +DDS_EXPORT struct xevent *qxev_end_startup_mode (nn_mtime_t tsched); +DDS_EXPORT struct xevent *qxev_delete_writer (nn_mtime_t tsched, const nn_guid_t *guid); /* cb will be called with now = T_NEVER if the event is still enqueued when when xeventq_free starts cleaning up */ -struct xevent *qxev_callback (nn_mtime_t tsched, void (*cb) (struct xevent *xev, void *arg, nn_mtime_t now), void *arg); +DDS_EXPORT struct xevent *qxev_callback (nn_mtime_t tsched, void (*cb) (struct xevent *xev, void *arg, nn_mtime_t now), void *arg); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/ddsi/q_xqos.h b/src/core/ddsi/include/ddsi/q_xqos.h index fd67be4..c39c765 100644 --- a/src/core/ddsi/include/ddsi/q_xqos.h +++ b/src/core/ddsi/include/ddsi/q_xqos.h @@ -326,21 +326,21 @@ typedef struct nn_xqos { struct nn_xmsg; -void nn_xqos_init_empty (nn_xqos_t *xqos); -void nn_xqos_init_default_reader (nn_xqos_t *xqos); -void nn_xqos_init_default_writer (nn_xqos_t *xqos); -void nn_xqos_init_default_writer_noautodispose (nn_xqos_t *xqos); -void nn_xqos_init_default_subscriber (nn_xqos_t *xqos); -void nn_xqos_init_default_publisher (nn_xqos_t *xqos); -void nn_xqos_init_default_topic (nn_xqos_t *xqos); -void nn_xqos_copy (nn_xqos_t *dst, const nn_xqos_t *src); -void nn_xqos_unalias (nn_xqos_t *xqos); -void nn_xqos_fini (nn_xqos_t *xqos); -void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b); -uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask); -void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted); -void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos); -nn_xqos_t *nn_xqos_dup (const nn_xqos_t *src); +DDS_EXPORT void nn_xqos_init_empty (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_init_default_reader (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_init_default_writer (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_init_default_writer_noautodispose (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_init_default_subscriber (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_init_default_publisher (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_init_default_topic (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_copy (nn_xqos_t *dst, const nn_xqos_t *src); +DDS_EXPORT void nn_xqos_unalias (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_fini (nn_xqos_t *xqos); +DDS_EXPORT void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b); +DDS_EXPORT uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask); +DDS_EXPORT void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted); +DDS_EXPORT void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos); +DDS_EXPORT nn_xqos_t *nn_xqos_dup (const nn_xqos_t *src); #if defined (__cplusplus) } diff --git a/src/core/ddsi/src/ddsi_rhc_plugin.c b/src/core/ddsi/src/ddsi_rhc_plugin.c index e5677c2..10dfe83 100644 --- a/src/core/ddsi/src/ddsi_rhc_plugin.c +++ b/src/core/ddsi/src/ddsi_rhc_plugin.c @@ -13,7 +13,7 @@ #include "ddsi/q_xqos.h" #include "ddsi/ddsi_rhc_plugin.h" -void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos) +DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos) { pwr_info->guid = e->guid; pwr_info->ownership_strength = xqos->ownership_strength.value; diff --git a/src/core/xtests/CMakeLists.txt b/src/core/xtests/CMakeLists.txt new file mode 100644 index 0000000..6815c89 --- /dev/null +++ b/src/core/xtests/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# Copyright(c) 2019 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 +# +idlc_generate(RhcTypes RhcTypes.idl) + +add_executable(rhc_torture rhc_torture.c mt19937ar.c mt19937ar.h) + +target_include_directories( + rhc_torture PRIVATE + "$" + "$") + +target_link_libraries(rhc_torture RhcTypes ddsc util OSAPI) + +add_test( + NAME rhc_torture + COMMAND rhc_torture 314159265 0 5000 0) +set_property(TEST rhc_torture PROPERTY TIMEOUT 20) diff --git a/src/core/xtests/RhcTypes.idl b/src/core/xtests/RhcTypes.idl new file mode 100644 index 0000000..d084372 --- /dev/null +++ b/src/core/xtests/RhcTypes.idl @@ -0,0 +1,20 @@ +/* + * Copyright(c) 2019 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 + */ +module RhcTypes { + struct T { + long k; + string ks; + long x, y; + string s; + }; +#pragma keylist T k ks +}; diff --git a/src/core/xtests/mt19937ar.c b/src/core/xtests/mt19937ar.c new file mode 100644 index 0000000..31e347e --- /dev/null +++ b/src/core/xtests/mt19937ar.c @@ -0,0 +1,184 @@ +/* + * Copyright(c) 2019 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 + */ + +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) +*/ + +#include "mt19937ar.h" + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0dfU /* constant vector a */ +#define UPPER_MASK 0x80000000U /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffffU /* least significant r bits */ + +static uint32_t mt[N]; /* the array for the state vector */ +static uint32_t mti=N+1; /* mti==N+1 means mt[N] is not initialized */ + +/* initializes mt[N] with a seed */ +void init_genrand(uint32_t s) +{ + mt[0]= s & 0xffffffffU; + for (mti=1; mti> 30)) + mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + mt[mti] &= 0xffffffffU; + /* for >32 bit machines */ + } +} + +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +/* slight change for C++, 2004/2/26 */ +void init_by_array(uint32_t init_key[], size_t key_length) +{ + uint32_t i, j, k; + init_genrand(19650218U); + i=1; j=0; + k = (N>key_length ? N : (uint32_t)key_length); + for (; k; k--) { + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U)) + + init_key[j] + j; /* non linear */ + mt[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ + i++; j++; + if (i>=N) { mt[0] = mt[N-1]; i=1; } + if (j>=(uint32_t)key_length) j=0; + } + for (k=N-1; k; k--) { + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U)) + - i; /* non linear */ + mt[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ + i++; + if (i>=N) { mt[0] = mt[N-1]; i=1; } + } + + mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ +} + +/* generates a random number on [0,0xffffffff]-interval */ +uint32_t genrand_int32(void) +{ + uint32_t y; + static uint32_t mag01[2]={0x0U, MATRIX_A}; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + if (mti >= N) { /* generate N words at one time */ + int kk; + + if (mti == N+1) /* if init_genrand() has not been called, */ + init_genrand(5489U); /* a default initial seed is used */ + + for (kk=0;kk> 1) ^ mag01[y & 0x1U]; + } + for (;kk> 1) ^ mag01[y & 0x1U]; + } + y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U]; + + mti = 0; + } + + y = mt[mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680U; + y ^= (y << 15) & 0xefc60000U; + y ^= (y >> 18); + + return (uint32_t) y; +} + +/* generates a random number on [0,0x7fffffff]-interval */ +int32_t genrand_int31(void) +{ + return (int32_t)(genrand_int32()>>1); +} + +/* generates a random number on [0,1]-real-interval */ +double genrand_real1(void) +{ + return genrand_int32()*(1.0/4294967295.0); + /* divided by 2^32-1 */ +} + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2(void) +{ + return genrand_int32()*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3(void) +{ + return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53(void) +{ + uint32_t a=genrand_int32()>>5, b=genrand_int32()>>6; + return(a*67108864.0+b)*(1.0/9007199254740992.0); +} +/* These real versions are due to Isaku Wada, 2002/01/09 added */ diff --git a/src/core/xtests/mt19937ar.h b/src/core/xtests/mt19937ar.h new file mode 100644 index 0000000..aaa08c8 --- /dev/null +++ b/src/core/xtests/mt19937ar.h @@ -0,0 +1,46 @@ +/* + * Copyright(c) 2019 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 MT19937AR_H +#define MT19937AR_H + +#include +#include + +/* initializes mt[N] with a seed */ +void init_genrand(uint32_t s); + +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +/* slight change for C++, 2004/2/26 */ +void init_by_array(uint32_t init_key[], size_t key_length); + +/* generates a random number on [0,0xffffffff]-interval */ +uint32_t genrand_int32(void); + +/* generates a random number on [0,0x7fffffff]-interval */ +int32_t genrand_int31(void); + +/* generates a random number on [0,1]-real-interval */ +double genrand_real1(void); + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2(void); + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3(void); + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53(void); +/* These real versions are due to Isaku Wada, 2002/01/09 added */ + +#endif diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture.c new file mode 100644 index 0000000..7592784 --- /dev/null +++ b/src/core/xtests/rhc_torture.c @@ -0,0 +1,983 @@ +/* + * Copyright(c) 2019 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 + */ +#include +#include +#include +#include +#include + +#include "os/os.h" + +#include "ddsc/dds.h" +#include "ddsi/ddsi_tkmap.h" +#include "dds__entity.h" +#include "ddsi/q_config.h" +#include "ddsi/q_bswap.h" +#include "ddsi/q_globals.h" +#include "ddsi/q_radmin.h" +#include "ddsi/q_entity.h" +#include "ddsi/q_gc.h" +#include "ddsi/ddsi_serdata.h" +#include "dds__topic.h" +#include "dds__rhc.h" +#include "ddsi/ddsi_iid.h" + +#include "mt19937ar.h" +#include "RhcTypes.h" + +#ifndef _MSC_VER +#define STATIC_ARRAY_DIM static +#else +#define STATIC_ARRAY_DIM +#endif + +static struct ddsi_sertopic *mdtopic; +static struct thread_state1 *mainthread; +static dds_time_t tref_dds; +static uint32_t seq; + +static os_mutex wait_gc_cycle_lock; +static os_cond wait_gc_cycle_cond; +static int wait_gc_cycle_trig; + +/* these are used to get a sufficiently large result buffer when takeing/reading everying */ +#define N_KEYVALS 27 +#define MAX_HIST_DEPTH 4 + +static dds_sample_info_t rres_iseq[(MAX_HIST_DEPTH + 1) * N_KEYVALS]; +static RhcTypes_T rres_mseq[sizeof (rres_iseq) / sizeof (rres_iseq[0])]; +static void *rres_ptrs[sizeof (rres_iseq) / sizeof (rres_iseq[0])]; +static int64_t last_dds_time = 0; + +static char *print_tstamp (char *buf, size_t sz, dds_time_t t) +{ + dds_time_t d = t - tref_dds; + size_t pos = 0; + pos += (size_t) snprintf (buf + pos, sz - pos, "T"); + if (d / 1000000000 != 0) + pos += (size_t) snprintf (buf + pos, sz - pos, "%+ds", (int) (d / 1000000000)); + if (d % 1000000000 != 0) + snprintf (buf + pos, sz - pos, "%+dns", (int) (d % 1000000000)); + return buf; +} + +static int64_t dds_time_uniq (void) +{ + /* behaviour depends on time stamps being strictly monotonically increasing, but there + is no way of knowing whether dds_time provides sufficient resolution, so fake it */ + int64_t t = dds_time (); + if (t > last_dds_time) + last_dds_time = t; + else + last_dds_time++; + return last_dds_time; +} + +static struct ddsi_serdata *mksample (int32_t keyval, unsigned statusinfo) +{ + RhcTypes_T d = { keyval, "A", (int32_t) ++seq, 0, "B" }; + struct ddsi_serdata *sd = ddsi_serdata_from_sample (mdtopic, SDK_DATA, &d); + sd->statusinfo = statusinfo; + sd->timestamp.v = dds_time_uniq (); + return sd; +} + +static struct ddsi_serdata *mkkeysample (int32_t keyval, unsigned statusinfo) +{ + RhcTypes_T d = { keyval, "A", 0, 0, "B" }; + struct ddsi_serdata *sd = ddsi_serdata_from_sample (mdtopic, SDK_KEY, &d); + sd->statusinfo = statusinfo; + sd->timestamp.v = dds_time_uniq (); + return sd; +} + +static uint64_t store (struct rhc *rhc, struct proxy_writer *wr, struct ddsi_serdata *sd, bool print) +{ + /* beware: unrefs sd */ + struct ddsi_tkmap_instance *tk; + struct proxy_writer_info pwr_info; + thread_state_awake (mainthread); + tk = ddsi_tkmap_lookup_instance_ref(sd); + uint64_t iid = tk->m_iid; + if (print) + { + RhcTypes_T d; + char buf[64]; + char si_d = (sd->statusinfo & NN_STATUSINFO_DISPOSE) ? 'D' : '.'; + char si_u = (sd->statusinfo & NN_STATUSINFO_UNREGISTER) ? 'U' : '.'; + memset (&d, 0, sizeof (d)); + ddsi_serdata_to_sample (sd, &d, NULL, NULL); + (void) print_tstamp (buf, sizeof (buf), sd->timestamp.v); + if (sd->kind == SDK_KEY) + printf ("STORE %c%c %16"PRIx64" %16"PRIx64" %2"PRId32" %6s %s\n", si_u, si_d, iid, wr->e.iid, d.k, "_", buf); + else + printf ("STORE %c%c %16"PRIx64" %16"PRIx64" %2"PRId32" %6"PRIu32" %s\n", si_u, si_d, iid, wr->e.iid, d.k, d.x, buf); + ddsi_sertopic_free_sample (sd->topic, &d, DDS_FREE_CONTENTS); + } + pwr_info.auto_dispose = wr->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances; + pwr_info.guid = wr->e.guid; + pwr_info.iid = wr->e.iid; + pwr_info.ownership_strength = wr->c.xqos->ownership_strength.value; + dds_rhc_store (rhc, &pwr_info, sd, tk); + ddsi_tkmap_instance_unref (tk); + thread_state_asleep (mainthread); + ddsi_serdata_unref (sd); + return iid; +} + +static struct proxy_writer *mkwr (bool auto_dispose) +{ + struct proxy_writer *pwr; + struct nn_xqos *xqos; + uint64_t wr_iid; + pwr = os_malloc (sizeof (*pwr)); + xqos = os_malloc (sizeof (*xqos)); + wr_iid = ddsi_iid_gen (); + memset (pwr, 0, sizeof (*pwr)); + nn_xqos_init_empty (xqos); + nn_xqos_mergein_missing (xqos, &gv.default_xqos_wr); + xqos->ownership_strength.value = 0; + xqos->writer_data_lifecycle.autodispose_unregistered_instances = auto_dispose; + pwr->e.iid = wr_iid; + pwr->c.xqos = xqos; + return pwr; +} + +static void fwr (struct proxy_writer *wr) +{ + free (wr->c.xqos); + free (wr); +} + +static struct rhc *mkrhc (dds_reader *rd, nn_history_kind_t hk, int32_t hdepth, nn_destination_order_kind_t dok) +{ + struct rhc *rhc; + nn_xqos_t rqos; + nn_xqos_init_empty (&rqos); + rqos.present |= QP_HISTORY | QP_DESTINATION_ORDER; + rqos.history.kind = hk; + rqos.history.depth = hdepth; + rqos.destination_order.kind = dok; + nn_xqos_mergein_missing (&rqos, &gv.default_xqos_rd); + thread_state_awake (mainthread); + rhc = dds_rhc_new (rd, mdtopic); + dds_rhc_set_qos(rhc, &rqos); + thread_state_asleep (mainthread); + return rhc; +} + +static void frhc (struct rhc *rhc) +{ + thread_state_awake (mainthread); + dds_rhc_free (rhc); + thread_state_asleep (mainthread); +} + +static char si2is (const dds_sample_info_t *si) +{ + switch (si->instance_state) + { + case DDS_ALIVE_INSTANCE_STATE: return 'A'; + case DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE: return 'D'; + case DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE: return 'U'; + default: return '?'; + } +} + +static char si2ss (const dds_sample_info_t *si) +{ + switch (si->sample_state) + { + case DDS_READ_SAMPLE_STATE: return 'R'; + case DDS_NOT_READ_SAMPLE_STATE: return 'N'; + default: return '?'; + } +} + +static char si2vs (const dds_sample_info_t *si) +{ + switch (si->view_state) + { + case DDS_NEW_VIEW_STATE: return 'N'; + case DDS_NOT_NEW_VIEW_STATE: return 'O'; + default: return '?'; + } +} + +struct check { + const char *st; + uint64_t iid; + uint64_t wr_iid; + uint32_t dgen; + uint32_t nwgen; + int vd; + int32_t keyval; + int32_t seq; +}; + +static void docheck (int n, const dds_sample_info_t *iseq, const RhcTypes_T *mseq, const struct check *chk) +{ +#ifndef NDEBUG + int i; + + for (i = 0; i < n; i++) + { + assert (chk[i].st != 0); + dds_sample_state_t sst = chk[i].st[0] == 'N' ? DDS_NOT_READ_SAMPLE_STATE : DDS_READ_SAMPLE_STATE; + dds_view_state_t vst = chk[i].st[1] == 'O' ? DDS_NOT_NEW_VIEW_STATE : DDS_NEW_VIEW_STATE; + dds_instance_state_t ist = chk[i].st[2] == 'A' ? DDS_ALIVE_INSTANCE_STATE : chk[i].st[2] == 'U' ? DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE : DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE; + assert (iseq[i].sample_state == sst); + assert (iseq[i].view_state == vst); + assert (iseq[i].instance_state == ist); + assert (iseq[i].instance_handle == chk[i].iid); + assert (chk[i].wr_iid == 0 || iseq[i].publication_handle == chk[i].wr_iid); + assert (iseq[i].disposed_generation_count == chk[i].dgen); + assert (iseq[i].no_writers_generation_count == chk[i].nwgen); + assert (!!iseq[i].valid_data == !!chk[i].vd); + assert (mseq[i].k == chk[i].keyval); + assert (!chk[i].vd || mseq[i].x == chk[i].seq); + } + + assert (chk[i].st == 0); +#else + (void)n; (void)iseq; (void)mseq; (void)chk; +#endif +} + +static void print_seq (int n, const dds_sample_info_t *iseq, const RhcTypes_T *mseq) +{ + int i; + printf ("INDX SVI %-16s %-16s DGEN NWRG SR GR AR KV SEQ %s\n", "INSTHANDLE", "PUBHANDLE", "TSTAMP"); + for (i = 0; i < n; i++) + { + dds_sample_info_t const * const si = &iseq[i]; + RhcTypes_T const * const d = &mseq[i]; + char buf[64]; + assert(si->instance_handle); + assert(si->publication_handle); + printf ("[%2d] %c%c%c %16"PRIx64" %16"PRIx64" %4d %4d %2d %2d %2d %2"PRId32, + i, si2ss(si), si2vs(si), si2is(si), + si->instance_handle, si->publication_handle, + si->disposed_generation_count, si->no_writers_generation_count, + si->sample_rank, si->generation_rank, si->absolute_generation_rank, + d->k); + if (si->valid_data) + printf (" %6"PRIu32, d->x); + else + printf (" %6s", "_"); + printf (" %s\n", print_tstamp (buf, sizeof (buf), si->source_timestamp)); + } +} + +static void rdtkcond (struct rhc *rhc, dds_readcond *cond, const struct check *chk, bool print, int max, const char *opname, int (*op) (struct rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond), uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2]) +{ + int cnt; + + if (print) + printf ("%s:\n", opname); + + thread_state_awake (mainthread); + cnt = op (rhc, true, rres_ptrs, rres_iseq, (max <= 0) ? (uint32_t) (sizeof (rres_iseq) / sizeof (rres_iseq[0])) : (uint32_t) max, cond ? NO_STATE_MASK_SET : (DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE), 0, cond); + thread_state_asleep (mainthread); + if (max > 0 && cnt > max) { + printf ("%s TOO MUCH DATA (%d > %d)\n", opname, cnt, max); + abort (); + } else if (cnt > 0) { + if (print) print_seq (cnt, rres_iseq, rres_mseq); + } else if (cnt == 0) { + if (print) printf ("(no data)\n"); + } else { + printf ("%s ERROR %d\n", opname, cnt); + abort (); + } + + for (int i = 0; i < cnt; i++) + { + const int is = (rres_iseq[i].instance_state == DDS_ALIVE_INSTANCE_STATE) ? 2 : (rres_iseq[i].instance_state == DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE) ? 1 : 0; + const int x = (rres_iseq[i].sample_state == DDS_NOT_READ_SAMPLE_STATE) + 2 * (rres_iseq[i].view_state == DDS_NEW_VIEW_STATE) + 4 * is; + states_seen[x][rres_iseq[i].valid_data]++; + + /* invalid samples are expected to be zero except for the key fields */ + if (!rres_iseq[i].valid_data) + { + if (rres_mseq[i].x != 0 || rres_mseq[i].y != 0 || rres_mseq[i].s != NULL) + abort (); + } + } + + /* all returned data must match cond */ + if (cond) + { + for (int i = 0; i < cnt; i++) + { + switch (cond->m_sample_states) + { + case DDS_SST_READ: + if (rres_iseq[i].sample_state != DDS_READ_SAMPLE_STATE) abort (); + break; + case DDS_SST_NOT_READ: + if (rres_iseq[i].sample_state != DDS_NOT_READ_SAMPLE_STATE) abort (); + break; + } + switch (cond->m_view_states) + { + case DDS_VST_NEW: + if (rres_iseq[i].view_state != DDS_NEW_VIEW_STATE) abort (); + break; + case DDS_VST_OLD: + if (rres_iseq[i].view_state != DDS_NOT_NEW_VIEW_STATE) abort (); + break; + } + switch (cond->m_instance_states) + { + case DDS_IST_ALIVE: + if (rres_iseq[i].instance_state != DDS_ALIVE_INSTANCE_STATE) abort (); + break; + case DDS_IST_NOT_ALIVE_NO_WRITERS: + if (rres_iseq[i].instance_state != DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE) abort (); + break; + case DDS_IST_NOT_ALIVE_DISPOSED: + if (rres_iseq[i].instance_state != DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE) abort (); + break; + case DDS_IST_NOT_ALIVE_NO_WRITERS | DDS_IST_NOT_ALIVE_DISPOSED: + if (rres_iseq[i].instance_state != DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE && rres_iseq[i].instance_state != DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE) + abort (); + break; + case DDS_IST_ALIVE | DDS_IST_NOT_ALIVE_NO_WRITERS: + if (rres_iseq[i].instance_state != DDS_ALIVE_INSTANCE_STATE && rres_iseq[i].instance_state != DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE) + abort (); + break; + case DDS_IST_ALIVE | DDS_IST_NOT_ALIVE_DISPOSED: + if (rres_iseq[i].instance_state != DDS_ALIVE_INSTANCE_STATE && rres_iseq[i].instance_state != DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE) + abort (); + break; + } + if (cond->m_query.m_filter) + { + /* invalid samples don't get the attributes zero'd out in the result, though the keys are guaranteed to be set; maybe I should change that and guarantee that the fields are 0 ... */ + if (!cond->m_query.m_filter (&rres_mseq[i])) + abort (); + } + } + } + + if (chk) + { + docheck (cnt, rres_iseq, rres_mseq, chk); + } +} + +static void rdall (struct rhc *rhc, const struct check *chk, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2]) +{ + rdtkcond (rhc, NULL, chk, print, 0, "READ ALL", dds_rhc_read, states_seen); +} + +static void tkall (struct rhc *rhc, const struct check *chk, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2]) +{ + rdtkcond (rhc, NULL, chk, print, 0, "TAKE ALL", dds_rhc_take, states_seen); +} + +static void print_condmask (char *buf, size_t bufsz, const dds_readcond *cond) +{ + size_t pos = 0; + const char *sep = ""; + pos += (size_t) snprintf (buf + pos, bufsz - pos, "["); + switch (cond->m_sample_states) + { + case DDS_SST_READ: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sREAD", sep); + sep = ", "; + break; + case DDS_SST_NOT_READ: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sNOT_READ", sep); + sep = ", "; + break; + } + switch (cond->m_view_states) + { + case DDS_VST_NEW: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sNEW", sep); + sep = ", "; + break; + case DDS_VST_OLD: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sOLD", sep); + sep = ", "; + break; + } + switch (cond->m_instance_states) + { + case DDS_IST_ALIVE: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sALIVE", sep); + break; + case DDS_IST_NOT_ALIVE_NO_WRITERS: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sNO_WRITERS", sep); + break; + case DDS_IST_NOT_ALIVE_DISPOSED: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sDISPOSED", sep); + break; + case DDS_IST_NOT_ALIVE_NO_WRITERS | DDS_IST_NOT_ALIVE_DISPOSED: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sNOT_ALIVE", sep); + break; + case DDS_IST_ALIVE | DDS_IST_NOT_ALIVE_NO_WRITERS: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sALIVE | NO_WRITERS", sep); + break; + case DDS_IST_ALIVE | DDS_IST_NOT_ALIVE_DISPOSED: + pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sALIVE | DISPOSED", sep); + break; + } + snprintf (buf + pos, bufsz - pos, "]"); +} + +static void rdcond (struct rhc *rhc, dds_readcond *cond, const struct check *chk, int max, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2]) +{ + char buf[100]; + int pos; + pos = snprintf (buf, sizeof (buf), "READ COND %p %d ", (void *) cond, max); + print_condmask (buf + pos, sizeof (buf) - (size_t) pos, cond); + rdtkcond (rhc, cond, chk, print, max, buf, dds_rhc_read, states_seen); +} + +static void tkcond (struct rhc *rhc, dds_readcond *cond, const struct check *chk, int max, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2]) +{ + char buf[100]; + int pos; + pos = snprintf (buf, sizeof (buf), "TAKE COND %p %d ", (void *) cond, max); + print_condmask (buf + pos, sizeof (buf) - (size_t) pos, cond); + rdtkcond (rhc, cond, chk, print, max, buf, dds_rhc_take, states_seen); +} + +static void wait_gc_cycle_impl (struct gcreq *gcreq) +{ + os_mutexLock (&wait_gc_cycle_lock); + wait_gc_cycle_trig = 1; + os_condBroadcast (&wait_gc_cycle_cond); + os_mutexUnlock (&wait_gc_cycle_lock); + gcreq_free (gcreq); +} + +static void wait_gc_cycle (void) +{ + /* only single-threaded for now */ + struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, wait_gc_cycle_impl); +#ifndef NDEBUG + os_mutexLock (&wait_gc_cycle_lock); + assert (wait_gc_cycle_trig == 0); + os_mutexUnlock (&wait_gc_cycle_lock); +#endif + gcreq_enqueue (gcreq); + os_mutexLock (&wait_gc_cycle_lock); + while (!wait_gc_cycle_trig) + os_condWait (&wait_gc_cycle_cond, &wait_gc_cycle_lock); + wait_gc_cycle_trig = 0; + os_mutexUnlock (&wait_gc_cycle_lock); +} + +static bool qcpred_key (const void *vx) +{ + const RhcTypes_T *x = vx; + return (x->k % 2) == 0; +} + +static bool qcpred_attr2 (const void *vx) +{ + const RhcTypes_T *x = vx; + return (x->x % 2) == 0; +} + +static bool qcpred_attr3 (const void *vx) +{ + const RhcTypes_T *x = vx; + return (x->x % 3) == 0; +} + +static dds_readcond *get_condaddr (dds_entity_t x) +{ + struct dds_entity *e; + if (dds_entity_lock (x, DDS_KIND_DONTCARE, &e) < 0) + abort(); + assert (dds_entity_kind (e) == DDS_KIND_COND_READ || dds_entity_kind (e) == DDS_KIND_COND_QUERY); + dds_entity_unlock (e); + return (dds_readcond *) e; +} + +static void print_cond_w_addr (const char *label, dds_entity_t x) +{ + char buf[100]; + struct dds_entity *e; + if (dds_entity_lock (x, DDS_KIND_DONTCARE, &e) < 0) + abort(); + assert (dds_entity_kind (e) == DDS_KIND_COND_READ || dds_entity_kind (e) == DDS_KIND_COND_QUERY); + print_condmask (buf, sizeof (buf), (dds_readcond *) e); + printf ("%s: %"PRIu32" => %p %s\n", label, x, (void *) e, buf); + dds_entity_unlock (e); +} + +static dds_entity_t readcond_wrapper (dds_entity_t reader, uint32_t mask, dds_querycondition_filter_fn filter) +{ + (void) filter; + return dds_create_readcondition (reader, mask); +} + +static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, dds_entity_t (*create_cond) (dds_entity_t reader, uint32_t mask, dds_querycondition_filter_fn filter), dds_querycondition_filter_fn filter0, dds_querycondition_filter_fn filter1, bool print) +{ + dds_qos_t *qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, MAX_HIST_DEPTH); + dds_qset_destination_order (qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); + /* two identical readers because we need 63 conditions while we can currently only attach 32 a single reader */ + dds_entity_t rd[] = { dds_create_reader (pp, tp, qos, NULL), dds_create_reader (pp, tp, qos, NULL) }; + const size_t nrd = sizeof (rd) / sizeof (rd[0]); + dds_delete_qos (qos); + struct rhc *rhc[sizeof (rd) / sizeof (rd[0])]; + for (size_t i = 0; i < sizeof (rd) / sizeof (rd[0]); i++) + { + struct dds_entity *x; + if (dds_entity_lock (rd[i], DDS_KIND_READER, &x) < 0) + abort (); + dds_reader *rdp = (dds_reader *) x; + rhc[i] = rdp->m_rd->rhc; + dds_entity_unlock (x); + } + struct proxy_writer *wr[] = { mkwr (0), mkwr (1), mkwr (1) }; + + static const uint32_t stab[] = { + DDS_READ_SAMPLE_STATE, DDS_NOT_READ_SAMPLE_STATE, + DDS_READ_SAMPLE_STATE | DDS_NOT_READ_SAMPLE_STATE + }; + const int nstab = (int) (sizeof (stab) / sizeof (stab[0])); + static const uint32_t vtab[] = { + DDS_NEW_VIEW_STATE, DDS_NOT_NEW_VIEW_STATE, + DDS_NEW_VIEW_STATE | DDS_NOT_NEW_VIEW_STATE + }; + const int nvtab = (int) (sizeof (vtab) / sizeof (vtab[0])); + static const uint32_t itab[] = { + DDS_ALIVE_INSTANCE_STATE, DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, + DDS_ALIVE_INSTANCE_STATE | DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE, + DDS_ALIVE_INSTANCE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, + DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, + DDS_ALIVE_INSTANCE_STATE | DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + }; + const int nitab = (int) (sizeof (itab) / sizeof (itab[0])); + const int nconds = nstab * nvtab * nitab; + + dds_entity_t gdcond = dds_create_guardcondition (pp); + dds_entity_t waitset = dds_create_waitset(pp); + dds_waitset_attach(waitset, gdcond, 888); + + /* create a conditions for every possible state mask */ + assert (nconds == 63); + dds_entity_t conds[63]; + dds_readcond *rhcconds[63]; + { + int ci = 0; + for (int s = 0; s < nstab; s++) + for (int v = 0; v < nvtab; v++) + for (int i = 0; i < nitab; i++) + { + assert (ci / 32 < (int) (sizeof (rd) / sizeof (rd[0]))); + conds[ci] = create_cond (rd[ci / 32], stab[s] | vtab[v] | itab[i], ((ci % 2) == 0) ? filter0 : filter1); + if (conds[ci] <= 0) abort (); + rhcconds[ci] = get_condaddr (conds[ci]); + if (print) { + char buf[10]; + snprintf (buf, sizeof (buf), "conds[%d]", ci); + print_cond_w_addr (buf, conds[ci]); + } + dds_waitset_attach(waitset, conds[ci], ci); + ci++; + } + } + + /* simply sanity check on the guard condition and waitset triggering */ + { + bool v; + int n; + dds_attach_t xs[2]; + dds_read_guardcondition (gdcond, &v); + assert (!v); + dds_set_guardcondition (gdcond, true); + n = dds_waitset_wait (waitset, xs, sizeof(xs) / sizeof(xs[0]), 0); + assert (n == 1); + (void)n; + assert (xs[0] == 888); + dds_read_guardcondition (gdcond, &v); + assert (v); + dds_take_guardcondition (gdcond, &v); + assert (v); + dds_read_guardcondition (gdcond, &v); + assert (!v); + n = dds_waitset_wait (waitset, xs, sizeof(xs) / sizeof(xs[0]), 0); + assert (n == 0); + (void)n; + } + + /* relative frequency table of operations: */ + static const char *operstr[] = { + [0] = "w", + [1] = "wd", + [2] = "d", + [3] = "u", + [4] = "du", + [5] = "wdu", + [6] = "rdall", + [7] = "tkall", + [8] = "rdc", + [9] = "tkc", + [10] = "tkc1", + [11] = "delwr" + }; + static const uint32_t opfreqs[] = { + [0] = 500, /* write */ + [1] = 100, /* variants with dispose & unregister */ + [2] = 100, + [3] = 300, /* just unregister */ + [4] = 100, /* variants with dispose & unregister */ + [5] = 100, + [6] = 50, /* read all */ + [7] = 5, /* take all */ + [8] = 200, /* read cond */ + [9] = 30, /* take cond */ + [10] = 100, /* take cond, max 1 */ + [11] = 1 /* unreg writer */ + }; + uint32_t opthres[sizeof (opfreqs) / sizeof (opfreqs[0])]; + { + const size_t n = sizeof (opfreqs) / sizeof (opfreqs[0]); + uint32_t sum = 0; + for (size_t i = 0; i < n; i++) + sum += opfreqs[i]; + const uint32_t scale = UINT32_MAX / sum; + sum = 0; + for (size_t i = 0; i < n; i++) + { + sum += opfreqs[i]; + opthres[i] = sum * scale; + } + } + + uint32_t states_seen[2 * 2 * 3][2] = {{ 0 }}; + uint32_t opcount[sizeof (opfreqs) / sizeof (opfreqs[0])] = { 0 }; + int lastprint_pct = 0; + for (int i = 0; i < count; i++) + { + const int32_t keyval = (int32_t) (genrand_int32 () % N_KEYVALS); + const uint32_t which = genrand_int32 () % 3; + uint32_t oper_base; + uint32_t oper; + + /* generate uniform number in range 0 .. N, then map to operation following the frequency table */ + do { + oper_base = genrand_int32 (); + } while (oper_base >= opthres[sizeof (opfreqs) / sizeof (opfreqs[0]) - 1]); + for (oper = 0; oper < sizeof (opfreqs) / sizeof (opfreqs[0]); oper++) + { + if (oper_base < opthres[oper]) + break; + } + opcount[oper]++; + + if (100 * i / count > lastprint_pct) + { + lastprint_pct = 100 * i / count; + printf ("%d%%%c", lastprint_pct, print ? '\n' : '\r'); + fflush (stdout); + } + + switch (oper) + { + case 0: { /* wr */ + struct ddsi_serdata *s = mksample (keyval, 0); + for (size_t k = 0; k < nrd; k++) + store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0); + ddsi_serdata_unref (s); + break; + } + case 1: { /* wr disp */ + struct ddsi_serdata *s = mksample (keyval, NN_STATUSINFO_DISPOSE); + for (size_t k = 0; k < nrd; k++) + store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0); + ddsi_serdata_unref (s); + break; + } + case 2: { /* disp */ + struct ddsi_serdata *s = mkkeysample (keyval, NN_STATUSINFO_DISPOSE); + for (size_t k = 0; k < nrd; k++) + store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0); + ddsi_serdata_unref (s); + break; + } + case 3: { /* unreg */ + struct ddsi_serdata *s = mkkeysample (keyval, NN_STATUSINFO_UNREGISTER); + for (size_t k = 0; k < nrd; k++) + store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0); + ddsi_serdata_unref (s); + break; + } + case 4: { /* disp unreg */ + struct ddsi_serdata *s = mkkeysample (keyval, NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER); + for (size_t k = 0; k < nrd; k++) + store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0); + ddsi_serdata_unref (s); + break; + } + case 5: { /* wr disp unreg */ + struct ddsi_serdata *s = mksample (keyval, NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER); + for (size_t k = 0; k < nrd; k++) + store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0); + ddsi_serdata_unref (s); + break; + } + case 6: + for (size_t k = 0; k < nrd; k++) + rdall (rhc[k], NULL, print && k == 0, states_seen); + break; + case 7: + for (size_t k = 0; k < nrd; k++) + tkall (rhc[k], NULL, print && k == 0, states_seen); + break; + case 8: { + uint32_t cond = genrand_int32 () % (uint32_t) nconds; + for (size_t k = 0; k < nrd; k++) + rdcond (rhc[k], rhcconds[cond], NULL, 0, print && k == 0, states_seen); + break; + } + case 9: { + uint32_t cond = genrand_int32 () % (uint32_t) nconds; + for (size_t k = 0; k < nrd; k++) + tkcond (rhc[k], rhcconds[cond], NULL, 0, print && k == 0, states_seen); + break; + } + case 10: { + uint32_t cond = genrand_int32 () % (uint32_t) nconds; + for (size_t k = 0; k < nrd; k++) + tkcond (rhc[k], rhcconds[cond], NULL, 1, print && k == 0, states_seen); + break; + } + case 11: + thread_state_awake (mainthread); + struct proxy_writer_info wr_info; + wr_info.auto_dispose = wr[which]->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances; + wr_info.guid = wr[which]->e.guid; + wr_info.iid = wr[which]->e.iid; + wr_info.ownership_strength = wr[which]->c.xqos->ownership_strength.value; + for (size_t k = 0; k < nrd; k++) + dds_rhc_unregister_wr (rhc[k], &wr_info); + thread_state_asleep (mainthread); + break; + } + + if ((i % 200) == 0) + wait_gc_cycle (); + } + + for (size_t oper = 0; oper < sizeof (opcount) / sizeof (opcount[0]); oper++) + printf ("%5s: %8"PRIu32"\n", operstr[oper], opcount[oper]); + for (int i = 0; i < (int) (sizeof (states_seen) / sizeof (states_seen[0])); i++) + { + const char sst = (i & 1) ? 'N' : 'R'; + const char vst = (i & 2) ? 'N' : 'O'; + const char ist = (i >> 2) == 2 ? 'A' : (i >> 2) == 1 ? 'D' : 'U'; + printf ("%c%c%c: invalid %8"PRIu32" valid %8"PRIu32"\n", sst, vst, ist, states_seen[i][0], states_seen[i][1]); + } + + dds_waitset_detach (waitset, gdcond); + for (int ci = 0; ci < nconds; ci++) + dds_waitset_detach (waitset, conds[ci]); + dds_delete (waitset); + dds_delete (gdcond); + for (int ci = 0; ci < nconds; ci++) + dds_delete (conds[ci]); + for (size_t i = 0; i < nrd; i++) + dds_delete (rd[i]); + for (size_t i = 0; i < sizeof (wr) / sizeof (wr[0]); i++) + fwr (wr[i]); +} + +int main (int argc, char **argv) +{ + dds_entity_t pp = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); + dds_entity_t tp = dds_create_topic(pp, &RhcTypes_T_desc, "RhcTypes_T", NULL, NULL); + uint32_t states_seen[2 * 2 * 3][2] = {{ 0 }}; + unsigned seed = 0; + bool print = false; + int first = 0, count = 10000; + + os_mutexInit (&wait_gc_cycle_lock); + os_condInit (&wait_gc_cycle_cond, &wait_gc_cycle_lock); + + if (argc > 1) + seed = (unsigned) atoi (argv[1]); + if (seed == 0) + seed = (unsigned) os_getpid (); + if (argc > 2) + first = atoi (argv[2]); + if (argc > 3) + count = atoi (argv[3]); + if (argc > 4) + print = (atoi (argv[4]) != 0); + + printf ("prng seed %u first %d count %d print %d\n", seed, first, count, print); + init_genrand (seed); + + memset (rres_mseq, 0, sizeof (rres_mseq)); + for (size_t i = 0; i < sizeof (rres_iseq) / sizeof(rres_iseq[0]); i++) + rres_ptrs[i] = &rres_mseq[i]; + + tref_dds = dds_time(); + mainthread = lookup_thread_state (); + { + struct dds_entity *x; + if (dds_entity_lock(tp, DDS_KIND_TOPIC, &x) < 0) abort(); + mdtopic = dds_topic_lookup(x->m_domain, "RhcTypes_T"); + dds_entity_unlock(x); + } + + if (0 >= first) + { + if (print) + printf ("************* 0 *************\n"); + struct rhc *rhc = mkrhc (NULL, NN_KEEP_LAST_HISTORY_QOS, 1, NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS); + struct proxy_writer *wr0 = mkwr (1); + uint64_t iid0, iid1, iid_t; + iid0 = store (rhc, wr0, mksample (0, 0), print); + iid1 = store (rhc, wr0, mksample (1, NN_STATUSINFO_DISPOSE), print); + const struct check c0[] = { + { "NNA", iid0, wr0->e.iid, 0,0, 1, 0,1 }, + { "NND", iid1, wr0->e.iid, 0,0, 1, 1,2 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } + }; + rdall (rhc, c0, print, states_seen); + iid_t = store (rhc, wr0, mkkeysample (0, NN_STATUSINFO_UNREGISTER), print); + assert (iid_t == iid0); + (void)iid0; + (void)iid_t; + const struct check c1[] = { + { "ROU", iid0, wr0->e.iid, 0,0, 1, 0,1 }, + { "NOU", iid0, 0, 0,0, 0, 0,0 }, + { "ROD", iid1, wr0->e.iid, 0,0, 1, 1,2 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } + }; + rdall (rhc, c1, print, states_seen); + thread_state_awake (mainthread); + struct proxy_writer_info wr0_info; + wr0_info.auto_dispose = wr0->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances; + wr0_info.guid = wr0->e.guid; + wr0_info.iid = wr0->e.iid; + wr0_info.ownership_strength = wr0->c.xqos->ownership_strength.value; + dds_rhc_unregister_wr (rhc, &wr0_info); + thread_state_asleep (mainthread); + const struct check c2[] = { + { "ROU", iid0, wr0->e.iid, 0,0, 1, 0,1 }, + { "ROU", iid0, 0, 0,0, 0, 0,0 }, + { "ROD", iid1, wr0->e.iid, 0,0, 1, 1,2 }, + { "NOD", iid1, 0, 0,0, 0, 1,0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } + }; + tkall (rhc, c2, print, states_seen); + frhc (rhc); + fwr (wr0); + } + + if (1 >= first) + { + if (print) + printf ("************* 1 *************\n"); + struct rhc *rhc = mkrhc (NULL, NN_KEEP_LAST_HISTORY_QOS, 4, NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS); + struct proxy_writer *wr[] = { mkwr (0), mkwr (0), mkwr (0) }; + uint64_t iid0, iid_t; + int nregs = 3, isreg[] = { 1, 1, 1 }; + iid0 = store (rhc, wr[0], mksample (0, 0), print); + iid_t = store (rhc, wr[1], mksample (0, 0), print); assert (iid0 == iid_t); + iid_t = store (rhc, wr[2], mksample (0, 0), print); assert (iid0 == iid_t); + (void)iid0; + tkall (rhc, NULL, print, states_seen); + for (int i = 0; i < 3*3 * 3*3 * 3*3 * 3*3; i++) + { + for (int pos = 0, base = 1; pos < 3; pos++, base *= 3*3) + { + int which = (((i / base) / 3) + pos) % 3; + int oper = (i / base) % 3; + switch (oper) + { + case 0: + iid_t = store (rhc, wr[which], mksample (0, 0), print); + if (!isreg[which]) { nregs++; isreg[which] = 1; } + break; + case 1: + iid_t = store (rhc, wr[which], mkkeysample (0, NN_STATUSINFO_DISPOSE), print); + if (!isreg[which]) { nregs++; isreg[which] = 1; } + break; + case 2: + if (nregs > 1 || !isreg[which]) + { + iid_t = store (rhc, wr[which], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print); + if (isreg[which]) { isreg[which] = 0; nregs--; } + } + break; + } + assert (iid_t == iid0); + } + } + tkall (rhc, 0, print, states_seen); + wait_gc_cycle (); + assert (nregs > 0); + for (int i = 0; i < 3; i++) + { + if (isreg[i]) + { + iid_t = store (rhc, wr[i], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print); + assert (iid_t == iid0); + isreg[i] = 0; + nregs--; + } + } + assert (nregs == 0); + tkall (rhc, 0, print, states_seen); + wait_gc_cycle (); + iid_t = store (rhc, wr[0], mksample (0, 0), print); + assert (iid_t != iid0); + iid0 = iid_t; + iid_t = store (rhc, wr[0], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print); + assert (iid_t == iid0); + frhc (rhc); + + for (size_t i = 0; i < sizeof (wr) / sizeof (wr[0]); i++) + fwr (wr[i]); + } + + { + static const struct { + dds_entity_t (*create) (dds_entity_t, uint32_t, dds_querycondition_filter_fn); + dds_querycondition_filter_fn filter0; + dds_querycondition_filter_fn filter1; + } zztab[] = { + { readcond_wrapper, 0, 0 }, + { dds_create_querycondition, qcpred_key, qcpred_attr2 }, + { dds_create_querycondition, qcpred_attr2, qcpred_attr3 } + }; + for (int zz = 0; zz < (int) (sizeof (zztab) / sizeof (zztab[0])); zz++) + if (zz + 2 >= first) + { + if (print) + printf ("************* %d *************\n", zz + 2); + test_conditions (pp, tp, count, zztab[zz].create, zztab[zz].filter0, zztab[zz].filter1, print); + } + } + + os_condDestroy (&wait_gc_cycle_cond); + os_mutexDestroy (&wait_gc_cycle_lock); + + for (size_t i = 0; i < sizeof (rres_iseq) / sizeof (rres_iseq[0]); i++) + RhcTypes_T_free (&rres_mseq[i], DDS_FREE_CONTENTS); + + dds_delete(pp); + return 0; +}