summaryrefslogtreecommitdiff
authorzecke <zecke>2002-10-16 18:24:48 (UTC)
committer zecke <zecke>2002-10-16 18:24:48 (UTC)
commit9047650faad7e64e0a36553dfe04dc7ad084f095 (patch) (unidiff)
treeb79a65f224b329d6dcc559d8b72d564ccce4a3c8
parent1a305f211913ce4a4d73ed0b36a0be535c0e03ec (diff)
downloadopie-9047650faad7e64e0a36553dfe04dc7ad084f095.zip
opie-9047650faad7e64e0a36553dfe04dc7ad084f095.tar.gz
opie-9047650faad7e64e0a36553dfe04dc7ad084f095.tar.bz2
More IPC integtration
OCOPClient::self() added so we keep the connections low
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--x11/ipc/client/ocopclient.cpp9
-rw-r--r--x11/ipc/client/ocopclient.h7
-rw-r--r--x11/ipc/server/ocopserver.cpp27
-rw-r--r--x11/libqpe-x11/qt/qcopchannel_qws.cpp45
-rw-r--r--x11/libqpe-x11/qt/qcopchannel_qws.h4
5 files changed, 69 insertions, 23 deletions
diff --git a/x11/ipc/client/ocopclient.cpp b/x11/ipc/client/ocopclient.cpp
index c1def73..6085481 100644
--- a/x11/ipc/client/ocopclient.cpp
+++ b/x11/ipc/client/ocopclient.cpp
@@ -1,64 +1,73 @@
1#include <errno.h> 1#include <errno.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include <stdio.h> 3#include <stdio.h>
4#include <unistd.h> 4#include <unistd.h>
5#include <sys/socket.h> 5#include <sys/socket.h>
6#include <sys/types.h> 6#include <sys/types.h>
7#include <sys/un.h> 7#include <sys/un.h>
8 8
9 9
10#include <qfile.h> 10#include <qfile.h>
11#include <qtimer.h> 11#include <qtimer.h>
12 12
13#include "../common/ocoppacket.h" 13#include "../common/ocoppacket.h"
14 14
15#include "ocopclient.h" 15#include "ocopclient.h"
16 16
17OCOPClient* OCOPClient::m_self = 0;
18
19OCOPClient* OCOPClient::self() {
20 if (!m_self ) {
21 m_self = new OCOPClient();
22 }
23 return m_self;
24}
25
17OCOPClient::OCOPClient( const QString& path, QObject* obj ) 26OCOPClient::OCOPClient( const QString& path, QObject* obj )
18 : QObject( obj ) 27 : QObject( obj )
19{ 28{
20 m_tries = 0; 29 m_tries = 0;
21 init(QFile::encodeName(path) ); 30 init(QFile::encodeName(path) );
22} 31}
23OCOPClient::~OCOPClient() { 32OCOPClient::~OCOPClient() {
24 delete m_notify; 33 delete m_notify;
25 close( m_socket ); 34 close( m_socket );
26} 35}
27void OCOPClient::init() { 36void OCOPClient::init() {
28 // failed start ther server NOW!!! 37 // failed start ther server NOW!!!
29 startUP(); 38 startUP();
30 QCString str; 39 QCString str;
31 init(str ); 40 init(str );
32} 41}
33void OCOPClient::init( const QCString& ) { 42void OCOPClient::init( const QCString& ) {
34 m_tries++; 43 m_tries++;
35 struct sockaddr_un unix_adr; 44 struct sockaddr_un unix_adr;
36 if ( (m_socket = socket(PF_UNIX, SOCK_STREAM, 0) ) < 0 ) { 45 if ( (m_socket = socket(PF_UNIX, SOCK_STREAM, 0) ) < 0 ) {
37 qWarning("could not socket"); 46 qWarning("could not socket");
38 if ( m_tries < 8 ) 47 if ( m_tries < 8 )
39 QTimer::singleShot(400, this,SLOT(init() ) ); 48 QTimer::singleShot(400, this,SLOT(init() ) );
40 return; 49 return;
41 } 50 }
42 memset(&unix_adr, 0, sizeof(unix_adr ) ); 51 memset(&unix_adr, 0, sizeof(unix_adr ) );
43 unix_adr.sun_family = AF_UNIX; 52 unix_adr.sun_family = AF_UNIX;
44 sprintf(unix_adr.sun_path,"%s/.opie.cop", getenv("HOME") ); 53 sprintf(unix_adr.sun_path,"%s/.opie.cop", getenv("HOME") );
45 int length = sizeof(unix_adr.sun_family) + strlen(unix_adr.sun_path); 54 int length = sizeof(unix_adr.sun_family) + strlen(unix_adr.sun_path);
46 55
47 if ( ::connect(m_socket, (struct sockaddr*)&unix_adr, length ) < 0 ) { 56 if ( ::connect(m_socket, (struct sockaddr*)&unix_adr, length ) < 0 ) {
48 qWarning("could not connect %d", errno ); 57 qWarning("could not connect %d", errno );
49 close( m_socket ); 58 close( m_socket );
50 if ( m_tries < 8 ) 59 if ( m_tries < 8 )
51 QTimer::singleShot(400, this, SLOT(init() ) ); 60 QTimer::singleShot(400, this, SLOT(init() ) );
52 return; 61 return;
53 } 62 }
54 m_notify = new QSocketNotifier(m_socket, QSocketNotifier::Read, this ); 63 m_notify = new QSocketNotifier(m_socket, QSocketNotifier::Read, this );
55 connect( m_notify, SIGNAL(activated(int) ), 64 connect( m_notify, SIGNAL(activated(int) ),
56 this, SLOT(newData() ) ); 65 this, SLOT(newData() ) );
57} 66}
58/** 67/**
59 * new data 68 * new data
60 * read the header check magic number 69 * read the header check magic number
61 * and maybe read body 70 * and maybe read body
62 */ 71 */
63void OCOPClient::newData() { 72void OCOPClient::newData() {
64 OCOPPacket pack = packet(); 73 OCOPPacket pack = packet();
diff --git a/x11/ipc/client/ocopclient.h b/x11/ipc/client/ocopclient.h
index 53018a5..ee2015a 100644
--- a/x11/ipc/client/ocopclient.h
+++ b/x11/ipc/client/ocopclient.h
@@ -1,61 +1,66 @@
1#ifndef OPIE_OCOP_CLIENT_H 1#ifndef OPIE_OCOP_CLIENT_H
2#define OPIE_OCOP_CLIENT_H 2#define OPIE_OCOP_CLIENT_H
3 3
4 4
5#include <qobject.h> 5#include <qobject.h>
6#include <qcstring.h> 6#include <qcstring.h>
7#include <qmap.h> 7#include <qmap.h>
8#include <qsignal.h> 8#include <qsignal.h>
9#include <qstring.h> 9#include <qstring.h>
10#include <qsocketnotifier.h> 10#include <qsocketnotifier.h>
11 11
12 12
13/** 13/**
14 * This is the OCOP client 14 * This is the OCOP client
15 * It currently only supports 15 * It currently only supports
16 * asking if a Channel is registered, 16 * asking if a Channel is registered,
17 * calling and receiving calls 17 * calling and receiving calls
18 */ 18 */
19class OCOPPacket; 19class OCOPPacket;
20class OCOPClient : public QObject{ 20class OCOPClient : public QObject{
21 Q_OBJECT 21 Q_OBJECT
22public: 22public:
23 23 /*
24 * this is the static
25 * OCopClient
26 */
27 static OCOPClient* self();
24 /** 28 /**
25 * Occasionally I decide to start a Server from here 29 * Occasionally I decide to start a Server from here
26 */ 30 */
27 OCOPClient(const QString& pathToServer = QString::null, QObject* obj = 0l); 31 OCOPClient(const QString& pathToServer = QString::null, QObject* obj = 0l);
28 ~OCOPClient(); 32 ~OCOPClient();
29 33
30 bool isRegistered( const QCString& )const; 34 bool isRegistered( const QCString& )const;
31 void send( const QCString& chan, const QCString&, const QByteArray& msg ); 35 void send( const QCString& chan, const QCString&, const QByteArray& msg );
32 36
33 /** 37 /**
34 * add a channel and does connect to a signal 38 * add a channel and does connect to a signal
35 * callback is the object 39 * callback is the object
36 * slot is the SLOT() 40 * slot is the SLOT()
37 */ 41 */
38 void addChannel( const QCString& channel ); 42 void addChannel( const QCString& channel );
39 void delChannel( const QCString& channel ); 43 void delChannel( const QCString& channel );
40 44
41 /* make it singleton? */ 45 /* make it singleton? */
42 //static OCOPClient* self(); 46 //static OCOPClient* self();
43/* no direct signals due the design */ 47/* no direct signals due the design */
44signals: 48signals:
45 void called(const QCString&, const QCString&, const QByteArray& ); 49 void called(const QCString&, const QCString&, const QByteArray& );
46private slots: 50private slots:
47 void init(); 51 void init();
48 void init(const QCString& pa); 52 void init(const QCString& pa);
49 void newData(); 53 void newData();
50private: 54private:
51 void startUP(); 55 void startUP();
52 OCOPPacket packet()const; 56 OCOPPacket packet()const;
53 void call( const OCOPPacket& ); 57 void call( const OCOPPacket& );
54 58
55 QSocketNotifier* m_notify; 59 QSocketNotifier* m_notify;
56 int m_socket; 60 int m_socket;
57 int m_tries; 61 int m_tries;
58 62
63 static OCOPClient* m_self;
59}; 64};
60 65
61#endif 66#endif
diff --git a/x11/ipc/server/ocopserver.cpp b/x11/ipc/server/ocopserver.cpp
index 421e49c..4940cb8 100644
--- a/x11/ipc/server/ocopserver.cpp
+++ b/x11/ipc/server/ocopserver.cpp
@@ -169,126 +169,139 @@ void OCopServer::newOnClient( int fd ) {
169 QCString func( head.funclen+1 ); 169 QCString func( head.funclen+1 );
170 QByteArray data ( head.datalen ); 170 QByteArray data ( head.datalen );
171 171
172 /* 172 /*
173 * we do not check for errors 173 * we do not check for errors
174 */ 174 */
175 qWarning("read "); 175 qWarning("read ");
176 int s = read(fd, channel.data(), head.chlen ); 176 int s = read(fd, channel.data(), head.chlen );
177 s = read(fd, func.data(), head.funclen ); 177 s = read(fd, func.data(), head.funclen );
178 s = read(fd, data.data(), head.datalen ); 178 s = read(fd, data.data(), head.datalen );
179 qWarning("read"); 179 qWarning("read");
180 180
181 /* debug output */ 181 /* debug output */
182 qWarning("channel %s %d", channel.data(), head.chlen ); 182 qWarning("channel %s %d", channel.data(), head.chlen );
183 qWarning("func %s %d", func.data(), head.funclen ); 183 qWarning("func %s %d", func.data(), head.funclen );
184 /* debug end */ 184 /* debug end */
185 185
186 /* 186 /*
187 * now that we got the complete body 187 * now that we got the complete body
188 * we need to make a package 188 * we need to make a package
189 * and then we need to send it to clients 189 * and then we need to send it to clients
190 * making a package is done here 190 * making a package is done here
191 * dispatching it not 191 * dispatching it not
192 */ 192 */
193 OCOPPacket packet( head.type, channel, func, data ); 193 OCOPPacket packet( head.type, channel, func, data );
194 dispatch( packet, fd ); 194 dispatch( packet, fd );
195 195
196 }else{ 196 }else{
197 qWarning("magic does not match"); 197 qWarning("magic does not match");
198 qWarning("magic %d", head.magic ); 198 qWarning("magic %d", head.magic );
199 } 199 }
200} 200}
201void OCopServer::registerClient( int fd ) { 201void OCopServer::registerClient( int fd ) {
202 if (m_clients.contains(fd) ) 202 if (m_clients.contains(fd) )
203 return; 203 return;
204 204
205 QSocketNotifier* notify = new QSocketNotifier(fd, QSocketNotifier::Read, this ); 205 QSocketNotifier* notify = new QSocketNotifier(fd, QSocketNotifier::Read, this );
206 connect(notify, SIGNAL(activated(int) ), 206 connect(notify, SIGNAL(activated(int) ),
207 this, SLOT(newOnClient(int) ) ); 207 this, SLOT(newOnClient(int) ) );
208 OCOPClient client; 208 OCOPClient client;
209 client.fd = fd; 209 client.fd = fd;
210 client.notify = notify; 210 client.notify = notify;
211 m_clients.insert( client.fd, client ); 211 m_clients.insert( client.fd, client );
212 qWarning("clients are up to %d", m_clients.count() ); 212 qWarning("clients are up to %d", m_clients.count() );
213}; 213};
214void OCopServer::deregisterClient(int fd ) { 214void OCopServer::deregisterClient(int fd ) {
215 QMap<int, OCOPClient>::Iterator it = m_clients.find( fd ); 215 QMap<int, OCOPClient>::Iterator it = m_clients.find( fd );
216 if (it != m_clients.end() ) { 216 if (it != m_clients.end() ) {
217 OCOPClient client = (*it); 217 OCOPClient client = it.data();
218 delete client.notify; 218 delete client.notify;
219 m_clients.remove(fd ); 219 m_clients.remove(fd );
220 close(fd ); 220 close(fd );
221 /* 221 /*
222 * TIME_ME 222 * TIME_ME
223 * 223 *
224 * now delete from all channels 224 * now delete from all channels
225 * go through all channels 225 * go through all channels
226 * remove the fd from the list 226 * remove the fd from the list
227 * if count becomes 0 remove the channel 227 * if count becomes 0 remove the channel
228 * otherwise replace QArray<int> 228 * otherwise replace QArray<int>
229 */ 229 */
230 QMap<QCString, QValueList<int> >::Iterator it; 230 QMap<QCString, QValueList<int> >::Iterator it2;
231 for ( it = m_channels.begin(); it != m_channels.end(); ++it ) { 231 repeatIt:
232 for ( it2 = m_channels.begin(); it2 != m_channels.end(); ++it2 ) {
232 /* 233 /*
233 * The channel contains this fd 234 * The channel contains this fd
234 */ 235 */
235 if ( it.data().contains( fd ) ) { 236 qWarning("Channel %s", it2.key().data() );
236 QValueList<int> array = it.data(); 237 if ( it2.data().contains( fd ) ) {
238 qWarning("contains");
239 QValueList<int> array = it2.data();
237 240
238 /* 241 /*
239 * remove channel or just replace 242 * remove channel or just replace
240 */ 243 */
241 if ( array.count() == 1 ) { 244 if ( array.count() == 1 ) {
245 qWarning("Invalidate!");
242 /* is the list now invalidatet? */ 246 /* is the list now invalidatet? */
243 m_channels.remove( it ); 247 m_channels.remove( it2 );
248 /* That is the first go to of my life
249 * but Iterator remove( Iterator )
250 * does not exist
251 * it2 = --it2;
252 * does not work reliable too
253 * so the only way is to reiterate :(
254 */
255 goto repeatIt;
244 }else{ 256 }else{
257 qWarning("removing");
245 array.remove( fd ); 258 array.remove( fd );
246 it = m_channels.replace( it.key(), array ); 259 it2 = m_channels.replace( it2.key(), array );
247 } 260 }
248 } 261 }
249 } // off all channels 262 } // off all channels
250 } 263 }
251 qWarning("clients are now at %d", m_clients.count() ); 264 qWarning("clients are now at %d", m_clients.count() );
252}; 265};
253/** 266/**
254 * this function will evaluate 267 * this function will evaluate
255 * the package and then do the appropriate thins 268 * the package and then do the appropriate thins
256 */ 269 */
257void OCopServer::dispatch( const OCOPPacket& packet, int sourceFD ) { 270void OCopServer::dispatch( const OCOPPacket& packet, int sourceFD ) {
258 qWarning("packet.type() == %d", packet.type() ); 271 qWarning("packet.type() == %d", packet.type() );
259 switch( packet.type() ) { 272 switch( packet.type() ) {
260 case OCOPPacket::Register: 273 case OCOPPacket::Register:
261 registerClient(sourceFD ); 274 registerClient(sourceFD );
262 break; 275 break;
263 case OCOPPacket::Unregister: 276 case OCOPPacket::Unregister:
264 deregisterClient(sourceFD ); 277 deregisterClient(sourceFD );
265 break; 278 break;
266 case OCOPPacket::Call: 279 case OCOPPacket::Call:
267 call( packet, sourceFD ); 280 call( packet, sourceFD );
268 break; 281 break;
269 /* not implemented */ 282 /* not implemented */
270 case OCOPPacket::Method: 283 case OCOPPacket::Method:
271 break; 284 break;
272 /* nit implemented */ 285 /* nit implemented */
273 case OCOPPacket::Reply: 286 case OCOPPacket::Reply:
274 break; 287 break;
275 case OCOPPacket::RegisterChannel: 288 case OCOPPacket::RegisterChannel:
276 addChannel( packet.channel() , sourceFD ); 289 addChannel( packet.channel() , sourceFD );
277 break; 290 break;
278 case OCOPPacket::UnregisterChannel: 291 case OCOPPacket::UnregisterChannel:
279 delChannel( packet.channel(), sourceFD ); 292 delChannel( packet.channel(), sourceFD );
280 break; 293 break;
281 /* not implemented */ 294 /* not implemented */
282 case OCOPPacket::Return: 295 case OCOPPacket::Return:
283 break; 296 break;
284 /* not implemented :( */ 297 /* not implemented :( */
285 case OCOPPacket::Signal: 298 case OCOPPacket::Signal:
286 break; 299 break;
287 case OCOPPacket::IsRegistered: 300 case OCOPPacket::IsRegistered:
288 qWarning("IsRegistered"); 301 qWarning("IsRegistered");
289 isRegistered( packet.channel(), sourceFD ); 302 isRegistered( packet.channel(), sourceFD );
290 break; 303 break;
291 }; 304 };
292} 305}
293void OCopServer::errorOnServer() { 306void OCopServer::errorOnServer() {
294 /* 307 /*
diff --git a/x11/libqpe-x11/qt/qcopchannel_qws.cpp b/x11/libqpe-x11/qt/qcopchannel_qws.cpp
index c315d66..e90f056 100644
--- a/x11/libqpe-x11/qt/qcopchannel_qws.cpp
+++ b/x11/libqpe-x11/qt/qcopchannel_qws.cpp
@@ -1,46 +1,63 @@
1 1
2#include "../../ipc/client/ocopclient.h" 2#include "../../ipc/client/ocopclient.h"
3 3
4#include <qcopchannel_qws.h> 4#include <qcopchannel_qws.h>
5 5
6QList<QCopChannel>* QCopChannel::m_list = 0;
7
6QCopChannel::QCopChannel( const QCString& channel, QObject* parent, 8QCopChannel::QCopChannel( const QCString& channel, QObject* parent,
7 const char* name ) 9 const char* name )
8 : QObject( parent, name ),m_chan(channel) { 10 : QObject( parent, name ),m_chan(channel) {
9 init(); 11 init();
12 if (!m_list ) {
13 m_list = new QList<QCopChannel>;
14 }
15 m_list->append(this);
16}
17void QCopChannel::receive( const QCString& msg, const QByteArray& ar ) {
18 emit received( msg, ar );
10} 19}
11QCopChannel::~QCopChannel() { 20QCopChannel::~QCopChannel() {
12 m_client->delChannel( m_chan ); 21 m_list->remove(this);
13 delete m_client; 22 if (m_list->count() == 0 ) {
23 delete m_list;
24 m_list = 0;
25 }
26 OCOPClient::self()->delChannel( m_chan );
14} 27}
15void QCopChannel::init() { 28void QCopChannel::init() {
16 m_client = new OCOPClient(QString::null, this ); 29 OCOPClient::self()->addChannel( m_chan );
17 m_client->addChannel(m_chan ); 30 connect(OCOPClient::self(), SIGNAL(called(const QCString&, const QCString&, const QByteArray& ) ),
18 connect(m_client, SIGNAL(called(const QCString&, const QCString&, const QByteArray& ) ),
19 this, SLOT(rev(const QCString&, const QCString&, const QByteArray&) ) ); 31 this, SLOT(rev(const QCString&, const QCString&, const QByteArray&) ) );
20} 32}
21QCString QCopChannel::channel()const { 33QCString QCopChannel::channel()const {
22 return m_chan; 34 return m_chan;
23} 35}
24bool QCopChannel::isRegistered( const QCString& chan) { 36bool QCopChannel::isRegistered( const QCString& chan) {;
25 OCOPClient client; 37 return OCOPClient::self()->isRegistered( chan );
26 return client.isRegistered( chan );
27} 38}
28bool QCopChannel::send( const QCString& chan, const QCString& msg ) { 39bool QCopChannel::send( const QCString& chan, const QCString& msg ) {
29 QByteArray ar(0); 40 QByteArray ar;
30 return sendLocally(chan, msg, ar ); 41 return send(chan, msg, ar );
31} 42}
32bool QCopChannel::send( const QCString& chan, const QCString& msg, 43bool QCopChannel::send( const QCString& chan, const QCString& msg,
33 const QByteArray& ar ) { 44 const QByteArray& ar ) {
34 return sendLocally( chan, msg, ar ); 45 OCOPClient::self()->send( chan, msg, ar );
46 return true;
35} 47}
36bool QCopChannel::sendLocally( const QCString& chan, const QCString& msg, 48bool QCopChannel::sendLocally( const QCString& chann, const QCString& msg,
37 const QByteArray& ar ) { 49 const QByteArray& ar ) {
38 OCOPClient client; 50 if (!m_list )
39 client.send( chan, msg, ar ); 51 return true;
52 QCopChannel* chan;
53 for ( chan = m_list->first(); chan; chan = m_list->next() ) {
54 if ( chan->channel() == chann )
55 chan->receive( msg, ar );
56 }
40 57
41 return true; 58 return true;
42} 59}
43void QCopChannel::rev( const QCString& chan, const QCString& msg, const QByteArray& ar ) { 60void QCopChannel::rev( const QCString& chan, const QCString& msg, const QByteArray& ar ) {
44 if (chan == m_chan ) 61 if (chan == m_chan )
45 emit received(msg, ar ); 62 emit received(msg, ar );
46} 63}
diff --git a/x11/libqpe-x11/qt/qcopchannel_qws.h b/x11/libqpe-x11/qt/qcopchannel_qws.h
index b0a6ce0..94b199e 100644
--- a/x11/libqpe-x11/qt/qcopchannel_qws.h
+++ b/x11/libqpe-x11/qt/qcopchannel_qws.h
@@ -1,40 +1,42 @@
1#ifndef OPIE_QCOP_CHANNEL_QWS_H 1#ifndef OPIE_QCOP_CHANNEL_QWS_H
2#define OPIE_QCOP_CHANNEL_QWS_H 2#define OPIE_QCOP_CHANNEL_QWS_H
3 3
4#include <qobject.h> 4#include <qobject.h>
5#include <qcstring.h> 5#include <qcstring.h>
6#include <qlist.h>
6 7
7class OCOPClient; 8class OCOPClient;
8class QCopChannel : public QObject { 9class QCopChannel : public QObject {
9 Q_OBJECT 10 Q_OBJECT
10public: 11public:
11 QCopChannel( const QCString& channel, QObject* parent = 0, 12 QCopChannel( const QCString& channel, QObject* parent = 0,
12 const char* name = 0); 13 const char* name = 0);
13 virtual ~QCopChannel(); 14 virtual ~QCopChannel();
14 15
15 QCString channel()const; 16 QCString channel()const;
16 17
17 static bool isRegistered( const QCString& channel ); 18 static bool isRegistered( const QCString& channel );
18 static bool send( const QCString& channel, const QCString& msg ); 19 static bool send( const QCString& channel, const QCString& msg );
19 static bool send( const QCString& channel, const QCString& msg, 20 static bool send( const QCString& channel, const QCString& msg,
20 const QByteArray& ); 21 const QByteArray& );
21 static bool sendLocally( const QCString& chan, const QCString& msg, 22 static bool sendLocally( const QCString& chan, const QCString& msg,
22 const QByteArray& data ); 23 const QByteArray& data );
24 void receive( const QCString& msg, const QByteArray& ar );
23 25
24signals: 26signals:
25 void received( const QCString& msg, const QByteArray& ); 27 void received( const QCString& msg, const QByteArray& );
26 28
27private slots: 29private slots:
28 void rev( const QCString& chan, const QCString&, const QByteArray& ); 30 void rev( const QCString& chan, const QCString&, const QByteArray& );
29 31
30private: 32private:
31 void init(); 33 void init();
32 OCOPClient* m_client; 34 static QList<QCopChannel> *m_list;
33 /* the channel */ 35 /* the channel */
34 QCString m_chan; 36 QCString m_chan;
35 class Private; 37 class Private;
36 Private *d; 38 Private *d;
37 39
38}; 40};
39 41
40#endif 42#endif