Hey Tom - this is owed a longer explanation, which I will attempt to provide tomorrow, but in the meantime...
Cinder includes Boost's threading library. To make use of it, all you need to do is
#include "cinder/Thread"
and now std::thread is available to you.
The great thing about learning boost::thread is that it has been accepted as the official C++ threading implementation, so you aren't learning something proprietary but rather the official C++ way of doing threads going forward. It's why we are future-proofing Cinder by aliasing it in the std:: namespace.
I am writing this from my head, so caveats abound - it probably doesn't compile, but roughly this should work:
void loadSurfaceUrl( Surface *destSurface, const Url &url )
{
*destSurface = Surface( loadImage( loadUrl( url ) ) );
}
Surface mySurface;
std::thread loaderThread( loadSurfaceUrl, &mySurface, Url( "http://apple.com/logo.png" ) );
Creating a gl::Texture is unfortunately not possible on secondary threads for reasons I think you're familiar with (not specific to Cinder). However loading into a ci::Surface is perfectly safe. In Cinder the most natural thing to do is to keep an eye on say, a std::vector<> of tiles awaiting final processing (presumably conversion to gl::Texture from their ci::Surface, insertion into the structure of active tiles, etc). This is all sort of the classic multithreading methodologies - producer/consumer type stuff. A very rough pseudocode kind of thing:
class PreloadedTile {
Surface image;
Rectf area; // or whatever other data associated with this tile you need to know
};
vector<PreloadedTile> completedPreloads;
mutex completedPreloadsMutex;
void preloadTile( const Url &url, const Rectf &area )
{
PreloadedTile result;
result.image = Surface( loadImage( loadUrl( url ) ) );
result.area = area;
completedPreloadsMutex.lock();
completedPreloads.push_back( result );
completedPreloadsMutex.unlock();
}
// do some preloading like this:
preloadTile( "http://blah.com/tile1.jpg", Rectf( 0, 0, 320, 240 ) );
preloadTile( "http://blah.com/tile2.jpg", Rectf( 0, 240, 320, 480 ) );
// from your app's update method, check in on completed preloads and
// process them as they become available
void MyApp::update()
{
completedPreloadsMutex.lock();
while( ! completedPreloads.empty() ) {
finishTileLoad( completedPreloads.back() );
completedPreloads.pop_back();
}
completedPreloadsMutex.unlock();
}
// since this is called from the primary thread, conversion to gl::Texture is no problem
void finishTileLoad( const PreloadTile &preload )
{
mTiles.push_back( Tile( gl::Texture( preload.image ), preload.area ) );
}
Again, this is sort of the regular producer/consumer ideas you've probably been exposed to in another language if not C++. I haven't studied your source in enough detail to give more specifics but I will happily do so if you'd like. We'd definitely be excited to have Modest Maps available on Cinder.