Skip to content

Instantly share code, notes, and snippets.

@chunkyguy
Created October 11, 2014 03:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chunkyguy/e4f52c0a75f5ae4c7088 to your computer and use it in GitHub Desktop.
Save chunkyguy/e4f52c0a75f5ae4c7088 to your computer and use it in GitHub Desktop.
//
// AsyncLoading.cpp
//
// Created by Sid on 11/10/14.
// Copyright (c) 2014 whackylabs. All rights reserved.
//
// Context: http://www.reddit.com/r/gamedev/comments/2ivsp6/async_loading_and_syncing_threads_with_your/
/** Output:
* Game::Init
* loadMap level1-1.map
* .x.x.x.x.x.x.x.x.S0.1.2.3
*/
#include <functional>
#include <queue>
#include <mutex>
#include <future>
#include <string>
#include <iostream>
std::queue<std::function<void()>> syncQueue;
std::mutex syncMutex;
std::condition_variable loadCondition;
class Game {
private:
bool spinner;
int drawCount;
const int kMaxDrawCount = 3; // quit game after rendering these many frames
public:
Game() :
drawCount(0),
spinner(true)
{
std::cout << "Game::Init" << std::endl;
}
void update()
{
std::cout << ".";
}
void draw()
{
// print x for loading screen
// and frame_number for actual screen
if (!spinner) {
std::cout << drawCount++;
} else {
std::cout << "x";
}
}
bool quit()
{
return (drawCount > kMaxDrawCount);
}
void start()
{
spinner = false;
std::cout << "S";
}
} game;
void syncToMainLoop(std::function<void()> in_callback)
{
std::lock_guard<std::mutex> lock(syncMutex);
syncQueue.push(in_callback);
loadCondition.notify_one();
}
void loadMap(const std::string &in_filename)
{
std::cout << "loadMap " << in_filename << std::endl;
// ... Do extensive work
std::this_thread::sleep_for(std::chrono::seconds(1));
// Notify that loading is done
syncToMainLoop([] {
game.start();
});
}
void loading()
{
// Do the sync requests
std::unique_lock<std::mutex> lock(syncMutex);
loadCondition.wait(lock, []{
return !syncQueue.empty();
});
auto callback = syncQueue.front(); // Get the next in line
syncQueue.pop(); // Remove it
lock.unlock();
callback(); // Call it
}
void onNewGame()
{
// Load the map, asynchronously
std::string level("level1-1.map");
std::thread loadThread(loadMap, std::ref(level));
loadThread.detach();
// wait for map loading to finish
std::thread waitThread(loading);
waitThread.detach();
}
/* This is main() */
void AsyncLoading_main()
{
onNewGame();
while (!game.quit())
{
game.update();
game.draw();
}
std::cout << std::endl;
}
@heLomaN
Copy link

heLomaN commented Apr 19, 2021

Simple & Clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment