Work to Survive!
Work to Survive! is a type of esolang (as well as a language standard) that forces the user to waste CPU cycles to "work" in order not to get the main process killed.
Specifications (Work to Survive! 1.0)
The user can work in Work to Survive! by calling the obscure work_to_survive
function and specifying the amount of work
(usually represented by a duration of time) that they are willing to do.
The user starts with some remaining_time
worth of time, and must complete works to gain more remaining_time
. When a Work to survive! runtime environment detects that a program's remaining_time
is equal to or less than 0ms, it must terminate the program immediately.
Tips for Work to Survive! implementation vendors:
- If you choose to use some units of time to represent the
work
amount (for this example: milliseconds), then completing the work is required to take at leastwork
milliseconds. It doesn't matter how much more time it actually takes, so it is fine to write awork_to_survive
function with considerable overhead.
- Regarding the time reward that the user gets for working, it is not specified in the standards. But the general recommendation is 1.5x the amount of
work
done in a fast language like C++ and 2x in a slower one like Python.
- In order to promote fair trade, the user is not allowed to hoard more than 1 second of remaining time. All implementations can freely define how to punish the user should this rule be violated.
- It is not allowed to use anything other than the main thread to do the works. However, what actually happens when the user violates this rule is implementation-defined.
Implementations
The following is a C++ implementation that anyone can include into their C++ source code to create a program that is accepted by the Work to Survive! 1.0 standards:
#include <chrono> #include <future> #include <iostream> #include <thread> ////////////////////////// Work now or Die!! /////////////////////////// // * You have to work to survive // // * You can only work in the main thread // // * You start with 100ms of time // // * It is illegal to have more than 1000ms of time // // * work > 0ms : Do work and get 1.5x the time you worked as reward // // * work <= 0ms : See the remaining time // //////////////////////////////////////////////////////////////////////// auto work_to_survive(std::chrono::milliseconds work = {}) -> std::chrono::milliseconds { using namespace std::chrono_literals; static std::thread::id main_thread_id = std::this_thread::get_id(); static std::mutex time_mutex; static std::chrono::milliseconds remaining_time = 100ms; static std::chrono::time_point prev_time = std::chrono::high_resolution_clock::now(); //// Time is ticking time_mutex.lock(); auto now = std::chrono::high_resolution_clock::now(); // std::max punishes those who call the function too frequently remaining_time -= std::max(std::chrono::duration_cast<std::chrono::milliseconds>(now - prev_time), 1ms); prev_time = now; time_mutex.unlock(); //// Return the remaining time if not working if (work <= 0ms || std::this_thread::get_id() != main_thread_id) return remaining_time; //// It's Working Time! std::this_thread::sleep_for(work); // Do work std::lock_guard lock(time_mutex); remaining_time += std::chrono::duration_cast<std::chrono::milliseconds>(work * 1.5); // Get your reward return remaining_time; } ////// Set up a time bomb to punish those who don't work (or those who work too much!) const volatile auto ____start_working_now_or_die = (work_to_survive(), std::async([]() { using namespace std::chrono_literals; while (true) { std::this_thread::sleep_for(10ms); // Check on the employee every 10ms 😈😈 auto remaining_time = work_to_survive(0ms); // Check the time if (remaining_time <= 0ms || remaining_time > 1000ms) break; } std::terminate(); // Punish the lazy or overworking employee }));