7.11.14

Running with pointers II

(This is the second in an occasional series of explorations of some of the stranger areas of C++ syntax.)

Let's assume that we're all familiar with the RAII idiom (which is basically a fancy way to say "using destructors to manage resources correctly"). So let's consider the following listing, and ask ourselves: what output might it produce, and "Is it safe?"

#include <stdio.h> // for printf()
#include <memory> // for std::unique_ptr<>

struct Lock {
    void lock() {
        printf("Lock::lock()\n");
        data = std::unique_ptr<int>(new int(23));
    }

    void unlock() {
        printf("Lock::unlock()\n");
        data.release();
    }

protected:
    // valid during lock: using unique_ptr for safety
    std::unique_ptr<int> data;
};

// RAII for safety
struct AutoLock {
    AutoLock(Lock &l): l(l) { l.lock(); }
    ~AutoLock() { l.unlock(); }

    Lock &l;
};

struct SafeCode: Lock {
    void safe() {
        AutoLock(*this);
        // we can access the data now...
        printf("My data is safe here!\n");
        printf("Locked data = %i\n", *data);
    }
};

int main() {
    SafeCode s;
    s.safe();
    return 0;
}

We have a type called Lock that has lock() and unlock() methods. These methods guard a resource which is only valid when the lock is locked. (For our purposes, the 'resource' we're managing is the number 23, and it is accessible directly through a member variable—neither of these are particularly defensible design decisions, but can be ignored.) We're even using a fancy C++11 unique_ptr to manage our resource to make sure we don't get burned by raw pointer errors (which might be ironic if it wasn't a terrible analogy). AutoLock wraps the lock's API in its constructor and destructor, which should ensure that Lock::data should be valid for the lifetime of an AutoLock object.

The type SafeCode inherits from Lock and provides a method called safe() which demonstrates the usage of AutoLock, which ought to be safe, right? It's right there in the name of the function.
So we'd expect to see this:

Lock::lock()
My data is safe here!
Locked data = 23
Lock::unlock()

SPOILERS: No, it's not safe. What I actually see, compiling with gcc -std=c++11 on Ubuntu 14.04 is this:

Lock::lock()
Lock::unlock()
My data is safe here!
Segmentation fault (core dumped)

Ouch. So what went wrong? The problem is actually with the definition of the AutoLock object at the start of safe(). We forgot to give it a name, so it is immediately destroyed after its creation, and more importantly, before we try to access the data. If we give it a name (so AutoLock lock(*this); or even AutoLock _(*this); would suffice) it will survive until the end of the scope it's contained in (i.e. the end of the function safe()).

We'll need to go digging in the standard to find out more. Section 12.2 (Temporary objects) contains verbiage which would indicate that the anonymous AutoLock instance is "a temporary whose lifetime is not extended by being bound to a reference". Because it has no name, it cannot possibly be referenced again after its introduction, so the compiler is justified in placing the call to its destructor immediately after the object is constructed. (We will leave aside the question of why we are allowed to create an anonymous instance like this, and if this is ever legitimate—please post a comment if you have a situation where defining an anonymous temporary variable like this is a valid and useful technique.)

The use of unique_ptr<> is pretty much a red herring, I just threw that in to dissuade critiquing which might've resulted from int *data; in the definition of Lock. (And, I suppose, smart pointers are now standard, so we should use them given the option. Unless, I also suppose, you really are concerned about performance, and you have a profile trace demonstrating that the use of a smart pointer is your performance bottleneck. But this is a lot of parenthetical supposition.) One thing I will say though, is that at least unique_ptr causes the broken code to crash—with a raw pointer, the program happily reported that the value of data was zero, and continued to run to completion. Although given the nature of the bug, we could assume that literally anything could happen.

"Forget it Jake, it's undefined behaviour..."

30.10.14

Trigonometry in awk

I've been doing a lot of work with OpenGL recently, attempting to get some glBegin()/glEnd()-era 'rendering' code into some kind of shape where I can port it from desktop OpenGL to mobile and web platforms running OpenGL ES or WebGL. This basically meant throwing the existing code into a well, burning it, learning how to OpenGL properly and starting again, but that's all going quite well—I've even started writing shaders! 1

This post, however, is not about that. Having got to a point where I have a basic 2D GL3.0/GLES2.0 framework in place, I wanted to actually draw something. Triangles are almost too easy to draw, and squares aren't much harder (you can either use glDrawArrays(GL_TRIANGLE_STRIP) or glDrawElements(GL_TRIANGLES)).

So, with mastery of 3 and 4 vertex shapes, I wanted to move on to the next challenge, which is obviously... a pentagon. But how to figure out the co-ordinates? The math behind regular polygons is pretty straightforward, so we just need to take sines and cosines of some angles. I thought that jumping into C++ for this was a bit over the top, and I wasn't in the mood to mess around with any 'batteries-included' interpreters. I just want something quick, light and iterative—agile, if you will. I wonder whether awk has any numeric capabilities...

Spoiler: It does!

#!/usr/bin/awk -f
BEGIN {
    PI = 3.141592654

    if("" == (SIDES = ARGV[1])) {
        SIDES = 5
    }
    if("" == (COMMENT = ARGV[2])) {
        COMMENT = "#"
    }

    print COMMENT " " SIDES "-sided regular polygon..."

    print COMMENT " vertices"
    for(n = 1; n <= SIDES; n++) {
        A = 2 * PI * n / SIDES
        printf "%.2f, %.2f,\n", cos(A), sin(A)
    }
    print COMMENT " texcoords"
    for(n = 1; n <= SIDES; n++) {
        A = 2 * PI * n / SIDES
        printf "%.2f, %.2f,\n", (.5 + cos(A)/2), (.5 + sin(A)/2)
    }
}

One of the niceties of awk is that there's no operator for string concatenation, you just glom string variables and constants together next to each other and it 'just works', which makes print statements a lot less noisy than most other languages. Another nice thing is that printf is available, and works exactly as you'd expect it would. Other than that, we only really need sin(), cos() and the ability to loop, and we're finished.

When run, this spits out data for vertex coordinates (ranging -1.0 to 1.0) and texture coordinates (ranging 0.0 to 1.0) for each point around the edge of a regular polygon (defaulting to a pentagon if no parameters are given).

$ ./poly.awk
# 5-sided regular polygon...
# vertices
0.31, 0.95,
-0.81, 0.59,
-0.81, -0.59,
0.31, -0.95,
1.00, 0.00,
# texcoords
0.65, 0.98,
0.10, 0.79,
0.10, 0.21,
0.65, 0.02,
1.00, 0.50,

It can generate coordinates for any number of sides, and there's even an optional parameter to change the comment syntax, so you can just copy and paste the output into the vertex array literal of your language of choice.

$ ./poly.awk 3 //
// 3-sided regular polygon...
// vertices
-0.50, 0.87,
-0.50, -0.87,
1.00, 0.00,
// texcoords
0.25, 0.93,
0.25, 0.07,
1.00, 0.50,
$ ./poly.awk 6 --
-- 6-sided regular polygon...
-- vertices
0.50, 0.87,
-0.50, 0.87,
-1.00, -0.00,
-0.50, -0.87,
0.50, -0.87,
1.00, 0.00,
-- texcoords
0.75, 0.93,
0.25, 0.93,
0.00, 0.50,
0.25, 0.07,
0.75, 0.07,
1.00, 0.50,

awk's execution model is geared towards reading files line-by-line, extracting patterns and processing them, so this isn't really playing to its strengths. But nevertheless, treating it like a high-level, loosely typed version of C, I was able to get from idea to implementation to refinement in about 10 minutes. (And then I was able to render a coloured, shaded OpenGL pentagon and it made me happy. I am easily pleased.) I think awk is a useful tool to get to know, seeing as it's almost certainly already installed on your machine2.

The Android NDK goes as far as to use awk to build a full XML parser (of sorts), which is entertaining, if not a little bit bonkers.

Here's a terrible-looking graphic of the Emscripten-powered pentagon!



1 I should probably write about cross-platform shader development at some point, it's all manner of fun!
2 Not you, Windows user! You'll have to make do with PowerShell.

10.9.14

Setting up a fossil server

When I'm working on personal projects, I've usually used a pen and paper to keep track of design issues, bugs to be fixed and so on, but I've recently found myself wanting an actual issue tracking database. My requirements are actually pretty straightforward:
  • Must be accessible from a browser
  • No PHP
  • Easy to set up
  • Use SQLite as a database backend if possible (see previous point)
I did some searching and reading around, and I thought about Apache Bloodhound, but I was scared off by the installation instructions. I also briefly looked at Trac which Bloodhound is apparently a fork of, but again, a baffling and intimidating installation procedure left me cold.
Next up Bugzilla, which I spent about 20mins trying to set up, installed a lot of Perl modules, and got some incomprehensible (and even worse, un-google-able) timezone error, so I didn't even get as far as trying to set up an instance of Apache webserver, which I wasn't expecting to enjoy anyway. At least with this one, I tried!
During my earlier research, I had read about fossil, as if you type issue tracker SQLite into a search engine of your choice, fossil will be on the first page of results. This is because it and SQLite are both written by the same person. I'd disregarded fossil as its primary purpose seems to be as a DVCS that happens to have bug tracking (and a wiki!) as additional features on the side. However, it's very very easy to set up a fossil server from a standing start. So very easy, in fact that I managed to get it up and running in under ten minutes, on a server running Debian 6:
After sshing into the box, I installed the distribution version of fossil with apt-get, and created a new user called fossil (because I am terrible at naming things, it turns out).
$ su
# apt-get install fossil
# adduser fossil
Follow the adduser prompts with with password and other information as desired here…
Now, as the fossil user, create a new database in the home directory (called bugs.db—names; terrible).
# su fossil
$ fossil new ~/bugs.db
Make a note of the username/password for your admin account of the fossil site in the output from this command (the username is probably fossil if you specified that to adduser), as you won't be able to do anything useful to the server without admin access. At this point, we could start the server running, but we want to configure it to start up when the machine starts up, so we need to go back to root and edit rc.local:
$ exit
# vim /etc/rc.local
Add this line to the end:
su fossil -c 'fossil server ~/bugs.db'
That's literally all you need to do. Reboot the server and boom, the server should be listening on port 8080 when the server comes back up, and you can log in using the username and password noted earlier. If you want to be all fancy and route HTTP traffic from port 80 over to 8080, you can add another line to rc.local, just before you kick off the fossil server:
iptables -t nat -A PREROUTING -i venet0 -p tcp --dport 80 -j REDIRECT --to-port 8080
If you're anything like me, you'll probably want to spend the next hour or so tweaking the site's CSS and HTML templates and making it your own.
Fossil is a triumph of minimalism—it is literally one single executable file and one database file. It contains a DVCS, wiki, issue tracking and source control browser with a web interface. I'm primarily only interested in the bug tracking for the time being, as at the moment I still want to keep my source code in SVN. But, now that I have a fossil repository available to me, I might want to import my history and give myself the option to work offline, git-style. Another possibility is that I can use the fossil repository to hold releases of my projects, and I can accept and version control patches and bugfixes for each release. Having a (bare-bones) wiki up and running is also nice.
The moral of this story is that from an installation perspective, fossil definitely beats out the competition here. It's not as configurable or as extensible as other solutions, but that doesn't really matter to me if I can't get the other solutions to run in the first place!