Thread Safety, using threads to load models.

Started by
10 comments, last by NineYearCycle 12 years, 10 months ago

What happens to list::remove_if if there are no elements, is it just skipped?

void sys_tick(void) {
if(!readops.size())
readops.remove_if(CompleteReadOp);
}


Is this necessary/faster?

Why do you prefer to use a callback instead of a regular function call? Is this to handle different filetypes in different ways?


Not sure what you mean by necessary/faster. The if statement isn't necessary (in fact it's wrong, there shouldn't be a "!". That's what I get for trying to clean out irrelevant portions code before posting). If you mean polling with GetOverlappedResult, there are 2 options with Overlapped IO. You can either create an event (the hEvent field of the OVERLAPPED struct) and wait on that (WaitForSingleObject), or just poll with GetOverlappedResult. In general, polling is better than events for games, since you're updating every frame anyway, and you never ever want to block.

Using a callback just gives me the most flexibility, and the best architecture. Any individual file can have specific code related to it, neatly tucked away in that callback. Or you can use a generic callback for different file types. Or do both by adding another layer between the sys_read and the user callback. That's what I do with graphics assets:

Header
struct asset_t;
typedef void (*loadhandler_t)(asset_t *);

struct asset_t {
const char *name;
int type;
int flags;
loadhandler_t onload;
void *usr;

H3DRes res;
bool loaded;
};


Implementation
static void OnReadAsset(byte *b, unsigned len, void *usr) {
asset_t *asset = (asset_t *)usr;
h3dLoadResource(asset->res, (const char *)b, len);
free(b);
asset->loaded = true;
if (asset->onload) {
asset->onload(asset);
}
}

void asset_read(asset_t *a) {
if (a && a->name) {
a->res = h3dAddResource(a->type, a->name, a->flags);
sys_read(a->name, OnReadAsset, a);
}
}


So for graphics assets, instead of using sys_read directly, I create an asset_t (containing flags/etc specific to the renderer). asset_read handles getting the data loaded into the renderer, and then gives me an optional callback for any other stuff I might want to do with that asset once it's loaded.

The end result is that it's very clear what's going on. You can make the flexibility vs abstraction tradeoff that's best for any given situation.

Other people I'm sure use a system where you register handlers for different file types. That works fine, but it's forcing you to use the same level of abstraction for all of your file loading. What if I have 1 .BMP that I want loaded by the renderer, but another that I'm just using as a heightmap, so I don't want to actually create a texture for it? Callbacks let you layer abstraction, so I can handle processing the file data at subsystem-level, filetype-level, or individual file level, as needed.

EDIT: I should mention that you can always use a virtual function instead of a function pointer to do these callbacks, if you don't like the whole "C feel". I just like the option to declare my assets statically:static asset_t map = { "materials/map.material.xml", H3DResTypes::Material, 0, InitMap }; You can tell at a glance what this asset is, where it is, and what happens when it's loaded.

Also

free(o);


As I see it, "b" points to the first adress allocated. And "o" is appended to the last adresses. Why not free "b" if (!ReadFileEx....?


Yup, that's a bug, should be freeing b there. :D Thanks.
Anthony Umfer
Advertisement

Unless you've already considered this, you should first detect how many cores are on the computer. If there's only one your code needs to recognize this and not try to multithread at all. If you don't care about single core machines then ignore this but it's an important factor regardless.


Not true. Sure you could detect how many cores there are, but it doesn't affect the topic of threading the loading.

"Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile"

"Life is short, [the] craft long, opportunity fleeting, experiment treacherous, judgement difficult."

This topic is closed to new replies.

Advertisement