5 ms·
A couple of my favorite types and functions in absl: - Span For when you want to take an array or a vector. - string_view Avoids string copies. Makes your p
by 7197ghr918hf 9y ago
A couple of my favorite types and functions in absl:
- Span
For when you want to take an array or a vector.
- string_view
Avoids string copies. Makes your program faster. Its creation was a reaction to situations like https://news.ycombinator.com/item?id=8704318 https://news.ycombinator.com/item?id=8704318. (It predates that revelation, but internally the plague of string copies has been known for some time.)
- Mutex
A better mutex with deadlock detection.
- Substitute
A string formatting function between 5 and 1000s of times faster than snprintf. Profile your code some time. If it's anything like mine, you might be surprised at how much this matters.
- base::Time and base::Duration
Excellent wall time utilities, similar to Go's wall clock time libraries.
- roel_v 9y ago"- Span For when you want to take an array or a vector." How's this different from taking a pair of iterators? "string_view" After having read all those articles about c++17's string_view, I still don't really get the real differences. OK, when parsing (i.e. using many substrings) it makes sense (but then you'd usually work with char* anyway); and maybe some people interact with C libraries that only take char* a lot (and in cases where they have to 'cross the boundary' often). So maybe in text-heavy applications (like I imagine C++ application for the web would be) it makes some sense, but I fail to understand why it's causing this much excitement. "Substitute" There are so many fast formatting libraries already - what does this one offer over those? Because it's generally a trade off between completeness/type safety on the one hand, and speed on the other. I use boost::format which is quite slow in benchmarks, but again I don't do much string processing. "base::Time and base::Duration" In what way are these different from boost::date_time and std::chrono? Here again the documentation (for Abseil) seem to be missing. I mean, I'm all for batteries-included libraries - but this just seems to be a few loosely-related classes slapped together and the only reason it's even on here is because it's from Google. There are dozens of similar libraries languishing on sourceforge and github. Compare it to e.g. POCO - this is not even in the same league.
- int_19h 9y ago> I fail to understand why it's causing this much excitement. C++ guys just like zero-overhead abstractions. The more we can get, the better. Passing std::string around has always been a sore point, and occasionally prompted misguided optimizations (like refcounting copy-on-write in g++).
- roel_v 9y agoWell yes, I'm what one would call a 'C++ guy' myself. Don't pass around, pass around const std::string&. What I see left and right is people saying 'you'll never pass a const std::string& any more!'. The way I see it: you'd pass a string_view in the cases where, in the past, you would have had to copy a part out of a string (which is rare, except in parsers), or when dealing with char* API's; what's better about passing a string_view than passing const string& ?
- int_19h 9y agoNothing. But I would disagree that having to copy a part of a string, or having to pass part of a char buffer that is not a string, is all that rare, even outside of parsers.
- humanrebar 9y ago> After having read all those articles about c++17's string_view, I still don't really get the real differences. `string_view` is a much cleaner parameter type. `char*` and a `size_t` is two parameters. `string` is really a character buffer, accepting a character buffer as input is odd. `string_view` can be trivially constructed from most non-string data structures, including `vector<char>` and `array<char>`. And, now that it's standard, `string_view` is a very lightweight dependency to add to your interface compared to `boost` or hand-rolled alternatives. To that last point, I'm not sure I'd use an abseil `string_view`, at least as an interface type, but I appreciate that they have migration to new standards as a design goal.
- duneroadrunner 9y ago> "- Span For when you want to take an array or a vector." > How's this different from taking a pair of iterators? Safety and (a little) convenience. If your function takes a pair of iterators, there's no way to ensure (at compile-time anyway) that both iterators are even pointing into the same array/vector. Also, spans can ensure, with bounds-checking, that only elements within a specified sub-range can be accessed. Such bounds-enforcement is particularly important in cases like, for example, SaferCPlusPlus' "TRASectionSplitter", which is a data type that allows you to partition an array/vector/whatever into subsections that can each be safely accessed/modified concurrently from different threads. ("TRASectionSplitter" is not yet documented, but for those interested, example code can be found here[1].) [1] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus/blob/master/msetl_example.cpp#L1903 https://github.com/duneroadrunner/SaferCPlusPlus/blob/master...
- duneroadrunner 9y ago> - Mutex From their "Devguide": Clients of Mutex must obey these rules: 1. Each time a thread acquires a Mutex it must later release it. 2. A thread may not attempt to release a Mutex unless it holds it. 3. A thread may not attempt to acquire an exclusive lock on a Mutex it already holds. For basic sharing of resources between threads, using "access requesters"[1] can be safer and more convenient as they automatically take care of these rules for you. And if you need to use the mutex directly, the SaferCPlusPlus library provides a "recursive_shared_timed_mutex"[2] (the one missing from the standard library), which allows a thread to hold multiple ("read" and/or "write") locks at the same time (relieving the "self-deadlock" issue). The mutex isn't documented, but it functions just as its name suggests. [1] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus#asynchronously-shared-objects https://github.com/duneroadrunner/SaferCPlusPlus#asynchronou... [2] https://github.com/duneroadrunner/SaferCPlusPlus/blob/master/mseasyncshared.h#L78 https://github.com/duneroadrunner/SaferCPlusPlus/blob/master...
- slrz 9y agoRecursive mutexes? SaferCPlusPlus is not seriously recommending to replace standard/sane mutexes with their disfigured recursive cousins? Yuck. I thought people agreed long ago that their only valid use-case was papering over broken/non-existing resource access schemes in applications of yore, so you could try to speed them up sprinkling magic multi-threading pixie dust.
- duneroadrunner 9y agoSaferCPlusPlus does not recommend relying directly on mutexes at all. For most straightforward cases, you can use the "access requesters" to safely manage asynchronous access automatically. Recursive mutexes are analogous to having multiple pointers (or iterators), some of which are "non-const", to an object in the same thread at the same time. Some suggest that this too is a bad idea. For example, the Rust language does not allow a "mutable" (i.e. "non-const") reference to an object to co-exist with any other reference to that object, even in the same thread. SaferCPlusPlus does not necessarily disagree with this position, but it also does not require adherence to it, like Rust does. So if SaferCPlusPlus is going to allow multiple pointers (or iterators) to a shared object in the same thread, then it's going to need to lock the mutex protecting the object multiple times from the same thread. Giving each pointer/iterator its own separate lock, as opposed to having one lock encompass the all the pointer/iterators, allows the locks to be managed automatically, which ensures against data races, and that resource locks will be released as soon as it is safe to do so. Again, there's rarely any reason you'd need to interact with the mutex directly. It's primarily there to support "access requester" functionality. Also, note that this is a recursive shared mutex, not just a recursive mutex, which means that, for example, it provides a kind of "upgrade mutex" functionality. So if a thread has a "read" lock, it can obtain a "write" lock (blocking if necessary), without having to give up its read lock. Then when it's done with the write lock, it can release it without fear of losing its read lock (or blocking).