Commit c7e877b88b7e0c9a4608e16df777ded5dd8f6593

Authored by Jay Berkenbilt
1 parent ef2b84c6

Update documentation for PointerHolder transition

README-maintainer
@@ -160,11 +160,16 @@ CODING RULES @@ -160,11 +160,16 @@ CODING RULES
160 it seems also for classes that are intended to be subclassed across 160 it seems also for classes that are intended to be subclassed across
161 the shared library boundary. 161 the shared library boundary.
162 162
163 -* Put private member variables in PointerHolder<Members> for all 163 +* Put private member variables in std::shared_ptr<Members> for all
164 public classes. Remember to use QPDF_DLL on ~Members(). Exception: 164 public classes. Remember to use QPDF_DLL on ~Members(). Exception:
165 - indirection through PointerHolder<Members> is expensive, so don't do  
166 - it for classes that are copied a lot, like QPDFObjectHandle and  
167 - QPDFObject. 165 + indirection through std::shared_ptr<Members> is expensive, so don't
  166 + do it for classes that are copied a lot, like QPDFObjectHandle and
  167 + QPDFObject. It may be possible to declare
  168 + std::shared_ptr<Members> m_ph;
  169 + Member* m;
  170 + with m = m_ph.get(), and then indirect through m in
  171 + performance-critical settings, though in 2022, std::shared_ptr is
  172 + sufficiently performant that this may not be worth it.
168 173
169 * Traversal of objects is expensive. It's worth adding some complexity 174 * Traversal of objects is expensive. It's worth adding some complexity
170 to avoid needless traversals of objects. 175 to avoid needless traversals of objects.
@@ -5,8 +5,7 @@ Next @@ -5,8 +5,7 @@ Next
5 * At next release, hide release-qpdf-10.6.3.0cmake* versions at readthedocs 5 * At next release, hide release-qpdf-10.6.3.0cmake* versions at readthedocs
6 6
7 In order: 7 In order:
8 -* cmake  
9 -* PointerHolder -> shared_ptr 8 +* cmake -- remaining steps
10 * ABI including --json default is latest 9 * ABI including --json default is latest
11 * json v2 10 * json v2
12 11
@@ -29,9 +28,6 @@ Misc @@ -29,9 +28,6 @@ Misc
29 --show-encryption could potentially retry with this option if the 28 --show-encryption could potentially retry with this option if the
30 first time doesn't work. Then, with the file open, we can read the 29 first time doesn't work. Then, with the file open, we can read the
31 encryption dictionary normally. 30 encryption dictionary normally.
32 -* Go through README-maintainer "CODING RULES" and update --  
33 - PointerHolder and other changes will make some of the rules  
34 - obsolete.  
35 * Have a warn in QPDF that passes its variable arguments onto QPDFExc 31 * Have a warn in QPDF that passes its variable arguments onto QPDFExc
36 so you don't have to do warn(QPDFExc(...)) 32 so you don't have to do warn(QPDFExc(...))
37 33
@@ -57,6 +53,7 @@ cmake @@ -57,6 +53,7 @@ cmake
57 QPDF_DLL are public because QPDF_DLL_LOCAL makes the other things 53 QPDF_DLL are public because QPDF_DLL_LOCAL makes the other things
58 private. See https://gcc.gnu.org/wiki/Visibility. Make sure this 54 private. See https://gcc.gnu.org/wiki/Visibility. Make sure this
59 is documented. 55 is documented.
  56 + * Update "CODING RULES" in "README-maintainer" - search for QPDF_DLL
60 * Nice to have: 57 * Nice to have:
61 * Split qpdf.test into multiple tests 58 * Split qpdf.test into multiple tests
62 * Rework tests so that nothing is written into the source directory. 59 * Rework tests so that nothing is written into the source directory.
@@ -500,103 +497,6 @@ Other notes: @@ -500,103 +497,6 @@ Other notes:
500 way that works for the qpdf/qpdf repository as well since they are 497 way that works for the qpdf/qpdf repository as well since they are
501 very similar. 498 very similar.
502 499
503 -PointerHolder to std::shared_ptr  
504 -================================  
505 -  
506 -To perform update:  
507 -  
508 -Cherry-pick pointerholder branch commit  
509 -  
510 -Upgrade just the library. This is not necessary, but it's an added  
511 -check that the compatibility code works since it will show that tests,  
512 -examples, and CLI will work properly with the upgraded APIs, which  
513 -provides some assurance that other people will have a smooth time with  
514 -their code.  
515 -  
516 -patrepl s/PointerHolder/std::shared_ptr/g {include,libqpdf}/qpdf/*.hh  
517 -patrepl s/PointerHolder/std::shared_ptr/g libqpdf/*.cc  
518 -patrepl s/make_pointer_holder/std::make_shared/g libqpdf/*.cc  
519 -patrepl s/make_array_pointer_holder/QUtil::make_shared_array/g libqpdf/*.cc  
520 -patrepl s,qpdf/std::shared_ptr,qpdf/PointerHolder, **/*.cc **/*.hh  
521 -git restore include/qpdf/PointerHolder.hh  
522 -cleanpatch  
523 -  
524 -Increase to POINTERHOLDER_TRANSITION=3  
525 -  
526 -make build_libqpdf -- no errors  
527 -  
528 -Drop back to POINTERHOLDER_TRANSITION=2  
529 -  
530 -make check -- everything passes  
531 -  
532 -Then upgrade everything else. It would work to just start here.  
533 -  
534 -Increase to POINTERHOLDER_TRANSITION=3  
535 -  
536 -patrepl s/PointerHolder/std::shared_ptr/g **/*.cc **/*.hh  
537 -patrepl s/make_pointer_holder/std::make_shared/g **/*.cc  
538 -patrepl s/make_array_pointer_holder/QUtil::make_shared_array/g **/*.cc  
539 -patrepl s,qpdf/std::shared_ptr,qpdf/PointerHolder, **/*.cc **/*.hh  
540 -git restore include/qpdf/PointerHolder.hh  
541 -git restore libtests/pointer_holder.cc  
542 -cleanpatch  
543 -  
544 -Remove all references to PointerHolder.hh from everything except  
545 -public headers and pointer_holder.cc.  
546 -  
547 -make check -- everything passes  
548 -  
549 -Increase to POINTERHOLDER_TRANSITION=4  
550 -  
551 -Do a clean build and make check -- everything passes  
552 -  
553 -Final steps:  
554 -  
555 -* Change to POINTERHOLDER_TRANSITION=4  
556 -* Check code formatting  
557 -* std::shared_ptr<Members> m can be replaced with  
558 - std::shared_ptr<Members> m_ph and Members* m if performance is critical  
559 -* Could try Members indirection with Members* for QPDFObjectHandle  
560 -  
561 -When done:  
562 -  
563 -* Update the smart-pointers section of the manual in design.rst  
564 -* Update comments in PointerHolder.hh  
565 -  
566 -PointerHolder in public API:  
567 -  
568 - PointerHolder<Buffer> Pl_Buffer::getBufferSharedPointer();  
569 - PointerHolder<Buffer> QPDFWriter::getBufferSharedPointer();  
570 - QUtil::read_file_into_memory(  
571 - char const*, PointerHolder<char>&, unsigned long&)  
572 - QPDFObjectHandle::addContentTokenFilter(  
573 - PointerHolder<QPDFObjectHandle::TokenFilter>)  
574 - QPDFObjectHandle::addTokenFilter(  
575 - PointerHolder<QPDFObjectHandle::TokenFilter>)  
576 - QPDFObjectHandle::newStream(  
577 - QPDF*, PointerHolder<Buffer>)  
578 - QPDFObjectHandle::parse(  
579 - PointerHolder<InputSource>, std::string const&,  
580 - QPDFTokenizer&, bool&, QPDFObjectHandle::StringDecrypter*, QPDF*)  
581 - QPDFObjectHandle::replaceStreamData(  
582 - PointerHolder<Buffer>, QPDFObjectHandle const&,  
583 - QPDFObjectHandle const&)  
584 - QPDFObjectHandle::replaceStreamData(  
585 - PointerHolder<QPDFObjectHandle::StreamDataProvider>,  
586 - QPDFObjectHandle const&, QPDFObjectHandle const&)  
587 - QPDFTokenizer::expectInlineImage(  
588 - PointerHolder<InputSource>)  
589 - QPDFTokenizer::readToken(  
590 - PointerHolder<InputSource>, std::string const&,  
591 - bool, unsigned long)  
592 - QPDF::processInputSource(  
593 - PointerHolder<InputSource>, char const*)  
594 - QPDFWriter::registerProgressReporter(  
595 - PointerHolder<QPDFWriter::ProgressReporter>)  
596 - QPDFEFStreamObjectHelper::createEFStream(  
597 - QPDF&, PointerHolder<Buffer>)  
598 - QPDFPageObjectHelper::addContentTokenFilter(  
599 - PointerHolder<QPDFObjectHandle::TokenFilter>)  
600 500
601 ABI Changes 501 ABI Changes
602 =========== 502 ===========
manual/design.rst
@@ -53,13 +53,11 @@ or not if this information is needed. All access to objects deals with @@ -53,13 +53,11 @@ or not if this information is needed. All access to objects deals with
53 this transparently. All memory management details are also handled by 53 this transparently. All memory management details are also handled by
54 the library. 54 the library.
55 55
56 -The ``PointerHolder`` object is used internally by the library to deal  
57 -with memory management. This is basically a smart pointer object very  
58 -similar in spirit to C++-11's ``std::shared_ptr`` object, but predating  
59 -it by several years. This library also makes use of a technique for  
60 -giving fine-grained access to methods in one class to other classes by  
61 -using public subclasses with friends and only private members that in  
62 -turn call private methods of the containing class. See 56 +Memory is managed mostly with ``std::shared_ptr`` object to minimize
  57 +explicit memory handling. This library also makes use of a technique
  58 +for giving fine-grained access to methods in one class to other
  59 +classes by using public subclasses with friends and only private
  60 +members that in turn call private methods of the containing class. See
63 ``QPDFObjectHandle::Factory`` as an example. 61 ``QPDFObjectHandle::Factory`` as an example.
64 62
65 The top-level qpdf class is ``QPDF``. A ``QPDF`` object represents a PDF 63 The top-level qpdf class is ``QPDF``. A ``QPDF`` object represents a PDF
@@ -68,13 +66,14 @@ files. @@ -68,13 +66,14 @@ files.
68 66
69 The primary class for interacting with PDF objects is 67 The primary class for interacting with PDF objects is
70 ``QPDFObjectHandle``. Instances of this class can be passed around by 68 ``QPDFObjectHandle``. Instances of this class can be passed around by
71 -value, copied, stored in containers, etc. with very low overhead.  
72 -Instances of ``QPDFObjectHandle`` created by reading from a file will  
73 -always contain a reference back to the ``QPDF`` object from which they  
74 -were created. A ``QPDFObjectHandle`` may be direct or indirect. If  
75 -indirect, the ``QPDFObject`` the ``PointerHolder`` initially points to  
76 -is a null pointer. In this case, the first attempt to access the  
77 -underlying ``QPDFObject`` will result in the ``QPDFObject`` being 69 +value, copied, stored in containers, etc. with very low overhead. The
  70 +``QPDFObjectHandle`` object contains an internal shared pointer to an
  71 +underyling ``QPDFObject``. Instances of ``QPDFObjectHandle`` created
  72 +by reading from a file will always contain a reference back to the
  73 +``QPDF`` object from which they were created. A ``QPDFObjectHandle``
  74 +may be direct or indirect. If indirect, the ``QPDFObject`` shared
  75 +pointer is initially null. In this case, the first attempt to access
  76 +the underlying ``QPDFObject`` will result in the ``QPDFObject`` being
78 resolved via a call to the referenced ``QPDF`` instance. This makes it 77 resolved via a call to the referenced ``QPDF`` instance. This makes it
79 essentially impossible to make coding errors in which certain things 78 essentially impossible to make coding errors in which certain things
80 will work for some PDF files and not for others based on which objects 79 will work for some PDF files and not for others based on which objects
@@ -248,17 +247,18 @@ During this process, the &quot;``R``&quot; keyword is recognized and an indirect @@ -248,17 +247,18 @@ During this process, the &quot;``R``&quot; keyword is recognized and an indirect
248 247
249 The ``QPDF::resolve()`` method, which is used to resolve an indirect 248 The ``QPDF::resolve()`` method, which is used to resolve an indirect
250 object, may be invoked from the ``QPDFObjectHandle`` class. It first 249 object, may be invoked from the ``QPDFObjectHandle`` class. It first
251 -checks a cache to see whether this object has already been read. If not,  
252 -it reads the object from the PDF file and caches it. It the returns the  
253 -resulting ``QPDFObjectHandle``. The calling object handle then replaces  
254 -its ``PointerHolder<QDFObject>`` with the one from the newly returned  
255 -``QPDFObjectHandle``. In this way, only a single copy of any direct  
256 -object need exist and clients can access objects transparently without  
257 -knowing or caring whether they are direct or indirect objects.  
258 -Additionally, no object is ever read from the file more than once. That  
259 -means that only the portions of the PDF file that are actually needed  
260 -are ever read from the input file, thus allowing the qpdf package to  
261 -take advantage of this important design goal of PDF files. 250 +checks a cache to see whether this object has already been read. If
  251 +not, it reads the object from the PDF file and caches it. It the
  252 +returns the resulting ``QPDFObjectHandle``. The calling object handle
  253 +then replaces its ``std::shared_ptr<QDFObject>`` with the one from the
  254 +newly returned ``QPDFObjectHandle``. In this way, only a single copy
  255 +of any direct object need exist and clients can access objects
  256 +transparently without knowing or caring whether they are direct or
  257 +indirect objects. Additionally, no object is ever read from the file
  258 +more than once. That means that only the portions of the PDF file that
  259 +are actually needed are ever read from the input file, thus allowing
  260 +the qpdf package to take advantage of this important design goal of
  261 +PDF files.
262 262
263 If the requested object is inside of an object stream, the object stream 263 If the requested object is inside of an object stream, the object stream
264 itself is first read into memory. Then the tokenizer reads objects from 264 itself is first read into memory. Then the tokenizer reads objects from
@@ -762,40 +762,47 @@ Smart Pointers @@ -762,40 +762,47 @@ Smart Pointers
762 -------------- 762 --------------
763 763
764 This section describes changes to the use of smart pointers that were 764 This section describes changes to the use of smart pointers that were
765 -made in qpdf 10.6.0 as well as some planned for 11.0.0. 765 +made in qpdf 10.6.0 and 11.0.0.
766 766
767 -Starting in qpdf 11, ``PointerHolder`` will be replaced with 767 +In qpdf 11.0.0, ``PointerHolder`` was replaced with
768 ``std::shared_ptr`` in qpdf's public API. A backward-compatible 768 ``std::shared_ptr`` in qpdf's public API. A backward-compatible
769 -``PointerHolder`` class will be provided that should make it possible  
770 -for most code to remain unchanged. ``PointerHolder`` may eventually be 769 +``PointerHolder`` class has been provided that makes it possible for
  770 +most code to remain unchanged. ``PointerHolder`` may eventually be
771 removed from qpdf entirely, but this will not happen for a while to 771 removed from qpdf entirely, but this will not happen for a while to
772 make it easier for people who need to support multiple versions of 772 make it easier for people who need to support multiple versions of
773 qpdf. 773 qpdf.
774 774
775 -The ``POINTERHOLDER_TRANSITION`` preprocessor symbol has been  
776 -introduced to help people transition from ``PointerHolder`` to  
777 -``std::shared_ptr``. After qpdf 11 is released, to prepare for a  
778 -future qpdf without ``PointerHolder`` and to let them know that it is  
779 -no longer needed, a warning will be issued if  
780 -``<qpdf/PointerHolder.hh>`` is included, though it will be possible to  
781 -suppress the warning by defining ``POINTERHOLDER_TRANSITION``. In  
782 -10.6.0, there are some steps you can perform to prepare, but no action  
783 -is required. 775 +In 10.6.0, some enhancements were made to ``PointerHolder`` to ease
  776 +the transition. These intermediate steps are relevant only for
  777 +versions 10.6.0 through 10.6.3 but can still help with incremental
  778 +modification of code.
784 779
785 -The remainder of this section describes how to prepare if you want to  
786 -eliminate ``PointerHolder`` from your code or what to do if you want  
787 -to stick with the old interfaces. 780 +The ``POINTERHOLDER_TRANSITION`` preprocessor symbol was introduced in
  781 +qpdf 10.6.0 to help people transition from ``PointerHolder`` to
  782 +``std::shared_ptr``. If you don't define this, you will get a compiler
  783 +warning. Defining it to any value will suppress the warning. An
  784 +explanation appears below of the different possible values for this
  785 +symbol and what they mean.
788 786
789 -Changes in 10.6.0  
790 -~~~~~~~~~~~~~~~~~ 787 +Starting in qpdf 11.0.0, including ``<qpdf/PointerHolder.hh>`` defines
  788 +the symbol ``POINTERHOLDER_IS_SHARED_POINTER``. This can be used with
  789 +conditional compilation to make it possible to support different
  790 +versions of qpdf.
791 791
792 -In qpdf 10.6.0, the following changes have been made to  
793 -``PointerHolder`` to make its behavior closer to that of  
794 -``std::shared_ptr``: 792 +The rest of this section provides the details.
795 793
796 -- ``get()`` has been added as an alternative to ``getPointer()`` 794 +Transitional Enhancements to PointerHolder
  795 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
797 796
798 -- ``use_count()`` has been added as an alternative to ``getRefcount()`` 797 +In qpdf 10.6.0, some changes were to ``PointerHolder`` to make it
  798 +easier to prepare for the transition to ``std::shared_ptr``. These
  799 +enhancements also make it easier to incrementally upgrade your code.
  800 +The following changes were made to ``PointerHolder`` to make its
  801 +behavior closer to that of ``std::shared_ptr``:
  802 +
  803 +- ``get()`` was added as an alternative to ``getPointer()``
  804 +
  805 +- ``use_count()`` was added as an alternative to ``getRefcount()``
799 806
800 - A new global helper function ``make_pointer_holder`` behaves 807 - A new global helper function ``make_pointer_holder`` behaves
801 similarly to ``std::make_shared``, so you can use 808 similarly to ``std::make_shared``, so you can use
@@ -807,7 +814,7 @@ In qpdf 10.6.0, the following changes have been made to @@ -807,7 +814,7 @@ In qpdf 10.6.0, the following changes have been made to
807 counterpart to the newly added ``QUtil::make_shared_array`` method, 814 counterpart to the newly added ``QUtil::make_shared_array`` method,
808 which does the same thing with a ``std::shared_ptr``. 815 which does the same thing with a ``std::shared_ptr``.
809 816
810 -``PointerHolder`` has had a long-standing bug: a ``const 817 +``PointerHolder`` had a long-standing bug: a ``const
811 PointerHolder<T>`` would only provide a ``T const*`` with its 818 PointerHolder<T>`` would only provide a ``T const*`` with its
812 ``getPointer`` method. This is incorrect and is not how standard 819 ``getPointer`` method. This is incorrect and is not how standard
813 library C++ smart pointers or regular pointers behave. The correct 820 library C++ smart pointers or regular pointers behave. The correct
@@ -873,16 +880,23 @@ preprocessor symbol or other C++ coding techniques. @@ -873,16 +880,23 @@ preprocessor symbol or other C++ coding techniques.
873 pointer. It also has the seldom-used ``getRefcount()`` method to get 880 pointer. It also has the seldom-used ``getRefcount()`` method to get
874 the reference count. ``std::shared_ptr<T>`` has ``get()`` and 881 the reference count. ``std::shared_ptr<T>`` has ``get()`` and
875 ``use_count()``. In qpdf 10.6, ``PointerHolder<T>`` also has 882 ``use_count()``. In qpdf 10.6, ``PointerHolder<T>`` also has
876 - would not be an issue unless you did this in your own code. 883 + ``get()`` and ``use_count()``.
877 884
878 Addressing the Differences 885 Addressing the Differences
879 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 886 ~~~~~~~~~~~~~~~~~~~~~~~~~~
880 887
881 -If you need to support versions of qpdf prior to qpdf 10.6, you don't  
882 -*need* to take any action at this time, but it is recommended that you  
883 -at least address the implicit constructor issue since this can be done  
884 -without breaking backward compatibility. (Explicit construction of  
885 -``PointerHolder<T>`` is and always has been allowed.) 888 +If you are not ready to take action yet, you can ``#define
  889 +POINTERHOLDER_TRANSITION 0`` before including any qpdf header file or
  890 +add the definition of that symbol to your build. This will provide the
  891 +backward-compatible ``PointerHolder`` API without any deprecation
  892 +warnings. This should be a temporary measure as ``PointerHolder`` may
  893 +disappear in the future. If you need to be able to support newer and
  894 +older versions of qpdf, there are other options, explained below.
  895 +
  896 +Note that, even with ``0``, you should rebuild and test your code.
  897 +There may be compiler errors if you have containers of
  898 +``PointerHolder``, but most code should compile without any changes.
  899 +There are no uses of containers of ``PointerHolder`` in qpdf's API.
886 900
887 There are two significant things you can do to minimize the impact of 901 There are two significant things you can do to minimize the impact of
888 switching from ``PointerHolder`` to ``std::shared_ptr``: 902 switching from ``PointerHolder`` to ``std::shared_ptr``:
@@ -908,31 +922,35 @@ without consulting this manual. @@ -908,31 +922,35 @@ without consulting this manual.
908 - meaning 922 - meaning
909 923
910 - - undefined 924 - - undefined
911 - - Same as ``0``, but starting with qpdf 11.0, issues a warning 925 + - Same as ``0`` but issues a warning
912 926
913 - - ``0`` 927 - - ``0``
914 - Provide a backward compatible ``PointerHolder`` and suppress 928 - Provide a backward compatible ``PointerHolder`` and suppress
915 - all deprecation warnings 929 + all deprecation warnings; supports all prior qpdf versions
916 930
917 - - ``1`` 931 - - ``1``
918 - - Make the ``PointerHolder<T>(T*)`` constructor explicit 932 + - Make the ``PointerHolder<T>(T*)`` constructor explicit;
  933 + resulting code supports all prior qpdf versions
919 934
920 - - ``2`` 935 - - ``2``
921 - - Deprecate ``getPointer()`` and ``getRefcount()`` 936 + - Deprecate ``getPointer()`` and ``getRefcount()``; requires
  937 + qpdf 10.6.0 or later.
922 938
923 - - ``3`` 939 - - ``3``
924 - - Starting with qpdf 11.0, deprecate all uses of ``PointerHolder`` 940 + - Deprecate all uses of ``PointerHolder``; requires qpdf 11.0.0
  941 + or later
925 942
926 - - ``4`` 943 - - ``4``
927 - - Starting with qpdf 11.0, disable all functionality from  
928 - ``qpdf/PointerHolder.hh`` so that ``#include``-ing it has no  
929 - effect. 944 + - Disable all functionality from ``qpdf/PointerHolder.hh`` so
  945 + that ``#include``-ing it has no effect other than defining
  946 + ``POINTERHOLDER_IS_SHARED_POINTER``; requires qpdf 11.0.0 or
  947 + later.
930 948
931 Based on the above, here is a procedure for preparing your code. This 949 Based on the above, here is a procedure for preparing your code. This
932 is the procedure that was used for the qpdf code itself. 950 is the procedure that was used for the qpdf code itself.
933 951
934 -If you need to support versions of qpdf prior to 10.6, you can still  
935 -do these steps: 952 +You can do these steps without breaking support for qpdf versions
  953 +before 10.6.0:
936 954
937 - Find all occurrences of ``PointerHolder`` in the code. See whether 955 - Find all occurrences of ``PointerHolder`` in the code. See whether
938 any of them can just be outright replaced with ``std::shared_ptr`` 956 any of them can just be outright replaced with ``std::shared_ptr``
@@ -974,8 +992,9 @@ do these steps: @@ -974,8 +992,9 @@ do these steps:
974 auto p = std::unique_ptr<X[]>(new X[n]); 992 auto p = std::unique_ptr<X[]>(new X[n]);
975 993
976 - If a ``PointerHolder<T>`` can't be replaced with a standard library 994 - If a ``PointerHolder<T>`` can't be replaced with a standard library
977 - smart pointer, perhaps it can be declared using ``auto`` or  
978 - ``decltype`` so that, when the qpdf API changes, your code will just 995 + smart pointer because it is used with an older qpdf API call,
  996 + perhaps it can be declared using ``auto`` or ``decltype`` so that,
  997 + when building with a newer qpdf API changes, your code will just
979 need to be recompiled. 998 need to be recompiled.
980 999
981 - ``#define POINTERHOLDER_TRANSITION 1`` to enable deprecation 1000 - ``#define POINTERHOLDER_TRANSITION 1`` to enable deprecation
@@ -1000,55 +1019,18 @@ do these steps: @@ -1000,55 +1019,18 @@ do these steps:
1000 Other examples appear above. 1019 Other examples appear above.
1001 1020
1002 If you need to support older versions of qpdf than 10.6, this is as 1021 If you need to support older versions of qpdf than 10.6, this is as
1003 -far as you can go until qpdf 11 comes out.  
1004 -  
1005 -If you only need to support the latest version of qpdf, proceed as  
1006 -follows:  
1007 -  
1008 -- ``#define POINTERHOLDER_TRANSITION 2`` to enable deprecation of  
1009 - ``getPointer()`` and ``getRefcount()``  
1010 -  
1011 -- Replace ``getPointer()`` with ``get()`` and ``getRefcount()`` with  
1012 - ``use_count()``. These methods were not present prior to 10.6.0. 1022 +far as you can go without conditional compilation.
1013 1023
1014 -When you have gotten your code to compile cleanly with  
1015 -``POINTERHOLDER_TRANSITION=2``, you are well on your way to being  
1016 -ready for eliminating ``PointerHolder`` entirely after qpdf 11 is  
1017 -released.  
1018 -  
1019 -After qpdf 11 is out  
1020 -~~~~~~~~~~~~~~~~~~~~  
1021 -  
1022 -In the 10.6 manual, this section represents a plan and is subject to  
1023 -change. However, it has been tested in practice using a version of the  
1024 -qpdf 11 ``PointerHolder`` on a branch, so it is likely to be accurate.  
1025 -In the meantime, think of this as a preview.  
1026 -  
1027 -First, make sure you have done the steps in the 10.6 section. (Note:  
1028 -once qpdf 11 comes out, the goal is to not have to migrate to 10.6  
1029 -first, so it is likely that these sections will be combined.)  
1030 -  
1031 -If you are explicitly choosing to stick with the backward compatible  
1032 -``PointerHolder`` for now, you should define  
1033 -``POINTERHOLDER_TRANSITION`` to ``0`` to suppress the warning from  
1034 -including ``qpdf/PointerHolder.hh``. Be aware that you may eventually  
1035 -have to deal with the transition, though the intention is to leave the  
1036 -compatibility layer in place for a while. You should rebuild and test  
1037 -your code. There may be compiler errors if you have containers of  
1038 -``PointerHolder``, but most code should compile without any changes.  
1039 -Even if you have errors, use of ``auto`` or ``decltype`` may enable  
1040 -you to write code that works with the old and new API without having  
1041 -to use conditional compilation. The  
1042 -``POINTERHOLDER_IS_SHARED_POINTER`` is defined in qpdf 11 if you  
1043 -``#include <qpdf/PointerHolder.hh>``.  
1044 -  
1045 -If you want to support older versions of qpdf and still transition so  
1046 -that the backward-compatible ``PointerHolder`` is not in use, you can  
1047 -separate old code and new code by testing with the 1024 +Starting in qpdf 11.0.0, including ``<qpdf/PointerHolder.hh>`` defines
  1025 +the symbol ``POINTERHOLDER_IS_SHARED_POINTER``. If you want to support
  1026 +older versions of qpdf and still transition so that the
  1027 +backward-compatible ``PointerHolder`` is not in use, you can separate
  1028 +old code and new code by testing with the
1048 ``POINTERHOLDER_IS_SHARED_POINTER`` preprocessor symbol, as in 1029 ``POINTERHOLDER_IS_SHARED_POINTER`` preprocessor symbol, as in
1049 1030
1050 .. code-block:: c++ 1031 .. code-block:: c++
1051 1032
  1033 + #include <qpdf/PointerHolder.hh>
1052 #ifdef POINTERHOLDER_IS_SHARED_POINTER 1034 #ifdef POINTERHOLDER_IS_SHARED_POINTER
1053 std::shared_ptr<X> x; 1035 std::shared_ptr<X> x;
1054 #else 1036 #else
@@ -1060,6 +1042,7 @@ or @@ -1060,6 +1042,7 @@ or
1060 1042
1061 .. code-block:: c++ 1043 .. code-block:: c++
1062 1044
  1045 + #include <qpdf/PointerHolder.hh>
1063 #ifdef POINTERHOLDER_IS_SHARED_POINTER 1046 #ifdef POINTERHOLDER_IS_SHARED_POINTER
1064 auto x_p = std::make_shared<X>(); 1047 auto x_p = std::make_shared<X>();
1065 X* x = x_p.get(); 1048 X* x = x_p.get();
@@ -1074,13 +1057,23 @@ If you don&#39;t need to support older versions of qpdf, you can proceed @@ -1074,13 +1057,23 @@ If you don&#39;t need to support older versions of qpdf, you can proceed
1074 with these steps without protecting changes with the preprocessor 1057 with these steps without protecting changes with the preprocessor
1075 symbol. Here are the remaining changes. 1058 symbol. Here are the remaining changes.
1076 1059
1077 -- Make sure you have a clean build with ``POINTERHOLDER_TRANSITION``  
1078 - set to ``2``. This means that you are using ``PointerHolder`` in a  
1079 - manner that is API-compatible with ``std::shared_ptr`` in all cases  
1080 - except for array pointers. 1060 +- ``#define POINTERHOLDER_TRANSITION 2`` to enable deprecation of
  1061 + ``getPointer()`` and ``getRefcount()``
  1062 +
  1063 +- Replace ``getPointer()`` with ``get()`` and ``getRefcount()`` with
  1064 + ``use_count()``. These methods were not present prior to 10.6.0.
  1065 +
  1066 +When you have gotten your code to compile cleanly with
  1067 +``POINTERHOLDER_TRANSITION=2``, you are well on your way to being
  1068 +ready for eliminating ``PointerHolder`` entirely. The code at this
  1069 +point will not work with any qpdf version prior to 10.6.0.
  1070 +
  1071 +To support qpdf 11.0.0 and newer and remove ``PointerHolder`` from
  1072 +your code, continue with the following steps:
1081 1073
1082 - Replace all occurrences of ``PointerHolder`` with 1074 - Replace all occurrences of ``PointerHolder`` with
1083 - ``std::shared_ptr`` except in ``#include <qpdf/PointerHolder.hh>`` 1075 + ``std::shared_ptr`` except in the literal statement ``#include
  1076 + <qpdf/PointerHolder.hh>``
1084 1077
1085 - Replace all occurrences of ``make_pointer_holder`` with 1078 - Replace all occurrences of ``make_pointer_holder`` with
1086 ``std::make_shared`` 1079 ``std::make_shared``