[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?


  • Lifetime Qt Champion

    Hi,

    Who access the QSharedMemory ? Different threads or different processes ?



  • Different processes



  • I understand that you want to synchronize read/write without pooling. I would create separated thread and use QSystemSemaphore, or QSharedMemory lock/unlock methods, to wait for access and then I would signal other threads that shared data is ready.



  • 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 :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.