Add evict functionalty to mq cancellation.
authorFlorian Dold <florian.dold@gmail.com>
Sun, 16 Oct 2016 19:13:45 +0000 (19:13 +0000)
committerFlorian Dold <florian.dold@gmail.com>
Sun, 16 Oct 2016 19:13:45 +0000 (19:13 +0000)
Useful to avoid copying of buffers when canceling a
partially sent message.

src/include/gnunet_mq_lib.h
src/util/mq.c

index 08434698e053935d22892eeea7ad26462a8f72b5..b339fe0ebc78501df080653ea0634a9b59aac21a 100644 (file)
@@ -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.
index 7c13265d8834229ccd20ec871e80b01d09b5202f..6978f662b5ee416ed552b0db9b07d1d523166e57 100644 (file)
@@ -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 */