- Mutually exclusive execution for threads, OK with g++ but not MSVC - 8 Updates
- C++ 2011 threading read/write locking? - 1 Update
- Nonconst method calls enumerator with const_cast - 4 Updates
- Usenet group for compiler development - 9 Updates
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 10 10:09PM +0200 Code at bottom. My questions are: * Why is it crashing with Visual C++? * Is there a much simpler / efficient / whatever way to do this (except using C++20 coroutines)? Output with MinGW g++, with logging suppressed: Starting. Thread 3 iteration 0. Thread 2 iteration 0. Thread 3 iteration 1. Thread 2 iteration 1. Thread 3 iteration 2. Thread 2 iteration 2. Thread 3 iteration 3. Thread 2 iteration 3. Thread 3 iteration 4. Thread 2 iteration 4. Thread 3 iteration 5. Thread 2 iteration 5. Thread 3 iteration 6. Thread 2 iteration 6. Thread 3 iteration 7. Thread 2 iteration 7. Thread 3 iteration 8. Thread 2 iteration 8. Thread 3 iteration 9. Thread 2 iteration 9. Finished. With Visual C++ 2019 there's no ordinary output, and the log output differs from run to run, but typically Starting. Thread 12828 yielding. Thread 4076 yielding. Thread 12828 registering unlocker. Thread 12828 entering wait state. Thread 4076 releasing another thread. The process exit code is then -1073740791, which Microsoft's errlook utility tells me is hex 0xC0000409 and that that's an unknown code. However, mr. Google leads to me to an SO question about it, where an answer claims that it's STATUS_STACK_BUFFER_OVERRUN, i.e. not an error code or HRESULT code, but a low level status code. Which means that I can possibly find out by creating a Visual Studio project and debugging, but debugging threads is tricky, so I ask first. ----------------------------------------------------------------------- #include <cppx-core/all.hpp> // https://github.com/alf-p-steinbach/cppx-core namespace my { $use_cppx( is_empty ); using namespace cppx::basic_string_building; // "<<"-notation. $use_std( clog, endl, exception, move, mutex, queue, string, unique_lock ); $use_std_namespace_names( this_thread ); void log( const string& s ) { static mutex m; $with( unique_lock<mutex>( m ) ) { clog << s << endl; } } class Mutually_exclusive_execution { using Lock = unique_lock<mutex>; mutex m_q_access; queue<Lock*> m_execution_locks_q; static auto popped( queue<Lock*>& q ) -> Lock* { Lock* result = q.front(); q.pop(); return result; } void yield( const bool do_wait ) { mutex m; Lock execution_lock( m ); log( "Thread "s << this_thread::get_id() << " yielding." ); $with( Lock( m_q_access ) ) { if( not is_empty( m_execution_locks_q ) ) { log( "Thread "s << this_thread::get_id() << " releasing another thread." ); popped( m_execution_locks_q )->unlock(); // Another thread runs. log( "Thread "s << this_thread::get_id() << " release succeeded." ); } if( do_wait ) { try { log( "Thread "s << this_thread::get_id() << " registering unlocker." ); m_execution_locks_q.emplace( &execution_lock ); } catch( const exception& x ) { log( "!"s << x.what() ); } } } if( do_wait ) { log( "Thread "s << this_thread::get_id() << " entering wait state." ); //(Lock( m )); // Waits until m is unlocked by another thread. $with( Lock( m ) ) {} } log( "Thread "s << this_thread::get_id() << " resuming." ); } public: void yield() { yield( true ); } void goodbye() { yield( false ); } }; } // namespace my namespace app { $use_cppx( up_to ); $use_std( cout, endl, thread ); $use_std_namespace_names( this_thread ); void run() { my::Mutually_exclusive_execution mee; const auto f = [&]() { for( const int i: up_to( 10 ) ) { mee.yield(); cout << "Thread " << this_thread::get_id() << " iteration " << i << "." << endl; } mee.goodbye(); }; thread t1( f ); thread t2( f ); t1.join(); t2.join(); } } // namespace app #include <stdexcept> // std::exception #include <stdlib.h> // EXIT_... $use_std( exception, cerr, cout, endl ); auto main() -> int { try { cout << "Starting." << endl; app::run(); cout << "Finished." << endl; return EXIT_SUCCESS; } catch( const exception& x ) { cerr << "!" << x.what() << endl; } return EXIT_FAILURE; } ----------------------------------------------------------------------- Cheers!, - Alf (perplexed, baffled, confounded, bewildered & for the time being stumped) |
"Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>: Apr 10 01:40PM -0700 On 4/10/2019 1:09 PM, Alf P. Steinbach wrote: > * Is there a much simpler / efficient / whatever way to do this > (except using C++20 coroutines)? > Output with MinGW g++, with logging suppressed: [...] > - Alf (perplexed, baffled, confounded, bewildered & for the time being > stumped) Can you possibly reduce it down to something that does not require all of the $... stuff? Something that just uses std primitives, perhaps? I have to learn what those $ things mean "under the covers" in order to help. Humm... |
Paavo Helde <myfirstname@osa.pri.ee>: Apr 10 11:44PM +0300 On 10.04.2019 23:09, Alf P. Steinbach wrote: > * Why is it crashing with Visual C++? > * Is there a much simpler / efficient / whatever way to do this > (except using C++20 coroutines)? If you could translate that to C++ and explain what it is what this is supposed to do I might be tempted to have a look. As for now my only advice is to not turn too much attention to the process exit code, its informational value is extremely low. A Windows exception code from a SEH handler or "Stopped working" box would be better, in my experience. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 10 11:08PM +0200 On 10.04.2019 22:40, Chris M. Thomasson wrote: > of the $... stuff? Something that just uses std primitives, perhaps? I > have to learn what those $ things mean "under the covers" in order to > help. Humm... Done. It's just that I prefer coding up things with the macros, cause it's less to write and less to read. Thanks. #if 1 // include <cppx-core/all.hpp> // https://github.com/alf-p-steinbach/cppx-core #include <iostream> #include <stdexcept> #include <thread> #include <mutex> #include <queue> #include <sstream> #include <string>
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment