Serializzare e condividere un QHash via QSharedMemory…

Salve gente.

Piccolo esempietto con le librerie Qt: serializziamo e condividiamo fra due processi un QHash via QSharedMemory.

Spero che l’esempio sia chiaro. Per testarlo, lanciare due volte il programma (in due terminali diversi).

Ciau! ^^

Codice d’esempio

/**
 *	FILE      : QHashInShm.cpp
 *	AUTHOR    : Gian Paolo "JP" Ghilardi (http://rejex.wordpress.com)
 *	LICENSE   : released under the terms of GPL v2.0 ("only")
 *	COMPILE   : via QtCreator (choose Qt Console Application template)
 *	PURPOSE   : simple Qt-based example showing how to serialize/deserialize
 *	            a QHash object and write/read it from shared memory
 *	TEST      : launch two time this program in a terminal. The first one
 *                  will start writing data to shared memory ("writer process")
 *	            while the second will read and print it ("reader process")
 *
 *	TESTED ON :
 *	- MacOSX 10.5.8, PPC 32-bit, G++ 4.0.1, Qt Libs 4.6 (QtCreator 1.3)
 *
 *	REFERENCES:
 *	[1]: http://en.wikipedia.org/wiki/Shared_memory
 *	[2]: http://en.wikipedia.org/wiki/Serialization
 *	[3]: http://doc.trolltech.com/4.6/ipc-sharedmemory.html
 *	[4]: http://efforts.embedded.ufcg.edu.br/qt/?p=145
 */

#include <QtCore/QCoreApplication>
#include <QBuffer>
#include <QDebug>
#include <QSharedMemory>
#include <QHash>

#define OUT     // used to visually remember objects to be filled
                // before returning from a function

typedef QHash<QString, QString> QDict; // for easy manipulation

/**
 * Serializes data in a QDict object and writes them to a QSharedMemory object
 * @param shm reference to a valid QSharedMemory object (created by caller)
 * @param source const reference to the QDict object to be serialized and
 *               written into the shared memory
 * @param createShm flag used to require space into the shared memory
 *                  (default is false - no shared memory creation)
 * @return true if all operations succeeded; false otherwise
 */
bool writeToShm(OUT QSharedMemory &shm,
                const QDict &source,
                bool createShm = false)
{
    QBuffer buffer;
    QDataStream out(&buffer);

    buffer.open(QBuffer::ReadWrite);    // data serialization
    out << source;

    int size = buffer.size();
    if (createShm && !shm.create(size)) // shared memory creation (if requested)
    {
        qDebug() << "Error while creating the shared memory!";
        return false;
    }

    shm.lock();
        char *to = (char*)shm.data();  // writing serialized data to shared mem
        const char *from = buffer.data().data();
        memcpy(to, from, qMin(shm.size(), size));
    shm.unlock();

    return true;
}

/**
 * Deserializes data read from shared memory to a QDict object
 * @param shm reference to a valid QSharedMemory object (created by caller)
 * @param destination reference to a QDict object that will receive
 *                    the deserialized data read from the shared memory
 * @return true if all operations succeeded; false otherwise
 */
bool readFromShm(QSharedMemory &shm,
                 OUT QDict &destination)
{
    QBuffer buffer;
    QDataStream in(&buffer);

    shm.lock();
        buffer.setData((char*)shm.constData(), shm.size()); // deserialization
        buffer.open(QBuffer::ReadOnly);
        in >> destination;
    shm.unlock();

    return true;
}

/**
 * Starting function for this program. If you launch this program two times, the
 * first "instance" will create the shared memory object and will periodically
 * write values in it; the second "instance" will read those values from the
 * shared memory and will print them on screen.
 */
int main(int argc, char *argv[])
{
    QDict dict;
    QSharedMemory shm("QDictInShm");
    qDebug() << "Simple Qt example showing how to share a QHash object via shm";

    if(shm.attach()) // "reader process" part
    {
        qDebug() << "[Reader Process]";
        for(int i=0; i<4; i++)
        {
            qDebug() << "- reading from shm:";
            readFromShm(shm, dict);

            foreach(QString key, dict.keys())
                qDebug() << "  [" << key << "]: " << dict[key];

            qDebug() << "";
            sleep(5);
        }

        // job done. if writer finished and detached, shm will now be
        // automaticaly freed at this point, )
        shm.detach();
    }
    else // "writer process" part
    {
        dict.insert("A", "AValue");
        dict.insert("B", "BValue");
        dict.insert("i", QString::number(0));
        dict.squeeze(); // compact/reclaim unused space

        qDebug() << "[Writer Process]";
        qDebug() << "- creating shm segment and writing into it...";
        writeToShm(shm, dict, true);

        for(int i=1; i<4; i++)
        {
            sleep(5);
            dict["i"] = QString::number(i); // change the value (space allocated unchanged)
            qDebug() << "- writing into shm...";
            writeToShm(shm, dict);            
        }

        // job done. if the reader process is still attached,
        // shm won't be freed until it finishes
        shm.detach();
    }

    return EXIT_SUCCESS;
}

Il codice in esecuzione

Questo è l’output del programma in esecuzione (si notino i due terminali aperti, uno per ciascun processo)…

QHashInShm Example - QHash+QSharedMemory example

Contrassegnato da tag , , , , ,

Lascia un Commento

Fill in your details below or click an icon to log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Log Out / Modifica )

Foto Twitter

You are commenting using your Twitter account. Log Out / Modifica )

Foto di Facebook

You are commenting using your Facebook account. Log Out / Modifica )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 259 other followers