File: ipc-sharedmemory.html

package info (click to toggle)
qt4-x11 4%3A4.8.2%2Bdfsg-11
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 701,696 kB
  • sloc: cpp: 2,686,179; ansic: 375,485; python: 25,859; sh: 19,349; xml: 17,091; perl: 14,765; yacc: 5,383; asm: 5,038; makefile: 1,259; lex: 555; ruby: 526; objc: 347; cs: 112; pascal: 112; php: 54; sed: 34
file content (164 lines) | stat: -rw-r--r-- 14,929 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- sharedmemory.qdoc -->
  <title>Qt 4.8: Shared Memory Example</title>
  <link rel="stylesheet" type="text/css" href="style/offline.css" />
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="content"> 
    <a href="index.html" class="qtref"><span>Qt Reference Documentation</span></a>
  </div>
  <div class="breadcrumb toolblock">
    <ul>
      <li class="first"><a href="index.html">Home</a></li>
      <!--  Breadcrumbs go here -->
<li><a href="all-examples.html">Examples</a></li>
<li>Shared Memory Example</li>
    </ul>
  </div>
</div>
<div class="content mainContent">
<h1 class="title">Shared Memory Example</h1>
<span class="subtitle"></span>
<!-- $$$ipc/sharedmemory-description -->
<div class="descr"> <a name="details"></a>
<p>Files:</p>
<ul>
<li><a href="ipc-sharedmemory-dialog-cpp.html">ipc/sharedmemory/dialog.cpp</a></li>
<li><a href="ipc-sharedmemory-dialog-h.html">ipc/sharedmemory/dialog.h</a></li>
<li><a href="ipc-sharedmemory-dialog-ui.html">ipc/sharedmemory/dialog.ui</a></li>
<li><a href="ipc-sharedmemory-main-cpp.html">ipc/sharedmemory/main.cpp</a></li>
<li><a href="ipc-sharedmemory-sharedmemory-pro.html">ipc/sharedmemory/sharedmemory.pro</a></li>
</ul>
<p>The Shared Memory example shows how to use the <a href="qsharedmemory.html">QSharedMemory</a> class to implement inter-process communication using shared memory.<p>To build the example, run make. To run the example, start two instances of the executable. The main() function creates an <a href="qapplication.html">application</a> 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.</p>
<pre class="cpp"> <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>)
 {
     <span class="type"><a href="qapplication.html">QApplication</a></span> application(argc<span class="operator">,</span> argv);
     Dialog dialog;
     dialog<span class="operator">.</span>show();
     <span class="keyword">return</span> application<span class="operator">.</span>exec();
 }</pre>
<p>Two instances of class Dialog appear.</p>
<p class="centerAlign"><img src="images/sharedmemory-example_1.png" alt="Screenshot of the Shared Memory example" /></p><p>Class Dialog inherits <a href="qdialog.html">QDialog</a>. It encapsulates the user interface and an instance of <a href="qsharedmemory.html">QSharedMemory</a>. It also has two public slots, loadFromFile() and loadFromMemory() that correspond to the two buttons on the dialog.</p>
<pre class="cpp"> <span class="keyword">class</span> Dialog : <span class="keyword">public</span> <span class="type"><a href="qdialog.html">QDialog</a></span>
 {
     Q_OBJECT

   <span class="keyword">public</span>:
     Dialog(<span class="type"><a href="qwidget.html">QWidget</a></span> <span class="operator">*</span>parent <span class="operator">=</span> <span class="number">0</span>);

   <span class="keyword">public</span> <span class="keyword">slots</span>:
     <span class="type">void</span> loadFromFile();
     <span class="type">void</span> loadFromMemory();

  <span class="keyword">private</span>:
     <span class="type">void</span> detach();

   <span class="keyword">private</span>:
     Ui<span class="operator">::</span>Dialog ui;
     <span class="type"><a href="qsharedmemory.html">QSharedMemory</a></span> sharedMemory;
 };</pre>
<p>The constructor builds the user interface widgets and connects the clicked() signal of each button to the corresponding slot function.</p>
<pre class="cpp"> Dialog<span class="operator">::</span>Dialog(<span class="type"><a href="qwidget.html">QWidget</a></span> <span class="operator">*</span>parent)
   : <span class="type"><a href="qdialog.html">QDialog</a></span>(parent)<span class="operator">,</span> sharedMemory(<span class="string">&quot;QSharedMemoryExample&quot;</span>)
 {
     ui<span class="operator">.</span>setupUi(<span class="keyword">this</span>);
     connect(ui<span class="operator">.</span>loadFromFileButton<span class="operator">,</span> SIGNAL(clicked())<span class="operator">,</span> SLOT(loadFromFile()));
     connect(ui<span class="operator">.</span>loadFromSharedMemoryButton<span class="operator">,</span>
             SIGNAL(clicked())<span class="operator">,</span>
             SLOT(loadFromMemory()));
     setWindowTitle(tr(<span class="string">&quot;SharedMemory Example&quot;</span>));
 }</pre>
<p>Note that &quot;QSharedMemoryExample&quot; is passed to the <a href="qsharedmemory.html">QSharedMemory()</a> constructor to be used as the key. This will be used by the system as the identifier of the underlying shared memory segment.</p>
<p>Click the <tt>Load Image From File..&#x2e;</tt> 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.</p>
<pre class="cpp"> <span class="type">void</span> Dialog<span class="operator">::</span>loadFromFile()
 {
     <span class="keyword">if</span> (sharedMemory<span class="operator">.</span>isAttached())
         detach();

     ui<span class="operator">.</span>label<span class="operator">-</span><span class="operator">&gt;</span>setText(tr(<span class="string">&quot;Select an image file&quot;</span>));
     <span class="type"><a href="qstring.html">QString</a></span> fileName <span class="operator">=</span> <span class="type"><a href="qfiledialog.html">QFileDialog</a></span><span class="operator">::</span>getOpenFileName(<span class="number">0</span><span class="operator">,</span> <span class="type"><a href="qstring.html">QString</a></span>()<span class="operator">,</span> <span class="type"><a href="qstring.html">QString</a></span>()<span class="operator">,</span>
                                         tr(<span class="string">&quot;Images (*.png *.xpm *.jpg)&quot;</span>));
     <span class="type"><a href="qimage.html">QImage</a></span> image;
     <span class="keyword">if</span> (<span class="operator">!</span>image<span class="operator">.</span>load(fileName)) {
         ui<span class="operator">.</span>label<span class="operator">-</span><span class="operator">&gt;</span>setText(tr(<span class="string">&quot;Selected file is not an image, please select another.&quot;</span>));
         <span class="keyword">return</span>;
     }
     ui<span class="operator">.</span>label<span class="operator">-</span><span class="operator">&gt;</span>setPixmap(<span class="type"><a href="qpixmap.html">QPixmap</a></span><span class="operator">::</span>fromImage(image));</pre>
<p>The user is then asked to select an image file using <a href="qfiledialog.html#getOpenFileName">QFileDialog::getOpenFileName</a>(). The selected file is loaded into a <a href="qimage.html">QImage</a>. Using a <a href="qimage.html">QImage</a> 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().</p>
<p>Next the image is streamed into a <a href="qbuffer.html">QBuffer</a> using a <a href="qdatastream.html">QDataStream</a>. This gives us the size, which we then use to <a href="qsharedmemory.html#create">create()</a> our shared memory segment. Creating a shared memory segment automatically <a href="qsharedmemory.html#attach">attaches</a> the segment to the process. Using a <a href="qbuffer.html">QBuffer</a> here lets us get a pointer to the image data, which we then use to do a memcopy() from the <a href="qbuffer.html">QBuffer</a> into the shared memory segment.</p>
<pre class="cpp">     <span class="comment">// load into shared memory</span>
     <span class="type"><a href="qbuffer.html">QBuffer</a></span> buffer;
     buffer<span class="operator">.</span>open(<span class="type"><a href="qbuffer.html">QBuffer</a></span><span class="operator">::</span>ReadWrite);
     <span class="type"><a href="qdatastream.html">QDataStream</a></span> out(<span class="operator">&amp;</span>buffer);
     out <span class="operator">&lt;</span><span class="operator">&lt;</span> image;
     <span class="type">int</span> size <span class="operator">=</span> buffer<span class="operator">.</span>size();

     <span class="keyword">if</span> (<span class="operator">!</span>sharedMemory<span class="operator">.</span>create(size)) {
         ui<span class="operator">.</span>label<span class="operator">-</span><span class="operator">&gt;</span>setText(tr(<span class="string">&quot;Unable to create shared memory segment.&quot;</span>));
         <span class="keyword">return</span>;
     }
     sharedMemory<span class="operator">.</span>lock();
     <span class="type">char</span> <span class="operator">*</span>to <span class="operator">=</span> (<span class="type">char</span><span class="operator">*</span>)sharedMemory<span class="operator">.</span>data();
     <span class="keyword">const</span> <span class="type">char</span> <span class="operator">*</span>from <span class="operator">=</span> buffer<span class="operator">.</span>data()<span class="operator">.</span>data();
     memcpy(to<span class="operator">,</span> from<span class="operator">,</span> <a href="qtglobal.html#qMin">qMin</a>(sharedMemory<span class="operator">.</span>size()<span class="operator">,</span> size));
     sharedMemory<span class="operator">.</span>unlock();
 }</pre>
<p>Note that we <a href="qsharedmemory.html#lock">lock()</a> the shared memory segment before we copy into it, and we <a href="qsharedmemory.html#unlock">unlock()</a> 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.</p>
<p>Note also that the function does not <a href="qsharedmemory.html#detach">detach()</a> 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.</p>
<p>When the function returns, if the file you selected was qt.png, your first dialog looks like this.</p>
<p class="centerAlign"><img src="images/sharedmemory-example_2.png" alt="Screenshot of the Shared Memory example" /></p><p>In the second dialog, click the <tt>Display Image From Shared Memory</tt> button. The loadFromMemory() slot is invoked. It first <a href="qsharedmemory.html#attach">attaches</a> the process to the same shared memory segment created by the first process. Then it <a href="qsharedmemory.html#lock">locks</a> the segment for exclusive access and links a <a href="qbuffer.html">QBuffer</a> to the image data in the shared memory segment. It then streams the data into a <a href="qimage.html">QImage</a> and <a href="qsharedmemory.html#unlock">unlocks</a> the segment.</p>
<pre class="cpp"> <span class="type">void</span> Dialog<span class="operator">::</span>loadFromMemory()
 {
     <span class="keyword">if</span> (<span class="operator">!</span>sharedMemory<span class="operator">.</span>attach()) {
         ui<span class="operator">.</span>label<span class="operator">-</span><span class="operator">&gt;</span>setText(tr(<span class="string">&quot;Unable to attach to shared memory segment.\n&quot;</span> \
                              <span class="string">&quot;Load an image first.&quot;</span>));
         <span class="keyword">return</span>;
     }

     <span class="type"><a href="qbuffer.html">QBuffer</a></span> buffer;
     <span class="type"><a href="qdatastream.html">QDataStream</a></span> in(<span class="operator">&amp;</span>buffer);
     <span class="type"><a href="qimage.html">QImage</a></span> image;

     sharedMemory<span class="operator">.</span>lock();
     buffer<span class="operator">.</span>setData((<span class="type">char</span><span class="operator">*</span>)sharedMemory<span class="operator">.</span>constData()<span class="operator">,</span> sharedMemory<span class="operator">.</span>size());
     buffer<span class="operator">.</span>open(<span class="type"><a href="qbuffer.html">QBuffer</a></span><span class="operator">::</span>ReadOnly);
     in <span class="operator">&gt;</span><span class="operator">&gt;</span> image;
     sharedMemory<span class="operator">.</span>unlock();

     sharedMemory<span class="operator">.</span>detach();
     ui<span class="operator">.</span>label<span class="operator">-</span><span class="operator">&gt;</span>setPixmap(<span class="type"><a href="qpixmap.html">QPixmap</a></span><span class="operator">::</span>fromImage(image));
 }</pre>
<p>In this case, the function does <a href="qsharedmemory.html#detach">detach()</a> from the segment, because now we are effectively finished using it. Finally, the <a href="qimage.html">QImage</a> is displayed. At this point, both dialogs should be showing the same image. When you close the first dialog, the Dialog destructor calls the <a href="qsharedmemory.html">QSharedMemory</a> 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.</p>
</div>
<!-- @@@ipc/sharedmemory -->
  <div class="ft">
    <span></span>
  </div>
</div> 
<div class="footer">
    <p>
      <acronym title="Copyright">&copy;</acronym> 2012 Nokia Corporation and/or its
      subsidiaries. Documentation contributions included herein are the copyrights of
      their respective owners.</p>
    <br />
    <p>
      The documentation provided herein is licensed under the terms of the
      <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation
      License version 1.3</a> as published by the Free Software Foundation.</p>
    <p>
      Documentation sources may be obtained from <a href="http://www.qt-project.org">
      www.qt-project.org</a>.</p>
    <br />
    <p>
      Nokia, Qt and their respective logos are trademarks of Nokia Corporation 
      in Finland and/or other countries worldwide. All other trademarks are property
      of their respective owners. <a title="Privacy Policy"
      href="http://en.gitorious.org/privacy_policy/">Privacy Policy</a></p>
</div>
</body>
</html>