[SOLVED] QSharedMemory checking
-
I would know if a way to call some function exists when a content of QSharedMemory is updated.
Now I have to check every second the content of a QShareMemory in order to know if it contains what I need.
I would like know if a way to avoid this continue checking exists.
But I saw QSharedMemory doesn't emit any signal (except destroyed() that it inherit from QObject).There is a way to do that?
-
Hi,
Who access the QSharedMemory ? Different threads or different processes ?
-
Different processes
-
-
Could you do a example? Please.
This "checking" thread should do pooling .... -
Well, I hope you can do something with my messy example. I didn't consider waiting for threads termination, memory freeing and server separated thread for sending messages (in case client reads data too long time), just the main problem: waiting for shared memory without active pooling.
You need to run two processes (the same executable), they will configure themselves. The first one sends message on button clicked event, and the second one waits, receives and shows text in QLabel. You can use QSharedMemory lock/unlock or QSystemSemaphore interchangeably, see comments in cpp. You need to use uic/moc and build ui by yourself, ther is only QLineEdit (whatToSend), QPushButton and QLabel (whatReceived).
@
//main.cpp
#include "MainDialog.h"#include <QtWidgets\qapplication.h>
int main( int _argc, char** _argv )
{
QApplication app( _argc, _argv );MainDialog dlg;
dlg.show();return app.exec();
}
@@
//MainDialog.h
#pragma once#include "dialog.h"
#include <QtWidgets\qdialog.h>
#include <QtCore\qsharedmemory.h>
#include <QtCore\qthread.h>
#include <QtCore\qsystemsemaphore.h>class Client
: public QThread
{
Q_OBJECT
public:
Client( QSharedMemory & _sharedMemory );
void run();Q_SIGNALS:
void textReady( QString );private:
QSystemSemaphore m_semaphoreWriteDone;
QSharedMemory & m_sharedMemory;
};class MainDialog :
public QDialog
, public Ui::Dialog
{
Q_OBJECT
public:
MainDialog();
~MainDialog();public Q_SLOTS:
void onTextReady( QString );
void onSend();private:
QSharedMemory m_sharedMemory;
QSystemSemaphore m_semaphoreWriteDone;
};
@@
//MainDialog.cpp
#include "MainDialog.h"#include <QtCore\qtextstream.h>
#include "MainDialog.moc"
//you can comment semaphores and uncomment lock/unlock, result will be the same
Client::Client( QSharedMemory & _sharedMemory )
: m_semaphoreWriteDone( "SemaphoreWriteDone" ) //I assume that counter is already initialized by the server
, m_sharedMemory( _sharedMemory )
{
start();
}void
Client::run()
{
while ( true )
{
//there is no active pooling, we just wait for semaphore
m_semaphoreWriteDone.acquire();//m_sharedMemory.lock();
char const * from = ( char const * )m_sharedMemory.data();QString text;
QTextStream stream( &text );
while ( from && *from )
{
stream << *from;
++from;
}//m_sharedMemory.unlock();
m_semaphoreWriteDone.release();
Q_EMIT textReady( text );
}
}MainDialog::MainDialog(void)
: m_sharedMemory( "MySharedMemory" )
, m_semaphoreWriteDone( "SemaphoreWriteDone", 0 )
{
setupUi( this );bool result;
if ( result = m_sharedMemory.create( 1024 ) )
{
//We've created memory, so we are first. This one will send messages.
char to = (char)m_sharedMemory.data();
memset( to, 0, m_sharedMemory.size() );connect( m_sendButton, SIGNAL( clicked() ), this, SLOT( onSend() ) );
}
else
{
//Shared memory already exists, so this is second process. This one will listen.
result = m_sharedMemory.attach();
Q_ASSERT( result );m_sendButton->setEnabled( false );
Client * client = new Client( m_sharedMemory );
connect( client, SIGNAL( textReady( QString ) ), this, SLOT( onTextReady( QString ) ) );
}
}MainDialog::~MainDialog(void)
{
//need to add waiting for thread termination
}void
MainDialog::onTextReady( QString _text )
{
m_receivedTextLabel->setText( _text );
}void
MainDialog::onSend()
{
//m_sharedMemory.lock();
char to = (char)m_sharedMemory.data();QString text = m_whatToSend->text();
QChar *data = text.data();
while ( !data->isNull() )
{
memset( to, data->toLatin1(), 1 );
++data;
++to;
}
memset( to, 0, 1 ); //null terminator
//m_sharedMemory.unlock();
//m_sharedMemory.lock();//resume other process
m_semaphoreWriteDone.release();//this one will block client again, however, it could take time for client to read data, so generally
//we should send data also from separated thread if we don't want to block gui
m_semaphoreWriteDone.acquire();
}
@ -
Thanks very much for the example and for the hints, I'll be working on it :)