Abinash Adhikari
Abinash Adhikari

Reputation: 21

thread local storage of a function

I am working on a program that requires a queue operation to be performed in multi threaded environment. I am not sure about the thread local storage for a function, not just a global variable i tried

__thread int head,tail;
__thread int q[MAX_NODES+2];

__thread void enqueue (int x) {
   q[tail] = x;
   tail++;
   color[x] = GRAY;
  }

__thread int dequeue () {
   int x = q[head];
   head++;
   color[x] = BLACK;
   return x;
   }

I got following error

fordp.c:71: error: function definition declared '__thread'

fordp.c:77: error: function definition declared '__thread'

I read somewhere that a function is already thread safe unless its using shared variables so I tried

__thread int head,tail;
__thread int q[MAX_NODES+2];

void enqueue (int x) {
   q[tail] = x;
   tail++;
   color[x] = GRAY;
   }

 int dequeue () {
   int x = q[head];
   head++;
   color[x] = BLACK;
   return x;
   } 

It did compile with no error, but my execution result was wrong hinting queue didnt work well with multi-threaded platform.

Can someone please explain me what is going on here??

Any help is appreciated.

Upvotes: 0

Views: 171

Answers (2)

alk
alk

Reputation: 70921

__thread advises the compiler to create an instance of the variable for every thread.

I doubt that's what you want for the queue, it's head and tail the threads should concurrently operate on, as modifications done by one thread would not be visible by any other thread.

So do not use __thread here, but protect the concurrent access to the global variables, for example using one or more mutexes.


For your reference: http://en.wikipedia.org/wiki/Thread-local_storage

Upvotes: 1

egur
egur

Reputation: 7960

I think you're tackling the problem in the wrong way.

Your problem is that you want to associate a Queue object with a function call (e.g. enqueue).

In C these objects are usually referred to as contexts.

What you did is a variation of a global variable. Using per thread local storage is good for scratch space or actual per thread resources. and this is not the case.

The only option to have thread safety and correctness is to add the context to the function call. I removed the reference to color to simplify things.

struct queue {
    unsigned head, tail;
    int q[MAX_NODES+2];
};

void enqueue (struct queue* q, int x) {
    q->q[q->tail++] = x;
}

int dequeue (struct queue* q) {
    int x = q->q[q->head++];
    return x;
} 

Note: you should perform checks on pointers and indexes.

Upvotes: 0

Related Questions