cpp-common/bt2: add `bt2::ConstMessageArray`
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 26 Oct 2023 14:43:05 +0000 (10:43 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Thu, 14 Dec 2023 15:57:04 +0000 (10:57 -0500)
commit736675a469fd4522ecea7af9075eae04e6196c88
tree2d87ba00a0f57aae949348f01af38d39ed36191d
parent762ca3c07c754ccf8cc2c9ca5051a865d0d66a3e
cpp-common/bt2: add `bt2::ConstMessageArray`

A `bt2::ConstMessageArray` instance wraps an array of `const` messages
(`bt_message_array_const`) which is used in everything related to "next"
message iterator methods.

There are two ways to build such a wrapper:

1. Use bt2::ConstMessageArray::wrapExisting() to wrap an existing
   library message array with a given length:

       bt_message_array_const libMsgs;
       uint64_t count;

       if (bt_message_iterator_next(myIter, &libMsgs, &count) !=
               BT_MESSAGE_ITERATOR_NEXT_STATUS_OK) {
           // Handle special status
       }

       const auto msgs = bt2::ConstMessageArray::wrapExisting(libMsgs,
                                                              count);

       ⭐

       if (!msgs[0].isEvent()) {
           // ...
       }

       for (const auto msg : msgs) {
           // Handle `msg`
       }

   At ⭐, `msgs` is now the owner of the messages of `libMsgs`,
   meaning:

   a) Its destructor puts all the contained message references.

   b) Do NOT put the message references of `libMsgs` yourself with
      bt_message_put_ref().

   c) Do NOT make another `ConstMessageArray` wrap `libMsgs`.

2. Use bt2::ConstMessageArray::wrapEmpty() to wrap an empty library
   message array with an explicit capacity:

       bt_message_iterator_class_next_method_status myNext(
               bt_self_message_iterator * const libSelfMsgIter,
               const bt_message_array_const libMsgs,
               const uint64_t capacity, uint64_t * const count)
       {
           auto msgs = bt2::ConstMessageArray::wrapEmpty(libMsgs,
                                                         capacity);

           // Create messages and append with `msgs.append(...)`

           *count = msgs.release();
           return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
       }

   If there's any thrown exception during the message appending part,
   the destructor of `msgs` will put the references of its messages.

   Then when you call ConstMessageArray::release(), you become the owner
   of the library array again. The returned value is its length before
   the release.

As you can see, this wrapper is a bit fragile and really on the "you
know what you're doing" territory, but I believe it can be useful and
safer when used as intended.

Conceptually, only one `ConstMessageArray` at a time may manage the
underlying library array. Therefore, copy operations are disabled, but
move operations are implemented.

Because the copy constructor isn't implemented, we can't use
`CommonIterator`, so `ConstMessageArrayIterator` is a dedicated,
lightweight version of the latter.

Get a message array length and capacity with the length() and
capacity() methods.

Check if a message array is empty or full with the isEmpty() and
isFull() methods.

Append a message to a message array with the append() method.

Release a message array with the release() method.

Borrow a message from a message array with the `[]` operator.

Iterate a message array with the begin() and end() methods.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: Iac8bea4195836f6f0d157eb08bec27b3d24ca506
Reviewed-on: https://review.lttng.org/c/babeltrace/+/11146
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Simon Marchi <simon.marchi@efficios.com>
CI-Build: Simon Marchi <simon.marchi@efficios.com>
src/Makefile.am
src/cpp-common/bt2/message-array.hpp [new file with mode: 0644]
This page took 0.026373 seconds and 4 git commands to generate.