From bc57c1cebf65b9d10c97961cc0cd8a7bf166d76e Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sun, 16 Oct 2016 19:13:45 +0000 Subject: Add evict functionalty to mq cancellation. Useful to avoid copying of buffers when canceling a partially sent message. --- src/include/gnunet_mq_lib.h | 18 ++++++++++++++++++ src/util/mq.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_mq_lib.h b/src/include/gnunet_mq_lib.h index 08434698e..b339fe0eb 100644 --- a/src/include/gnunet_mq_lib.h +++ b/src/include/gnunet_mq_lib.h @@ -725,6 +725,24 @@ const struct GNUNET_MessageHeader * GNUNET_MQ_impl_current (struct GNUNET_MQ_Handle *mq); +/** + * Get the message that is currently being sent when cancellation of that + * message is requested. Returns an opaque pointer which contains the memory + * for the message, as well as some control data used by mq. + * + * This function may be called at most once in the cancel_impl + * function of a message queue. + * + * Use this function to avoid copying a half-sent message. + * + * @param mq message queue + * @parem msg pointer to store the message being canceled + * @return memory block that contains the message, must be freed by the caller + */ +void * +GNUNET_MQ_impl_cancel_evict (struct GNUNET_MQ_Handle *mq, struct GNUNET_MessageHeader **msg); + + /** * Get the implementation state associated with the * message queue. diff --git a/src/util/mq.c b/src/util/mq.c index 7c13265d8..6978f662b 100644 --- a/src/util/mq.c +++ b/src/util/mq.c @@ -82,7 +82,6 @@ struct GNUNET_MQ_Envelope * Did the application call #GNUNET_MQ_env_set_options()? */ int have_custom_options; - }; @@ -187,6 +186,11 @@ struct GNUNET_MQ_Handle * Number of entries we have in the envelope-DLL. */ unsigned int queue_length; + + /** + * GNUNET_YES if GNUNET_MQ_impl_evict was called. + */ + int evict_called; }; @@ -1105,6 +1109,8 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev) GNUNET_assert (NULL != mq); GNUNET_assert (NULL != mq->cancel_impl); + + mq->evict_called = GNUNET_NO; if (mq->current_envelope == ev) { @@ -1140,9 +1146,12 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev) mq->queue_length--; } - ev->parent_queue = NULL; - ev->mh = NULL; - GNUNET_free (ev); + if (GNUNET_YES != mq->evict_called) + { + ev->parent_queue = NULL; + ev->mh = NULL; + GNUNET_free (ev); + } } @@ -1285,4 +1294,31 @@ GNUNET_MQ_destroy_notify_cancel (struct GNUNET_MQ_DestroyNotificationHandle *dnh } +/** + * Get the message that is currently being sent when cancellation of that + * message is requested. Returns an opaque pointer which contains the memory + * for the message, as well as some control data used by mq. + * + * This function may be called at most once in the cancel_impl + * function of a message queue. + * + * Use this function to avoid copying a half-sent message. + * + * @param mq message queue + * @parem msg pointer to store the message being canceled + * @return memory block that contains the message, must be freed by the caller + */ +void * +GNUNET_MQ_impl_cancel_evict (struct GNUNET_MQ_Handle *mq, struct GNUNET_MessageHeader **msg) +{ + GNUNET_assert (GNUNET_NO == mq->evict_called); + GNUNET_assert (NULL != mq->current_envelope); + mq->evict_called = GNUNET_YES; + mq->current_envelope->parent_queue = NULL; + mq->current_envelope->mh = NULL; + *msg = mq->current_envelope->mh; + return mq->current_envelope; +} + + /* end of mq.c */ -- cgit v1.2.3