About The Contest
The first ever Olympiad of Misguided Geeks contest at Worse Than Failure (or OMGWTF for short) is a new kind of programming contest. Readers are invited to be creative with devising a calculator with the craziest code they can write. One lucky and potentially insane winner will get either a brand new MacBook Pro or comparable Sony VAIO laptop.
Entry #100291: The Scalable Calculator
by Håvard Skinnemoen
This simple calculator uses a tabbed GUI with one operator (+, -, *, /) per tab. Each tab has a thread controlling it and a number of vertical sliders that are used to enter digits into the calculator. Each vertical slider has its own thread as well.
A horizontal slider at the bottom of each tab controls the number of vertical sliders available for entering number. With the maximum of 10 sliders per tab and four tabs, the calculator may spawn up to 46 threads.
When switching tabs, the current result is used as the first operand of the operator which was switched to. The result is updated on the fly when the sliders are moved.
Note that merely clicking on the current tab doesn't latch the result into the first operator. For example, to calculate 1 + 1 you need to first make sure that the current result is 0 (by selecting the C tab, for example). Then, select the + tab and enter the number 1 using the sliders, select the - tab to latch the result into the first operand and set all the sliders a 0, and finally go back to the + tab to enter the second number 1. The display should now show the number 2.
Division by zero is caught by handling the SIGFPE signal, which sets the is_err flag, causing the display to show Err regardless of the actual result. As it turned out that a plain floating-point div-by-zero simply returned +/- Inf or NaN instead of generating SIGFPE on some (most?) computers, the division routine does a dummy integer division just in case.
The calculator may deadlock from time to time, leaving the UI completely unresponsive, but it will hopefully stay alive long enough to get through the test cases at least if you try a couple of times. The locking is quite painful, as it should be in a competition like this.
The threads communicate using mutexes, rwlocks, condvars and regular glib signals. Note that gdk_threads_enter() also grabs a mutex, which is probably the reason why it sometimes deadlocks. It also seems like this mutex is implicitly locked when calling the glib signal handlers, so grabbing additional mutexes in the signal handlers isn't entirely safe, but we do it anyway.