Original Post
Okay, hopefully I am putting this in the right forum. This is more of a programming practice question than anything else in my opinion. This post may be a little long, since I will try to explain this as best as I can. I am the lead developer on DevIL, and I have recently been thinking about making DevIL thread-safe. Unfortunately, being away from programming for several years, I am not very familiar with thread safety and proper programming practices with it. Right now, DevIL keeps a list of images in an array that is accessed through ilGenImages/ilBindImage (similar to OpenGL). The images are pointers to structs that contain all the information about an image, including data. When you call ilBindImage, a global image pointer called iCurImage points to an entry in that array. Any functions that you call always operate on iCurImage. Obviously, this would not work at all in a multithreaded application (with multiple threads calling DevIL). The main part of making DevIL thread-safe would not be too terribly hard to implement, since I can just require an image pointer parameter to any function instead of using iCurImage. This is actually what DevIL did in its very first releases (when it was called OpenIL). I can also provide an interface to DevIL that mimics the current functionality, so hopefully people will not be put off by a new interface. Now comes the part that I am really not sure of. There are a lot of parameters that you can set via ilEnable/ilDisable and ilSetInteger. Things like setting the quality of .jpg files that are saved, compression types for files that support them, etc. These values are all currently stored in a global struct. I can see two possible paths to take here. I could require that the user pass a pointer of the struct that they fill out and control (or could be automatically filled out by a DevIL function with defaults). The other option that I see is to have the global struct like I have it now. There are not any pointers in this structure - just integers. This option would be preferable, but I am not sure how safe this is to do. What happens if a user is trying to change the value of one of the members of the struct while a function in DevIL is trying to access the same struct member to find out what it should do? The problem I see with the first option is that if I add a member to the struct in a future version of DevIL, programs compiled against an earlier version will not work properly. I have a similar problem with read/write functions. I allow the user to overload the read/write functions so that DevIL can load from either file streams or memory (along with any other method they wish to implement). I think that I will have to require that a structure with pointers to these functions will have to be passed when loading or saving, especially since one thread may want to load from memory while the other is trying to load from a file. Changing a global file access function mid-load would be pretty disastrous. Does anyone have any suggestions, comments or links to pages that describe proper thread-safe programming practices? [Edited by - Physics on January 14, 2009 6:09:08 AM]