-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Discussion]: Get rid of global member variables #3901
Comments
Oh another solution I just came about: Use For more info see https://stackoverflow.com/questions/31978324/what-exactly-is-stdatomic |
Thank you very much for the very detailed info! Using atomic types is definitely the best solution, in my opinion. |
I’m not reading the full text now, but from the topic: Getting rid of the global state/variables has always been a wish and goal, at least ever since I have been here, so at least 10 years. It is not a question of desire or acceptance but of effort, time resource and priority. |
Indeed. At least Mumble doesn't seem to have serious race conditions, Murmur on the other hand (see #3893)... |
The problem with atomics that I see is in a situation like this:
In this example |
This is what #4195 is about (not exclusively though). No need to have 2 issues for the same thing |
Currently there are multiple places in which classes expose some of their member variables as public allowing direct read/write access to it. This however (in my opinion) makes it very easy for a multi-threaded application like Mumble to produce data-races and similar stuff. The solution for this (I have encountered in the source) is to add a public lock-object either for the whole class or on a per-variable-basis that has to be locked before using the variable.
Although this perfectly resolves the above-mentioned problem , it still appears quite error-prone to me as the use of the lock is not enforced. Thus I could go ahead, use/change that variable without acquiring the lock first which eventually will most likely result in some nasty bugs in the application.
One solution to this problem would be to make all member variables protected or private and supplying public getter and setter methods for them. Then these methods would implement the locking and once that is done properly, no one will be able to access these fields without locking them first (except of course he/she is working on the class itself but that is something you can't protect against).
Now I know that getters and setters are not everyone's favorites but I recommend reading through https://stackoverflow.com/questions/760777/c-getters-setters-coding-style for some arguments in its favour.
It's not all sunny though. Here are the disadvantages I can think of:
Another solution to this could be to rework how we get a hold of these classes. Currently this (often) happens via a static
get
method returning the respective class instance that is then used to access all its fields. If instead we returned a (class-specific) wrapper instead, we could implement that one in such a way that it will automatically lock the respective locks in that class.In essence I have something syntactically similar to a smart-pointer in my mind. Instead of returning the pointer to that instance, we return
Wrapper<MyClass>
which has an overloaded->
operator allowing the access to the underlying instance. It will acquire all locks in its constructor and release them in its destructor though.In order to decide whether a read- or a write-lock has to be acquired, an extra parameter has to be given to the respective
get
method (e.g.ClientUser::get(Access::Read)
).Pros:
Cons:
All in all though I think it is somewhat important to choose a way of enforcing locking (be it either of the two solutions or something you can come up with) as this (I think) makes the Mumble code more future-proof and in general more sophisticated.
Another bonus of this would be that it'd be easy to tell if a certain method is thread-safe or not. As of now there are a bunch of methods I don't know this, because they (apparently) access variables without holding a lock. Is this because no other code uses that variable or is this because that variable is not meant for multi-threaded access? I can't tell. If variable-access was lock-protected by default, this would be a lot easier to tell.
Another thing to consider here is that with the new plugin framework (#3743, #3742) a whole new layer of complexity is added to the underlying problem as the plugin's code is out of control for the Mumble-devs. Thus it might spawn new threads that access some data fields via the API. Thus a strategy of "we know what variables we access when, thus we don't need to lock them" doesn't hold (anymore). This of course implies that my PR will actually get merged into master at some point but if this weren't the case I hope someone would have stopped it by now xD
The text was updated successfully, but these errors were encountered: