// FIFO queue of load 'functors' with time limit; enables displaying // load progress without resorting to threads (complicated). // // Jan Wassenberg, initial implementation finished 2005-03-21 // jan@wildfiregames.com // intended use: // replace the InitEverything function with the following: // LDR_BeginRegistering() // LDR_Register() for each sub-function (*) // LDR_EndRegistering() // then in the main loop, call LDR_ProgressiveLoad(). // // *: splitting up InitEverything is required so that control returns to // the main loop occasionally; that allows displaying the progress. // note that we can't interrupt loading without threads (complex). // // this module is not thread-safe! #include // call before starting to register load requests. // this routine is provided so we can prevent 2 simultaneous load operations, // which is bogus. that can happen by clicking the load button quickly, // or issuing via console while already loading. extern int LDR_BeginRegistering(); // callback function of a load request; performs the actual work. // it receives a param (see below) and the exact time remaining [s]. // // return semantics: // - if the work can be split into smaller subtasks, process those until // is reached or exceeded and then return ERR_TIMED_OUT. // - if the entire task was successfully completed, return 0: // the load request will then be de-queued. // - any other return value indicates failure and causes // LDR_ProgressiveLoad to immediately abort and return that. typedef int (*LoadFunc)(void* param, double time_left); // register a load request (later processed in FIFO order). // : function that will perform the actual work; see LoadFunc. // : (optional) parameter/persistent state; must be freed by func. // : user-visible description of the current task, e.g. // "Loading map". // : used to calculate progress, and when checking // whether there is enough of the time budget left to process this task // (reduces timeslice overruns, making the main loop more responsive). extern int LDR_Register(LoadFunc func, void* param, const wchar_t* description, int estimated_duration_ms); // call when finished registering load requests; subsequent calls to // LDR_ProgressiveLoad will then work off the queued entries. extern int LDR_EndRegistering(); // immediately cancel the load. note: no special notification will be // returned by LDR_ProgressiveLoad. extern int LDR_Cancel(); // process as many of the queued load requests as possible within // [s]. if a request is lengthy, the budget may be exceeded. // call from the main loop. // // passes back a description of the next task that will be undertaken // ("" if finished) and the progress value established by the // last request to complete. // // return semantics: // - if loading just completed, return 0. // - if loading is in progress but didn't finish, return ERR_TIMED_OUT. // - if not currently loading (no-op), return 1. // - any other value indicates a failure; the request has been de-queued. // // string interface rationale: for better interoperability, we avoid C++ // std::wstring and PS CStr. since the registered description may not be // persistent, we can't just store a pointer. returning a pointer to // our copy of the description doesn't work either, since it's freed when // the request is de-queued. that leaves writing into caller's buffer. extern int LDR_ProgressiveLoad(double time_budget, wchar_t* next_description, size_t max_chars, int* progress_percent);