include/salhelper/simplereferenceobject.hxx |   29 ++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

New commits:
commit 914e79524cdd9c4176e6508d1401fb7dca6264e2
Author:     Michael Meeks <michael.me...@collabora.com>
AuthorDate: Thu Oct 17 07:24:10 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Mon Oct 21 09:47:28 2024 +0200

    SimpleReferenceObject: add ability to staticize the ref-count.
    
    Useful for when we allocate data at startup and want to share it
    across multiple threads. Also potentiall useful for turning
    extreme cases of ref-count wrap-around into a more benign leak.
    
    Change-Id: I04e6a62dbd366d294d86ab72036c3498402357f0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175196
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/include/salhelper/simplereferenceobject.hxx 
b/include/salhelper/simplereferenceobject.hxx
index ac721ad3da98..59a2baf83bc6 100644
--- a/include/salhelper/simplereferenceobject.hxx
+++ b/include/salhelper/simplereferenceobject.hxx
@@ -60,20 +60,28 @@ namespace salhelper {
  */
 class SALHELPER_DLLPUBLIC SimpleReferenceObject
 {
+    static const size_t nStaticFlag = 0x80000000;
+
 public:
     SimpleReferenceObject(): m_nCount(0) {}
 
     /** @attention
-        The results are undefined if, for any individual instance of
-        SimpleReferenceObject, the total number of calls to acquire() exceeds
-        the total number of calls to release() by a platform dependent amount
-        (which, hopefully, is quite large).
+        If, for any individual instance of SimpleReferenceObject, the total
+        number of calls to acquire() exceeds the total number of calls to
+        release() by 2^31 - the object will never subsequently be released.
      */
     void acquire()
-    { osl_atomic_increment(&m_nCount); }
+    {
+        if (!(m_nCount & nStaticFlag))
+            osl_atomic_increment(&m_nCount);
+    }
 
     void release()
-    { if (osl_atomic_decrement(&m_nCount) == 0) delete this; }
+    {
+        if (!(m_nCount & nStaticFlag) &&
+            osl_atomic_decrement(&m_nCount) == 0)
+            delete this;
+    }
 
     /** see general class documentation
      */
@@ -95,6 +103,15 @@ public:
 protected:
     virtual ~SimpleReferenceObject() COVERITY_NOEXCEPT_FALSE;
 
+    /** mark reference count as not to be touched, and the
+     * related object as having an indefinite lifespan.
+     * NB. do not use if you have a non-empty destructor.
+     */
+    void staticize()
+    {
+        m_nCount |= nStaticFlag;
+    }
+
     oslInterlockedCount m_nCount;
 
 private:

Reply via email to