What I understood from previous posts is this: OpenGL uses contexts to manage render targets, and those contexts are not "safe" for multithreading, so they have restricted each context to a single active thread. You can deactivate one thread and activate another, but you can't have two active threads on the same context, so in other words it just forces the user to do the synchronization.
All that is important to know, I already mentioned in the list in the original post. You can multi-thread with contexts safely, you just have to keep those constraints in mind. Instead of activating and deactivating threads, which I never talked anywhere about, you activate and deactivate contexts. Even if a thread is "inactive" whatever that means, if a context is still active on that thread, it won't be able to be activated anywhere else. You have to consider things from the context's point of view and not the thread's point of view.
I meant to say that you can deactivate a context on a thread and activate it on another thread, but you can't activate it on multiple threads at the same time. I though it was obvious, but sorry for the bad wording.
My suggestion is that the synchronization is done hidden inside SFML, so that the API can stay the same.
This is the way it currently is, and if you've read what has already been posted in this thread again, you will see that this leads to problems. And before you say anything else, no, your solution will not solve any of these problems. It will merely create more of them.
I know it is already like this, that is why I've said that the API would stay the same. What I am discussing here is possible implementation changes that could solve the said problems without affecting the API.
I didn't know we had to synchronize data retrival functions as well. As I've said before, I only know this issue from what I've read here, so if I don't know all of the problems my suggestions will be flawed from the start. How does data retrieval work on OpenGL? Is it thread-safe? Does it support parallel data retrival on multiple threads? Does it use the contexts for that? In what way? I am realy clueless to this point.
Data retrieval isn't as complicated as you think, but that still doesn't mean you don't have to give it a bit of thought. It can have many manifestations. The most common and simple one is getting a single state value from the driver. This can be different depending on which context is active when you call the respective function. For things like taking screenshots, it is a bit more complicated. You will have to pass in a correctly sized array so that the GL can write the data you request from it into the array. This is also context dependent, and is a rather slow operation since we are reading data directly from the GPU.
Ok, the data depends on the active context, so we have to synchronize data retrieval as well. That could be done by blocking the calling thread until the "drawing thread" retrieves the data, and sharing the return value between threads, but I agree that it is not as clean as it could be.
If you heed what I said in the original post in regards to contexts and threads, then yes, it is thread-safe. Yes it supports parallel retrieval on multiple threads, also constrained by the same requirements. Yes it uses contexts, everything in OpenGL uses contexts, didn't you read the original post?
If it uses the active context, it can't be used in parallel. Or am I missunderstanding something? If you can't have two different threads retrieving data from the same context at the same time, I wouldn't consider it thread-safe, but that might be bad wording, so I am sorry for the missunderstanding. In the end, we have to synchronize drawing and data retrieval functions to the same context ourselves.
This is worse than I expected... Now I understand that you were aiming to have a separate "rendering thread" for each context that can be used in some way... just so you can omit having to constantly select which one to activate? There are beginners on this forum... that just start out with game development, and after not too long, even they understand that having more threads than necessary is not a good thing. I don't know where you are coming from, but if you think that resorting to creating an excessive number of threads to get anything done is a good idea, I am sorry to have to tell you that you are mistaken. The same is said to beginners as well as advanced developers: Avoid threads while you can. Unless you know exactly why they provide a benefit, you won't gain much from them.
Ok then, lets avoid multiple meaningless threads. I'll suggest another solution at the end of the post that doesn't create any aditional thread.
If that is the case, then you must also oppose usage of smart pointers over raw pointers too right? Raw pointers don't create unsolvable issues and have better resource usage than smart pointers, and yet the universal opinion from any established C++ programmer is that you should rarely ever use raw pointers (and certainly not owning ones) in modern C++ code.
Using raw pointers directly is much harder than using smart pointer. It is bad practice because unless you pay attention to all of the allocation and freeing of memory, you will create serious problems. Sure, if you don't pay attention to the synchronization of OpenGL operations it will create serious problems, but as long as we manage to take care of those problems internally, it will cease to be bad practice to the final user. If SFML used raw pointers on some internal sections of code, for example, but used them correctly, the user code wouldn't be affected by it in the least. The user wouldn't even see the pointers.
Ok, it is unheard of, but would it work?
You tell me... I am not going to go ahead and spend 10s maybe even 100s of hours implementing something I find problematic from the start. From reading what you have proposed, I would say, yeah, it can work, but have fun with your 2 FPS applications. Ultimately, most ideas in software development, no matter how crazy they are, can be implemented. You just have to spend a varying amount of time dealing with the effects you did not anticipate during brainstorming.
I still fail to see the reason for the drop in performance. Sleeping threads shouldn't affect the performance of the active threads. Anyway, I'll suggest another solution at the end of this post, please take a look.
What are the possible drawbacks? Is the number of threads limited to less than the number of possible contexts on an application? Would multiple sleeping threads (since the threads will be mostly sleeping, except when waken to draw stuff and sleep again) affect the performance of the user's thread? Would those sleeping threads compromise memory in any significant way?
I've already reiterated over the drawbacks enough times in the last posts and this one. If you still don't understand them, please read them again. I assume that you are somewhat familiar with threading (and more importantly efficient multi-threading), since you often propose "solutions" to problems that involve them in some way. So can't you just draw your own conclusions? If this is not the case, i.e. you are not experienced in threading, then I highly recommend you refrain from using them in any future solutions you propose anywhere. I don't mean to be offensive, but these solutions don't necessarily make you look good...
From what I did understand from your previous posts, the main drawback was that SFML created a lot of useless contexts so that every operation performs on a different context and we don't have to synchronize anything. I might have missunderstood the issues, but my suggestion was made considering this scenario. Please elucidate me if I am mistaken, but after reading the first post of the thread again this is still what I understood.
Ok, so I agree that creating a dedicated thread for each render target and having the context active on that thread might not be a very clean solution. An alternative solution would be to always deactivate contexts after each OpenGL operation, and block threads that want to do OpenGL operations until the previous one stops.
I am not very familiar to C++ mutexes and synchronization, but on Java the code would be something like this for every OpenGL operation:
synchronize (context) {
// activate context
// perform OpenGL operation
// deactivate context
}
I assume it would be similar on C++. That way the context will only be active during the operation, and multiple threads trying to use the same context in parallel would be executed one at a time. What I don't know is: does activation and deactivation of contexts take much time, or is it instantaneous? This solution would be bad if activating and deactivating contexts multiple times would lead to performance issues, but if it is as trivial as changing one state, it won't matter much.
Another possible variant of the dedicated internal threads suggestion would be to have only one internal thread, and have it doing the OpenGL operations for all of the contexts. If I understood what you've said on the first post, we might gain some performance if driver operations are issued in parallel to different contexts, so this suggestion would remove this possible performance gain, but you make it sound like driver operations are so fast that the gain is trivial. If that is the case, then this solution will be viable.