Skip to content


Marin Bobcat Trail bike maintenance

I just spent a few days overhauling my aging mountain bike. It was an interesting (and at times frustrating) process, partly due to this being the first time I’ve done anything like it, and partly due to the apparent lack of maintenance manuals for the bike or many of its components. I thought it might be useful to put together a brief Marin Bobcat Trail maintenance manual, in the hope it’s useful to someone else who owns the 2008 or 2009 edition of the bike. I’m new to this, so it’s probably a laughable effort in cycling circles, but it’ll be useful to me next time I overhaul the bike anyway. Feedback welcome at the address given in the document!

Posted in General.

Tagged with , .


Weston frame buffer backend

Just over a week ago everyone’s favourite Xorg replacement, Weston, gained a frame buffer backend I put together as part of some university work. It was remarkably easy to write, since almost all of the code already existed in the DRM and RPI backends; I just needed to hook pixman up to /dev/fb0 and everything worked!

Weston’s code base was a pleasure to work on. Hopefully someone stuck on a frame buffer somewhere finds this work useful. Since I did this work, I also got the frame buffer backend working on FreeBSD (as part of the same university project), but haven’t had time to update, tidy up and submit my patches yet. They’re pretty hacky in (many) places.

Without further ado, a gratuitous flowery screenshot (taken using fbcat):

Weston running on a Linux frame buffer, taken on 2013-01-15.

Weston running on a Linux frame buffer, taken on 2013-01-15.

Posted in General.

Tagged with , , , , , , .


Single-thread synchronisation in Vala

In libfolks, there are some asynchronous prepare() methods, which may be called multiple times, but must only change program state when called for the first time — subsequent calls must do nothing. As the prepare() method is asynchronous, and yields on other asynchronous methods, control may be yielded to the main loop part-way through running. At this point, another call to prepare() could happen from the same thread; and without adequate synchronisation the second call would proceed to change program state a second time. This is bad. (Throughout this post I’m only considering calls from a single thread; multi-threaded concurrency is completely different, and can rely on locking for safety.)

What are the possible solutions?

  • Locking.
  • Condition variables.
  • Boolean “prepare() in progress” flag.

Locking and condition variables can’t be used because the prepare() calls may come from any thread. Vala uses recursive locks, so calls from the same thread wouldn’t get blocked at all. If non-recursive locks were used, calls from the same thread would cause a deadlock.

A boolean “prepare() in progress” flag is what folks used to use. This was set to true as soon as the first asynchronous call began, so it prevented subsequent calls from changing program state erroneously, but also meant that subsequent calls returned immediately. Returning from a prepare() call typically implies that preparation has completed — but with this implementation that wasn’t correct for anything except the first call to prepare(). How can a call know that it’s not the first call? It can’t. This solution is unsatisfactory.

The solution which has just been implemented in folks is to use a list of waiting continuations for all calls subsequent to the first. The first call will execute all these continuations once it’s finished. This solution feels quite elegant to me, but suggestions from improvement are more than welcome.

A code example and explanation:

public class Logger : GLib.Object
{
  private static Logger _logger;
  private static DelegateWrapper[] _prepare_waiters = null;

  public async void prepare () throws GLib.Error
    {
      if (Logger._logger == null && Logger._prepare_waiters == null)
        {
          /* If this is the first call to prepare(), start some async calls. We
           * then yield to the main thread. Any subsequent calls to prepare()
           * will have their continuations added to the _prepare_waiters list,
           * and will be signalled once the first call returns. */
          Logger._prepare_waiters = new DelegateWrapper[0];

          /* Insert asynchronous initial preparation code here. */
          Logger._logger = yield new Logger ();

          /* Wake up any waiters. */
          foreach (unowned DelegateWrapper wrapper in Logger._prepare_waiters)
            {
              wrapper.cb ();
            }

          Logger._prepare_waiters = null;
        }
      else if (Logger._logger == null && Logger._prepare_waiters != null)
        {
          /* Yield until the first ongoing prepare() call finishes. */
          var wrapper = new DelegateWrapper ();
          wrapper.cb = prepare.callback;
          Logger._prepare_waiters += (owned) wrapper;
          yield;
        }

      /* Put shared code here which is executed on every call to prepare().
       * For example, it could check for failure in the results of the
       * initial call and throw an error as appropriate. */
      if (Logger._logger == null)
        {
          /* Throw an error or something. */
          return;
        }
    }
}

/* See: https://mail.gnome.org/archives/vala-list/2011-June/msg00005.html */
[Compact]
private class DelegateWrapper
{
  public SourceFunc cb;
}

(For the full code to this example, see folks’ source code.) The first call to prepare() is meant to asynchronously set the static Logger._logger variable. Subsequent calls must not re-initialise this variable, but should block until the variable has been set.

How does this work? The first call to prepare() finds Logger._logger is null and Logger._prepare_waiters is also null, so it falls into the initialisation block. It sets Logger._prepare_waiters to be an empty array (which is distinct from null), then proceeds to initialise Logger._logger asynchronously. Since the initialisation is asynchronous, control returns to the main loop, and a second call to prepare() could be made. Assume it is. The second call finds Logger._logger is still null, but finds that Logger._prepare_waiters is non-null, and so falls into the second branch of the if-statement. This saves its continuation into the array of waiters, and then yields control to the main loop again, indefinitely delaying the second asynchronous call from finishing. The first call returns from its asynchronous initialisation code, and proceeds to “Wake up any waiters”. For each of the saved waiters, it calls the waiter’s continuation (in an idle callback), which resumes execution just after the yield statement. Consequently, each waiter executes the shared code at the bottom of prepare(), then its prepare() call finishes and any asynchronous callbacks are executed in normal GLib fashion. The first call then proceeds to the shared code at the bottom of prepare(). Finally, its asynchronous callback is executed, and everything’s finished.

This all hinges on the fact that Vala supports “delegates with targets” (or continuations): the prepare.callback in the code above. This is a copy of the runtime state of the prepare() call, complete enough that it can later be called (using wrapper.cb()) to continue execution as if it never stopped at the yield. In C terms, a delegate is a function pointer; a delegate with a target is a function pointer with a struct full of the values of local variables at the time the delegate was stored. This is similar to the this pointer in C++, but includes more local state.

Why is DelegateWrapper needed? Why can’t the array just contain the continuations directly? Good question. I’d like to know the answer. Vala throws an error message if one tries to define an array of delegates with targets (“Delegates with target are not supported as array element type”). Other methods of encapsulating the continuations result in just the delegate being stored, and the target (local state) being lost, which is not what we want. I got the tip to use a DelegateWrapper class from Jim Nelson in this mailing list post (thanks!).

So that’s it: one way to synchronise multiple concurrent asynchronous method calls in Vala.

Posted in GNOME.

Tagged with , , , , .


Adventures with an ATmega

As part of some university coursework, I’ve recently been playing around with an Atmel 8-bit microcontroller in a quest to build a data logger for home brewing. The aim is to log various sensor readings over the course of primary fermentation of a batch of beer to see how it’s progressing without having to disturb the brew.

While working with hardware is fun, it has the downside that you’re working with hardware. Things break as much as they do in software, but are harder to debug. A nice solution to this is to use a simulator to test the software, rather than using the hardware itself. I’ve been using the simavr simulator. It’s got all the right features, but more importantly its code is easy to understand and extend. In fact, most of the simulator is written as a library which one can build a simulated circuit board around.

I’ve built simulations of several of the components used in the brewing logger now, including an SD card and a flash memory. The code isn’t brilliant, but they’re working well enough to get my firmware booting. Hopefully they might be useful to other people too — hence the code is on gitorious. The SD card simulator is for a generic SDv2 card. The flash memory is for an ST M25P16 (but should support any of the M25P family, with a little work). The serial LCD is for a custom LCD daughter board provided by my university, so that’s probably not so useful. The RHT03 temperature/humidity sensor is general purpose; as is the DS3231 real-time clock.

Put together, and with a little extra work, these will allow closed loop testing of the microcontroller firmware — without ever having to go near the hardware itself. Bliss. (This is all under the misguided assumption that the simulations are sound and complete, but they’ll get there eventually.)

As an example of how easy simavr makes this, take a look at the code needed to instantiate and hook up the humidity sensor simulation:

/* Create the sensor. */
rht03_t rht03;
rht03_init (avr, &rht03);

/* Connect its bidirectional data pin to pin D3 on the microcontroller. */
avr_connect_irq (avr_io_getirq (avr, AVR_IOCTL_IOPORT_GETIRQ ('D'), 3), rht03.irq + IRQ_RHT03_DATA);
avr_connect_irq (rht03.irq + IRQ_RHT03_DATA, avr_io_getirq (avr, AVR_IOCTL_IOPORT_GETIRQ ('D'), 3));

Posted in General, Projects.

Tagged with , , , , .


Web APIs: a moving target

Google have recently announced version 3 of their YouTube API. This is great news for libgdata: it means we can have access to all the same functionality as before, just with a JSON flavour, rather than Atom.

Sarcasm aside, the last few years of working (on and off) on libgdata has made a number of things obvious about web APIs. Here are some ideas I’ve had for best practices for writing code which interacts with them. Some of these have made their way into libgdata; others would require an API break to implement. References to relevant examples of APIs in libgdata are given inline, but if something isn’t clear please leave a comment. As always, this list is probably incomplete and any additions or alterations to it would be appreciated.

  • Have a very general, flexible core API (example), and add a layer of specialisation on top of it (example). This allows client programs to use the general APIs to access new features in the web API if your library hasn’t yet caught up.
  • Use objects liberally. Objects can be extended with new properties without breaking API. Structs and function parameter lists cannot. Even if you end up creating objects with a single property (example), don’t create them as structs!
  • Don’t worry about CPU efficiency. The cost of creating objects or doing some ‘unnecessary’ extra processing to give your API more flexibility is nothing compared to the cost of a network round trip. Network round trips and memory consumption are the main costs.
  • As a corollary to the previous point, the API should be zero-copy for consumers. If possible, try to design the API so that programs using it won’t have to take copies of all the data they access, as this will end up doubling the memory consumption of the application unnecessarily. One way to do this (which is what libgdata does) is to make the objects returned by network requests effectively immutable — e.g. a query will return a new set of result objects each time it’s performed, rather than updating an existing set of them.
  • Always try to think one step ahead of the web API designers. This is part of making your API flexible: if you’re thinking about the directions the web API could go in and the features which could be added to it in future, you’ll be more prepared when the web API designers suddenly spring them on you. libgdata managed this with its authentication API, but didn’t manage it with the core feed/entry API.
  • Report bugs against the web API. In the case of libgdata, many of the bugs we reported have been ignored, but that’s not the point. By reporting bugs, you help other consumers of the web API, and give (a little) feedback to the web API designers as to how people are using, or expecting to use, the web API. (And also how broken it is.)
  • Make everything asynchronous (example). Absolutely everything which could result in a network request should be asynchronous, cancellable, and support returning errors (even if cancellation isn’t initially implemented and no errors are initially returned). This prevents having to break API in the future to make a method asynchronous. Methods which will result in network requests should be clearly separated from non-networking methods, e.g. by using a different naming scheme for them (my_object_request_property() versus my_object_get_property(), for example).
  • Design the API with batch processing in mind. Wherever possible, allow sets of objects to be passed to methods, rather than individual objects. If the web API doesn’t support batch processing, the method can just implement a loop internally. If it does, the use of batch processing allows for an order n reduction in network round trips. libgdata failed at this, having to tack batch operations onto the API as an afterthought (example). Fortunately (or perhaps unfortunately) it hasn’t been much of an issue because Google’s batch API never really went anywhere. Clients of libgdata have wanted to use batch functionality, however, and it would have been best implemented from the start.
  • Integrate concurrency control in the core of your API (example). Web APIs are interfaces to large distributed systems. As we’ve found with libgdata, concurrency control is important, both in managing conflicts between different clients (e.g. when concurrently modifying an object) — but also in managing conflicts between clients and internal server processes. For example, just after a client creates a document on Google Docs, the server will modify it to add missing metadata. These modifications (and the accompanying change in the object’s version number) are exposed to clients. Google’s APIs (and hence libgdata) implement optimistic concurrency control using HTTP ETags. All operations in libgdata take an ETag parameter. This works fairly well (ignoring the fact that some web API operations inexplicably don’t support ETags).
  • Don’t expose specifics of the web API in your API. Take a look at all the functionality exposed by the web API (and all the functionality you think might be added in future), then design an API for it without reference to the existing web API. Once you’re done, try to reconcile the two APIs to make sure yours is actually implementable. This means your API isn’t tied to some esoteric behaviour when the web API gets fixed. However, if done incorrectly this can backfire and leave your API unable to map to future changes in the web API. Your mileage may vary.
  • Testing is tricky. You want to test your code against the web API’s production servers, since that’s what it’ll be used against. However, this requires that the machine running the tests is connected to the Internet (which often isn’t the case). It also means your unit tests can (and will) spuriously fail due to transient network problems. The alternative is to test your code against an offline mock-up of the web API. This solves the issues above, but means that you won’t notice changes and incompatibilities in the web API as they’re introduced by the web API developers. libgdata has never managed to get this right. I suspect the best solution is to write unit tests which can be run against either a mock-up or the real web API. Automated regression testing would run the tests against the mock-up, but developers would also regularly manually run the tests against the real web API.

Posted in GNOME.

Tagged with , , , .


Interaction in team projects

I had an interesting experience over the summer, working in a small but diverse team on a single project for several months. I was contracted to design and maintain the build system, and so ended up getting involved in all areas of the project. As a result, I came across many of the problems which my team mates were having. A lot of these problems were my fault, some were my team mates’ faults; but a lot of the problems were a result of bad communication.

While this all occurred in a (unfortunately) closed source project, I’ve seen similar things happen in open source. I thought I’d come up with a list of suggestions for people starting out in the open source world, to try and help them understand the best way to interact with other people on the same project, or with their mentors in GSoC (for example). None of this is targeted at anyone in particular (especially not the GSoC students I had the pleasure of interacting with this summer)!

Thinking about this has been useful to me; hopefully I won’t do any of these things in future (because I certainly have in the past). I just hope it’s useful to someone, somewhere.

  • Don’t spam chats with half-written messages. Take your time and formulate your thoughts properly in a full sentence. Spamming messages just means the other conversant has to sit there and wait for the rest of the sentence, rather than getting on with something else.
  • Don’t join a chat, say “hi” or “someone please help” or “ping” and then sit there without giving more information. This just introduces an extraneous round trip in communication, since someone has to then ask what the problem is before they can start to help. Conversely, if someone joins a chat and says “someone please help”, don’t lecture them about it. Be patient, and help them as much as you can.
  • After asking a question in a chat, wait patiently for the answer to the question. Although they’d love to help, developers are not constantly looking at their chat client. If you leave a fully-formed question in the chat and then wait, a developer should answer in their own time.
  • If you encounter an error or warning (e.g. from a compiler or program) and want help with it, always provide the full error message and some context. The person who’s helping you isn’t psychic.
  • Always give context and be careful of over-using pronouns. “It’s running awfully slow” is not specific enough. What is ‘it’? What were you doing with ‘it’ when things slowed down?
  • Look at man pages and --help output before asking people. Documentation for established software (e.g. SVN) is generally quite good. The person who’s helping you will probably just look at the man page anyway.
  • Read VCS commit logs. Ideally, people will explain and justify all of their work in their commit messages, and mention things which you should be aware of. Reading the logs may well save you debugging later.
  • Use the correct terminology as much as possible, and don’t use that terminology in other contexts where it could confuse matters. Communication is a lot faster if a common vocabulary is used.
  • Learn your version control system and learn it well. It’s a tool you’ll be using every day, and making mistakes with it can be costly for your (uncommitted) work and/or for other people’s productivity. Always check the changes you’re about to commit, especially if conflicts have occurred. People will not take kindly to their work being overwritten because you’ve made a mistake, especially if it happens regularly.
  • If you’re making use of someone else’s code/APIs and you have a problem or can’t get it working, double check (against the documentation which they have written) that you’re using the code correctly. In many cases, the problem might be the way you’re invoking/using that code, not the work itself (thought such problems do suggest a lack of user friendliness in the work which could be fixed).
  • Always check to see if the code at least compiles before committing it to VCS. Committing something which doesn’t compile due to a trivial error shows a complete lack of testing or care. Compile it using the build system which everyone else uses, too. Manually invoking the compiler doesn’t count.

Posted in General, Gripes.

Tagged with , .


Obligatory post-GUADEC post

Many thanks to the local team for this year's GUADEC, which is definitely the best organised one I've been to. They were really hospitable, and had
sorted everything out, down to the last complementary apple.

I had some great evenings with friends at the Rialta and on the beach, and even got some hacking done (on automake macros, of all things). It was great
to see everyone again and, as always, meet new members of the GNOME community.

Thanks to the GNOME Foundation for sponsoring my accommodation at GUADEC. It was really nice to have so many of the conference attendees staying in
one place (with its own cheap bar), and to have the pre-registration party there.

Posted in GNOME.

Tagged with .


Bendy Bus and libfolks slides

Slides for my presentations on Bendy Bus and libfolks are now available from the GUADEC website (and here). Thanks to people for coming along. If anyone wants to get involved in Bendy Bus, please take a look at its gitorious page. For libfolks, join us on #folks on irc.gnome.org!

Posted in GNOME.

Tagged with , , .


GUADEC!

I've arrived at GUADEC! I'll be giving two talks this time: one on Bendy Bus, at 16:15 today (Thursday) in Room 3.2; and one on libfolks at 18:15 tomorrow (Friday) in Room 3.0. Come along if you've got nothing better to do.

Posted in GNOME.

Tagged with , , .


Bendy dissertation, Bendy GUADEC

Hot on the heels of Daniel Siegel, I've recently submitted my bachelor's dissertation to my university about the development of Bendy Bus. It's a much less impressive piece of work (and not bound as nicely) than Daniel's, but I too will be giving a talk about my dissertation at GUADEC, titled “Bendy Bus: fuzzily impersonating D-Bus services”. Come along to it to learn how to use Bendy Bus to fuzz test D-Bus clients. I might even prepare some slides, or something.

In time for submission of my dissertation, I released version 0.1.0 (and then the inevitable 0.1.1 and 0.1.2 brown paper bag releases) of Bendy Bus. You can get the source on gitorious, and the 0.1.2 tarball on my website. The manual's also available online (as well as in the tarball). Have a play!

(I'll also be giving a talk about libfolks, “folks of the future: more contacts everwhere”; more details to follow later.)

Posted in GNOME.

Tagged with , .