Internal change
PiperOrigin-RevId: 506982474
This commit is contained in:
		
							parent
							
								
									046efddf8b
								
							
						
					
					
						commit
						01834a5cdf
					
				| 
						 | 
					@ -242,6 +242,8 @@ class Packet : public Packet<internal::Generic> {
 | 
				
			||||||
  friend Packet<U> PacketAdopting(const U* ptr);
 | 
					  friend Packet<U> PacketAdopting(const U* ptr);
 | 
				
			||||||
  template <typename U>
 | 
					  template <typename U>
 | 
				
			||||||
  friend Packet<U> PacketAdopting(std::unique_ptr<U> ptr);
 | 
					  friend Packet<U> PacketAdopting(std::unique_ptr<U> ptr);
 | 
				
			||||||
 | 
					  template <typename U>
 | 
				
			||||||
 | 
					  friend Packet<U> PacketSharingOwnership(std::shared_ptr<const U> ptr);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace internal {
 | 
					namespace internal {
 | 
				
			||||||
| 
						 | 
					@ -464,6 +466,17 @@ Packet<T> PacketAdopting(std::unique_ptr<T> ptr) {
 | 
				
			||||||
  return Packet<T>(std::make_shared<packet_internal::Holder<T>>(ptr.release()));
 | 
					  return Packet<T>(std::make_shared<packet_internal::Holder<T>>(ptr.release()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					Packet<T> PacketSharingOwnership(std::shared_ptr<const T> ptr) {
 | 
				
			||||||
 | 
					  return Packet<T>(
 | 
				
			||||||
 | 
					      std::make_shared<packet_internal::ForeignHolder<T>>(std::move(ptr)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					std::shared_ptr<const T> SharedPtrWithPacket(Packet<T> packet) {
 | 
				
			||||||
 | 
					  return mediapipe::SharedPtrWithPacket<T>(std::move(packet));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api2
 | 
					}  // namespace api2
 | 
				
			||||||
}  // namespace mediapipe
 | 
					}  // namespace mediapipe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -162,6 +162,21 @@ TEST(PacketTest, PacketAdopting) {
 | 
				
			||||||
  EXPECT_FALSE(p.IsEmpty());
 | 
					  EXPECT_FALSE(p.IsEmpty());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(PacketTest, PacketSharingOwnership) {
 | 
				
			||||||
 | 
					  bool deleted = false;
 | 
				
			||||||
 | 
					  std::shared_ptr<const int> object(new int(42), [&deleted](const int* p) {
 | 
				
			||||||
 | 
					    delete p;
 | 
				
			||||||
 | 
					    deleted = true;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  Packet<int> p = PacketSharingOwnership(object);
 | 
				
			||||||
 | 
					  EXPECT_FALSE(p.IsEmpty());
 | 
				
			||||||
 | 
					  EXPECT_EQ(p.Get(), 42);
 | 
				
			||||||
 | 
					  object = nullptr;
 | 
				
			||||||
 | 
					  EXPECT_FALSE(deleted);  // Packet keeps it alive.
 | 
				
			||||||
 | 
					  p = {};
 | 
				
			||||||
 | 
					  ASSERT_TRUE(deleted);  // last owner expired.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(PacketTest, PacketGeneric) {
 | 
					TEST(PacketTest, PacketGeneric) {
 | 
				
			||||||
  // With C++17, Packet<> could be written simply as Packet.
 | 
					  // With C++17, Packet<> could be written simply as Packet.
 | 
				
			||||||
  Packet<> p = PacketAdopting(new float(1.0));
 | 
					  Packet<> p = PacketAdopting(new float(1.0));
 | 
				
			||||||
| 
						 | 
					@ -281,6 +296,24 @@ TEST(PacketTest, PolymorphismAbstract) {
 | 
				
			||||||
  EXPECT_EQ(base->name(), "ConcreteDerived");
 | 
					  EXPECT_EQ(base->name(), "ConcreteDerived");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(PacketTest, ShareSubobjectOwnership) {
 | 
				
			||||||
 | 
					  // Create a packet that contains a vector and tracks deletion.
 | 
				
			||||||
 | 
					  bool deleted = false;
 | 
				
			||||||
 | 
					  std::shared_ptr<const std::vector<int>> ints(new std::vector<int>{0, 1, 2, 3},
 | 
				
			||||||
 | 
					                                               [&deleted](std::vector<int>* p) {
 | 
				
			||||||
 | 
					                                                 delete p;
 | 
				
			||||||
 | 
					                                                 deleted = true;
 | 
				
			||||||
 | 
					                                               });
 | 
				
			||||||
 | 
					  auto vector_packet = PacketSharingOwnership(std::move(ints));
 | 
				
			||||||
 | 
					  // Create a packet that references one of the items in the vector.
 | 
				
			||||||
 | 
					  Packet<int> item_packet = PacketSharingOwnership(std::shared_ptr<const int>(
 | 
				
			||||||
 | 
					      SharedPtrWithPacket(vector_packet), &vector_packet.Get()[1]));
 | 
				
			||||||
 | 
					  vector_packet = {};
 | 
				
			||||||
 | 
					  ASSERT_FALSE(deleted);  // item_packet keeps it alive
 | 
				
			||||||
 | 
					  item_packet = {};
 | 
				
			||||||
 | 
					  ASSERT_TRUE(deleted);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace
 | 
					}  // namespace
 | 
				
			||||||
}  // namespace api2
 | 
					}  // namespace api2
 | 
				
			||||||
}  // namespace mediapipe
 | 
					}  // namespace mediapipe
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,6 +242,12 @@ Packet Adopt(const T* ptr);
 | 
				
			||||||
// returned Packet but also all of its copies. The timestamp of the returned
 | 
					// returned Packet but also all of its copies. The timestamp of the returned
 | 
				
			||||||
// Packet is Timestamp::Unset(). To set the timestamp, the caller should do
 | 
					// Packet is Timestamp::Unset(). To set the timestamp, the caller should do
 | 
				
			||||||
// PointToForeign(...).At(...).
 | 
					// PointToForeign(...).At(...).
 | 
				
			||||||
 | 
					// TODO: deprecate PointToForeign in favor of
 | 
				
			||||||
 | 
					// MakePacketSharingOwnership. Currently, we have to provide two separate
 | 
				
			||||||
 | 
					// implementations for handling static array vs. non static array types as
 | 
				
			||||||
 | 
					// the shared_ptr does not work with static array for backward compatibility.
 | 
				
			||||||
 | 
					// Eventually we should encourage the clients to deprecate the usage of these
 | 
				
			||||||
 | 
					// functions.
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
Packet PointToForeign(const T* ptr);
 | 
					Packet PointToForeign(const T* ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -324,6 +330,17 @@ Packet MakePacket(Args&&... args) {  // NOLINT(build/c++11)
 | 
				
			||||||
      new T{std::forward<typename std::remove_extent<T>::type>(args)...}));
 | 
					      new T{std::forward<typename std::remove_extent<T>::type>(args)...}));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns a Packet that shares ownership of its data. The packet will hold a
 | 
				
			||||||
 | 
					// reference to the provided shared_ptr throughout its lifetime. Since the
 | 
				
			||||||
 | 
					// payload of packets is expected to be immutable, the caller MUST ensure that
 | 
				
			||||||
 | 
					// the data does not change as long as the Packet is alive.
 | 
				
			||||||
 | 
					// Unlike PointToForeign, which takes a raw pointer, this allows the caller to
 | 
				
			||||||
 | 
					// know when MediaPipe (as well as any other owners) is done using the data.
 | 
				
			||||||
 | 
					// The timestamp of the returned Packet is Timestamp::Unset(). To set the
 | 
				
			||||||
 | 
					// timestamp, the caller should do MakePacketSharingOwnership(...).At(...).
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					Packet MakePacketSharingOwnership(std::shared_ptr<const T> ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Returns a mutable pointer to the data in a unique_ptr in a packet. This
 | 
					// Returns a mutable pointer to the data in a unique_ptr in a packet. This
 | 
				
			||||||
// is useful in combination with AdoptAsUniquePtr.  The caller must
 | 
					// is useful in combination with AdoptAsUniquePtr.  The caller must
 | 
				
			||||||
// exercise caution when mutating the retrieved data, since the data
 | 
					// exercise caution when mutating the retrieved data, since the data
 | 
				
			||||||
| 
						 | 
					@ -579,11 +596,14 @@ class Holder : public HolderBase {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Like Holder, but does not own its data.
 | 
					// Like Holder, but does not exclusively own its data.
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
class ForeignHolder : public Holder<T> {
 | 
					class ForeignHolder : public Holder<T> {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  using Holder<T>::Holder;
 | 
					  explicit ForeignHolder(std::shared_ptr<const T> ptr)
 | 
				
			||||||
 | 
					      : Holder<T>(reinterpret_cast<const T*>(ptr.get())),
 | 
				
			||||||
 | 
					        owner_(std::move(ptr)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ~ForeignHolder() override {
 | 
					  ~ForeignHolder() override {
 | 
				
			||||||
    // Null out ptr_ so it doesn't get deleted by ~Holder.
 | 
					    // Null out ptr_ so it doesn't get deleted by ~Holder.
 | 
				
			||||||
    // Note that ~Holder cannot call HasForeignOwner because the subclass's
 | 
					    // Note that ~Holder cannot call HasForeignOwner because the subclass's
 | 
				
			||||||
| 
						 | 
					@ -591,6 +611,9 @@ class ForeignHolder : public Holder<T> {
 | 
				
			||||||
    this->ptr_ = nullptr;
 | 
					    this->ptr_ = nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  bool HasForeignOwner() const final { return true; }
 | 
					  bool HasForeignOwner() const final { return true; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  const std::shared_ptr<const T> owner_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
| 
						 | 
					@ -768,7 +791,22 @@ Packet Adopt(const T* ptr) {
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
Packet PointToForeign(const T* ptr) {
 | 
					Packet PointToForeign(const T* ptr) {
 | 
				
			||||||
  CHECK(ptr != nullptr);
 | 
					  CHECK(ptr != nullptr);
 | 
				
			||||||
  return packet_internal::Create(new packet_internal::ForeignHolder<T>(ptr));
 | 
					  using U = typename std::shared_ptr<T>::element_type;
 | 
				
			||||||
 | 
					  // The reinterpret_cast is required here and in the ForeignHolder constructor
 | 
				
			||||||
 | 
					  // in order to handle the type decay introduced by the shared_ptr for the
 | 
				
			||||||
 | 
					  // statically allocated array.
 | 
				
			||||||
 | 
					  return packet_internal::Create(new packet_internal::ForeignHolder<T>(
 | 
				
			||||||
 | 
					      std::shared_ptr<const T>(reinterpret_cast<const U*>(ptr), [](const U*) {
 | 
				
			||||||
 | 
					        // Note: PointToForeign does not own its data in any way, so
 | 
				
			||||||
 | 
					        // the deleter does nothing.
 | 
				
			||||||
 | 
					      })));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					Packet MakePacketSharingOwnership(std::shared_ptr<const T> ptr) {
 | 
				
			||||||
 | 
					  CHECK(ptr != nullptr);
 | 
				
			||||||
 | 
					  return packet_internal::Create(
 | 
				
			||||||
 | 
					      new packet_internal::ForeignHolder<T>(std::move(ptr)));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Equal Packets refer to the same memory contents, like equal pointers.
 | 
					// Equal Packets refer to the same memory contents, like equal pointers.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "mediapipe/framework/packet.h"
 | 
					#include "mediapipe/framework/packet.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
#include <map>
 | 
					#include <map>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
| 
						 | 
					@ -262,6 +263,68 @@ TEST(PacketTest, MakePacketOfIntVector) {
 | 
				
			||||||
            vector_packet2.Get<std::vector<int>>());
 | 
					            vector_packet2.Get<std::vector<int>>());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(PacketTest, MakePacketSharingOwnership) {
 | 
				
			||||||
 | 
					  bool deleted = false;
 | 
				
			||||||
 | 
					  std::shared_ptr<const int> object(new int(42), [&deleted](const int* p) {
 | 
				
			||||||
 | 
					    delete p;
 | 
				
			||||||
 | 
					    deleted = true;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  Packet packet = MakePacketSharingOwnership(object);
 | 
				
			||||||
 | 
					  MP_ASSERT_OK(packet.ValidateAsType<int>());
 | 
				
			||||||
 | 
					  EXPECT_EQ(packet.Get<int>(), 42);
 | 
				
			||||||
 | 
					  EXPECT_FALSE(deleted);
 | 
				
			||||||
 | 
					  object = nullptr;
 | 
				
			||||||
 | 
					  EXPECT_FALSE(deleted);  // Packet keeps it alive.
 | 
				
			||||||
 | 
					  packet = {};
 | 
				
			||||||
 | 
					  EXPECT_TRUE(deleted);  // last owner expired.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(PacketTest, ShareSubobjectOwnership) {
 | 
				
			||||||
 | 
					  // Create a packet that contains a vector and tracks deletion.
 | 
				
			||||||
 | 
					  bool deleted = false;
 | 
				
			||||||
 | 
					  std::shared_ptr<const std::vector<int>> ints(new std::vector<int>{0, 1, 2, 3},
 | 
				
			||||||
 | 
					                                               [&deleted](std::vector<int>* p) {
 | 
				
			||||||
 | 
					                                                 delete p;
 | 
				
			||||||
 | 
					                                                 deleted = true;
 | 
				
			||||||
 | 
					                                               });
 | 
				
			||||||
 | 
					  Packet vector_packet = MakePacketSharingOwnership(std::move(ints));
 | 
				
			||||||
 | 
					  // Create a packet that references one of the items in the vector.
 | 
				
			||||||
 | 
					  Packet item_packet = MakePacketSharingOwnership(std::shared_ptr<const int>(
 | 
				
			||||||
 | 
					      SharedPtrWithPacket<std::vector<int>>(vector_packet),
 | 
				
			||||||
 | 
					      &vector_packet.Get<std::vector<int>>()[1]));
 | 
				
			||||||
 | 
					  vector_packet = {};
 | 
				
			||||||
 | 
					  ASSERT_FALSE(deleted);  // item_packet keeps it alive
 | 
				
			||||||
 | 
					  item_packet = {};
 | 
				
			||||||
 | 
					  ASSERT_TRUE(deleted);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(PacketTest, PointToForeignDynamicArray) {
 | 
				
			||||||
 | 
					  int* input_translation = new int[2];
 | 
				
			||||||
 | 
					  input_translation[0] = 0;
 | 
				
			||||||
 | 
					  input_translation[1] = 1;
 | 
				
			||||||
 | 
					  Packet packet = PointToForeign(&input_translation);
 | 
				
			||||||
 | 
					  const auto& content = packet.Get<int*>();
 | 
				
			||||||
 | 
					  // The packet content should point to the array.
 | 
				
			||||||
 | 
					  EXPECT_EQ(content[0], 0);
 | 
				
			||||||
 | 
					  EXPECT_EQ(content[1], 1);
 | 
				
			||||||
 | 
					  packet = {};
 | 
				
			||||||
 | 
					  // The vector values should be unaffected.
 | 
				
			||||||
 | 
					  EXPECT_EQ(input_translation[0], 0);
 | 
				
			||||||
 | 
					  EXPECT_EQ(input_translation[1], 1);
 | 
				
			||||||
 | 
					  delete[] input_translation;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(PacketTest, PointToForeignStaticArray) {
 | 
				
			||||||
 | 
					  const int input_translation[] = {0, 1};
 | 
				
			||||||
 | 
					  auto packet = PointToForeign(&input_translation);
 | 
				
			||||||
 | 
					  const auto& content = packet.Get<int[2]>();
 | 
				
			||||||
 | 
					  // The packet content should point to the array.
 | 
				
			||||||
 | 
					  EXPECT_THAT(content, testing::ElementsAre(0, 1));
 | 
				
			||||||
 | 
					  packet = {};
 | 
				
			||||||
 | 
					  // The vector values should be unaffected.
 | 
				
			||||||
 | 
					  EXPECT_THAT(input_translation, testing::ElementsAre(0, 1));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(PacketTest, TestPacketMoveConstructor) {
 | 
					TEST(PacketTest, TestPacketMoveConstructor) {
 | 
				
			||||||
  std::vector<Packet>* packet_vector_ptr = new std::vector<Packet>();
 | 
					  std::vector<Packet>* packet_vector_ptr = new std::vector<Packet>();
 | 
				
			||||||
  packet_vector_ptr->push_back(MakePacket<float>(42));
 | 
					  packet_vector_ptr->push_back(MakePacket<float>(42));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user