This is an automated email from the ASF dual-hosted git repository.

astitcher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git

commit 2ccfe74438ba283428a22a251e80bf25f6060457
Author: Andrew Stitcher <[email protected]>
AuthorDate: Fri Mar 6 17:01:12 2026 -0500

    PROTON-1442: [C++] Implement iterator for unsettled transfers
    
    This returns an iterator for all unsettled transfers on a link.
    
    Used to access transfers within a transaction or left unsettled after
    one has failed.
    
    This code was written with the assistance of Cursor.
---
 cpp/include/proton/delivery.hpp | 23 +++++++++++++++++++++++
 cpp/include/proton/receiver.hpp |  9 +++++++--
 cpp/include/proton/sender.hpp   | 10 +++++++---
 cpp/include/proton/session.hpp  |  4 ++--
 cpp/include/proton/tracker.hpp  | 23 +++++++++++++++++++++++
 cpp/src/delivery.cpp            | 10 ++++++++++
 cpp/src/link.cpp                |  4 ----
 cpp/src/receiver.cpp            |  7 +++++++
 cpp/src/sender.cpp              |  5 +++++
 cpp/src/tracker.cpp             | 10 ++++++++++
 cpp/src/transfer.cpp            |  3 +--
 11 files changed, 95 insertions(+), 13 deletions(-)

diff --git a/cpp/include/proton/delivery.hpp b/cpp/include/proton/delivery.hpp
index 4c4ac030e..f60ea5438 100644
--- a/cpp/include/proton/delivery.hpp
+++ b/cpp/include/proton/delivery.hpp
@@ -23,6 +23,7 @@
  */
 
 #include "./binary.hpp"
+#include "./endpoint.hpp"
 #include "./fwd.hpp"
 #include "./internal/export.hpp"
 #include "./internal/object.hpp"
@@ -70,9 +71,31 @@ class delivery : public transfer {
 
     /// @cond INTERNAL
   friend class internal::factory<delivery>;
+  friend class receiver;
     /// @endcond
 };
 
+/// @cond INTERNAL
+
+/// An iterator of unsettled deliveries on a receiver.
+class delivery_iterator : public internal::iter_base<delivery, 
delivery_iterator> {
+  delivery_iterator(delivery d) :
+      internal::iter_base<delivery, delivery_iterator>(d) {}
+
+public:
+  explicit delivery_iterator() :
+      internal::iter_base<delivery, delivery_iterator>(delivery()) {}
+  /// Advance to the next unsettled delivery.
+  PN_CPP_EXTERN delivery_iterator operator++();
+
+  friend class receiver;
+};
+
+/// A range of unsettled deliveries.
+typedef internal::iter_range<delivery_iterator> delivery_range;
+
+/// @endcond
+
 } // proton
 
 #endif // PROTON_DELIVERY_HPP
diff --git a/cpp/include/proton/receiver.hpp b/cpp/include/proton/receiver.hpp
index 353f1d269..8c58cadd1 100644
--- a/cpp/include/proton/receiver.hpp
+++ b/cpp/include/proton/receiver.hpp
@@ -22,6 +22,7 @@
  *
  */
 
+#include "./delivery.hpp"
 #include "./fwd.hpp"
 #include "./internal/export.hpp"
 #include "./link.hpp"
@@ -76,6 +77,10 @@ PN_CPP_CLASS_EXTERN receiver : public link {
     /// outstanding drained credit reaches zero.
     PN_CPP_EXTERN void drain();
 
+    /// **Unsettled API** - Get a range of unsettled deliveries on this 
receiver.
+    /// Settled deliveries are not included.
+    PN_CPP_EXTERN delivery_range unsettled_deliveries() const;
+
     /// @cond INTERNAL
   friend class internal::factory<receiver>;
   friend class receiver_iterator;
@@ -86,13 +91,13 @@ PN_CPP_CLASS_EXTERN receiver : public link {
 
 /// An iterator of receivers.
 class receiver_iterator : public internal::iter_base<receiver, 
receiver_iterator> {
-    explicit receiver_iterator(receiver r, pn_session_t* s = 0) :
+    explicit receiver_iterator(receiver r, pn_session_t* s = nullptr) :
         internal::iter_base<receiver, receiver_iterator>(r), session_(s) {}
 
   public:
     /// Create an iterator of receivers.
     explicit receiver_iterator() :
-        internal::iter_base<receiver, receiver_iterator>(0), session_(0) {}
+        internal::iter_base<receiver, receiver_iterator>(nullptr), 
session_(nullptr) {}
 
     /// Advance to the next receiver.
     PN_CPP_EXTERN receiver_iterator operator++();
diff --git a/cpp/include/proton/sender.hpp b/cpp/include/proton/sender.hpp
index 59fd74bd4..7118ad780 100644
--- a/cpp/include/proton/sender.hpp
+++ b/cpp/include/proton/sender.hpp
@@ -72,6 +72,10 @@ PN_CPP_CLASS_EXTERN sender : public link {
     /// @see receiver::drain
     PN_CPP_EXTERN void return_credit();
 
+    /// **Unsettled API** - Get a range of unsettled trackers on this sender.
+    /// Settled trackers are not included.
+    PN_CPP_EXTERN tracker_range unsettled_trackers() const;
+
     /// @cond INTERNAL
     friend class internal::factory<sender>;
     friend class sender_iterator;
@@ -87,13 +91,13 @@ PN_CPP_CLASS_EXTERN sender : public link {
 
 /// An iterator of senders.
 class sender_iterator : public internal::iter_base<sender, sender_iterator> {
-    sender_iterator(sender snd, pn_session_t* s = 0) :
+    sender_iterator(sender snd, pn_session_t* s = nullptr) :
         internal::iter_base<sender, sender_iterator>(snd), session_(s) {}
 
   public:
     /// Create an iterator of senders.
-    sender_iterator() :
-        internal::iter_base<sender, sender_iterator>(0), session_(0) {}
+    explicit sender_iterator() :
+        internal::iter_base<sender, sender_iterator>(nullptr), 
session_(nullptr) {}
     /// Advance to the next sender.
     PN_CPP_EXTERN sender_iterator operator++();
 
diff --git a/cpp/include/proton/session.hpp b/cpp/include/proton/session.hpp
index 60522c817..ea7d3bbc1 100644
--- a/cpp/include/proton/session.hpp
+++ b/cpp/include/proton/session.hpp
@@ -115,8 +115,8 @@ PN_CPP_CLASS_EXTERN session : public 
internal::object<pn_session_t>, public endp
     
 /// An iterator of sessions.
 class session_iterator : public internal::iter_base<session, session_iterator> 
{
- public:
-    explicit session_iterator(session s = 0) : internal::iter_base<session, 
session_iterator>(s) {}
+  public:
+    explicit session_iterator(session s = nullptr) : 
internal::iter_base<session, session_iterator>(s) {}
 
     /// Advance to the next session.
     PN_CPP_EXTERN session_iterator operator++();
diff --git a/cpp/include/proton/tracker.hpp b/cpp/include/proton/tracker.hpp
index 3d8ad0aab..0c5efef27 100644
--- a/cpp/include/proton/tracker.hpp
+++ b/cpp/include/proton/tracker.hpp
@@ -23,6 +23,7 @@
  */
 
 #include "./binary.hpp"
+#include "./endpoint.hpp"
 #include "./internal/export.hpp"
 #include "./transfer.hpp"
 
@@ -55,9 +56,31 @@ class tracker : public transfer {
 
     /// @cond INTERNAL
   friend class internal::factory<tracker>;
+  friend class sender;
     /// @endcond
 };
 
+/// @cond INTERNAL
+
+/// An iterator of unsettled trackers on a sender.
+class tracker_iterator : public internal::iter_base<tracker, tracker_iterator> 
{
+  tracker_iterator(tracker t) :
+      internal::iter_base<tracker, tracker_iterator>(t) {}
+
+public:
+  explicit tracker_iterator() :
+      internal::iter_base<tracker, tracker_iterator>(tracker()) {}
+  /// Advance to the next unsettled tracker.
+  PN_CPP_EXTERN tracker_iterator operator++();
+
+  friend class sender;
+};
+
+/// A range of unsettled trackers.
+typedef internal::iter_range<tracker_iterator> tracker_range;
+
+/// @endcond
+
 } // proton
 
 #endif // PROTON_TRACKER_HPP
diff --git a/cpp/src/delivery.cpp b/cpp/src/delivery.cpp
index 9f03eaf73..654f50a36 100644
--- a/cpp/src/delivery.cpp
+++ b/cpp/src/delivery.cpp
@@ -26,6 +26,8 @@
 #include "proton_bits.hpp"
 
 #include <proton/delivery.h>
+#include <proton/disposition.h>
+#include <proton/link.h>
 
 #include "types_internal.hpp"
 
@@ -51,4 +53,12 @@ void delivery::reject() { settle_delivery(pn_object(), 
REJECTED); }
 void delivery::release() { settle_delivery(pn_object(), RELEASED); }
 void delivery::modify() { 
pn_disposition_set_failed(pn_delivery_local(pn_object()), true); 
settle_delivery(pn_object(), MODIFIED); }
 
+delivery_iterator delivery_iterator::operator++() {
+    if (!!obj_) {
+        pn_delivery_t* next = pn_unsettled_next(unwrap(obj_));
+        obj_ = make_wrapper<delivery>(next);
+    }
+    return *this;
+}
+
 }
diff --git a/cpp/src/link.cpp b/cpp/src/link.cpp
index c6f58f48d..6d28081ac 100644
--- a/cpp/src/link.cpp
+++ b/cpp/src/link.cpp
@@ -19,11 +19,8 @@
  *
  */
 
-#include "proton_bits.hpp"
-
 #include "proton/codec/map.hpp"
 #include "proton/link.hpp"
-#include "proton/error.hpp"
 #include "proton/connection.hpp"
 
 #include <proton/connection.h>
@@ -31,7 +28,6 @@
 #include <proton/link.h>
 
 #include "contexts.hpp"
-#include "msg.hpp"
 #include "proton_bits.hpp"
 
 namespace proton {
diff --git a/cpp/src/receiver.cpp b/cpp/src/receiver.cpp
index 9f3c77062..97cafa475 100644
--- a/cpp/src/receiver.cpp
+++ b/cpp/src/receiver.cpp
@@ -19,6 +19,7 @@
  *
  */
 #include "proton/receiver.hpp"
+#include "proton/delivery.hpp"
 
 #include "proton/error.hpp"
 #include "proton/link.hpp"
@@ -33,6 +34,7 @@
 #include <proton/connection.h>
 #include <proton/session.h>
 #include <proton/link.h>
+#include <proton/delivery.h>
 #include <proton/event.h>
 
 namespace proton {
@@ -83,6 +85,11 @@ void receiver::drain() {
     }
 }
 
+delivery_range receiver::unsettled_deliveries() const {
+    pn_delivery_t* d = pn_unsettled_head(pn_object());
+    return delivery_range(delivery_iterator(make_wrapper<delivery>(d)));
+}
+
 receiver_iterator receiver_iterator::operator++() {
     if (!!obj_) {
         pn_link_t *lnk = pn_link_next(obj_.pn_object(), 0);
diff --git a/cpp/src/sender.cpp b/cpp/src/sender.cpp
index 942e755b0..8b3942bfe 100644
--- a/cpp/src/sender.cpp
+++ b/cpp/src/sender.cpp
@@ -87,6 +87,11 @@ tracker sender::send(const message &message, const binary 
&tag) {
     return track;
 }
 
+tracker_range sender::unsettled_trackers() const {
+    pn_delivery_t* d = pn_unsettled_head(pn_object());
+    return tracker_range(tracker_iterator(make_wrapper<tracker>(d)));
+}
+
 void sender::return_credit() {
     link_context &lctx = link_context::get(pn_object());
     lctx.draining = false;
diff --git a/cpp/src/tracker.cpp b/cpp/src/tracker.cpp
index e703767ef..3f4db11aa 100644
--- a/cpp/src/tracker.cpp
+++ b/cpp/src/tracker.cpp
@@ -28,10 +28,20 @@
 #include "proton/binary.hpp"
 
 #include <proton/delivery.h>
+#include <proton/link.h>
 
 namespace proton {
 
 tracker::tracker(pn_delivery_t *d): transfer(make_wrapper(d)) {}
 sender tracker::sender() const { return make_wrapper<class 
sender>(pn_delivery_link(pn_object())); }
 binary tracker::tag() const { return bin(pn_delivery_tag(pn_object())); }
+
+tracker_iterator tracker_iterator::operator++() {
+    if (!!obj_) {
+        pn_delivery_t* next = pn_unsettled_next(unwrap(obj_));
+        obj_ = make_wrapper<tracker>(next);
+    }
+    return *this;
+}
+
 }
diff --git a/cpp/src/transfer.cpp b/cpp/src/transfer.cpp
index 063254267..5fdf34ecd 100644
--- a/cpp/src/transfer.cpp
+++ b/cpp/src/transfer.cpp
@@ -19,10 +19,9 @@
  *
  */
 
-#include "proton/delivery.hpp"
+#include "proton/transfer.hpp"
 
 #include "proton/connection.hpp"
-#include "proton/link.hpp"
 #include "proton/session.hpp"
 
 #include <proton/delivery.h>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to