aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--include/qpdf/PointerHolder.hh20
-rw-r--r--libtests/pointer_holder.cc16
-rw-r--r--libtests/qtest/ph/ph.out12
4 files changed, 58 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 337b197d..77c63419 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2022-02-04 Jay Berkenbilt <ejb@ql.org>
+
+ * PointerHolder: add a get() method and a use_count() method for
+ compatibility with std::shared_ptr. In qpdf 11, qpdf's APIs will
+ switch to using std::shared_ptr instead of PointerHolder, though
+ there will be a PointerHolder class with a backward-compatible
+ API. To ease the transition, we are adding get() now with the same
+ semantics as std::shared_ptr's get. Note that there is a
+ difference in behavior: const PointerHolder has always behaved
+ incorrectly. const PointerHolder objects only returned const
+ pointers. This is wrong. If you want a const pointer, use
+ PointerHolder<T const>. A const PointerHolder just shouldn't allow
+ its pointer to be reassigned. The new get() method behaves
+ correctly in that calling get() on a const PointerHolder to a
+ non-const pointer returns a non-const pointer. This is the way
+ regular pointers behave.
+
2022-02-01 Jay Berkenbilt <ejb@ql.org>
* Major refactor: all functionality from the qpdf CLI is now
diff --git a/include/qpdf/PointerHolder.hh b/include/qpdf/PointerHolder.hh
index a85df8bb..bc60f7f0 100644
--- a/include/qpdf/PointerHolder.hh
+++ b/include/qpdf/PointerHolder.hh
@@ -22,6 +22,14 @@
#ifndef POINTERHOLDER_HH
#define POINTERHOLDER_HH
+// In qpdf 11, PointerHolder will be derived from std::shared_ptr and
+// will also include a fix to incorrect semantics of const
+// PointerHolder objects. PointerHolder only allows a const
+// PointerHolder to return a const pointer. This is wrong. Use a
+// PointerHolder<const T> for that. A const PointerHolder should just
+// not allow you to change what it points to. This is consistent with
+// how regular pointers and standard library shared pointers work.
+
// This class is basically std::shared_ptr but predates that by
// several years.
@@ -119,6 +127,12 @@ class PointerHolder
return this->data->pointer < rhs.data->pointer;
}
+ // get() is for interface compatibility with std::shared_ptr
+ T* get() const
+ {
+ return this->data->pointer;
+ }
+
// NOTE: The pointer returned by getPointer turns into a pumpkin
// when the last PointerHolder that contains it disappears.
T* getPointer()
@@ -134,6 +148,12 @@ class PointerHolder
return this->data->refcount;
}
+ // use_count() is for compatibility with std::shared_ptr
+ long use_count()
+ {
+ return static_cast<long>(this->data->refcount);
+ }
+
T const& operator*() const
{
return *this->data->pointer;
diff --git a/libtests/pointer_holder.cc b/libtests/pointer_holder.cc
index 469bfc21..913449e4 100644
--- a/libtests/pointer_holder.cc
+++ b/libtests/pointer_holder.cc
@@ -4,8 +4,6 @@
#include <stdlib.h>
#include <list>
-#include <qpdf/QUtil.hh>
-
class Object
{
public:
@@ -47,13 +45,20 @@ Object::hello() const
typedef PointerHolder<Object> ObjectHolder;
-void callHello(ObjectHolder const& oh)
+void callHello(ObjectHolder& oh)
{
oh.getPointer()->hello();
oh->hello();
(*oh).hello();
}
+void callHelloWithGet(ObjectHolder const& oh)
+{
+ oh.get()->hello();
+ oh->hello();
+ (*oh).hello();
+}
+
int main(int argc, char* argv[])
{
std::list<ObjectHolder> ol1;
@@ -66,7 +71,7 @@ int main(int argc, char* argv[])
std::cout << "oh1 refcount = " << oh1.getRefcount() << std::endl;
ObjectHolder oh2(oh1);
std::cout << "oh1 refcount = " << oh1.getRefcount() << std::endl;
- std::cout << "oh2 refcount = " << oh2.getRefcount() << std::endl;
+ std::cout << "oh2 refcount = " << oh2.use_count() << std::endl;
ObjectHolder oh3(new Object);
ObjectHolder oh4;
ObjectHolder oh5;
@@ -89,12 +94,15 @@ int main(int argc, char* argv[])
ol1.push_back(oh3);
Object* o3 = new Object;
oh0 = o3;
+ PointerHolder<Object const> oh6(new Object());
+ oh6->hello();
}
ol1.front().getPointer()->hello();
ol1.front()->hello();
(*ol1.front()).hello();
callHello(ol1.front());
+ callHelloWithGet(ol1.front());
ol1.pop_front();
std::cout << "array" << std::endl;
PointerHolder<Object> oarr1_ph(true, new Object[2]);
diff --git a/libtests/qtest/ph/ph.out b/libtests/qtest/ph/ph.out
index 5d249712..a7efe1bb 100644
--- a/libtests/qtest/ph/ph.out
+++ b/libtests/qtest/ph/ph.out
@@ -10,17 +10,23 @@ destroyed Object, id 2
equal okay
less than okay
created Object, id 3
+created Object, id 4
+calling Object::hello const for 4
+destroyed Object, id 4
+calling Object::hello for 1
+calling Object::hello for 1
+calling Object::hello for 1
+calling Object::hello for 1
calling Object::hello for 1
calling Object::hello for 1
calling Object::hello for 1
-calling Object::hello const for 1
calling Object::hello const for 1
calling Object::hello const for 1
array
-created Object, id 4
created Object, id 5
+created Object, id 6
goodbye
+destroyed Object, id 6
destroyed Object, id 5
-destroyed Object, id 4
destroyed Object, id 3
destroyed Object, id 1