// BlockyFroggy
// Copyright © 2017 John Ryland.
// All rights reserved.
#pragma once
#ifndef RESOURCE_LOADER_H
#define RESOURCE_LOADER_H
/*!
@page Topics
@subpage ResourceLoading
@page ResourceLoading Resource Loading
Resource loading can be time consuming. The time can be taken up by
waiting for IO to complete. This means the CPU is idle while this happens
if we were to block while waiting for this to complete. However ideally
the loading should happen asynchronously so we do not block the CPU from
doing other useful work.
Therefore the APIs need to be designed to make the requests in an
asynchronous manner, but make it convienent for the programmer to use this
API.
One simple way is using a callback which gets called when the load completes.
One issue is that if the implementation is multi-threaded, the callbacks may
be called on another thread, however we would prefer that didn't happen.
Instead the requests should occur on a main GUI thread, and the callbacks
should be called on this thread also.
More advanced usage might want to query how much percentage the load has
completed and also being able to cancel the request.
In our design, the loader needs to be pumped, eg an update function needs to
be called regularly so that the callbacks can be sent to the thread doing this
update pumping.
*/
#include <mutex>
#include <condition_variable>
#include <vector>
#include <atomic>
#include <functional>
using ByteArray = std::vector<uint8_t>;
struct Resource
{
virtual ~Resource();
virtual void load() = 0;
template <typename T>
bool operator==(T& other) {
return false;
}
virtual bool operator==(Resource&);
bool isLoaded();
void wait();
enum State {
Pending,
Loading,
CallbackPending,
Complete
};
std::mutex mutex;
std::condition_variable cond;
std::atomic<State> state;
std::function<void(Resource*)> callback;
ByteArray data;
};
//! Async API
Resource* loadFileAsync(const char* filename, bool onlineAsset, std::function<void(Resource*)> callback);
//! Non-async API
Resource* loadFile(const char* filename, bool onlineAsset = false);
//! Call periodically to allow dispatch of pending callbacks on the main thread (so things like OpenGL are happy)
void resourceLoaderUpdate(float dt);
#endif // RESOURCE_LOADER_H