30_threads/thread/native_handle/typesizes.cc is no good
Jonathan Wakely
jwakely.gcc@gmail.com
Fri May 10 13:58:00 GMT 2019
Resending as plaint text so the lists don't reject it ...
On Thu, 9 May 2019, 11:37 Alexandre Oliva wrote:
> Other classes that have native_handle/typesizes.cc tests have
> native_type_handle defined as a pointer type, and the pointed-to type is
> native_handle, the type of the single data member of the class (*). It
> thus makes sense to check that the single data member and the enclosing
> class type have the same size and alignment: a pointer to the enclosing
> type should also be a valid pointer to its single member.
>
> (*) this single data member is actually inherited or enclosed in another
> class, but let's not get distracted by this irrelevant detail.
>
> std::thread, however, does not follow this pattern. Not because the
> single data member is defined as a direct data member of a nested class,
> rather than inherited from another class. The key difference is that it
> does not use native_type_handle's pointed-to type as the single data
> member, it rather uses native_type_handle directly as the type of the
> single data member.
>
> On GNU/Linux, and presumably on most platforms, native_handle_type =
> __gthread_t is not even a pointer type. This key difference would have
> been obvious if remove_pointer<T> rejected non-pointer types, but that's
> not the case. When given __gthread_t -> pthread_t -> unsigned long int,
> remove_pointer<T>::type is T, so we get unsigned long int back. The
> test works because there's no pointer type to strip off.
>
Which is by design. The test is written to work for the cases where
native_handle() returns &m_handle and also the std::thread case where it
returns m_handle directly.
The problem is this:
> However, on a platform that defines __gthread_t as a pointer type, we
> use that pointer type as native_type_handle and as the type for the
> single data member of std::thread. But then, the test compares size and
> alignment of that type with those of the type obtained by removing one
> indirection level. We're comparing properties of different, unrelated
> types. Unless the pointed-to type happens to have, by chance, the size
> and alignment of a pointer, the test will fail.
>
>
Good catch.
>
> IOW, the test is no good: it's not testing what it should, and wherever
> it passes, it's by accident.
>
It's not by accident on GNU/Linux, or other targets where pthread_t is not
a pointer.
> In order to test what it should, we'd need to use an alternate test
> function that does not strip off one indirection level from
> native_handle_type, if the test is to remain.
>
Or just adapt the current test to work for the std::thread case too, by
only removing the pointer when we know we need to remove it, as in the
attached patch. Does this work on targets using a pointer type for
pthread_t?
Should I introduce such an alternate test function and adjust the test,
> or just remove the broken test?
>
> Or should we change std::thread::native_handle_type to __gthread_t*,
> while keeping unchanged the type of the single data member
> std::thread::id::_M_thread?
>
We could do that, but it would break any user code using the native handle.
I'd prefer not to do that just because we have a buggy testcase.
-------------- next part --------------
diff --git a/libstdc++-v3/testsuite/util/thread/all.h b/libstdc++-v3/testsuite/util/thread/all.h
index e5794fa4a97..ec24822a8ce 100644
--- a/libstdc++-v3/testsuite/util/thread/all.h
+++ b/libstdc++-v3/testsuite/util/thread/all.h
@@ -39,7 +39,12 @@ namespace __gnu_test
// Remove possible pointer type.
typedef typename test_type::native_handle_type native_handle;
- typedef typename std::remove_pointer<native_handle>::type native_type;
+ // For std::thread native_handle_type is the type of its data member,
+ // for other types it's a pointer to the type of the data member.
+ typedef typename std::conditional<
+ std::is_same<test_type, std::thread>::value,
+ ::native_handle,
+ typename std::remove_pointer<native_handle>::type>::type native_type;
int st = sizeof(test_type);
int snt = sizeof(native_type);
More information about the Libstdc++
mailing list