Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to create shared 'null' private data when using QSharedData?
Forum Updated to NodeBB v4.3 + New Features

How to create shared 'null' private data when using QSharedData?

Scheduled Pinned Locked Moved General and Desktop
7 Posts 2 Posters 4.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    TristanB
    wrote on last edited by
    #1

    Implicitly shared classes like QString have a static instance of their internal data called shared_null. New instances of those classes refer to that shared data until they are detached-on-write, and the isNull test just checks if the data is referencing that shared data.

    I have created an implicitly shared type using QSharedData and QSharedDataPointer, and I wanted to use a similar technique to not create many identical copies of the 'null' private data for every new instance I create.

    This is the code I have tried.

    @#ifndef SHARED_DATA_HPP
    #define SHARED_DATA_HPP

    #include <QSharedDataPointer>

    class PrivateData;

    class SharedData
    {
    public:
    SharedData();
    SharedData(const SharedData &);
    ~SharedData();

    bool    isNull() const;
    

    protected:

    QSharedDataPointer<PrivateData> d;
    

    };

    #endif // ndef SHARED_DATA_HPP@

    @#include "shared_data.hpp"

    class PrivateData : public QSharedData
    {

    };

    static PrivateData shared_null;

    SharedData::SharedData()
    : d(&shared_null)
    {

    }

    SharedData::SharedData(const SharedData & rhs)
    : d(rhs.d)
    {

    }

    SharedData::~SharedData()
    {

    }

    bool SharedData::isNull() const
    {
    return (d.data() == &shared_null);
    }@

    @#include "shared_data.hpp"

    int main(int argc, char * argv[])
    {
    SharedData sd;

    return 0;
    

    }@

    This code compiles and runs, but will crash when main() exits. When the SharedData object is created, it increments the reference count for shared_null to 1. When main() exits, the object is destroyed, the reference count for shared_null drops to 0 and this causes it to be deleted. Since shared_null wasn't allocated on the heap, this results in an crash.

    I have tried various ways to allocate shared_null or to get its reference count set to one before I create any instances of SharedData, but have had no luck.

    Any ideas?

    1 Reply Last reply
    0
    • F Offline
      F Offline
      Franzk
      wrote on last edited by
      #2

      The reference count for your shared null is zero. Your instantiation will increase it to one, and upon destruction find that ref count is zero again. If ref count is zero, the SharedDataPointer will try to delete the shared data, which in this case will be unsuccessful. I haven't had a look at the QString code, but maybe you overlooked something there.

      "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

      http://www.catb.org/~esr/faqs/smart-questions.html

      1 Reply Last reply
      0
      • F Offline
        F Offline
        Franzk
        wrote on last edited by
        #3

        Something I don't understand about this approach is the fact that QSharedDataPointer can be default constructed, which results in a null object. Why then have the explicitly created shared null thing?

        "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

        http://www.catb.org/~esr/faqs/smart-questions.html

        1 Reply Last reply
        0
        • F Offline
          F Offline
          Franzk
          wrote on last edited by
          #4

          OK I had a look at the code and QString is one of the classes that has not yet been updated to make use of QSharedData and QSharedDataPointer. QString does a lot of the work that is now in QSharedDataPointer. Therefore I would say there is no need for you to take this same approach.

          That means: If you want to have an isNull() function, use the following (or something like it):

          @bool MySharedObject::isNull() const
          {
          return !d;
          }@

          "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

          http://www.catb.org/~esr/faqs/smart-questions.html

          1 Reply Last reply
          0
          • T Offline
            T Offline
            TristanB
            wrote on last edited by
            #5

            Thanks for your responses.

            I understand why the crash is happening, and I have tried to find ways to get the reference count of the shared null data starts as 1 so that the destruction of any actual null objects I created can never set it back to zero, but I haven't found a way of doing it.

            I note that all of the classes in Qt that use this 'shared null' technique do not use QSharedData but handle their own reference counting and detach-on-write behaviour, so maybe that is a clue that I am wasting my time with this approach.

            The reason why I haven't just left my d-pointer as NULL is that I would have to test for this case in all of the functions where I want to write to the private data and instantiate it where necessary. Also, in the read functions, I would need to return something, but without a shared null instance of the data, I would be instantiating objects to return all the time, which defeats the object of using this approach.

            I just liked the elegance of the shared_null idea and wanted to replicate it.

            1 Reply Last reply
            0
            • F Offline
              F Offline
              Franzk
              wrote on last edited by
              #6

              In that case, use
              @static QSharedDataPointer<PrivateData> shared_null(new PrivateData);@

              This solves your reference counting problem.

              Concerning the checks, you don't have to do that in the write functions. Because of the non-constness of those functions, the QSharedDataPointer creates a new object if necessary. Checks for read data would be necessary, indeed.

              "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

              http://www.catb.org/~esr/faqs/smart-questions.html

              1 Reply Last reply
              0
              • T Offline
                T Offline
                TristanB
                wrote on last edited by
                #7

                That's done the trick. So simple, I can't believe I didn't see that. Thanks for your input.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved