Revision control
++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \example ipc/sharedmemory
++ \examplecategory {Data Processing & I/O}
++ \title IPC: Shared Memory
++ \ingroup examples-ipc
++ \ingroup corelib_examples
++ \brief Demonstrates how to share image data between different processes
++ using the Shared Memory IPC mechanism.
++
++ The Shared Memory example shows how to use the QSharedMemory class
++ to implement inter-process communication using shared memory. To
++ build the example, run make. To run the example, start two instances
++ of the executable. The main() function creates an \l {QApplication}
++ {application} and an instance of our example's Dialog class. The
++ dialog is displayed and then control is passed to the application in
++ the standard way.
++
++ \snippet ipc/sharedmemory/main.cpp 0
++
++ Two instances of class Dialog appear.
++
++ \image sharedmemory-example_1.png Screenshot of the Shared Memory example
++
++ Class Dialog inherits QDialog. It encapsulates the user interface
++ and an instance of QSharedMemory. It also has two public slots,
++ loadFromFile() and loadFromMemory() that correspond to the two
++ buttons on the dialog.
++
++ \snippet ipc/sharedmemory/dialog.h 0
++
++ The constructor builds the user interface widgets and connects the
++ clicked() signal of each button to the corresponding slot function.
++
++ \snippet ipc/sharedmemory/dialog.cpp 0
++
++ Note that "QSharedMemoryExample" is passed to the \l {QSharedMemory}
++ {QSharedMemory()} constructor to be used as the key. This will be
++ used by the system as the identifier of the underlying shared memory
++ segment.
++
++ Click the \tt {Load Image From File...} button on one of the
++ dialogs. The loadFromFile() slot is invoked. First, it tests whether
++ a shared memory segment is already attached to the process. If so,
++ that segment is detached from the process, so we can be assured of
++ starting off the example correctly.
++
++ \snippet ipc/sharedmemory/dialog.cpp 1
++
++ The user is then asked to select an image file using
++ QFileDialog::getOpenFileName(). The selected file is loaded into a
++ QImage. Using a QImage lets us ensure that the selected file is a
++ valid image, and it also allows us to immediately display the image
++ in the dialog using setPixmap().
++
++ Next the image is streamed into a QBuffer using a QDataStream. This
++ gives us the size, which we then use to \l {QSharedMemory::}
++ {create()} our shared memory segment. Creating a shared memory
++ segment automatically \l {QSharedMemory::attach()} {attaches} the
++ segment to the process. Using a QBuffer here lets us get a pointer
++ to the image data, which we then use to do a memcopy() from the
++ QBuffer into the shared memory segment.
++
++ \snippet ipc/sharedmemory/dialog.cpp 2
++
++ Note that we \l {QSharedMemory::} {lock()} the shared memory segment
++ before we copy into it, and we \l {QSharedMemory::} {unlock()} it
++ again immediately after the copy. This ensures we have exclusive
++ access to the shared memory segment to do our memcopy(). If some
++ other process has the segment lock, then our process will block
++ until the lock becomes available.
++
++ Note also that the function does not \l {QSharedMemory::} {detach()}
++ from the shared memory segment after the memcopy() and
++ unlock(). Recall that when the last process detaches from a shared
++ memory segment, the segment is released by the operating
++ system. Since this process only one that is attached to the shared
++ memory segment at the moment, if loadFromFile() detached from the
++ shared memory segment, the segment would be destroyed before we get
++ to the next step.
++
++ When the function returns, if the file you selected was qt.png, your
++ first dialog looks like this.
++
++ \image sharedmemory-example_2.png Screenshot of the Shared Memory example
++
++ In the second dialog, click the \tt {Display Image From Shared
++ Memory} button. The loadFromMemory() slot is invoked. It first \l
++ {QSharedMemory::attach()} {attaches} the process to the same shared
++ memory segment created by the first process. Then it \l
++ {QSharedMemory::lock()} {locks} the segment for exclusive access and
++ links a QBuffer to the image data in the shared memory segment. It
++ then streams the data into a QImage and \l {QSharedMemory::unlock()}
++ {unlocks} the segment.
++
++ \snippet ipc/sharedmemory/dialog.cpp 3
++
++ In this case, the function does \l {QSharedMemory::} {detach()} from
++ the segment, because now we are effectively finished using
++ it. Finally, the QImage is displayed. At this point, both dialogs
++ should be showing the same image. When you close the first dialog,
++ the Dialog destructor calls the QSharedMemory destructor, which
++ detaches from the shared memory segment. Since this is the last
++ process to be detached from the segment, the operating system will
++ now release the shared memory.
++
++ */