Refactored linked list administration in rhc so that it becomes reusable
Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
This commit is contained in:
parent
a41a615999
commit
219cb6cf4f
4 changed files with 182 additions and 80 deletions
|
@ -30,6 +30,7 @@
|
||||||
#include "dds/ddsi/ddsi_tkmap.h"
|
#include "dds/ddsi/ddsi_tkmap.h"
|
||||||
#include "dds/ddsrt/hopscotch.h"
|
#include "dds/ddsrt/hopscotch.h"
|
||||||
#include "dds/ddsrt/avl.h"
|
#include "dds/ddsrt/avl.h"
|
||||||
|
#include "dds/ddsrt/circlist.h"
|
||||||
#include "dds/ddsi/ddsi_rhc.h"
|
#include "dds/ddsi/ddsi_rhc.h"
|
||||||
#include "dds/ddsi/q_xqos.h"
|
#include "dds/ddsi/q_xqos.h"
|
||||||
#include "dds/ddsi/q_unused.h"
|
#include "dds/ddsi/q_unused.h"
|
||||||
|
@ -271,8 +272,7 @@ struct rhc_instance {
|
||||||
int32_t strength; /* "current" ownership strength */
|
int32_t strength; /* "current" ownership strength */
|
||||||
ddsi_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */
|
ddsi_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */
|
||||||
nn_wctime_t tstamp; /* source time stamp of last update */
|
nn_wctime_t tstamp; /* source time stamp of last update */
|
||||||
struct rhc_instance *next; /* next non-empty instance in arbitrary ordering */
|
struct ddsrt_circlist_elem nonempty_list; /* links non-empty instances in arbitrary ordering */
|
||||||
struct rhc_instance *prev;
|
|
||||||
struct ddsi_tkmap_instance *tk; /* backref into TK for unref'ing */
|
struct ddsi_tkmap_instance *tk; /* backref into TK for unref'ing */
|
||||||
struct rhc_sample a_sample; /* pre-allocated storage for 1 sample */
|
struct rhc_sample a_sample; /* pre-allocated storage for 1 sample */
|
||||||
};
|
};
|
||||||
|
@ -286,7 +286,7 @@ typedef enum rhc_store_result {
|
||||||
struct dds_rhc_default {
|
struct dds_rhc_default {
|
||||||
struct dds_rhc common;
|
struct dds_rhc common;
|
||||||
struct ddsrt_hh *instances;
|
struct ddsrt_hh *instances;
|
||||||
struct rhc_instance *nonempty_instances; /* circular, points to most recently added one, NULL if none */
|
struct ddsrt_circlist nonempty_instances; /* circular, points to most recently added one, NULL if none */
|
||||||
struct lwregs registrations; /* should be a global one (with lock-free lookups) */
|
struct lwregs registrations; /* should be a global one (with lock-free lookups) */
|
||||||
|
|
||||||
/* Instance/Sample maximums from resource limits QoS */
|
/* Instance/Sample maximums from resource limits QoS */
|
||||||
|
@ -494,57 +494,33 @@ static int instance_iid_eq (const void *va, const void *vb)
|
||||||
|
|
||||||
static void add_inst_to_nonempty_list (struct dds_rhc_default *rhc, struct rhc_instance *inst)
|
static void add_inst_to_nonempty_list (struct dds_rhc_default *rhc, struct rhc_instance *inst)
|
||||||
{
|
{
|
||||||
if (rhc->nonempty_instances == NULL)
|
ddsrt_circlist_append (&rhc->nonempty_instances, &inst->nonempty_list);
|
||||||
{
|
|
||||||
inst->next = inst->prev = inst;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct rhc_instance * const hd = rhc->nonempty_instances;
|
|
||||||
#ifndef NDEBUG
|
|
||||||
{
|
|
||||||
const struct rhc_instance *x = hd;
|
|
||||||
do { assert (x != inst); x = x->next; } while (x != hd);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
inst->next = hd->next;
|
|
||||||
inst->prev = hd;
|
|
||||||
hd->next = inst;
|
|
||||||
inst->next->prev = inst;
|
|
||||||
}
|
|
||||||
rhc->nonempty_instances = inst;
|
|
||||||
rhc->n_nonempty_instances++;
|
rhc->n_nonempty_instances++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_inst_from_nonempty_list (struct dds_rhc_default *rhc, struct rhc_instance *inst)
|
static void remove_inst_from_nonempty_list (struct dds_rhc_default *rhc, struct rhc_instance *inst)
|
||||||
{
|
{
|
||||||
assert (inst_is_empty (inst));
|
assert (inst_is_empty (inst));
|
||||||
#ifndef NDEBUG
|
ddsrt_circlist_remove (&rhc->nonempty_instances, &inst->nonempty_list);
|
||||||
{
|
|
||||||
const struct rhc_instance *x = rhc->nonempty_instances;
|
|
||||||
assert (x);
|
|
||||||
do { if (x == inst) break; x = x->next; } while (x != rhc->nonempty_instances);
|
|
||||||
assert (x == inst);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (inst->next == inst)
|
|
||||||
{
|
|
||||||
rhc->nonempty_instances = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct rhc_instance * const inst_prev = inst->prev;
|
|
||||||
struct rhc_instance * const inst_next = inst->next;
|
|
||||||
inst_prev->next = inst_next;
|
|
||||||
inst_next->prev = inst_prev;
|
|
||||||
if (rhc->nonempty_instances == inst)
|
|
||||||
rhc->nonempty_instances = inst_prev;
|
|
||||||
}
|
|
||||||
assert (rhc->n_nonempty_instances > 0);
|
assert (rhc->n_nonempty_instances > 0);
|
||||||
rhc->n_nonempty_instances--;
|
rhc->n_nonempty_instances--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct rhc_instance *oldest_nonempty_instance (const struct dds_rhc_default *rhc)
|
||||||
|
{
|
||||||
|
return DDSRT_FROM_CIRCLIST (struct rhc_instance, nonempty_list, ddsrt_circlist_oldest (&rhc->nonempty_instances));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rhc_instance *latest_nonempty_instance (const struct dds_rhc_default *rhc)
|
||||||
|
{
|
||||||
|
return DDSRT_FROM_CIRCLIST (struct rhc_instance, nonempty_list, ddsrt_circlist_latest (&rhc->nonempty_instances));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rhc_instance *next_nonempty_instance (const struct rhc_instance *inst)
|
||||||
|
{
|
||||||
|
return DDSRT_FROM_CIRCLIST (struct rhc_instance, nonempty_list, inst->nonempty_list.next);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DDSI_INCLUDE_LIFESPAN
|
#ifdef DDSI_INCLUDE_LIFESPAN
|
||||||
static void drop_expired_samples (struct dds_rhc_default *rhc, struct rhc_sample *sample)
|
static void drop_expired_samples (struct dds_rhc_default *rhc, struct rhc_sample *sample)
|
||||||
{
|
{
|
||||||
|
@ -631,6 +607,7 @@ struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct q_global
|
||||||
lwregs_init (&rhc->registrations);
|
lwregs_init (&rhc->registrations);
|
||||||
ddsrt_mutex_init (&rhc->lock);
|
ddsrt_mutex_init (&rhc->lock);
|
||||||
rhc->instances = ddsrt_hh_new (1, instance_iid_hash, instance_iid_eq);
|
rhc->instances = ddsrt_hh_new (1, instance_iid_hash, instance_iid_eq);
|
||||||
|
ddsrt_circlist_init (&rhc->nonempty_instances);
|
||||||
rhc->topic = topic;
|
rhc->topic = topic;
|
||||||
rhc->reader = reader;
|
rhc->reader = reader;
|
||||||
rhc->tkmap = gv->m_tkmap;
|
rhc->tkmap = gv->m_tkmap;
|
||||||
|
@ -814,7 +791,7 @@ static void dds_rhc_default_free (struct dds_rhc_default *rhc)
|
||||||
lifespan_fini (&rhc->lifespan);
|
lifespan_fini (&rhc->lifespan);
|
||||||
#endif
|
#endif
|
||||||
ddsrt_hh_enum (rhc->instances, free_instance_rhc_free_wrap, rhc);
|
ddsrt_hh_enum (rhc->instances, free_instance_rhc_free_wrap, rhc);
|
||||||
assert (rhc->nonempty_instances == NULL);
|
assert (ddsrt_circlist_isempty (&rhc->nonempty_instances));
|
||||||
ddsrt_hh_free (rhc->instances);
|
ddsrt_hh_free (rhc->instances);
|
||||||
lwregs_fini (&rhc->registrations);
|
lwregs_fini (&rhc->registrations);
|
||||||
if (rhc->qcond_eval_samplebuf != NULL)
|
if (rhc->qcond_eval_samplebuf != NULL)
|
||||||
|
@ -1966,10 +1943,10 @@ static int dds_rhc_read_w_qminv (struct dds_rhc_default *rhc, bool lock, void **
|
||||||
rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples,
|
rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples,
|
||||||
rhc->n_vread, rhc->n_invread);
|
rhc->n_vread, rhc->n_invread);
|
||||||
|
|
||||||
if (rhc->nonempty_instances)
|
if (!ddsrt_circlist_isempty (&rhc->nonempty_instances))
|
||||||
{
|
{
|
||||||
const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0;
|
const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0;
|
||||||
struct rhc_instance * inst = rhc->nonempty_instances->next;
|
struct rhc_instance * inst = oldest_nonempty_instance (rhc);
|
||||||
struct rhc_instance * const end = inst;
|
struct rhc_instance * const end = inst;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -2055,7 +2032,7 @@ static int dds_rhc_read_w_qminv (struct dds_rhc_default *rhc, bool lock, void **
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inst = inst->next;
|
inst = next_nonempty_instance (inst);
|
||||||
}
|
}
|
||||||
while (inst != end && n < max_samples);
|
while (inst != end && n < max_samples);
|
||||||
}
|
}
|
||||||
|
@ -2083,14 +2060,14 @@ static int dds_rhc_take_w_qminv (struct dds_rhc_default *rhc, bool lock, void **
|
||||||
rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples,
|
rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples,
|
||||||
rhc->n_invsamples, rhc->n_vread, rhc->n_invread);
|
rhc->n_invsamples, rhc->n_vread, rhc->n_invread);
|
||||||
|
|
||||||
if (rhc->nonempty_instances)
|
if (!ddsrt_circlist_isempty (&rhc->nonempty_instances))
|
||||||
{
|
{
|
||||||
const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0;
|
const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0;
|
||||||
struct rhc_instance *inst = rhc->nonempty_instances->next;
|
struct rhc_instance *inst = oldest_nonempty_instance (rhc);
|
||||||
unsigned n_insts = rhc->n_nonempty_instances;
|
unsigned n_insts = rhc->n_nonempty_instances;
|
||||||
while (n_insts-- > 0 && n < max_samples)
|
while (n_insts-- > 0 && n < max_samples)
|
||||||
{
|
{
|
||||||
struct rhc_instance * const inst1 = inst->next;
|
struct rhc_instance * const inst1 = next_nonempty_instance (inst);
|
||||||
iid = inst->iid;
|
iid = inst->iid;
|
||||||
if (handle == DDS_HANDLE_NIL || iid == handle)
|
if (handle == DDS_HANDLE_NIL || iid == handle)
|
||||||
{
|
{
|
||||||
|
@ -2238,14 +2215,14 @@ static int dds_rhc_takecdr_w_qminv (struct dds_rhc_default *rhc, bool lock, stru
|
||||||
rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples,
|
rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples,
|
||||||
rhc->n_invsamples, rhc->n_vread, rhc->n_invread);
|
rhc->n_invsamples, rhc->n_vread, rhc->n_invread);
|
||||||
|
|
||||||
if (rhc->nonempty_instances)
|
if (!ddsrt_circlist_isempty (&rhc->nonempty_instances))
|
||||||
{
|
{
|
||||||
const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0;
|
const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0;
|
||||||
struct rhc_instance *inst = rhc->nonempty_instances->next;
|
struct rhc_instance *inst = oldest_nonempty_instance (rhc);
|
||||||
unsigned n_insts = rhc->n_nonempty_instances;
|
unsigned n_insts = rhc->n_nonempty_instances;
|
||||||
while (n_insts-- > 0 && n < max_samples)
|
while (n_insts-- > 0 && n < max_samples)
|
||||||
{
|
{
|
||||||
struct rhc_instance * const inst1 = inst->next;
|
struct rhc_instance * const inst1 = next_nonempty_instance (inst);
|
||||||
iid = inst->iid;
|
iid = inst->iid;
|
||||||
if (handle == DDS_HANDLE_NIL || iid == handle)
|
if (handle == DDS_HANDLE_NIL || iid == handle)
|
||||||
{
|
{
|
||||||
|
@ -2454,13 +2431,14 @@ static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_
|
||||||
{
|
{
|
||||||
/* Read condition is not cached inside the instances and samples, so it only needs
|
/* Read condition is not cached inside the instances and samples, so it only needs
|
||||||
to be evaluated on the non-empty instances */
|
to be evaluated on the non-empty instances */
|
||||||
if (rhc->nonempty_instances)
|
if (!ddsrt_circlist_isempty (&rhc->nonempty_instances))
|
||||||
{
|
{
|
||||||
struct rhc_instance *inst = rhc->nonempty_instances;
|
struct rhc_instance *inst = latest_nonempty_instance (rhc);
|
||||||
|
struct rhc_instance const * const end = inst;
|
||||||
do {
|
do {
|
||||||
trigger += rhc_get_cond_trigger (inst, cond);
|
trigger += rhc_get_cond_trigger (inst, cond);
|
||||||
inst = inst->next;
|
inst = next_nonempty_instance (inst);
|
||||||
} while (inst != rhc->nonempty_instances);
|
} while (inst != end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2904,26 +2882,25 @@ static int rhc_check_counts_locked (struct dds_rhc_default *rhc, bool check_cond
|
||||||
{
|
{
|
||||||
for (i = 0, rciter = rhc->conds; i < ncheck; i++, rciter = rciter->m_next)
|
for (i = 0, rciter = rhc->conds; i < ncheck; i++, rciter = rciter->m_next)
|
||||||
assert (cond_match_count[i] == ddsrt_atomic_ld32 (&rciter->m_entity.m_status.m_trigger));
|
assert (cond_match_count[i] == ddsrt_atomic_ld32 (&rciter->m_entity.m_status.m_trigger));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rhc->n_nonempty_instances == 0)
|
if (rhc->n_nonempty_instances == 0)
|
||||||
{
|
{
|
||||||
assert (rhc->nonempty_instances == NULL);
|
assert (ddsrt_circlist_isempty (&rhc->nonempty_instances));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct rhc_instance *prev, *end;
|
assert (!ddsrt_circlist_isempty (&rhc->nonempty_instances));
|
||||||
assert (rhc->nonempty_instances != NULL);
|
struct ddsrt_circlist_elem const *prev = rhc->nonempty_instances.latest->prev;
|
||||||
prev = rhc->nonempty_instances->prev;
|
inst = latest_nonempty_instance (rhc);
|
||||||
end = rhc->nonempty_instances;
|
struct rhc_instance const * const end = inst;
|
||||||
inst = rhc->nonempty_instances;
|
|
||||||
n_nonempty_instances = 0;
|
n_nonempty_instances = 0;
|
||||||
do {
|
do {
|
||||||
assert (!inst_is_empty (inst));
|
assert (!inst_is_empty (inst));
|
||||||
assert (prev->next == inst);
|
assert (prev->next == &inst->nonempty_list);
|
||||||
assert (inst->prev == prev);
|
assert (inst->nonempty_list.prev == prev);
|
||||||
prev = inst;
|
prev = &inst->nonempty_list;
|
||||||
inst = inst->next;
|
inst = next_nonempty_instance (inst);
|
||||||
n_nonempty_instances++;
|
n_nonempty_instances++;
|
||||||
} while (inst != end);
|
} while (inst != end);
|
||||||
assert (rhc->n_nonempty_instances == n_nonempty_instances);
|
assert (rhc->n_nonempty_instances == n_nonempty_instances);
|
||||||
|
|
|
@ -101,6 +101,10 @@ set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||||
set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||||
|
|
||||||
list(APPEND headers
|
list(APPEND headers
|
||||||
|
"${include_path}/dds/ddsrt/avl.h"
|
||||||
|
"${include_path}/dds/ddsrt/fibheap.h"
|
||||||
|
"${include_path}/dds/ddsrt/hopscotch.h"
|
||||||
|
"${include_path}/dds/ddsrt/thread_pool.h"
|
||||||
"${include_path}/dds/ddsrt/log.h"
|
"${include_path}/dds/ddsrt/log.h"
|
||||||
"${include_path}/dds/ddsrt/retcode.h"
|
"${include_path}/dds/ddsrt/retcode.h"
|
||||||
"${include_path}/dds/ddsrt/attributes.h"
|
"${include_path}/dds/ddsrt/attributes.h"
|
||||||
|
@ -113,7 +117,8 @@ list(APPEND headers
|
||||||
"${include_path}/dds/ddsrt/strtol.h"
|
"${include_path}/dds/ddsrt/strtol.h"
|
||||||
"${include_path}/dds/ddsrt/types.h"
|
"${include_path}/dds/ddsrt/types.h"
|
||||||
"${include_path}/dds/ddsrt/countargs.h"
|
"${include_path}/dds/ddsrt/countargs.h"
|
||||||
"${include_path}/dds/ddsrt/static_assert.h")
|
"${include_path}/dds/ddsrt/static_assert.h"
|
||||||
|
"${include_path}/dds/ddsrt/circlist.h")
|
||||||
|
|
||||||
list(APPEND sources
|
list(APPEND sources
|
||||||
"${source_path}/bswap.c"
|
"${source_path}/bswap.c"
|
||||||
|
@ -121,21 +126,14 @@ list(APPEND sources
|
||||||
"${source_path}/log.c"
|
"${source_path}/log.c"
|
||||||
"${source_path}/retcode.c"
|
"${source_path}/retcode.c"
|
||||||
"${source_path}/strtod.c"
|
"${source_path}/strtod.c"
|
||||||
"${source_path}/strtol.c")
|
"${source_path}/strtol.c"
|
||||||
|
|
||||||
list(APPEND headers
|
|
||||||
"${include_path}/dds/ddsrt/avl.h"
|
|
||||||
"${include_path}/dds/ddsrt/fibheap.h"
|
|
||||||
"${include_path}/dds/ddsrt/hopscotch.h"
|
|
||||||
"${include_path}/dds/ddsrt/thread_pool.h")
|
|
||||||
|
|
||||||
list(APPEND sources
|
|
||||||
"${source_path}/avl.c"
|
"${source_path}/avl.c"
|
||||||
"${source_path}/expand_envvars.c"
|
"${source_path}/expand_envvars.c"
|
||||||
"${source_path}/fibheap.c"
|
"${source_path}/fibheap.c"
|
||||||
"${source_path}/hopscotch.c"
|
"${source_path}/hopscotch.c"
|
||||||
"${source_path}/thread_pool.c"
|
"${source_path}/thread_pool.c"
|
||||||
"${source_path}/xmlparser.c")
|
"${source_path}/xmlparser.c"
|
||||||
|
"${source_path}/circlist.c")
|
||||||
|
|
||||||
# Not every target offers the same set of features. For embedded targets the
|
# Not every target offers the same set of features. For embedded targets the
|
||||||
# set of features may even be different between builds. e.g. a FreeRTOS build
|
# set of features may even be different between builds. e.g. a FreeRTOS build
|
||||||
|
|
43
src/ddsrt/include/dds/ddsrt/circlist.h
Normal file
43
src/ddsrt/include/dds/ddsrt/circlist.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 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 DDSRT_CIRCLIST_H
|
||||||
|
#define DDSRT_CIRCLIST_H
|
||||||
|
|
||||||
|
/* Circular doubly linked list implementation */
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "dds/export.h"
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DDSRT_FROM_CIRCLIST(typ_, member_, cle_) ((typ_ *) ((char *) (cle_) - offsetof (typ_, member_)))
|
||||||
|
|
||||||
|
struct ddsrt_circlist {
|
||||||
|
struct ddsrt_circlist_elem *latest; /* pointer to latest inserted element */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ddsrt_circlist_elem {
|
||||||
|
struct ddsrt_circlist_elem *next;
|
||||||
|
struct ddsrt_circlist_elem *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
DDS_EXPORT void ddsrt_circlist_init (struct ddsrt_circlist *list);
|
||||||
|
DDS_EXPORT bool ddsrt_circlist_isempty (const struct ddsrt_circlist *list);
|
||||||
|
DDS_EXPORT void ddsrt_circlist_append (struct ddsrt_circlist *list, struct ddsrt_circlist_elem *elem);
|
||||||
|
DDS_EXPORT void ddsrt_circlist_remove (struct ddsrt_circlist *list, struct ddsrt_circlist_elem *elem);
|
||||||
|
DDS_EXPORT struct ddsrt_circlist_elem *ddsrt_circlist_oldest (const struct ddsrt_circlist *list);
|
||||||
|
DDS_EXPORT struct ddsrt_circlist_elem *ddsrt_circlist_latest (const struct ddsrt_circlist *list);
|
||||||
|
|
||||||
|
#endif /* DDSRT_CIRCLIST_H */
|
84
src/ddsrt/src/circlist.c
Normal file
84
src/ddsrt/src/circlist.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 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 <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "dds/ddsrt/circlist.h"
|
||||||
|
|
||||||
|
void ddsrt_circlist_init (struct ddsrt_circlist *list)
|
||||||
|
{
|
||||||
|
list->latest = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ddsrt_circlist_isempty (const struct ddsrt_circlist *list)
|
||||||
|
{
|
||||||
|
return list->latest == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ddsrt_circlist_append (struct ddsrt_circlist *list, struct ddsrt_circlist_elem *elem)
|
||||||
|
{
|
||||||
|
if (list->latest == NULL)
|
||||||
|
elem->next = elem->prev = elem;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct ddsrt_circlist_elem * const hd = list->latest;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
{
|
||||||
|
const struct ddsrt_circlist_elem *x = hd;
|
||||||
|
do { assert (x != elem); x = x->next; } while (x != hd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
elem->next = hd->next;
|
||||||
|
elem->prev = hd;
|
||||||
|
hd->next = elem;
|
||||||
|
elem->next->prev = elem;
|
||||||
|
}
|
||||||
|
list->latest = elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ddsrt_circlist_remove (struct ddsrt_circlist *list, struct ddsrt_circlist_elem *elem)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
{
|
||||||
|
const struct ddsrt_circlist_elem *x = list->latest;
|
||||||
|
assert (x);
|
||||||
|
do { if (x == elem) break; x = x->next; } while (x != list->latest);
|
||||||
|
assert (x == elem);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (elem->next == elem)
|
||||||
|
list->latest = NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct ddsrt_circlist_elem * const elem_prev = elem->prev;
|
||||||
|
struct ddsrt_circlist_elem * const elem_next = elem->next;
|
||||||
|
elem_prev->next = elem_next;
|
||||||
|
elem_next->prev = elem_prev;
|
||||||
|
if (list->latest == elem)
|
||||||
|
list->latest = elem_prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ddsrt_circlist_elem *ddsrt_circlist_oldest (const struct ddsrt_circlist *list)
|
||||||
|
{
|
||||||
|
assert (!ddsrt_circlist_isempty (list));
|
||||||
|
return list->latest->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ddsrt_circlist_elem *ddsrt_circlist_latest (const struct ddsrt_circlist *list)
|
||||||
|
{
|
||||||
|
assert (!ddsrt_circlist_isempty (list));
|
||||||
|
return list->latest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue