The promise could be deallocated before promise.set_value() had returned,
which apparently caused an invalid read on some implementations.
By moving the promise declaration up the stack, we ensure that the map is
deallocated first, and therefore the map thread is joined, before the
promise is deallocated.
Both Android and iOS now use pause/resume. The map thread is
always running, and be able to receive messages. When paused,
it will just refuse to render.
previously, we used multiple different projects for various targets (app, test, render) that overwrote each other, so it was impossible to have one project to build them all, one project to compile them, one project to run them all and in the darkness bind them
- static rendering now also runs in a separate thread; you have to start it with map.start(Map::Mode::Static) and join the thread with map.stop() before destructing the Map object
- map.renderStill() takes a callback with will be invoked on the *map* thread, so you'll have to figure out your own method of dispatching back to the main thread.
Thread<T> is a generic thread management object that starts a thread, creates an object T in that thread and calls its .start() function. When the Thread<T> object is destructed (which must happen in the thread that created it), it'll call the object's .stop() function, and wait for thread termination. The .stop() function must somehow get the thread to terminate. Note that object T's constructor/destructor/start()/stop() must be protected/private, and Thread<T> must be declared as a friend class. All public functions may be called from any thread and are exposed through operator->().
RunLoop encapsulates a libuv runloop and has a facility of dispatching function objects to the thread. It can be used either as a worker thread class by itself, or it can be derived from. This commit converts SQLiteCache to derive from RunLoop and removes the custom code used previously for managing the cache thread.
- catch SQLite exceptions and report them
- failed statements are ignored, we're really just caching here, so if it fails we're handling it gracefully elsewhere
- handle cases where the database file goes away after we opened it
- handle cases where the schema wasn't created after the database file was opened successfully
- add tests