the umbrella dilemma

On the rainiest day of the year, Jack was walking home. It was February, so to say it was the rainiest day of the year wasn't saying much, but being February, it was the type of rain that chills you to the bone and makes you consider whether it had intended to be snow, but someone had made a mistake. Ordinarily, Jack liked rain. When it was summer. Or late spring. Autumn rain in particular held a special place in his heart.

But it wasn't autumn. It was February. Jack tried to pretend to like the rain, regardless of how cold it was making him, as a steady stream of droplets made their way from his soaked hair into his eyes. Jack didn't have an umbrella. It's not that he didn't have one with him, he didn't own one. Today, he decided, was the day he'd buy an umbrella. Or rather, tomorrow. Right now, all he wanted was to get home and out of the rain. Tomorrow would be a better day to go to the shops. It probably wouldn't be raining tomorrow.

But what kind of umbrella should he get? The kind that folded in and retracted were really easy to carry around. You'd be far more likely to have the umbrella handy for unexpected rainfall. But he detested the handles on those things. They were always short, stubby things that were awkward to hold properly, especially when the wind picked up and threatened to take the umbrella away from you. And besides, they were always too small. It seemed like they were purposefully designed to keep your head dry but let about half of the rest of your body get soaked. The big, full size umbrellas seemed like far better umbrellas. They protected your entire body from the cold rain. They were like parents, he thought, hovering around their child, shielding them from all the dangers of the world while the child skips on, blissfully unaware. But just like how the parents' protection becomes overbearing and stifling when there aren't any dangers around that the child can't handle, the large umbrellas become oppressive to carry around when it isn't raining.

He'd check online when he arrived home, he decided. Someone must have been anguished by the same dilemma before, and they would have come to some conclusion about what the best umbrellas were. There might even be some type of umbrella he never knew about that solved every problem, and there'd be reviews of it.

Once Jack finally made it home, he wiped the wet mud from his shoes on the non-existing door mat and tracked muddy water all over the hallway. He'd never gotten a doormat. Never gotten around to it, and besides, it was such a hassle to clean the floors with a doormat that you needed to deal with. And it was important that whatever banal message, or lack thereof, that was on the doormat you got was a message you could stand by for years to come.

Doing his best to contain the mud to the entrance, he undressed and changed into dry clothes, then glanced at the clock in the hallway. Five thirty. He could do some quick searches online before he had to worry about food.

The best umbrella. 542,000,000 results. There were regular, full size umbrellas, the standard retractable ones, a bunch of transparent, extra domed umbrellas that he suddenly recalled having seen in some pictures from Japan, umbrellas with a hole on top and another layer of cloth over the hole, a bit like a hot air balloon, to protect it from damage when the wind caught it, lopsided umbrellas, parasols, photography diffuser umbrellas, and cocktail umbrellas. Some of those were, perhaps, more useful than others as a tool to protect yourself from rain, but Jack had been right. There was a whole world of different umbrellas out there. All he had to do was choose, and hope he could find one at the store tomorrow.

As he went clicking through the different umbrellas, reading and watching video reviews, the clock ticked past six and was well on its way to seven before Jack had the presence of mind to look at it. Crap. He still had to eat, and it was getting too late to cook anything worthwhile.

He decided to order in. A couple clicks online, and like magic there'd be food at his doorstep in half an hour, while he went about doing some chores around the house. The 21st century.

Except, it all took a bit longer than half an hour. As he was scrolling through available restaurants on the food delivery website, he had to decide what he wanted to eat. Pizza? He had had pizza a couple days ago. Maybe he'd order a burger. Oh, but burgers never survived the delivery particularly well. He finally decided to order some Indian food, and went looking for his regular, comfortable Indian restaurant.

He knew he liked it, it had been his default Indian restaurant for three years, but for some reason he decided to look at the reviews. There were a bunch of bad ones in the past month. Slow delivery. Wrong order. One even complained about under-cooked chicken. Uh-oh. Maybe he'd try out a different restaurant today. Maybe he'd just order pizza again.

Eventually, finally, he had decided what to order and from whom to order it, and he hit confirm on the ordering page. Seven forty-five. He decided to skip the chores for today, and went into the living room to find something to watch for the evening.

Starting up his video streaming app of choice, Jack started scrolling through the selection. He had about twenty-three movies and series on his watchlist, but he quickly went through and discarded all of them. Most of them were movies that you didn't just watch, you had to be in the right mood for them and feel like you could devote the entire running length to really watch the movie. Maybe a light comedy?

When the sushi finally arrived, Jack still hadn't selected anything to watch. In frustration, he hit the shuffle button. And then he hit it again. And a few more times before a nature documentary show came up. He threw the remote aside with an audible sigh. It wasn't really what he was in the mood for, but it'd probably be good and at this point he just wanted to eat his food and go to bed.

Jack woke up to the smattering of rain on his bedroom window. For a moment he lay there, listening, enjoying the soothing sound of randomness striking the window. Sporadically the wind would pick up, creating a wave of high frequency smattering, and then it'd slow down until it almost seemed like it had stopped. And then it'd pick up again. He looked over to the window and saw the droplets hanging on to the surface, some of them growing heavy and falling down, many of them staying put and refracting the light into thousands of tiny, upside down versions of the outside world. And then he remembered that it was February, and he had to get to work.

Preparing the best he could for the outside conditions, which wasn't all that much when you didn't have an umbrella, Jack went to work. He'd definitely get an umbrella on his way home. He'd go and buy a small retractable one so he could carry it with him at all times and never again be forced to arrive to work soaked to his underwear.

Eight and something hours later, Jack was on his way home. He had promised himself to go buy an umbrella after work, but he was on his way home. Today had been a lousy day, and he just wanted to get home, put his feet up, and watch something stupid on the TV for a couple of hours. And anyway, it had stopped raining, and there wasn't any rain on the forecast. It'd be days before the next rain, maybe weeks. He could get an umbrella later.

apples vs oranges

Comparing apples to oranges is one of society's greatest unsolved mysteries. So many people have tried and failed that it has given birth to the idiom "comparing apples to oranges" as a way of saying that something is incomparable.

Not daunted by the failure of civilisation for thousands of years before me, and fueled by the random, racing thoughts of insomnia, this is my humble attempt to crack the problem, once and for all.

According to folk wisdom, an apple a day keeps the doctor away. As such, I'd recommend apples to anyone with a phobia for white robes or who wishes to avoid persons with doctorate titles in their twitter display name.

The skin of an apple can easily get stuck in your teeth. This is very uncomfortable for anyone, but for someone with dentures or braces it may ruin the experience altogether. For the dentured people, I instead recommend oranges. Provided that they have access to a young person to peel their oranges, as peeling an orange requires a grip strength often not present in the very old.

Oranges are a well known remedy for scurvy. If you're planning an extended voyage at sea, pack a few barrels of oranges. Also consider bringing a few rugby balls to stave off loneliness.

Peeling an orange can also prove a squirting hazard of acidic liquid that, if it gets in your eyes, can be very painful. I suggest wearing protective eyewear at all times when peeling or consuming oranges.

When consuming an orange one has to be constantly on the look out for seeds. Although our modern oranges often have very few or zero seeds, an unexpected rogue seed can not only be particularly unpleassant, it may prove a choking hazard which could drastically lower the life expectancy of the subject.

Oranges, being orange, has a much higher contrast to the surrounding environment compared to apples, which are usually green and disappear in grass or yellow-red which disappear in leaves. If you are worried about losing your fruits, or have a sadistic parent who are trying to ruin easter by hiding fruits instead of sweets, oranges should be your fruit of choice.

A dropped apple quickly develop discoloured blemishes on the skin, hinting at a compromised and mushy piece of apple underneath. The same drop with an orange usually do not develop the same kind of sign of damage on the the outside, but once peeled, might nevertheless reveal damage to the flesh of the orange. However, this damage is usually pretty minor and the orange is usually still good to eat.

When it's all said and done, it seems pretty clear to me that oranges have the upper hand. Unless you're old and lack the grip strength required to peel the orange, in which case you probably want to avoid apples anyway, as avoiding doctors at that stage seems like avoiding the very people still keeping you alive.

Finally, apple juice is far superior to orange juice, and therefore apples are better than oranges.

fsg

I wrote my own site generator, it's called fsg. The s and g stands for Site Generator. I'll leave it to the creativity of the reader to figure out what the f stands for. It took a weekend. It's written for myself and by myself, so it doesn't have many bells and whistles, but it does what I need.

I don't put as much content on this site as I think I should. Most of the time I just update my resume whenever that needs updating. Despite that, every single time I've updated this site I've ran into issues with Hugo, which is the static site generator I use. Or did use, I should say. See, I update my site rarely enough that I generally forget which version of hugo I was using. So every time I download the latest, naively thinking that it'll be fine. Every time I have to spend a day fixing it, dealing with various changes in the framework.

Lately I've been telling myself that at least a part of the reason I haven't been putting more stuff on here is because of frustrations with the site generator situation, which brings us to the present.

There's really only a couple things I wanted out of fsg. It doesn't need to be able to deal with particularly large websites. I don't mind writing the posts in html. All I really need out of it is a way to specify a template or a couple different templates to use for the different pages, and to generate different lists of posts on the front page and the full blog list. For a while I was considering just going back to doing it the way I first learned to make websites and duplicate each page's html entirely and just deal with the hassle of updating menus and site layout changes across all pages. Instead I chose the road of procrastination, until a conversation on twitter prompted me to think about it for a bit and I had one of those classic "y'know what, I could probably knock that out in a weekend". And then I did.

The results are available at https://github.com/grouse/fsg. Alongside the generator in fsg.cpp the repo also contains the source asset files, which are intentionally vanilla html files with a bit of custom syntax in html comment blocks which are parsed by the generator in fsg.cpp to correctly insert page titles, look up templates, static pages, etc. It also has a server mode that opens a socket on port 80 and serves the generated site back. And it has file watches on the source asset to automatically re-generate the site as the source assets change.

There are definitely a bunch of improvements that could be made in the site generation part, but most of them would be so marginal an improvement I doubt I'll ever bother. The only thing I am likely to do on that end is auto-escaping the contents of code blocks, because that would be trivial to do and because it has already been a bit of a headache to ensure symbols like < don't break the code block. The other thing is figuring out a way for the webserver to keep the socket open to the browser and push new data on it whenever the site is re-generated, or in some way make the browser re-request the same page when its source assets change. That one I'd be inclined to actually solve if writing becomes more of a habit. It's also very wasteful in what it has to re-generate when things change, and there are probably a bunch of memory-leaks, and I don't care about either at all; it re-generates the site faster than I can look over to the browser window and the webserver just will not be running long enough for memory to ever become a problem.

I'm not really gonna say anything more about details of the implementation of fsg. It's really not all that interesting. It's just my little tool that I wrote in a spare weekend for my own needs, and what I ended up with is simply what I ended up with following the process of implementing the most straight forward, simplest solution to each problem as I came across them, step by step. That process is something I find much more interesting and valuable, and so that's what I'll be ending this post talking about.

I enjoy writing things from scratch, mostly or entirely without libraries. Definitely without frameworks. It allows me to learn things at a deep level which is usable in the future to a much greater degree than some trivia knowledge about how to massage some framework into doing what you need, and it gives me opportunity to practice the fundamentals - every time I write a lexer it gets a little better and I get a little faster at writing it. I think we all just need to invent the wheel a bunch of times before we actually arrive at a wheel that works well. It also just doesn't take as long as many seem to think - if you limit yourself to solving the problems that you actually need to solve. Programmers trying to solve the imaginary problem of tomorrow and making their solutions more general happens far too often, which inherently leads to a solution more complex than required. When applied to a personal tool, you might be surprised how simple things end up.

By the way, did you know that the earliest archeological find of a wheel is a potter's wheel? I should say we're lucky our ancestors re-invented that wheel a few times to get to wheels for flour mills, trolleys, carts, and carriages before they got to the smooth, rubberised wheels of the modern car.

defer

I'm not a big fan of the destructors in C++. Don't get me wrong, they can certainly be useful. I just think they solve a problem in a way that could've been implemented in a much more powerful way, without the implicit changes in behaviour or performance characteristics that adding a destructor comes with. I'm also not at all a fan of non-trivial code hidden away in destructors that I wasn't expecting, but that's primarily a programmer error.

Enough teasing, here's the code:

template <typename F> struct Defer { Defer(F f) : f(f) {} ~Defer() { f(); } F f; }; template <typename F> Defer<F> defer_create(F f) { return Defer<F>(f); }; #define defer__(line) defer_ ## line #define defer_(line) defer__(line) struct DeferDummy {}; template<typename F> Defer<F>operator+ (DeferDummy, F&& f) { return defer_create<F>(std::forward<F>(f)); } #define defer auto defer_(__LINE__) = DeferDummy() + [&]()

Full credit of this snippet goes to the folks over at https://handmade.network where this is copied from, with a small change to the naming of the expansion macros to not clash with glibc.

Don't prepend anything with double underscore, you're probably gonna clash with something, somewhere as it's reserved by the compilers in C and C++.

In short, the way this works is that you pass a lambda expression to the constructor for the Defer struct, that it calls during its destructor. The DeferDummy struct exists so that we can default-construct an object and pass in the lambda using operator+, this is entirely done in order to keep the defer macro usage neat and simple.

I've seen this sort of thing mentioned in a few places, and it's certainly not a concept invented by C++ macro magicians. It's a first class feature in Go, Swift, and probably a bunch of other languages. Personally, I was first introduced to it during one of Jonathan Blow's JAI compiler streams. It's just recently that I decided to actually incorporate it into my own projects and see how I actually like it in practice.

It turns out, I like it. I like it a lot. But first, some usage code to figure out what that macro magic actually allows us to do.

void foo() { defer { printf("world 1!\n"); }; defer { printf("hello, "); }; defer { printf("hello, "); printf("world 2!\n"); }; } // outputs: // hello world 2! // hello world 1!

Referring back to the macro magic, the first statement expands into

auto defer_(__LINE__) = DeferDummy() + [&](){ printf("world 1!\n"); };

In other words, the defer macro starts a lambda expression declaration but doesn't properly open or close it, we do that ourselves with the {}; The ; after the curly braces might look weird at first glance, and would indeed be the first thing would want removed in a proper first class version of defer, but it's required as long as we're forced to hack the feature in using destructors and lambda expressions.

Because defer is implemented using destructors of Defer objects, the destructors are called in opposite order of declaration, like unwinding a stack. This turns out to not only make a lot of sense, but be exactly what we want, as we want any defer statements close to the beginning of a scope to be called later than the ones near the end, in order to get proper order of execution in the cases where the latter defer depends on state cleaned up by the former defer.

There's a few things this allows us to do. The most obvious one is to add a defer statement freeing a resource or closing a file handle just after we've opened it, making it much more obvious that this is taken care of. This is particularly useful if you like to do early returns, while also avoiding use of goto to jump to clean-up code. Of course, all of this is one of the primary reasons for a destructor, but defer is much more versatile as you can trivially customise which statements are execute or whether it depends on some state in the function, without having to change or implement a destructor for a struct which would incur those changes everywhere the struct is already used, potentially changing performance characteristics or behaviour dependence.

Defer is one of the only things I really want added to the C++ specification as a first class citizen, but I've all but given up on the C++ committee actually adding something useful to the language, so this macro magic solution will keep me happy for now.

live code editing

Fast iteration times on large projects is often cited as one of the primary reasons to incorporate a scripting language, such as Lua, Python or JavaScript, into the project. The primary downside to this is overall complexity, performance, maintenance, and debugging. So wouldn't it be great if we can get the benefits of scripting languages with none of, or close to none of, the downsides?

This post is written from the perspective of game development. With that said, most if not all principles are applicable to any software project of similar size and complexity.

Certainly there are other benefits to a more high level scripting language, particularly if the rest of the code base is in a rather low level programming language, such as C or C++. It allows people who would generally not classify themselves as programmers for their primary skill or interest, like designers, artists and writers, to put their content into the game and seeing how it works in practice.

This is not a benefit I'm going to put a lot of effort into exploring or considering, simply because I can't speak for what kind of tangible benefits designers, artists and the like can derive from a scripting language when looking at the project as a whole compared to the amount of man hours required to make a scripting language integration perform well, not to mention that the debugging facilities for such an integration tend to be far worse than what we have available for native languages.

So how do we get the fast iteration time of scripting languages using ordinary C or C++? It turns out, it's actually not that complicated. In fact, most of us have been only a few steps away from achieving it while doing other things. The solution is dynamically linked libraries, .dll on Windows, .so on Linux.

// file: foo.c void foo(int a, int b) { // ... } // file: bar.c typedef void foo_t(int, int); foo_t *foo = nullptr; void foo_stub(int, int) {} void* load_foo() { void *lib = dlopen("foo.so", RTLD_NOW | RTLD_GLOBAL); if (lib) { foo = (foo_t*)dlysym(lib, "foo"); // ... } if (!foo) foo = &foo_stub; // ... return lib; }

The above snippet is a simple example of how to dynamically load code at runtime, the code is written for Linux using dlopen and dlsym functions, the Windows equivalent is copied verbatim but with the necessary replacements to use LoadLibrary and GetProcAddress instead of dlopen and dlsym.

So, first of, there are a couple of different things that needs to be done to get the code base ready to be loaded at runtime. I've already implemented live code editing in one of my main hobby projects, Leary (https://github.com/grouse/leary), so I'l be using that as a reference to describe what needs to be done and how to achieve it.

Figure out what to reload

The first thing that needs to be done is deciding which parts of the code base should be loaded at runtime and start making the changes necessary to make it possible to compile these parts into a .dll or .so. For Leary I wanted as much as possible to fall in this category. That means initialisation, input handling, simulation, and rendering.

Make a few small, concise entry points to the reloaded code

We could simply reload every single function in the code, but that is quickly going to turn into a nightmare to maintain. Instead, I suggest you provide a very simple interface to the code that is reloaded with just a few different functions and move all code behind those, making a concise and easy to maintain interface between the dynamically loaded code and the main entry point of the program.

In Leary, I decided to make this interface four functions: game_init, game_pre_reload, game_reload, and game_update. The purpose for game_pre_reload might not be immediately apparent, and at the time of writing this post it actually isn't required for Leary, but it's there so that if anything relies on other outside state, such as Vulkan driver state, the game code has a chance to make sure that this state is ready to be reloaded. In the case of Vulkan, which is the most immediate case it'll be needed for in Leary, it means I can make sure the graphics device is idle and have finished all its work before I reload the code and recreate shader, buffer and texture resources.

game_reload is called after the game module has been reloaded. The function is used so that we can pass all the global state that we've gathered from the module back to be set accordingly. As you might imagine, the less global state you rely on the less this function has to be doing.

game_init and game_update are fairly self evident. game_init is called once at program startup to set up the primary state object that it then returns for the primary program to keep track of across module reloads. game_update is our single entry point into the module that we call every frame with the game state object from game_init to perform work.

In a more traditional input-based program without a non-stalling infinite main loop traditional to games, you can imagine a fifth function work_available which would block the main loop in the main program until there are input events that need processing or we have found in some other way that we need to perform work.

After these code changes the function to load all the game code in Leary off of the disk looks like this:

#define DLOAD_FUNC(lib, name) (name##_t*)dlsym(lib, #name) void* load_code() { void *lib = dlopen("/path/to/game.so", RTLD_NOW | RTLD_GLOBAL); if (lib) { game_init = DLOAD_FUNC(lib, game_init); game_pre_reload = DLOAD_FUNC(lib, game_pre_reload); game_reload = DLOAD_FUNC(lib, game_reload); game_update = DLOAD_FUNC(lib, game_update); } if (!game_init) game_init = &game_init_stub; if (!game_pre_reload) game_pre_reload = &game_pre_reload_stub; if (!game_reload) game_reload = &game_reload_stub; if (!game_update) game_update = &game_update_stub; return lib; }

Coalesce state

If all you do is run the above code in your main entry point once, it should 'just work'. But that's not why we're here. We want to be able to continuously reload the code as it changes.

If you're not relying on any static variables, global or local, in your code base, you're in luck. Just make sure game_init returns the primary state object that you pass into game_update and you're pretty much good to go.

If you do use any static variables you need to understand how static initialisation works, in particular in regards to dynamically linked libraries.

Static local variables

Static variables that are declared locally in function or block scope is initialised at first execution of that scope. The deinitialisation of the static variables occurs at program or module exit. Because we'll be reloading the code continuously we'l be calling dlclose followed by dlopen every time we reload. Static deinitialisation of all block or function scoped static variables in the dynamic library will occur at dlclose.

There are a few potential pitfalls with this that we need to take care of. The first obvious one is if the static variable is being allocated on the heap that means we end up leaking the memory of that static variable every time we reload the code. That'd be bad. The other pitfall is if the static variable is initialised by executing some non-trivial code. That might be bad.

There isn't really any simple solution that fits all in this case. You're just gonna have to go through each static variable and figure out if multiple initialisations and deinitialisatons of the variable would result in bad behaviour. As a personal preference, I tend to avoid the type of static variables that would cause these types of problems for a number of different reasons, live code editing being just one minor one of them. These reasons may become the subject of a future post.

Static global variables

Static global variables will be initialised with dlopen and deinitialised with dlclose. Fortunately, these are a lot easier to handle cleanly in our use case of reloading the module.

Put simply, avoid initialising static variables using function calls, e.g. static Foo foo = some_foo_init();. Similarly as with the static block and function scoped variables, these assignments mean that some_foo_init will be executed every time we reload the module. The same thing applies if the static variable is used to track state that needs to persist across reloads, as the reload will reset the state.

Instead, put all these initialisations behind an init or reload function. In the case of Leary, that's exactly what game_reload is used for. The state object from game_init is used to store and restore the values of the variables.

Putting it all together

At last. We've coalesced all the state required into a single object that we can pass into the drastically reduced entry point interface that we've defined, and we've (hopefully) cleaned up all static variables or made sure they all behave well when being initialised multiple times. It's time to write the main loop that pulls it all together and reloads the code when appropriate.

typedef void game_init_t(GameState*); typedef void game_pre_reload_t(GameState*); typedef void game_reload_t(GameState*); typedef void game_update_t(GameState*); void game_init_stub(GameState*) {} void game_pre_reload_stub(GameState*) {} void game_reload_stub(GameState*) {} void game_update_stub(GameState*) {} game_init_t *game_init = nullptr; game_pre_reload_t *game_pre_reload = nullptr; game_reload_t *game_reload = nullptr; game_update_t *game_update = nullptr; #define DLOAD_FUNC(lib, name) (name##_t*)dlsym(lib, #name) void* load_code() { void *lib = dlopen("/path/to/game.so", RTLD_LAZY | RTLD_GLOBAL); if (lib) { game_init = DLOAD_FUNC(lib.handle, game_init); game_pre_reload = DLOAD_FUNC(lib.handle, game_pre_reload); game_reload = DLOAD_FUNC(lib.handle, game_reload); game_update = DLOAD_FUNC(lib.handle, game_update); } if (!game_init) game_init = &game_init_stub; if (!game_pre_reload) game_pre_reload = &game_pre_reload_stub; if (!game_reload) game_reload = &game_reload_stub; if (!game_update) game_update = &game_update_stub; return lib; } void main(int, char **) { void *lib = load_code(); GameState game = {}; game_init(&game); while (true) { game_update(&game); game_pre_reload(&game); dlclose(lib); lib = load_code(); game_reload(&game); } return 0; }

Naturally, reloading the game code every frame is a horrendously bad idea. It'll tank the performance and you're pretty much asking for trouble. There are a number of ways to get around that problem: either reload the code after some predetermined, arbitrary amount of time, or use a way to determine whether the game.so file has changed and only reload the code when that happens. To accomplish the latter you can simply query the last modified date of the file whenever you want to reload it, or you can look into the various platform specific ways that exist to be notified via callbacks or events when a file changes. Right now in Leary I simply query the last modified time of the dynamic library every second and reload it if it has changed.

Final words

There you have it. Natively compiled C/C++ code reloaded dynamically at runtime, allowing you to very rapidly change a piece of code, compile it, and have the changes immediately take effect in the running program. It's magic.

Some caveats still exist. For example, if the layout of your data changes, by changing the order of variables in a struct or their type you're going to have to do a proper full reload of the game. Secondly, as alluded to earlier in the post, you're going to have to take extra care that any libraries that you use won't behave badly when reloaded dynamically like this.

Debugging can also be somewhat temperamental at times. Visual Studio in particular likes to lock both the .pdb and executable files when it's debugging so that they can't be changed at all, and GDB seems to freak out somewhat when symbols have changed without it realising.

In the case of Visual Studio's locking you pretty much just have to make sure to copy the binaries and debug symbols to intermediate copies before you load them, so that the symbols and binaries being generated by the compiling isn't the ones you're actually loading.

For GDB's freak out, I'll get back to you on that one. I'm sure there are reasonable solutions to work around it.

These problems have, so far, for me, been rather secondary in priority. Generally when I want to debug something I'm not very interested in being able to do live code editing, so I have a simple #define to turn it off in favour of traditional static linking.

As a programmer very comfortable in the low level trenches of C/C++, this then gives me the best of both worlds. When I need fast iteration testing gameplay I turn on the live code editing and I just have to compile for my changes to take effect immediately, when I need to debug I turn it off and I get the stable, 'normal', statically linked code that GDB and Visual Studio plays nicely with. All with none of the massive performance cost of scripting languages or the immense man hours required for the maintenance.

Hello, World

Just like every blog needs a "Hello World" post to start things off, so does this one. And just like every introductionary post promising times of grandeur, interesting content providing food for thought, and frequent updates, just to fall into obscurity with no update in sight for months, this one is no exception.

My name's Jesper Stefansson. I'm an aspiring game developer from Sweden currently employed by Feral Interactive to port video games to Linux. At the time of writing this employment has resulted in primary involvement in the Linux ports Tomb Raider, the 2013 reboot, and Total War: WARHAMMER.

So what's with the blog? Well, I've always quite enjoyed writing, and over the years I've deluded myself into thinking I'm rather decent at it. And what better way to share in the insanity that is every day life as a game developer, as my hair grows greyer and my mind ever more cynical.

As alluded to by the start of this post, I have a few ideas and rough notes for a few topics I wish to write about. I also have far too many books to read, and code to code, so we'll see what happens. Don't hold your breath.

Until next time,
Jesper