Created
October 11, 2014 03:06
-
-
Save chunkyguy/e4f52c0a75f5ae4c7088 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Simple & Clear.