Opened 9 years ago

Closed 4 years ago

#9124 closed Bugs (obsolete)

Boost.Thread using of _beginthreadex prohibits its use on Windows Store application

Reported by: beholder@… Owned by: John Maddock
Milestone: To Be Determined Component: config
Version: Boost Development Trunk Severity: Problem
Keywords: Cc:

Description (last modified by viboes)

_beginthreadex function is absent in Windows Store application so one can't link with boost.thread when build an application which targets windows 8.1. It seems that it did link well with apps targeting Windows 8.0, though.

See the full list of the forsaken API here: http://msdn.microsoft.com/en-us/library/windows/apps/jj606124.aspx

Attachments (1)

visualc.hpp.patch (432 bytes ) - added by ixSci <beholder@…> 9 years ago.
simple patch

Download all attachments as: .zip

Change History (20)

comment:1 by viboes, 9 years ago

I'm unable to test on this platform. Do you have a patch?

comment:2 by viboes, 9 years ago

Description: modified (diff)
Owner: changed from Anthony Williams to viboes
Status: newassigned

comment:3 by viboes, 9 years ago

Summary: Boost.Thread using of _beginthreadx prohibits its use on Windows Store applicationBoost.Thread using of _beginthreadex prohibits its use on Windows Store application

comment:4 by viboes, 9 years ago

Boost.Config contain in boost/config/compiler/visualc.hpp the definition of

// we have ThreadEx or GetSystemTimeAsFileTime unless we're running WindowsCE
#if !defined(_WIN32_WCE) && !defined(UNDER_CE)
#  define BOOST_HAS_THREADEX
#  define BOOST_HAS_GETSYSTEMTIMEASFILETIME
#endif

Do you have a define that can be used to don't define BOOST_HAS_THREADEX

comment:5 by ixSci <beholder@…>, 9 years ago

Yes it has this define but _WIN32_WCE and UNDER_CE bring some more than just implementation of _beginthreadex. It adds some more includes etc. It would be better to have different define for WinRT. I've just tried with _WIN32_WCE and it broke Interlocked* family.

in reply to:  5 comment:6 by viboes, 9 years ago

Replying to ixSci <beholder@…>:

Yes it has this define but _WIN32_WCE and UNDER_CE bring some more than just implementation of _beginthreadex. It adds some more includes etc. It would be better to have different define for WinRT. I've just tried with _WIN32_WCE and it broke Interlocked* family.

What a meant was a define that is specific to your platform that can be used to inhibit the definition of BOOST_HAS_THREADEX as for example

#if !defined(_WIN32_WCE) && !defined(UNDER_CE) && !defined(XXX) # define BOOST_HAS_THREADEX # define BOOST_HAS_GETSYSTEMTIMEASFILETIME #endif

comment:7 by ixSci <beholder@…>, 9 years ago

I belive there is no such a define out there. Windows 8.1 is not just Metro apps but plain old apps also. So it is up to the user to build boost specifically for Metro apps. So I propose to either add new define(e.g UNDER_WINRT) which allows to not define BOOST_HAS_THREADEX or(better) replace existing BOOST_HAS_THREADEX with something like BOOST_IMPL_THREADEX. If BOOST_IMPL_THREADEX defined then use boost implemented _beginthreadex if not then use the native one. It allows to build boost.thread with custom _beginthreadex just by defining macros in bjam. Also it won't disturb current code much since only a few places must be touch to replace current logic about BOOST_HAS_THREADEX

in reply to:  7 comment:8 by viboes, 9 years ago

Replying to ixSci <beholder@…>:

I belive there is no such a define out there. Windows 8.1 is not just Metro apps but plain old apps also. So it is up to the user to build boost specifically for Metro apps. So I propose to either add new define(e.g UNDER_WINRT) which allows to not define BOOST_HAS_THREADEX

This can be done, see bellow. The major drawback is that you this forces you to have your own Boost installation. Are you sure there is no such a macro or set of macros (versions) that tell that _beginthreadex is not defined?

or(better) replace existing BOOST_HAS_THREADEX with something like BOOST_IMPL_THREADEX. If BOOST_IMPL_THREADEX defined then use boost implemented _beginthreadex if not then use the native one. It allows to build boost.thread with custom _beginthreadex just by defining macros in bjam.

Also it won't disturb current code much since only a few places must be touch to replace current logic about BOOST_HAS_THREADEX

Are you suggesting that I change Boost.Thread current behavior on working platforms? Sorry, this could mean a lot of regressions.

What I can do is add two configuration variables BOOST_THREAD_USE_THREADEX and BOOST_THREAD_DONT_USE_THREADEX in the following way:

#if defined BOOST_THREAD_USE_THREADEX && defined BOOST_THREAD_DONT_USE_THREADEX
#error "BOOST_THREAD_USE_THREADEX and BOOST_THREAD_DONT_USE_THREADEX can not be defined simultaneously"
#elif ! defined BOOST_THREAD_USE_THREADEX && ! defined BOOST_THREAD_DONT_USE_THREADEX
#if defined BOOST_HAS_THREADEX
#define defined BOOST_THREAD_USE_THREADEX
#endif

and change the uses of BOOST_HAS_THREADEX in Boost.Thread by BOOST_THREAD_USE_THREADEX.

Then in your case you would need to define BOOST_THREAD_DONT_USE_THREADEX to build Boost.

comment:9 by ixSci <beholder@…>, 9 years ago

This can be done, see bellow. The major drawback is that you this forces you to have your own Boost installation. Are you sure there is no such a macro or set of macros (versions) that tell that _beginthreadex is not defined?

Yes it is ugly and not very convenient but there is no other choice we can achieve it without introducing another library(.lib file) which would contain custom _beginthreadex implementation and would be linked if native one is absent. I've done it that way for now in my application: I just provided stub implementation of _beginthreadex for my app and it works.

Why there is no other choice? Because you can create Metro app as well as any other app for Windows 8.1. And existence of _beginthreadex depends on Visual Studio project type(more accurately on compiler switch). So one may want to create Metro app and for that he needs boost with custom _beginthreadex. But one may also have some desktop app he's working on so for that app he would better use boost with native _beginthreadex.

Actually Boost.Thread is almost useless for Metro Apps since they have strict rules of what can be used with it and current Boost.Thread doesn't conform(at least boost::thread). So there is no point to use boost::thread with WinRT(Metro). Yet many other boost libs depends on Boost.Thread and it gives a pain.

Are you suggesting that I change Boost.Thread current behavior on working platforms? Sorry, this could mean a lot of regressions.

Yes, I meant exactly it. I don't think it will introduce any regression since it may be integrated quite smoothly since the only change which is needed is to change macro name and change ifndef to ifdef. Moreover WinCE not a popular platform these days, if it still alive. But I'm sure you know what is better since you're a maintainer.

Your proposition also seems to be a solution for the issue.

comment:10 by viboes, 9 years ago

Maybe I have not understood you correctly. Note that I'm not a Windows programmer and I don't know even what a Metro application is.

Please could you provide a patch. I will apply it if your patch doesn't changes the behavior on the working platforms.

by ixSci <beholder@…>, 9 years ago

Attachment: visualc.hpp.patch added

simple patch

comment:11 by ixSci <beholder@…>, 9 years ago

BOOST_FOR_WINRT macro should be defined during compilation by an user explicitly. I believe this macro could be used in other boost libs as well. Since Boost.Thread not the only one library which has some incompatibility with Windows 8 sandboxed applications. Also it could be used in the future if Boost.Thread would be fully ported for WinRT API

comment:12 by viboes, 9 years ago

Component: threadconfig

Well, I would move it to Boost.Config to see what they think.

comment:13 by viboes, 9 years ago

Owner: changed from viboes to John Maddock
Status: assignednew

comment:14 by John Maddock, 9 years ago

I've done some digging, and:

  • It appears that __cplusplus_winrt is defined when building with /ZW can you confirm that?
  • Simply disabling BOOST_HAS_THREADEX doesn't seem the correct solution: calling that API is required in order to correctly initialize the C++ runtime library, in any case http://msdn.microsoft.com/en-us/library/windows/apps/jj606124.aspx indicates that all the Windows Thread API functions are missing/deprecated on that platform, and that the C# components should be used instead :(

So I don't really see that there's a quick/easy fix here. Maybe we should disable threading support altogether for that platform? Except that would disable thread safety/synchronization support as well, and I don't see mutex support in the C# primitives - is code supposed to still use the regular Windows API's for that? Or perhaps we should be using http://msdn.microsoft.com/en-us/library/dd492843.aspx? Either way it seems like Boost.Threads would need a significant rewrite to support this stuff.

comment:15 by ixSci <beholder@…>, 9 years ago

I confirm there is such a macro(cplusplus_winrt) when building with /ZW.

The solution proposed is not meant to be fully fledged solution for using boost.thread with WinRT but just to get it linking with project with WinRT. Currently you can't link against boost.thread(and as well at least with boost.locale, issue:https://svn.boost.org/trac/boost/ticket/9125). So the main purpose of the patch is to allow at least link against boost. Since a few other libraries depends on boost.thread you just can't use them also(e.g. boost.log).

You get it slightly wrong the API doesn't have any C# components. They are pure C++ they are just like COM. It is away Widows API evolving for C-like to C++-like. The only restriction is that WinRT could be used with so called Metro(windows store) applications only.

And it is the very reason you can't count on any system macros: you don't have true new platform actually. You just have a sandboxed platform inside existing WIndows platform. So one can use boost to build Metro app and Win32 app on the same machine. But to have it right one will have to use separate boost bulds anyway: one for win32 and one for winrt. It is just a reality. There is no way to fix it by using system macros. I hope my explanation will shed some light.

That is why I proposed this patch. Real solution for the boost.thread problem is to add WinRT support to the boost.thread. Or even add not a WinT support but just C++11 support underneath. Since every Visual Studio which could be used to write WinRT does have C++11 thread support. But still it is whole another story. Right now it should be at least possible to link against boost.thread.

comment:16 by John Maddock, 9 years ago

I'm still wary of this patch: disabling use of __beginthreadex will presumably cause your program to crash at runtime due to an incorrectly initialized std lib if you create any threads? I still feel that someone with access to this MSVC build option needs to provide a proper patch that allows the thread lib tests to pass, otherwise we're just thrashing around in the dark breaking random stuff...

comment:17 by ixSci <beholder@…>, 9 years ago

johnmaddock, honestly I don't know how to explain it better... std lib for Windows Store application DOESN'T HAVE _ _beginthreadex and it DOESN'T participate in any initialization. So basically you can't use Boost.Thread with Windows Store application anyway. To make it possible to use Boost.Thread with Windows Store application Boost.Thread should be changed as I said above(either implement boost.thread with WinRT API or use standard std::thread inside it). The patch I provided simply allows to compile boost for Windows Store application. I don't know maybe it would be better to add static_assert to warn anyone who tries to use boost::thread that it is unsupported.

Anyway this patch didn't mean to add support for Windows Store apps, only to add the possibility to compile boost at all.

comment:18 by John Maddock, 9 years ago

I understand the issue and your frustration.

What I'm against is changing Boost.Thread in a way that allows it to compile, but causes hidden/silent/unpredictable breakages at runtime.

Note that you still have the option to either define BOOST_DISABLE_THREADS when building to build single threaded versions of Boost libraries, or of changing boost/config/user.hpp to modify the Config setting for your specific case.

comment:19 by John Maddock, 4 years ago

Resolution: obsolete
Status: newclosed
Note: See TracTickets for help on using tickets.