woodbrian77@gmail.com: Aug 11 06:27PM -0700 Shalom What do you think is the worst thing about 2020 C++? I'd say it's the lack of static exceptions. Are Clang or Gcc making any progress with that in spite of 2020 C++? Brian Ebenezer Enterprises - Enjoying programming again. https://github.com/Ebenezer-group/onwards |
Sam <sam@email-scan.com>: Aug 12 06:28PM -0400 > I'd say it's the lack of static exceptions. Are Clang > or Gcc making any progress with that in spite of 2020 > C++? Co-routines is the undisputed winner, hands down. A solution in search of a problem. If I was on the committee and ate some mushrooms, this is what I would come up with. |
Frederick Gotham <cauldwell.thomas@gmail.com>: Aug 12 03:09AM -0700 Before I begin, I have deliberately left out necessary code in order to make this as simplistic as possible (for example I've neglected to join all std::thread objects before destroying them). I have the following global constant, along with an atomic counter variable: unsigned constexpr g_N_threads = 6u; std::atomic<unsigned> g_counter{0}; And then I have the following global array to store the thread ID's: std::array< std::atomic<std::thread::id>, g_N_threads > g_ids_for_threads{}; In my main thread, I have this code in 'main': int main(void) { array<std::thread,g_N_threads> threads; /* Create std::thread objects without starting threads yet */ for ( unsigned i = 0; i != g_N_threads; ++i ) { threads[i] = std::thread(Thread_Entry_Point); } //Give threads a chance to start std::this_thread::sleep_for(std::chrono::seconds(2)); //Right now, g_counter is still 0 for ( unsigned i = 0; i != g_N_threads; ++i ) { assert( std::thread::id{} != threads[i].get_id() ); g_ids_for_threads[i] = threads[i].get_id(); } ++g_counter; } And then for each of the 6 threads, I first have this helper function: unsigned Get_Thread_Index_From_StdID(std::thread::id const arg_id) { assert( std::thread::id{} != arg_id ); for (unsigned i = 0; i != g_N_threads; ++i) { if ( arg_id == g_ids_for_threads[i] ) return i; } assert( nullptr == "Control should never reach here!" ); } And here's the entry point to the thread: void Thread_Entry_Point(void) { unsigned counter = 0; while ( counter >= g_counter ); //spin until g_counter increments static thread_local SomeType some_object{ Get_Thread_Index_From_StdID( std::this_thread::get_id() ) }; for (; /* ever */ ;) { /* Do Something */ } } When I build and run this, the error I'm getting is as follows: gotham: gotham.cpp:147: unsigned int Get_Thread_Index_From_StdID(std::thread::id): Assertion `nullptr == "Control should never reach here!"' failed. This means that there's a problem with how I'm retrieving and storing the thread ID's. Can anyone see what's wrong here? |
Paavo Helde <eesnimi@osa.pri.ee>: Aug 12 01:54PM +0300 12.08.2020 13:09 Frederick Gotham kirjutas: > Before I begin, I have deliberately left out necessary code in order to make this as simplistic as possible (for example I've neglected to join all std::thread objects before destroying them). [random uncompilable code snippets clipped] > gotham: gotham.cpp:147: unsigned int Get_Thread_Index_From_StdID(std::thread::id): Assertion `nullptr == "Control should never reach here!"' failed. > This means that there's a problem with how I'm retrieving and storing the thread ID's. > Can anyone see what's wrong here? There are lots of things wrong with your code (hint: random sleeping and spin-waiting are pretty bad ideas), but the most obvious is that you have not provided a compilable and runnable example which would demonstrate the problem. I copy-pasted the pieces in some order which compiled, fixed some syntax errors, added needed includes and missing thread joining. The final program worked without problems with two different compilers. I suspect the problem is in your code which you have not shown or have altered while posting. |
Ben Bacarisse <ben.usenet@bsb.me.uk>: Aug 12 12:02PM +0100 > } > } > When I build and run this, the error I'm getting is as follows: It would be helpful if you posted something we could build and run. When I make minimal additions to make it a whole program, I don't get the behaviour that you see: > This means that there's a problem with how I'm retrieving and storing > the thread ID's. > Can anyone see what's wrong here? I haven't looked at the program because it's often hard (and sometimes pointless) to debug code when you can't re-recreate the problem. -- Ben. |
Frederick Gotham <cauldwell.thomas@gmail.com>: Aug 12 04:33AM -0700 On Wednesday, August 12, 2020 at 11:54:54 AM UTC+1, Paavo Helde wrote: > program worked without problems with two different compilers. I suspect > the problem is in your code which you have not shown or have altered > while posting. I've put it all together as compilable code: #include <cassert> #include <array> #include <atomic> #include <thread> #include <iostream> using namespace std; unsigned constexpr g_N_threads = 6u; std::atomic<unsigned> g_counter{0}; std::array< std::atomic<std::thread::id>, g_N_threads > g_ids_for_threads{}; unsigned Get_Thread_Index_From_StdID(std::thread::id const arg_id) { assert( std::thread::id{} != arg_id ); for (unsigned i = 0; i != g_N_threads; ++i) { if ( arg_id == g_ids_for_threads[i] ) return i; } assert( nullptr == "Control should never reach here!" ); } void Thread_Entry_Point(void) { struct SomeType { unsigned i; SomeType(unsigned arg) : i(arg) {} }; unsigned counter = 0; while ( counter >= g_counter ); //spin until g_counter increments static thread_local SomeType some_object{ Get_Thread_Index_From_StdID( std::this_thread::get_id() ) }; for (; /* ever */ ;) { /* Do Something */ } } int main(void) { array<std::thread,g_N_threads> threads; /* Create std::thread objects without starting threads yet */ for ( unsigned i = 0; i != g_N_threads; ++i ) { threads[i] = std::thread(Thread_Entry_Point); } //Give threads a chance to start std::this_thread::sleep_for(std::chrono::seconds(2)); //Right now, g_counter is still 0 for ( unsigned i = 0; i != g_N_threads; ++i ) { assert( std::thread::id{} != threads[i].get_id() ); g_ids_for_threads[i] = threads[i].get_id(); } ++g_counter; cout << "Last line of main\n"; // expect error about unjoined threads after this } And unfortunately it works fine. I therefore don't know where the problem is in my code, I'll have to look more closely. |
Frederick Gotham <cauldwell.thomas@gmail.com>: Aug 12 04:39AM -0700 On Wednesday, August 12, 2020 at 12:33:23 PM UTC+1, Frederick Gotham wrote: > I therefore don't know where the problem is in my code, I'll have to look more closely. I found out the problem by doing this: std::thread::id g_main_thread_id; int main() { g_main_thread_id = std::this_thread::get_id(); /* */ } It turns out that the main thread was calling a function which I didn't think it was calling (so the ID of the main thread didn't exist in the array of thread ID's). |
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 12 10:15AM -0400 On 8/12/20 6:54 AM, Paavo Helde wrote: > 12.08.2020 13:09 Frederick Gotham kirjutas: >> Before I begin, I have deliberately left out necessary code in order to make this as simplistic as possible (for example I've neglected to join all std::thread objects before destroying > them). ... > program worked without problems with two different compilers. I suspect > the problem is in your code which you have not shown or have altered > while posting. It seems paradoxical, but empirically, people who post only the part of their code that they think is relevant to the problem are very likely to have removed the part that caused the problem. If you can't post the entire program where you ran into your problem, either because it's too big and complicated, or proprietary or classified, what you should do is put together simplified version (with any proprietary or classified features removed) that is complete and compilable. Most importantly, before posting your simplified version - confirm that it still demonstrates the problem. Sometimes it seems impossible to put together such a simplified version, but there's a straightforward approach to systematically simplifying a program that demonstrates a problem into a much simpler program that still demonstrates it: You'll need to have two copies of your code, WORK, which you do your work on, and FAIL, which has been confirmed to fail. Initialize both of them by copying the original program. 1. Identify a portion of WORK that should be removable without interfering with the failure, preferably as large as possible. A good starting candidate is all code that should have executed after the code which produced the first symptom that something had gone wrong, but toward the end of the process you might be stuck with removing only a single line of code. If you can't find anything more to remove, you're done - you should post the entire code of FAIL along with your question. 2. Remove that portion from WORK. 3. MOST IMPORTANT: check that WORK still demonstrates the problem. If it does, replace FAIL with a copy of WORK. If not, think very carefully about the part you just removed. You thought that it wouldn't remove the problem, but it did - that's a very important clue. Replace WORK with a copy of FAIL, and go back to step 1 - but make sure to remove a different part of the program the next time, generally a smaller one. It's quite common for people following this procedure to end up finding the problem by themselves, because of the clues they accumulate from changes that fixed the problem. Once you're ready to post your simplified example, there's a few additional facts you need to provide with your question: 1. Identify the precise tool chain you used to create the code, including which options you chose. It's often the case that people will be unable to duplicate your problem if they use a different tool chain or make a different choices for one or more of the options. 2. Identify which result you expected to get. That might seem obvious to you, but I've frequently seen people post code that contained no obvious defect, and which produced exactly the results that I would expect it to produce - the problem was that the person who wrote it was expecting different results. 3. Identify the actual results you got. If at all possible, they should be cut-and-pasted from the actual output. You don't want us to waste time trying to figure out a typo that was introduced by you when you retyped the output. Warning: this process is not guaranteed to work. The worst problem I ever used this approach on, I was only able to remove 52% of the code, everything else I tried to remove made the problem disappear (and it was unacceptable to deliver the code with that part removed). I was unable to remove dependencies on three different third-party libraries. I sent the simplified version to the help desk for the library that seemed most relevant, and worked together with them for three months trying to track down the problem - without success. The program still periodically fails due to that problem. |
"Öö Tiib" <ootiib@hot.ee>: Aug 12 10:52AM -0700 On Wednesday, 12 August 2020 14:39:38 UTC+3, Frederick Gotham wrote: > /* */ > } > It turns out that the main thread was calling a function which I didn't think it was calling (so the ID of the main thread didn't exist in the array of thread ID's). Yes, usually by making code that really compiles and runs (and demonstrates the problem that they think there is) people find out what they really did wrongly. But when they post some kind of pseudo-code without ever trying it then it is as rule about something that does not demonstrate the issue. There was very similar post only recently: <https://groups.google.com/d/msg/comp.lang.c++/Y1J8W4q4Vo8/VLUBXiR3BAAJ> |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Aug 12 01:15PM -0700 On 8/12/2020 4:33 AM, Frederick Gotham wrote: > struct SomeType { unsigned i; SomeType(unsigned arg) : i(arg) {} }; > unsigned counter = 0; > while ( counter >= g_counter ); //spin until g_counter increments Strange! > } > //Give threads a chance to start > std::this_thread::sleep_for(std::chrono::seconds(2)); This is very strange to me. > } > ++g_counter; > cout << "Last line of main\n"; // expect error about unjoined threads after this You need to join the threads. Also, why not pass in a thread id that you created before you even create a thread? // pseudo code void thread_entry(unsigned long id) { //[...] } Why are you trying to extract their ids after they are created? |
Lynn McGuire <lynnmcguire5@gmail.com>: Aug 12 01:54PM -0500 "Why the C Language Will Never Stop You from Making Mistakes" by JeanHeyd Meneide https://thephd.github.io/your-c-compiler-and-standard-library-will-not-help-you "Short answer: because we said so." Yup. "The C Language" "Or, as I like to call it, "The Type Safety Is For Losers Language". Of course, that's a mouthful, so "C" will have to do. You may be wondering why I would call a language like C as having no type safety." Cool, them are fighting words ! Oh wait, he is correct. Lynn |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Aug 11 04:27PM -0700 On 8/11/2020 1:07 PM, Chris M. Thomasson wrote: > Relacy and Address Sanitizer. We had the best conversations way back on > comp.programming.threads. Back when it was not a spam infested > nightmare. Thanks to animer... ramine the plague! I know he is on the development team over at Google. |
legalize+jeeves@mail.xmission.com (Richard): Aug 12 03:50PM [Please do not mail me a copy of your followup] Lynn McGuire <lynnmcguire5@gmail.com> spake the secret code >Purify on Sun Workstations back in the 1990s. It dragged our software >down horribly and made our software unusable with it on. But it helped >immensely. Purify worked by instrumenting every load and store instruction from/to memory. I believe modern approaches use data flow analysis to minimize the amount of instrumentation applied in order to ameliorate the affect on performance. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Terminals Wiki <http://terminals-wiki.org> The Computer Graphics Museum <http://computergraphicsmuseum.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment