Qurp Updates

2015/4/19 06:36

Over on github Kramble Has very kindly added sound to qurp and improved the woeful input support which I had added some time ago. Kramble also sent me links to these two articles which cover the basics on linux input quite nicely. I've subsequently made a few changes myself to the input so that connecting and disconnecting the device is handled properly in game:

Initially I tried just dropping and reinitialising the file descriptors to the dev/input/event* files every second or so, which is dumb but works. Unfortunatley the calls to close() were just too slow and caused noticable juddering in the game. So after a bit of googling it seems that the udev (http://www.signal11.us/oss/udev/) library can be used to monitor the plugging in and removal of devices.

Most of what follows is a slight refactoring of the udev sample code which can be found here http://www.signal11.us/oss/udev/udev_example.c . There is also the Reference Manual The full source code can be found in the platform.pi.c file on the git repo.


// setup udev stuff so we can enumerate and monitor 
// devices being connected or disconnected.
// Create the udev object
pState->udev = udev_new();
if (!pState->udev) {
    printf("Can't create udev! \n");

// Initial enumeration and registering of input devices.
// we only do this for "event" inputs
    struct udev_enumerate *enumerate;
    struct udev_list_entry *devices, *dev_list_entry;
    struct udev_device *dev;

    enumerate = udev_enumerate_new(pState->udev);
    udev_enumerate_add_match_subsystem(enumerate, "input"); //only enumerate for kb/mouse etc
    devices = udev_enumerate_get_list_entry(enumerate);

    udev_list_entry_foreach(dev_list_entry, devices) {
        const char *path, *devnode;
        path = udev_list_entry_get_name(dev_list_entry);
        dev = udev_device_new_from_syspath(pState->udev, path);
        devnode = udev_device_get_devnode(dev);

        if (devnode != NULL){
            // This opens the "dev/input/event*" file
            // which we can monitor as before for input events
            RegisterInputDeviceByName(pState, devnode);				

// Create a monitor for input devices being added or removed
// The monitor is polled on the Tick Function
pState->p_device_monitor = udev_monitor_new_from_netlink(pState->udev, "udev");
// Again only monitor for kb/mouse events  etc
udev_monitor_filter_add_match_subsystem_devtype(pState->p_device_monitor, "input", NULL);
// I only get this once after initialising it, i think this is correct
pState->device_monitor_fd = udev_monitor_get_fd(pState->p_device_monitor);	

Monitoring For changes

Called once per frame during the plaform Tick update.

// Poll the udev stuff for device changes
    struct udev_device *dev;
    fd_set fds;
    struct timeval tv;
    int ret;

    FD_SET(pState->device_monitor_fd, &fds);
    tv.tv_sec = 0;
    tv.tv_usec = 0;

    ret = select(pState->device_monitor_fd + 1, &fds, NULL, NULL, &tv);

    // Check if our file descriptor has received data.
    if (ret > 0 && FD_ISSET(pState->device_monitor_fd, &fds)) {
        // Make the call to receive the device.
        // select() ensured that this will not block.
        dev = udev_monitor_receive_device(pState->p_device_monitor);
        if (dev) {
            const char *p_devnode = udev_device_get_devnode(dev);
            if (p_devnode){
                if (!strcmp(udev_device_get_action(dev), "remove"))
                    // call close on this device's file handle
                    ResetInputDeviceByName(pState, p_devnode);
                if (!strcmp(udev_device_get_action(dev), "add"))
                    // open a connection to this device
                    RegisterInputDeviceByName(pState, p_devnode);
            printf("No Device from receive_device(). An error occured.\n");



View As Single Post >>

Ulrich Drepper Memory Article

2015/4/17 06:06

Eventually I will post something other than links to articles on here, but in the meantime here is a link to another memory/cpu related article: 'What Every Programmer Should Know About Memory' by Ulrich Drepper, split into several parts:

  1. Introduction
  2. CPU caches
  3. Virtual memory
  4. NUMA systems
  5. What programmers can do - cache optimization
  6. What programmers can do - multi-threaded optimizations
  7. Memory performance tools
  8. Future technologies
  9. Appendices and bibliography

Or, if you prefer, in PDF form: http://www.akkadia.org/drepper/cpumemory.pdf

It's written with Linux in mind, but covers basic enough stuff that it can be considered applicable to other OSs.

It's far too long to be covered in anything but the briefest of detail here, I even skipped over some of the sections regarding NUMA. I learned a lot in all that I did read though and have many notes of things to look up as a result. It's a bit of an information overload, even his test methods and results are educational.

View As Single Post >>

Mike Acton Data-Orientated Design

2015/4/6 02:32

Another data related talk from cppcon:

Related Slides : http://macton.smugmug.com/gallery/8936708_T6zQX#!i=593426709&k=ZX4pZ


  • Everything is a data problem.
  • Hardware is the platform.
  • Coders job is the transform data not to write code.
  • Good to think about the transforms you are applying when you write code.
  • Keep data that is use with each other close together.
  • Bools in structs provide low information density
  • can push data out of cache lines

00:28:00 Interesting Example about cache reads, and compiler optimization space.

00:41:50 Bools in structs

01:02:00 Last minute decision making is not a good idea

From the QA at the end he mentions that Link Time Optimization and Profile Guided optimization are too slow to use in code.

View As Single Post >>

Modern Microprocessors

2015/3/29 05:31

Someone on twitter posted this interesting guide to modern microprocessor architecture. The section on Memory Hierarchy somewhat links it to the previous post


Definitely worth a read.

View As Single Post >>

Efficiency with Algorithms, Performance with Data Structures, cppcon

2015/2/9 03:47

A nice talk from Chandler Carruth at cppcon last year:

Which features this nice table which helps to highlight why data structures are so important.

One cycle on a 3 GHz processor1
L1 cache reference0.5
Branch mispredict5
L2 cache reference714x L1 cache
Mutex lock/unlock25
Main memory reference10020x L2, 200x L1
Compress 1K bytes with Snappy3,000
Send 1K bytes over 1 Gbps network10,0000.01
Read 4K randomly from SSD*150,0000.15
Read 1 MB sequentially from memory250,0000.25
Round trip within same datacenter500,0000.5
Read 1 MB sequentially from SSD*1,000,00014X memory
Disk seek10,000,0001020x datacenter RT
Read 1 MB sequentially from disk20,000,0002080x memory, 20X SSD
Send packet CA->Netherlands->CA150,000,000150

Good hash table design : 00:49:00

View As Single Post >>


2015/1/4 19:31

My webpage has been left empty and ununsed since my wordpress blog was hacked over one year ago. Not that I regularly updated it when there was any content here to speak of but I haven't reinstated the old site or replaced it with a new one since that incident.

That all changes this year with my fancy new blog, the details of which you can read about in the aptly name about section. It's still a little experimental and likely to change but I have started by bringing over some of the old site's content which can be found in the tags section under

The old content's formatting could still use a little attention and some of the links either no longer lead anywhere or are completely missing. All of which I plan to fix in time as well as adding a bunch of new posts about what I am working on at home.

View As Single Post >>