[Mingw-w64-public] Thoughts on supporting the C++11 thread library on Windows

Jonathan Wakely jwakely.gcc@gmail.com
Wed May 9 13:29:00 GMT 2012


On 7 May 2012 18:28, K. Frank wrote:
> Hello Gabriel (and Ruben)!
>
> By the way, I'm the guy Ruben mentioned in his subsequent post.
>
> On Sat, May 5, 2012 at 11:20 PM, Gabriel Dos Reis
> <gdr@integrable-solutions.net> wrote:
>> Including the mingw64 project about this.
>>
>> On Sat, May 5, 2012 at 5:59 PM, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>>> For GCC 4.7 I enabled most of <thread> (without timed mutexes) on Mac
>>> OS X by making the _GLIBCXX_HAS_GTHREADS macro more fine-grained.  I
>>> think we could quite easily do the same again for the win32 thread
>>> model (defined in gthr-win32.h) so that <thread> and <mutex> are
>>> available (including timed mutexes), but without <condition_variable>
>>> and <future>.
>
> Just my opinion:  One could make the macro more fine-grained, but I
> really wouldn't want to do this.  If I'm using <thread> I'm using c++11,
> so I like to think I'm in the "modern world."  I think (in the modern world)
> that condition variables are a core part of threading, so I'd find is a
> significant limitation if my c++11 implementation didn't have them.

Well currently you get none of the thread support when GCC is built
with --enable-threads=win32.  IMHO that's an even more significant
limitation than no <condition_variable>


> (Also, I think that once you have the threading primitives (<thread>,
> <mutex>, and <condition_variable>), you get <future> "for free" in the
> sense that it's written on top of the primitives, and you don't need any
> further os-specific support.)

Right.

>>> It's harder to support <condition_variable> because Windows didn't
>>> provide condition variables until Vista, and even then they interact
>>> with a CRITICAL_SECTION and gthr-win32.h defines mutexes in terms of a
>>> semaphore not a critical section.
>
> Even leaving condition variables aside, I really don't think you want to
> implement mutexes in terms of windows semaphores (or windows mutexes)
> (unless your primary goal is to support older (pre-xp?) versions of windows.)

Too late. That's how they're implemented when GCC is built with
--enable-threads=win32

> I believe (speaking from memory) that I built a trial implementation of <thread>
> using  windows mutexes and that it was much slower than using windows
> critical sections.  I think both creation and locking were slower, but I don't
> remember the details.  This is reasonable, because windows mutexes (and
> semaphores) are heavier-weight objects -- they provide cross-process
> synchronization, not just intra-process, cross-thread synchronization.
>
> And, as you mentioned, if you want to support condition variables (in terms
> of windows condition variables), you need to base your mutexes on windows
> critical sections.
>
>>> Douglas Schmidt describes an
>>> implementation of condition variables at
>>> http://www.cs.wustl.edu/~schmidt/win32-cv-1.html but that also
>>> requires mutexes to be critical sections - maybe that could be adapted
>>> to use the gthr-win32.h semaphore-based definition of
>>> __gthread_mutex_t, I haven't looked into it in detail.   My suggestion
>>> would be to support <thread> and <mutex> but not <condition_variable>
>>> (or <future> because our implementation uses a
>>> std::condition_variable.)
>
> My personal feeling is that a version of <thread> that is complete
> (i.e., supports condition variables and futures), but requires windows
> vista or later is a fine way to go.
>
> Certainly given an either-or choice of an incomplete <thread> that
> works pre-vista, or a complete <thread> that requires vista or later,
> I would certainly vote for the complete <thread> and forgo pre-vista
> support.
>
>>> I have some untested implementations of
>>> __gthread_create, __gthread_join etc. if anyone wants to work on
>>> implementing that suggestion.  I don't have a Windows machine or
>>> enough free time to do that myself in the near future.
>>>
>>> As a second idea, supporting the full C++11 thread library could be
>>> done by creating a new thread model to be used instead of win32, which
>>> would only be supported on Vista or later and would use Windows
>>> critical sections for std::mutex and Windows  condition variables for
>>> std::condition_variable.
>
> I've done this, and it seems to work fine.  I would recommend it.
>
> (I'm not sure what you mean by "a new thread model to be used instead
> of win32."

I mean instead of GCC's win32 thread model that you get by building
with --enable-thread=win32

That existing thread model uses semaphores.

My first suggestion is to improve that one in limited ways, retaining
backwards compatibility but adding <thread> and <mutex> which AFAIK
don't currently work.

My second suggestion is to write a replacement (call it
--enable-threads=win64 for the sake of argument) which would use
critical sections and support <thread>, <mutex>, <ondition_variable>
and <future>.

The suggestions are independent of each other.



> The way I look at it I used win32, i.e., I implemented <thread>
> on top of the vista-and-later version of win32.)
>
>>> Critical sections don't support a timed
>>> wait, so that thread model would be similar to the Mac OS X support
>>> and omit timed mutexes.
>
> I had to write some extra code to get timed mutexes to work.  I used
> windows critical sections (just as for untimed mutexes), but spawned
> a helper thread that blocked on the critical section, and had the original
> thread use a timed windows WaitForSingleObject to wait (with a
> timeout) for the helper thread.

Spawning a new thread to block on a mutex seems over the top, but if
it works it works.

>>> That could easily be solved by implementing
>>> std::timed_mutex as a Windows mutex instead of a critical section,
>
> Again, I wouldn't recommend using windows mutexes as you would
> lose condition variables.

No you wouldn't.  std::condition_variable only works with std::mutex
(which we agree should use a critical section), so it's irrelevant how
std::timed_mutex is implemented.  If you want to use a condition
variable with a std:timed_mutex then you have to use
std::condition_variable_any and that internally uses a std::mutex, so
can internally use native OS condition varaibles.

>  Also, as I mentioned above, they are much
> more expensive than critical sections.
>
>>> but
>>> that would be difficult in the current Gthreads design because it
>>> follows POSIX and assumes that a timed mutex is exactly the same type
>>> as a non-timed mutex and you just use a different function to wait.
>>> We should consider adding a __gthread_timed_mutex type which can be
>>> different to __gthread_mutex_t, but would be the same type on POSIX
>>> platforms that support the Timeouts option and define
>>> pthread_mutex_timedlock.   Again, I have some sketches to make that
>>> work but nothing concrete.
>>>
>>> If there are any Windows hackers out there who want to improve thread
>>> support on their platform please get in touch, I'll be happy to help
>>> and advise (although not for the next two weeks as I'm about to go on
>>> holiday.)
>
> I have a pretty complete mingw / mingw-w64 <thread> implementation
> that uses win32 directly and doesn't rely on pthreads.  I'd certainly be
> happy to make it available, if people would find it useful.  As noted, it
> requires vista or later.  (I've only tested in on 64-bit windows 7.)
>
> But I'm not sure that there is any problem that needs to be solved.
>
> For my own <thread> programming, I have been using "The Mighty
> Ruben's Wacky Build" (TM) of mingw-w64 gcc 4.7.0 that has <thread>
> implemented on top of winpthreads.  It passes all of my (not particularly
> complete) <thread> tests.  Presumably it works pre vista.
>
> And although I don't care much about pthreads, as a practical matter
> there is an awful lot of pthreads code out there so a mingw-w64
> offering that doesn't support pthreads would be a significant limitation.
> Now that mingw-w64 has winpthreads, it's very little work to modify
> the linux gcc <thread> implementation to work on windows.

There isn't a linux <thread> implementation, there is a POSIX one,
used by building GCC with --enable-threads=posix.  I expect that
already works on Windows, I'm only talking about
--enable-threads=win32

>  Plus,
> you get the added benefit that you can more easily mix pthreads
> code with c++11 <thread> code because they use the same
> underlying threading implementation (if you care).
>
> Also, there are (as would be expected) some performance differences.
> I ran some tests about half a year ago.  A parallel_accumulate
> "practical" multithreading test was modestly slower with the
> winpthreads implementation of <thread> than with the native
> implementation; a mutex-contention test was more that an order
> of magnitude slower; and a condition-variable test was significantly
> faster.
>
> Please let me know if you would like any follow-up information.
>
>
> Happy Threading!
>
>
> K. Frank

Thanks for the mail, it confirms a lot of what I thought based on some
basic research and zero experience of Windows threading :)



More information about the Libstdc++ mailing list