Closed phma closed 5 years ago
This would typically occur if an unusually early version of Windows were requested (and the mechanisms for selecting an XP-compatible mutex were bypassed). It might also occur if you were using a Windows API header from Windows Vista or XP.
The most likely scenario is that a Qt header also pulls in all or part of windows.h
, but requests a different Windows version when it does so. Are you setting _WIN32_WINNT
at the command-line or #defining
it? The latter is prone to header inclusion order problems.
With that in mind, I have a few questions:
mingw_stdthread
namespace, and this library only places objects into std
if they are not already supplied by the standard library.I don't know how to request a version of Windows.
I am not setting _WIN32_WINNT
to anything. I am compiling on Windows 10 and running on the same computer.
The namespace issue was that mingw-std-threads declares both std::mutex
and mingw_stdthread::mutex
, so just mutex
was ambiguous. I fixed this as follows:
using namespace std;
#ifdef __MINGW64__
using namespace mingw_stdthread;
namespace th=mingw_stdthread;
#else
namespace th=std;
#endif
namespace cr=std::chrono;
th::shared_mutex wingEdge; // Lock this while changing pointers in the winged edge structure.
map<int,th::mutex> triMutex; // Lock this while locking or unlocking triangles.
th::shared_mutex holderMutex; // for triangleHolders
th::mutex adjLog;
th::mutex actMutex;
th::mutex bucketMutex;
The Qt scenario looks like what's happening, as the error occurs when compiling gui.cpp, not when compiling threads.cpp. The headers of gui.cpp are:
#include <QtGui>
#include <QtWidgets>
#include <QTranslator>
#include <iostream>
#include "point.h"
#include "octagon.h"
#include "config.h"
#include "mainwindow.h"
#include "threads.h"
gui.cpp calls startThreads, which is declared in threads.h, but gui.cpp does not itself lock or unlock anything. There is one .cpp file which both includes Qt and locks a mutex, namely tincanvas.cpp. How do I fix it?
I don't know if GCC uses the latest headers. How do I find out? I installed it with Chocolatey.
Though I do not have access to your build, I suspect that Qt might be defining the macros that request a different version of Windows. If they do this improperly, then it can cause this library to think that it has access to Windows 7 (for example) even though the headers have only provided Windows XP functions.
Try rearranging your include order.
On the topic of namespaces: Just use the one in std
. It's the correct one. The other namespace exists only so that someone who already has std::thread
can use this library (for performance comparisons, as an example).
P.S. The errors that you are seeing should only occur if a macro for selecting a Windows version is defined. In particular, the macro _WIN32_WINNT
will cause WINVER
to be defined (by the Windows headers), and WINVER
is in turn used to select which Windows API features to use. If WINVER
is assigned a large enough value, the library switches to using more recent (more efficient) features. For you to have seen this particular error, WINVER
must be at least 0x0600
.
I rearranged the include files (putting threads.h before the Qt headers) and got it to compile and run the thread function. However, all threads are running as thread number 0.
void startThreads(int n)
{
int i,m;
threadCommand=TH_WAIT;
threadStatus.resize(n);
heldTriangles.resize(n);
sleepTime.resize(n);
initTempPointlist(n);
mtxSquareSize=ceil(sqrt(33*n));
m=mtxSquareSize*mtxSquareSize;
for (i=0;i<m;i++)
triMutex[i];
for (i=0;i<n;i++)
threads.push_back(th::thread(TinThread(),i));
}
A stack trace in what should be thread 2 looks like this:
#0 0x00007fff280bc6e4 in ntdll!ZwDelayExecution ()
from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007fff25ac6931 in SleepEx () from C:\Windows\System32\KernelBase.dll
#2 0x000000000043d50a in mingw_stdthread::this_thread::sleep_for<long long, std::ratio<1ll, 1000ll> > (sleep_duration=...)
at C:/Users/phma/src/mingw-std-threads/mingw.thread.h:279
#3 0x0000000000424f0a in sleep (thread=0)
at C:/Users/phma/src/perfecttin/threads.cpp:246
#4 0x000000000042626a in TinThread::operator() (this=0x27770570, thread=0)
at C:/Users/phma/src/perfecttin/threads.cpp:513
#5 0x0000000000469d3d in std::__invoke_impl<void, TinThread, int&> (__f=...,
__args#0=@0x120fa6c: 0)
at C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/invoke.h:60
#6 0x000000000046df97 in std::__invoke<TinThread, int&> (__fn=...,
__args#0=@0x120fa6c: 0)
at C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/invoke.h:95
#7 0x000000000046d3b9 in std::invoke<TinThread, int&> (__fn=...,
__args#0=@0x120fa6c: 0)
at C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/functional:81
#8 0x000000000043da07 in mingw_stdthread::detail::ThreadFuncCall<TinThread, int&>::callFunc<0ull> (this=0x27770570)
at C:/Users/phma/src/mingw-std-threads/mingw.thread.h:82
#9 0x000000000043d9b7 in mingw_stdthread::detail::ThreadFuncCall<TinThread, int&>::callFunc (this=0x27770570)
at C:/Users/phma/src/mingw-std-threads/mingw.thread.h:90
#10 0x000000000043da96 in mingw_stdthread::thread::threadfunc<mingw_stdthread::detail::ThreadFuncCall<TinThread, int&> > (arg=0x27770570)
at C:/Users/phma/src/mingw-std-threads/mingw.thread.h:138
#11 0x00007fff2706b04a in msvcrt!_beginthreadex ()
from C:\Windows\System32\msvcrt.dll
#12 0x00007fff2706b11c in msvcrt!_endthreadex ()
from C:\Windows\System32\msvcrt.dll
#13 0x00007fff27107bd4 in KERNEL32!BaseThreadInitThunk ()
from C:\Windows\System32\kernel32.dll
#14 0x00007fff2808ce71 in ntdll!RtlUserThreadStart ()
from C:\Windows\SYSTEM32\ntdll.dll
(gdb) frame 8
#8 0x000000000043da07 in mingw_stdthread::detail::ThreadFuncCall<TinThread, int&>::callFunc<0ull> (this=0x27770570)
at C:/Users/phma/src/mingw-std-threads/mingw.thread.h:82
82 detail::invoke(std::forward<Func>(mFunc), std::get<S>(std::forward<Tuple>(mArgs)) ...);
(gdb) print mArgs
$3 = std::tuple containing = {[1] = @0x120fa6c}
(gdb) print *(int *)0x120fa6c
$4 = 0
(gdb) print *(int *)0x120fa70
$5 = 60
The 0 appears to be what's passed to the thread function; it should be 2. The 60 is I don't know what.
The program is working well enough now that I can work around this problem.
Thank you for bringing this up; it appears that arguments are being passed by reference rather than copied, even if the function requests them by value. I'll add a regression test and see what I can do to address this.
I'm trying to port a multithreading program to Windows 10. It works fine in Linux and DragonFly BSD, and I got it to compile, run, and show its window in Windows. But attempting to load a file (which is done by a thread) resulted in nothing happening. I ran it in gdb and found that Qt's threads were apparently acting normally, but mine were not running the thread function. I modified it to use mingw-std-threads; after I fixed the namespace issues, these compile errors remain:
I'm using these versions: