1

What I actually need is portable compare and print for *nix pthread identifiers (pthread_t). pthread_equal function exists to compare two thread id's for equality, however it's not possible to compare them with operators < <= >= > (portable I mean of course) because on some of implementations pthread_t is a pointer to structure. So I found solution which I would like to share and discuss it's portability.

Suppose we have thred_id class wrapper, which should be less-then-comparable, equality-comparable and of course printable. I'm making template class with two partial specialization - one for pointers and one for arithmetic types

template <typename T, bool A = is_arithmetic<T>::value>
struct hash
{
    static unsigned long calculate(T thread_id)
    {
        return hash<T*, A>::calculate(&thread_id);
    }
};

template <typename T>
struct hash<T*, false>
{
    static unsigned long calculate(T* thread_id)
    {
        std::size_t hash = 0;
        if (char* data = reinterpret_cast<char*>(thread_id))
        {
            for (int i = 0; i < sizeof(T); ++i)
            {
                hash = (hash << 6) ^ (hash >> 26) ^ data[i];
            }
        }
        return hash;
    }
};

template <typename T>
struct hash<T, true>
{
    static unsigned long calculate(T thread_id)
    {
        return static_cast<unsigned long>(thread_id);
    }
};

So how does it work. If we need to compare two thread ids we just simply call

pthread_equal(tid1, tid2);

but for operator < we use hash to compare

hash<pthread_t>::calculate(tid1) < hash<pthread_t>::calculate(tid2)

So here

if pthread_t is implemented as a pointer then we will calculate hash for the pointed object.

If it is arithmetic type then we will just try to cast it to unsigned int.

If it is implemented as a structure - we will calculate hash for the structure object itself.

Hash value is going to be used only for operator less and thread id output.

What do you think of it? How portable is this solution and is there anything better then that?

Thanks everybody in advance.

axe
  • 217
  • 3
  • 9
  • Why do you want to enforce an order on inherently unorderable types? What conceptually do you try to accomplish? – FooF Jul 12 '13 at 04:53

3 Answers3

1

pthread_t is also not necessarily a scalar data type, the standard says it should be an opaque type, it could be a struct or union or a bit field.

In addition to that, pthread_t, including scalar pthread_t, may contain padding bits that will introduce 'noise' which affects the hash result. At this time there is no universally portable way to compare pthread_t at the user level.

In fact, pthread_equal on systems where pthread_t is a pointer can return equality even though the two args actually refer to different threads, e.g. a thread can exit and a new thread can be created that has the same pointer value and thus pthread_t value.

The mapped unique ID technique will work provided you never need to do a reverse lookup because the map may be 1:n. The map also becomes very large if you continuously exit and create threads.

1

Instead of trying to compare pthread_t you could just encapsulate thread creation and add the new thread to a map<some_id, pthread_t> where the id is generated and unique. Then you always refer to threads by the id and you can order, sort, compare them however you like.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • Actually I don't need to store threads in a container, I need ti write thread_id wrapper, which can be stored in associative container, compared and printed. Of course I can set handler on thread creation and store id in some global map, but that is not a solution I'm looking for, in most cases pthread_t is a artithmetical value which uniquely represents thread in a system and I wouldn't like to use surrogate id's. – axe Jan 21 '11 at 18:51
0

Data type of pthread_t is not fixed by standard, threfore I guess pthread_compare() is provided.

In my appl I also maps pthread_t to some unique id, as Mark proposed.

See here

Community
  • 1
  • 1
dimba
  • 26,717
  • 34
  • 141
  • 196
  • 1
    I know that it is not fixed. That's I'm trying to solve. There is no function pthread_compare, there is pthread_equal, which checks only equality of two thread id's. What I'm talking about is compare with less operator (operator <), which POSIX doesn't provide, so I'm trying to make some. – axe Jan 22 '11 at 08:33