- :: scope resolution operator - 1 Update
- What practice can get speed improvement in C++? - 1 Update
- Using smart pointers in containers - 1 Update
- Concrete classes considered harmful - 2 Updates
- auto i:v as iterator - 4 Updates
- Why are there throw() following the delete[]? - 3 Updates
- SQL filesortcc question - 7 Updates
- Available C++ Libraries FAQ - 1 Update
- Use of rvalue reference in the given scenario - 2 Updates
- Chess prog - 2 Updates
- What does this struct line do? - 1 Update
red floyd <no.spam.here@its.invalid>: Jul 21 08:19AM -0700 On 7/20/2015 11:59 AM, Richard wrote: > A tautology is a thing that is tautological. https://xkcd.com/703/ |
Martijn van Buul <pino@dohd.org>: Jul 21 09:28AM * fl: > about programming for embedded RTOS system, although the code may be for the > test bench (less embedded in some sense). I code a lot at the lower level. It > is the first time I know valgrind+callgrind. Programming for an RTOS requires a different mindset every now and then, depending on the real-time restrictions and the platform. For example, the *maximum* runtime requirements of an algorithm is often more important than the *average* requirement, because the first is a limiting factor on response time. Available memory and processor resources often don't scale as easily, and some C++ features (or parts of the standard library) just don't combine well with a hard real-time behaviour. Often, the mere fact that you use an RTOS has implications beyond the obvious. On modern desktop and server operating systems, a stack overflow is almost unheard of, but on RTOS systems, stack space is usually *very* limited, so you need to be aware of deeply recursive routines, or large objects placed on the stack. Deadlocks are often more fatal; if your browser stalls for a couple of seconds it is annoying; if the ECU of a car stalls it can lead to a deadly accident. Granted, this is all about "how to write your algorithm" and "what pitfalls to avoid" rather than "what tricks to use to get a perceived boost", and personally, I don't think "speed improvement" covers anything of the required skills to sucessfully handle real-time programming. -- Martijn van Buul - pino@dohd.org |
legalize+jeeves@mail.xmission.com (Richard): Jul 20 10:52PM [Please do not mail me a copy of your followup] Paul <pepstein5@gmail.com> spake the secret code >Suppose, for example, that I'm designing a tree where the number of >nodes descending from any particular node is variable. Any reason not >to put nodes in vectors of std::unique_ptr<T> Use shared_ptr<> and unique_ptr<> to indicate ownership lifetimes. There's no reason to stop using local variables (including parameters) that are raw pointers when it is clear that this does not imply a transfer of ownership. Usually, but not always, a container of items allocated on the heap manages the lifetime of those items. If those items are shared, then it's a container of shared_ptrs, if those items are uniquely owned by the container, then it's a container of unique_ptr. There are times when a container does not manage the lifetime of the pointers inside it (temporary data structures built up during processing are a good example) and in these cases, it could be disastrous to have a container of smart pointers because the container doesn't own the resources pointed to by the raw pointers. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
Ian Collins <ian-news@hotmail.com>: Jul 16 09:49AM +1200 Richard wrote: > side benefit of creating the insulting domain specific layer. You end > up with interfaces that more directly describe the specific services > needed by your application. A lot of the code I write (and have to test) falls into that category, hence the need to mock the system calls! -- Ian Collins |
legalize+jeeves@mail.xmission.com (Richard): Jul 16 03:53PM [Please do not mail me a copy of your followup] Ian Collins <ian-news@hotmail.com> spake the secret code >> from Win32 then you'll want something more automated. >A lot of the code I write (and have to test) falls into that category, >hence the need to mock the system calls! Yeah, I can see that if you're writing lots of system oriented code. However, lots of C APIs are really thinly disguised objects. They have some C function you call to obtain a resource and another function you call to release a resource. So a wrapper can still be useful in these circumstances to map the C api to a more object-oriented api that ensures that resources are always properly released. Still, for unit testing that stuff you need to mock out the underlying system API calls. I've done it via both static and dynamic polymorphism to allow me to decouple myself from the specific API call. It's more tedious to do link-time substitution when the things you're mocking are in Windows DLLs. I haven't tried link-time mocking Windows DLLs myself but a coworker who tried it said that it was really quite painful. I didn't review the code he did, so I don't know exactly what the pain was, but I can imagine that link-time mocking without some sort of tool that automates the process could be quite tedious. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
Ralf Goertz <me@myprovider.invalid>: Jul 16 10:39AM +0200 Hi, is it possible to have the new auto syntax for loops and get an iterator instead of a copy or a reference to the stored object itself? I would love to use the new syntax, but often I need to know what number in a vector the current object is. The following program doesn't compile. #include <vector> #include <iostream> int main() { std::vector<int> v={47,11}; for (auto i:v) { //std::cout<<i<<std::endl; std::cout<<distance(i,v.begin())<<endl; } return 0; } |
Bo Persson <bop@gmb.dk>: Jul 16 11:09AM +0200 On 2015-07-16 10:39, Ralf Goertz wrote: > } > return 0; > } If you have a reference to the element (auto&...), you can compute the difference between &i and &v[0]. Bo Persson |
Ralf Goertz <me@myprovider.invalid>: Jul 16 12:00PM +0200 Am Thu, 16 Jul 2015 11:09:51 +0200 > > } > If you have a reference to the element (auto&...), you can compute > the difference between &i and &v[0]. Thanks, that works for vector and array, but what about lists or even sets and maps? I guess I can't add another variable declaration within the "for" parenthesis like for (auto c=0, i:v) {…} |
Ralf Goertz <me@myprovider.invalid>: Jul 16 03:47PM +0200 Am Thu, 16 Jul 2015 05:17:03 -0700 (PDT) > On Thursday, 16 July 2015 13:00:20 UTC+3, Ralf Goertz wrote: [dequoted to make the news server happy] #include <vector> #include <iostream> #include <iterator> int main() { std::vector<int> v={47,11}; for (auto i:v) { //std::cout<<i<<std::endl; std::cout<<std::distance(i,v.begin())<<std::endl; } return 0; } > this code would just output 0 and -1. It does not feel like good way > for achieving such output, so there must be some sort of point to > it. Sure, I was merely trying to give a non compiling example (which in the OP turned out to be non-compilable not only because of the auto=/=iterator problem). And of course I meant std::distance(v.begin(),i) > Element's reference is cheap to convert to iterator only for > containers where the elements are stored contiguously in memory I know that and I have to admit that I was stretching the limits. (I actually need it only for vectors and Bo told me how to do it.) But anyway, what is bad about the idea that the auto keyword in range based for loops for container C can also be standing for C::iterator? The compiler would need to check the first appearence of the (in my case) i and deduce it is an iterator. > int c = 0; for (auto i:v) {...} > If you need to limit scope of c for whatever reason then limit: > {int c = 0; for (auto i:v) {...}} But don't you agree that this approach is somewhat less elegant? > It may be that you need something from Boost.Range or the like but it > is hard to tell without knowing what you actually want to achieve. Sometimes I need to handle the say 10th element of a vector differently than the others: for (auto &i:v) { if (&i-&v[0]==10) {…} // special stuff else {…} // do ordinary stuff } |
Ian Collins <ian-news@hotmail.com>: Jul 16 11:44AM +1200 fl wrote: > Thanks. As you said, it is a declaration. Good. > As I am a newbie to C++, I still feel it is different from a normal > declaration. What role of the throw() in the declaration? As I said above, throw() (noexcept in modern C++) is telling you that the operators will not throw an exception. -- Ian Collins |
Ian Collins <ian-news@hotmail.com>: Jul 16 11:18AM +1200 fl wrote: > void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw(); > placement (3) > void operator delete[] (void* ptr, void* voidptr2) throw(); <snip> > 1. In the normal use of delete[], I never see the throw() following it; > 2. The description does not mention about throw() although the upper part > has throw() These describe the operators as defined in <new>. The throw() (noexcept in modern C++) is telling you that the operators will not throw. You don't include the throw() when you use operator delete, it is only appropriate in the declaration. -- Ian Collins |
Bo Persson <bop@gmb.dk>: Jul 16 11:03AM +0200 On 2015-07-16 01:36, fl wrote: > As I am a newbie to C++, I still feel it is different from a normal > declaration. What role of the throw() in the declaration? > I hope your further explanation can teach me more on this. The throw-part lists the execeptions the function (or operator) is allowed to throw. Here the list is empty, meaning that it throws no exceptions. Bo Persson |
Ian Collins <ian-news@hotmail.com>: Jul 16 09:55AM +1200 The Doctor wrote: Nothing relevant to c.l.c! > All right to essentials on this one. > Using g++ 3.2.3 , Gmake 4.01 and Cmake 2.6.4 Why are you using such an old compiler? -- Ian Collins |
Paavo Helde <myfirstname@osa.pri.ee>: Jul 15 04:08PM -0500 doctor@doctor.nl2k.ab.ca (The Doctor) wrote in > /usr/source/mysql-5.6.25/sql/filesort_utils.cc:202: > `return_temporary_buffer' > undeclared in namespace `std' [...] > What can I do to compile this? #include <memory> ? hth Paavo |
James Kuyper <jameskuyper@verizon.net>: Jul 15 05:15PM -0400 On 07/15/2015 04:40 PM, The Doctor wrote: > <unnamed>::try_reserve(std::pair<type*, ptrdiff_t>*, int)': > /usr/source/mysql-5.6.25/sql/filesort_utils.cc:178: parse error before `>' > token You're getting a parse error inside a C++ template function. More specifically, it's a parse error inside the template portion of the C++ syntax for calling a templated function. Why did you think cross-posting to comp.lang.c would be any help? I know a fair amount of C++, more than the average person on comp.lang.c - but I can't figure out what's causing the parse error - so you need a better C++ expert than me. It might be an interaction between the code you've actually given us, and the user-defined header files that you didn't give us - so I'd recommend posting the contents of those files as well. But post it only to comp.lang.C++ > Filesort_buffer::sort_buffer(const Sort_param*, unsigned int)': > /usr/source/mysql-5.6.25/sql/filesort_utils.cc:202: `return_temporary_buffer' > undeclared in namespace `std' My copy of the C++2011 standard says that std::get_temporary_buffer<>() and std::return_temporary_buffer<>() are both declared in <memory>, which is not one of the headers you #included directly. Is it #included indirectly through one of the other headers? If not, that would explain the above error message. If that's the problem, your use of get_temporary_buffer would probably also have generated such an error message, if it hadn't been for the parse failure. |
doctor@doctor.nl2k.ab.ca (The Doctor): Jul 15 08:40PM All right to essentials on this one. Using g++ 3.2.3 , Gmake 4.01 and Cmake 2.6.4 I get Script started on Wed Jul 15 06:45:13 2015 doctor.nl2k.ab.ca//usr/source/mysql-5.6.25$ gmake [ 0%] Built target INFO_BIN ... Scanning dependencies of target sql [ 47%] Building CXX object sql/CMakeFiles/sql.dir/sql_yacc.cc.o [ 47%] Building CXX object sql/CMakeFiles/sql.dir/abstract_query_plan.cc.o [ 47%] Building CXX object sql/CMakeFiles/sql.dir/datadict.cc.o [ 47%] Building CXX object sql/CMakeFiles/sql.dir/debug_sync.cc.o [ 47%] Building CXX object sql/CMakeFiles/sql.dir/derror.cc.o [ 47%] Building CXX object sql/CMakeFiles/sql.dir/des_key_file.cc.o [ 47%] Building CXX object sql/CMakeFiles/sql.dir/discover.cc.o [ 48%] Building CXX object sql/CMakeFiles/sql.dir/field.cc.o /usr/source/mysql-5.6.25/sql/field.cc: In member function `virtual void Field_string::make_sort_key(uchar*, unsigned int)': /usr/source/mysql-5.6.25/sql/field.cc:6886: warning: unused variable `uint tmp' [ 48%] Building CXX object sql/CMakeFiles/sql.dir/field_conv.cc.o [ 48%] Building CXX object sql/CMakeFiles/sql.dir/filesort.cc.o [ 48%] Building CXX object sql/CMakeFiles/sql.dir/filesort_utils.cc.o /usr/source/mysql-5.6.25/sql/filesort_utils.cc: In function `size_t <unnamed>::try_reserve(std::pair<type*, ptrdiff_t>*, int)': /usr/source/mysql-5.6.25/sql/filesort_utils.cc:178: parse error before `>' token /usr/source/mysql-5.6.25/sql/filesort_utils.cc: In member function `void Filesort_buffer::sort_buffer(const Sort_param*, unsigned int)': /usr/source/mysql-5.6.25/sql/filesort_utils.cc:202: `return_temporary_buffer' undeclared in namespace `std' /usr/source/mysql-5.6.25/sql/filesort_utils.cc: In function `size_t <unnamed>::try_reserve(std::pair<type*, ptrdiff_t>*, int) [with type = uchar*]': /usr/source/mysql-5.6.25/sql/filesort_utils.cc:199: instantiated from here /usr/source/mysql-5.6.25/sql/filesort_utils.cc:181: `return_temporary_buffer' undeclared in namespace `std' gmake[2]: *** [sql/CMakeFiles/sql.dir/filesort_utils.cc.o] Error 1 gmake[1]: *** [sql/CMakeFiles/sql.dir/all] Error 2 gmake: *** [all] Error 2 doctor.nl2k.ab.ca//usr/source/mysql-5.6.25$ exit exit Script done on Wed Jul 15 07:21:55 2015 The code in question is /* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "filesort_utils.h" #include "sql_const.h" #include "sql_sort.h" #include "table.h" #include <stddef.h> #include <algorithm> #include <functional> #include <vector> namespace { /** A local helper function. See comments for get_merge_buffers_cost(). */ double get_merge_cost(ha_rows num_elements, ha_rows num_buffers, uint elem_size) { return 2.0 * ((double) num_elements * elem_size) / IO_SIZE + num_elements * log((double) num_buffers) * ROWID_COMPARE_COST / M_LN2; } } /** This is a simplified, and faster version of @see get_merge_many_buffs_cost(). We calculate the cost of merging buffers, by simulating the actions of @see merge_many_buff. For explanations of formulas below, see comments for get_merge_buffers_cost(). TODO: Use this function for Unique::get_use_cost(). */ double get_merge_many_buffs_cost_fast(ha_rows num_rows, ha_rows num_keys_per_buffer, uint elem_size) { ha_rows num_buffers= num_rows / num_keys_per_buffer; ha_rows last_n_elems= num_rows % num_keys_per_buffer; double total_cost; // Calculate CPU cost of sorting buffers. total_cost= ( num_buffers * num_keys_per_buffer * log(1.0 + num_keys_per_buffer) + last_n_elems * log(1.0 + last_n_elems) ) * ROWID_COMPARE_COST; // Simulate behavior of merge_many_buff(). while (num_buffers >= MERGEBUFF2) { // Calculate # of calls to merge_buffers(). const ha_rows loop_limit= num_buffers - MERGEBUFF*3/2; const ha_rows num_merge_calls= 1 + loop_limit/MERGEBUFF; const ha_rows num_remaining_buffs= num_buffers - num_merge_calls * MERGEBUFF; // Cost of merge sort 'num_merge_calls'. total_cost+= num_merge_calls * get_merge_cost(num_keys_per_buffer * MERGEBUFF, MERGEBUFF, elem_size); // # of records in remaining buffers. last_n_elems+= num_remaining_buffs * num_keys_per_buffer; // Cost of merge sort of remaining buffers. total_cost+= get_merge_cost(last_n_elems, 1 + num_remaining_buffs, elem_size); num_buffers= num_merge_calls; num_keys_per_buffer*= MERGEBUFF; } // Simulate final merge_buff call. last_n_elems+= num_keys_per_buffer * num_buffers; total_cost+= get_merge_cost(last_n_elems, 1 + num_buffers, elem_size); return total_cost; } uchar **Filesort_buffer::alloc_sort_buffer(uint num_records, uint record_length) { DBUG_ENTER("alloc_sort_buffer"); DBUG_EXECUTE_IF("alloc_sort_buffer_fail", DBUG_SET("+d,simulate_out_of_memory");); /* For subqueries we try to re-use the buffer, in order to save expensive malloc/free calls. Both of the sizing parameters may change: - num_records due to e.g. different statistics from the engine. - record_length due to different buffer usage: a heap table may be flushed to myisam, which allows us to sort by <key, addon fields> rather than <key, rowid> If we already have a buffer, but with wrong size, we simply delete it. */ if (!m_idx_array.is_null()) { if (num_records != m_idx_array.size() || record_length != m_record_length) free_sort_buffer(); } if (m_idx_array.is_null()) { uchar **sort_keys= (uchar**) my_malloc(num_records * (record_length + sizeof(uchar*)), MYF(0)); m_idx_array= Idx_array(sort_keys, num_records); m_record_length= record_length; uchar **start_of_data= m_idx_array.array() + m_idx_array.size(); m_start_of_data= reinterpret_cast<uchar*>(start_of_data); } DBUG_RETURN(m_idx_array.array()); } void Filesort_buffer::free_sort_buffer() { my_free(m_idx_array.array()); m_idx_array= Idx_array(); m_record_length= 0; m_start_of_data= NULL; } namespace { /* An inline function which does memcmp(). This one turns out to be pretty fast on all platforms, except sparc. See the accompanying unit tests, which measure various implementations. */ inline bool my_mem_compare(const uchar *s1, const uchar *s2, size_t len) { DBUG_ASSERT(len > 0); DBUG_ASSERT(s1 != NULL); DBUG_ASSERT(s2 != NULL); do { if (*s1++ != *s2++) return *--s1 < *--s2; } while (--len != 0); return false; } class Mem_compare : public std::binary_function<const uchar*, const uchar*, bool> { public: Mem_compare(size_t n) : m_size(n) {} bool operator()(const uchar *s1, const uchar *s2) const { #ifdef __sun // Usually faster on SUN, see comment for native_compare() return memcmp(s1, s2, m_size) < 0; #else return my_mem_compare(s1, s2, m_size);
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment