Pumpin’ ain’t easy

An example in my last post used a Grantlee::Pump to transfer data from one QIODevice to another. I’ve just added the Pump class to the Grantlee::Tubes library.

Pumping tends to limits of capacity and drainage

QIODevice provides an asynchronous API for clients to use. A call to readAll() will return available data from the device, but with turning of time and the event loop, more data may eventually become available.

  QTcpSocket *socket = getSocket();
  QFile *logFile = getLogFile();

  // Read all data from the socket and write it to the log file as it becomes available.
  Grantlee::Pump *pump = new Grantlee::Pump(this);
  pump->setSource(socket);
  pump->setTarget(logFile);

The Pump encapsulates the handling of the readyRead() signal so that clients don’t need to do that themselves.

Actually, pumpin’ IS easy

I used this class just a short time ago as a debugging tool. Working on an embedded platform with only a single serial cable can be a significant constraint. While evaluating performance on the system I was attempting to run top -d 1 -b & and then starting the target application along with a command line interface to the application. The problem is that any attempt to make top run and record in the background failed. The command line interaction system seemed to conflict with proper execution of top, which simply terminated.

Enter QProcess with Grantlee::Pump.

The trick was to make QProcess run top instead of starting it over the serial connection. The output of top (batched) would be written out by QProcess. Of course, QProcess implements QIODevice, so all I needed to do was pump from the QProcess into a QFile:

int main(int argc, char **argv) 
{
  QProcess topProc;
  topProc.start(QLatin1String("top"), QStringList() << QString::fromLatin1("-d") << QString::fromLatin1("1") << QString::fromLatin1("-b"));

  QApplication app(argc, argv);

  QFile logFile(app.applicationDirPath() + QLatin1String("/topoutput"), this);
  logFile.open(QFile::WriteOnly);

  Grantlee::Pump pump;
  pump.setSource(topProc);
  pump.setTarget(logFile);

  int exitCode = app.exec();

  logFile.close();
  return exitCode;
}

Of course, this is equally possible without Grantlee::Pump. The class does not solve a hard problem, but it solves it in an object orientated way, making it easy to use and reuse as part of larger systems.

Pump takes care of the limiting rate of drainage from the source device. To handle the limiting capacity of the target will require a different Tube.

4 Responses to “Pumpin’ ain’t easy”

  1. piotrdobrogost Says:

    Would there be any sense in allowing to limit the maximum size of data transfered in one pump? Could it improve responsivness in some scenarios?

  2. QIODevice Cat is(-not)-a QIODevice « Steveire's Blog Says:

    […] Steveire's Blog Cute model enthusiast « Pumpin’ ain’t easy […]

  3. steveire Says:

    @piotrdobrogost:

    I don’t have any such plans yet. The Pump assumes it can write to its target pretty much immediately and it doesn’t need to cache anything. It’s designed for entirely for pass-through purposes currently.

  4. An elaborate joke? « Steveire's Blog Says:

    […] an appearance in my last post. The idea is to solve a connection problem with QIODevices. While Pump can transfer data from a device that should be read to a device that should be written to, […]

Leave a Reply

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

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: