-
Notifications
You must be signed in to change notification settings - Fork 194
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
Please consider replacing foreign language idioms with proper C++ equivalents #79
Comments
Thank you for your feedback.
These are optional features that marl does not require you to use.
This is a valid point, and one I will fix by deleting the copy / move constructors on this class. Good spot!
The "proper way" here seems rather opinionated. Cheers, |
`marl::Scheduler` is not safe to copy or move. Bug: google#79
`marl::Scheduler` is not safe to copy or move. Bug: google#79
`marl::Scheduler` is not safe to copy or move. Bug: #79
Sorry, but the question isn't about what offends me or not. It's about what practices are common and widespread in which lang. C++ doesn't have GC, so both resources and memory are handled with smart wrapper. And RAII with deterministic destructor is a common right way to do so. If you do it the other way, you put aside certain best-practices and make things much less obvious. As for the
Again, it's a best-practice used throughout C++ world. You can go to
In this case, if I understand you correctly, Scheduler binds to HW thread and makes it its execution thread. What would happen if the thread which holds Scheduler on stack dies? Please don't get me wrong. It's your project. I'm just saying that using idioms from one language in another without reconsidering how they map isn't the best idea. And C++ is very, very different from Go. It gives you much flexibility but requires you being very careful. And it doesn't have GC. So resource leakage is the least of your issues. I urge you to consult with Google's own C++ guidelines and a seasoned C++ engineer. |
Yes, that's precisely what
What exactly is this best-practice used throughout C++ world? Having schedulers automatically unbind themselves from the one thread that called the destructor?
If it is destructed without being unbound on any bound thread, it would assert, as this is invalid usage. This is much like calling the destructor of
Thank you for your thoughts here. While you seem to have strong opinions, I can assure you that we did try to consider that C++ is not golang. That doesn't mean I didn't try to borrow some of the more convenient features from the language.
Please keep respectful. I've been writing C++ professionally for over 15 years in many lead roles for several big companies. While I'd never consider myself an expert in C++ (or yet meet anyone else I would call an expert), I do like to think I'm moderately competent. |
The helper function is okay on its own. What's concerning here is its use as the main way of resource management.
Of course not. The best-practice I'm referring is that object should properly clean resources it owns (or unbinds from resources it shares) in destructor.
Please note that
I thought at first that scheduler, when created, spawns multiple worker threads and manages them. Seems that I was wrong. If I'm correct now, it's user's responsibility to create worker threads and bind scheduler to them. In such a case I'd suggest to create thread binder class, similar to
I didn't say so. A completely correct usage may yield no issues. My main point is that manual binding is error-prone, and is usually avoided similarly to manual resource or memory management.
I sincerely apologize if I offended you somehow. What made me come to such conclusion is the use of Golang-specific resource management with manual |
Okay, let's put Let me firstly explain why we have the
The Scheduler can work in two distinct modes: single-threaded-worker and multi-threaded-worker. This is controlled by When in multi-threaded mode, N worker threads are automatically spun up by the scheduler, and these are shared across all bound threads. Calling If In either mode, you have tasks that may not have completed, holding on to resources by the time the scheduler destructor is called. The This single-threaded-worker case is also the reason the destructor cannot automatically do what you're asking. If you have tasks enqueued on other bound threads, they must execute on those same threads (a task yielded on one thread is guaranteed to resume on that thread - this is to avoid TLS bugs at yield points). There is simply no way in the single-threaded-worker case to get these threads to clean up their tasks because some other thread decided to pull the plug on the shared scheduler.
Okay - so there's no warning given that you're going to leak if your program doesn't adhere to the library's interface and you use a release build.
Okay, I buy this argument. We could create a new RAII helper to pair up a bind and unbind. I see why this would be helpful as a member to a class. For the simple Edits: fixed some incorrect method names as I was writing this on my phone without the ability to refer back to source. |
Based on the discussions of google#79
As far as I understand, the original issue had 3 main points:
Attempting to address each of these:
Given that there's a lot going on in this issue, I'm going to close this. If you'd like to discuss any of these topics further (or others), please feel free to open new bugs and optionally link back to this. Thanks for all the feedback. |
The RAII idiom is a native way in C++ land to handle resources management while
try-with-resources
/finally
/defer
-like idiom is an escape hatch for rare occasions. External destruction makes code prone to resources leakage and, more importantly, memory corruption and misuse.The other issue is lack of proper copy/move constructors/operators. Please check C++ guidelines on movable/copyable classes.
One such example is Scheduler class
The text was updated successfully, but these errors were encountered: