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");
exit(1);
}
// 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
udev_enumerate_scan_devices(enumerate);
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);
}
}
udev_enumerate_unref(enumerate);
}
// 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);
udev_monitor_enable_receiving(pState->p_device_monitor);
// 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);
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_ZERO(&fds);
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);
}
}
}
else
{
printf("No Device from receive_device(). An error occured.\n");
}
}
}
udev_unref(pState->udev);
udev_monitor_unref(pState->p_device_monitor);
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:
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.
Another data related talk from cppcon:
Related Slides : http://macton.smugmug.com/gallery/8936708_T6zQX#!i=593426709&k=ZX4pZ
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.
Someone on twitter posted this interesting guide to modern microprocessor architecture. The section on Memory Hierarchy somewhat links it to the previous post
http://www.lighterra.com/papers/modernmicroprocessors/
Definitely worth a read.
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.
ns | ms | Notes | |
One cycle on a 3 GHz processor | 1 | ||
L1 cache reference | 0.5 | ||
Branch mispredict | 5 | ||
L2 cache reference | 7 | 14x L1 cache | |
Mutex lock/unlock | 25 | ||
Main memory reference | 100 | 20x L2, 200x L1 | |
Compress 1K bytes with Snappy | 3,000 | ||
Send 1K bytes over 1 Gbps network | 10,000 | 0.01 | |
Read 4K randomly from SSD* | 150,000 | 0.15 | |
Read 1 MB sequentially from memory | 250,000 | 0.25 | |
Round trip within same datacenter | 500,000 | 0.5 | |
Read 1 MB sequentially from SSD* | 1,000,000 | 1 | 4X memory |
Disk seek | 10,000,000 | 10 | 20x datacenter RT |
Read 1 MB sequentially from disk | 20,000,000 | 20 | 80x memory, 20X SSD |
Send packet CA->Netherlands->CA | 150,000,000 | 150 |
Good hash table design : 00:49:00
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.