Christian's Projects » C++ http://www.incasoftware.de/~kamm/projects Mon, 26 Jun 2017 20:29:06 +0000 en-US hourly 1 http://wordpress.org/?v=3.5.1 Improving REQ sockets in ZMQ 4 http://www.incasoftware.de/~kamm/projects/index.static/2013/09/25/improving-req-sockets-in-zmq-4/ http://www.incasoftware.de/~kamm/projects/index.static/2013/09/25/improving-req-sockets-in-zmq-4/#comments Wed, 25 Sep 2013 10:12:30 +0000 Christian http://www.incasoftware.de/~kamm/projects/?p=166 I contributed two new socket options to libzmq 4.0: ZMQ_REQ_CORRELATE and ZMQ_REQ_RELAXED. They simplify usage of REQ sockets in situations where you would have had to reset the whole socket or switch to a DEALER socket with earlier versions. More specifically, you can now send a new request on a REQ socket when you’ve given up on getting a response for the preceding request.

ZMQ defines several socket types that can be used to implement different messaging patterns. REQ sockets provide the basic “send a request, wait for the response, send the next request, …” pattern and are used frequently. In practice things break though and you’re not guaranteed to actually get a response to a request. The old REQ sockets strictly enforce the send/recv/send/recv/… cycle and have to be completely reset when a timeout is detected.

This is unintuitive and people have commented on it in several times.

With ZMQ_REQ_RELAXED enabled, calling send() while waiting for a reply becomes valid. It will give up on the old request and send a new one.

When enabling ZMQ_REQ_RELAXED, always enable ZMQ_REQ_CORRELATE as well. It ensures the receive call only reports the reply to the latest request. Otherwise, if the old reply comes in after all, you might receive that and think it’s the reply for the later request.

The new option only changes the behavior for send() in a state where it would previously have returned an EFSM error. It is safe to enable it in nearly all cases. libzmq wants to make it as easy as possible for users to migrate to new versions, however, so it is not enabled by default.

Contributing to libzmq has been simple and rewarding. They use a interesting “merge first, review later” process which sounds problematic – but which seems to work for them and definitely made me feel welcome as a contributor.

]]>
http://www.incasoftware.de/~kamm/projects/index.static/2013/09/25/improving-req-sockets-in-zmq-4/feed/ 0
Getting more out of the range-based for statement in C++11 http://www.incasoftware.de/~kamm/projects/index.static/2013/03/06/getting-more-out-of-the-range-based-for-statement-in-c11/ http://www.incasoftware.de/~kamm/projects/index.static/2013/03/06/getting-more-out-of-the-range-based-for-statement-in-c11/#comments Wed, 06 Mar 2013 15:14:10 +0000 Christian http://www.incasoftware.de/~kamm/projects/?p=132 Among the most useful features added to C++11 is the range-based for statement. It is defined to be equivalent to the usual iterator-based loop from begin() to end() and makes standard iteration look way more appealing.

Keeping the noise out of a large fraction of iterator-based loops is great, but other common for loops are missing out! They have not received a convenient shorthand. Luckily, you can make some yourself by feeding the right containers to the range-based for statement.

For example, the regular counting loops

for (auto i = begin, e = end; i < e; ++i)
for (size_t i = 0, e = container.size(); i < e; ++i)

can be written as

for (const auto i : range(begin, end))
for (const auto i : indices(container))

if you define indices() and range() the right way.

Using the range-based version has no drawbacks: it is easier to read, quicker to write and compiles to equivalent assembly (calls to operator!= and operator++ get optimized away even at g++ -O1).

You can do a lot with the range-based for statement. What I have found useful so far is:

  • range(begin, end): for (auto i = begin, e = end; i != e; ++i)
  • range(end): same as range(0, end)
  • indices(container): same as range(container.size())
  • keys(container_of_pairs): shorthand for getting only value.first
  • values(container_of_pairs): shorthand for getting only value.second

The code is available on github under the Boost Software License. It has no external dependencies and using it should be as simple as putting the header file into your include path. It is also fairly minimal, implementing only what is needed to make it work. A lot could be added, like rbegin(), rend(), generic reverse(), correct iterators, …

The approach has its limits, and one of them is exposed when you implement something like enumerate():

for (auto e : enumerate(c)) {
    // e.index is the current index
    // e.value is the current value
}

For standard containers (as well as the keys() and values() ranges above) the type in the for statement controls whether you get a copy or a reference of what you are iterating over as well as whether it should be const or not:

for (const auto e : c) // e is a const copy
for (auto & e : c) // e is a mutable reference

That can only work as long as what you want to put into e is an lvalue (i.e. c.begin() is an output iterator). It breaks down for enumerate() which cannot return a reference without extra overhead.

That is why I decided to split enumerate() into two functions. enumerate_byref() always grabs ‘value’ by reference and enumerate_byval() makes a copy. Usage then becomes:

for (const auto e : enumerate_byref(container))
    e.value = true; // ok, modifies container!
for (auto e : enumerate_byval(container))
    e.value = true; // ok, changes copy

Which is far from the ideal syntax, but at least it is explicit about what is going on.

Thanks to my employer, CeleraOne GmbH, for permitting me to publish this.

]]>
http://www.incasoftware.de/~kamm/projects/index.static/2013/03/06/getting-more-out-of-the-range-based-for-statement-in-c11/feed/ 3
Recent activity http://www.incasoftware.de/~kamm/projects/index.static/2011/11/03/recent-activity/ http://www.incasoftware.de/~kamm/projects/index.static/2011/11/03/recent-activity/#comments Thu, 03 Nov 2011 19:52:03 +0000 Christian http://www.incasoftware.de/~kamm/projects/?p=125 Over the last year I’ve been focusing on Qt Creator and have done several posts on the Qt Labs blog:

]]>
http://www.incasoftware.de/~kamm/projects/index.static/2011/11/03/recent-activity/feed/ 0
Star Guard level editor http://www.incasoftware.de/~kamm/projects/index.static/2010/05/06/star-guard-level-editor/ http://www.incasoftware.de/~kamm/projects/index.static/2010/05/06/star-guard-level-editor/#comments Thu, 06 May 2010 17:22:28 +0000 Christian http://www.incasoftware.de/~kamm/projects/?p=85 I spent the last few evenings working on a fun side project which is now complete: a level editor for Loren Schmidt’s Star Guard.

first level of Star Guard

the first level of Star Guard

the same scene in the editor

the same scene in the editor

A few things came together that caused me to make this level editor:

  • I was looking for an excuse to do something interesting with QML.
  • Star Guard is a great game and stores its levels in friendly, easily accessible XML files.
  • When I emailed Loren about the project, he allowed me to use some of the game’s artwork.

The whole thing was surprisingly easy to do, took a couple of days and amounted to less than 1200 lines of code – one half of it QML and the other C++.

If you don’t know about QML: It’s a fairly new part of the Qt framework, essentially an extension of JavaScript to build user interfaces declaratively – and great fun to work with. All the details can be found on its documentation page and if you want to get started, the Qt 4.7 beta1 packages have just been released.

The editor uses QML to describe every aspect of the user interface. It’s turned out to be very useful in the beginning of the project when the editor was still QML-only and the interface layout and behavior changed a lot. It also means that it’d be very easy to redo the user interface now – even for someone without any C++ knowledge. Also, not having to recompile after every step simply makes fiddling with the UI a lot more pleasant.

Of course there’s the disadvantage of not following the native look and feel. But no one ever complains that most games don’t use it – and I don’t think it’s necessary for a level editor to look just like your spreadsheet application either.

The C++ part deals with the backend work, like providing a model that holds the map, a QML item that paints it, and loading from and saving to files. I used the QML plugin mechanism to expose these to the UI code.

The editor is fully functional; I consider it done and will not continue working on it. If someone wants to improve it or base his own tile based level editor on it, feel free! I release the code under the Boost Software License 1.0.

Linux binary (64 bit) and source code (12 MB)
Windows binary and source code (10 MB)
source code only (.tar.bz2, 20 kB)
source code only (.zip, 30 kB)

]]>
http://www.incasoftware.de/~kamm/projects/index.static/2010/05/06/star-guard-level-editor/feed/ 0
Compilers for the D programming language: DMD, GDC and LDC http://www.incasoftware.de/~kamm/projects/index.static/2008/07/09/compilers-for-the-d-programming-language/ http://www.incasoftware.de/~kamm/projects/index.static/2008/07/09/compilers-for-the-d-programming-language/#comments Wed, 09 Jul 2008 17:12:26 +0000 Christian http://www.incasoftware.de/~kamm/projects/?p=8 Currently, users of the D programming language can essentially choose between two mature compilers: DMD and GDC. I’ve started helping with the development of a third, LDC, and think the first public alpha version can’t be far off. In this post, I’ll give a short overview of the compilers available and say a few words about LDC.

First, there is the reference compiler DMD that is maintained and improved by D’s inventor Walter Bright. It has a stable branch for D 1.0 as well as a bleeding edge counterpart for version 2.0 of the D specification that’s still under development. One part of it, the front-end responsible for parsing code, building a syntax tree and running semantics, is open source, available under the GPL or Artistic license. Its back-end, however, is not available and thus only Walter can compile DMD.

This is not a failing in itself. Indeed most users will never have the need or desire to compile their compiler from source. Yet it also prohibits testing patches for the front-end, makes debugging nigh impossible and generally complicates helping with DMD’s development.

The alternative – and often the only alternative if your target is not x86 Linux or Windows – is GDC. David Friedman took the open front-end and tied it to the GCC back-end, he even supports D 2.0 to some extend. While it works well and is fully open source, it has, unfortunately, remained a one-man effort. For me it was a combination of GCC’s daunting code base and the fact that there had been no activity for several months that stopped me from helping out.

Instead I eventually joined a different project: LDC. It is similar to GDC in that it also takes the open DMD front-end and aims to combine it with an equally free code generator. The back-end, though, is different: as the name suggests LDC emits LLVM bitcode, which can be compiled to native code, but could also be used for Just-in-Time compilation among other things. I’m also happy to say that even though LLVM is a large and ambitious project, it remains surprisingly easy to learn and work with.

Almost the first thing I did when I started contributing to LDC a few months back, was to integrate Thomas Kühne’s exhaustive DStress test suite with LDC: it is very useful for finding bugs and regressions and can even serve as a sort of crude progress indicator (crude because there is no relationship between number of bugs and number of tests; there are about 1000 tests for inline assembly and only 30 or so for exception handling). As you can see, there are still a handful (517 at the last count) of regressions with respect to DMD, but their number has been decreasing steadily.

In the last months, Tomas Lindquist Olsen, who started the project about a year ago and is responsible for almost all of its existing functionality, and I have added the last major missing parts to the compiler: inline assembly (thanks to David Friedman for the asm parsing and rewriting code!), exception handling and the synchronized statement are now supported. With these out of the way, goals for the future are squashing bugs, fixing some linking issues and getting LDC to work properly on Windows.

Speaking of other platforms: As Tomas and I both develop on x86 Linux, other configurations didn’t get much testing yet. Some people reported partial successes on FreeBSD and Sparc but more testers would be welcome. You can generally contact us by email or in #ldc on freenode. All in all, we’ve made great progress and if we can keep it up, LDC will be in the same league as DMD and GDC soon.

]]>
http://www.incasoftware.de/~kamm/projects/index.static/2008/07/09/compilers-for-the-d-programming-language/feed/ 6
MATLAB file access http://www.incasoftware.de/~kamm/projects/index.static/2007/10/05/matlab-file-access/ http://www.incasoftware.de/~kamm/projects/index.static/2007/10/05/matlab-file-access/#comments Fri, 05 Oct 2007 19:51:57 +0000 Christian http://www.incasoftware.de/~kamm/projects/index.static/2007/10/05/matlab-file-access/ Quite a while ago I was looking at ways to interface between MATLAB and a C++ program for a job at university. In the end I wrote a C++ wrapper for the C API to access MAT files which turned out to be quite useful. Since it’s small and easy to use, I decided to release it.

At first the plan was to make the program into a MEX file (basically a dynamically linked extension program), but I quickly ran into a problem with deal II (an excellent, well documented and object-oriented library for solving partial differential equations with adaptive finite elements): MATLAB altered some of the floating point precision settings which lead to an algorithm in deal II running in an infinite loop (the epsilon value was hardcoded at that time and basically became zero). While the bug was promptly fixed, there were other issues and it was decided that embedding the program was not worth the trouble.

Long story short, I needed a way to read and write the MAT files that MATLAB generates and loads with the ‘load’ and ‘save’ commands. Using the C API directly seemed cumbersome and error prone, so this C++ wrapper was born.

Download it (4 kB) as .tar.bz2 or as zip.

A basic use case looks like this (also check out test.cc):

#include "matlabfile.h"
using namespace MatlabUtilities;
 
File matfile("some.mat");
std::vector<double> vec1;
matfile.read<Types::real_vector>("v1", vec1);
 
double[100] vec2;
matfile.read<Types::fixed_length_real_vector<100> >("v2", vec2);
 
matfile.write<Types::string>("hw", "Hello World!");

Not all MATLAB types are implemented (check Types namespace in matlabaccessors.h for a list), in particular real matrices with a column and row length different from one are missing for two reasons: I didn’t need them for the job and you probably have your own preferred matrix type anyway. But don’t worry, the template-design makes it easy to add these missing features. What needs to be implemented is

struct real_matrix {};
 
template <>
struct Reader<real_matrix, MyMatrix> {
    static void read(mxArray* var, MyMatrix& result);
}
 
template <>
struct Writer<real_matrix, MyMatrix> {
    static mxArray* write(MyMatrix& source);
}
 
template <>
struct TypeCheck<real_matrix> {
    static bool typeCheck(mxArray* var);
}

where the ‘read’ function reads data from the mxArray into result, ‘write’ returns a new mxArray filled with source’s data and ‘typeCheck’ returns true if the mxArray contains a real_matrix. With these template specializations in place you can use the new code like this:

MyMatrix mat;
matfile.read<real_matrix>("somevarname", mat);
matfile.write<real_matrix>("someother", mat);

Similarly, you can add a new reader to say ‘real_vector’ to accomodate for your own vector type.

The code snippet only contains code for reading and writing data. Other management functionality, like listing all fields in a MAT file is not implemented. I hope it will nevertheless be useful for someone.

]]>
http://www.incasoftware.de/~kamm/projects/index.static/2007/10/05/matlab-file-access/feed/ 5