First public contribution.
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 // Interface : POSIX, pthread
17 // POSIX implementation of pthread on Symbian
23 #include "condvartypes.h"
26 This internal function initializes the passed queue to be an empty queue
28 bool _QueueInit(_CondQueue* aQueue)
34 pthread_mutex_init(&aQueue->iMutex,NULL);
35 aQueue->iHead = aQueue->iTail = NULL;
40 This internal function destroys the passed
42 int _QueueDestroy(_CondQueue* aQueue)
48 pthread_mutex_lock(&aQueue->iMutex);
49 _CondNode* head = aQueue->iHead;
50 pthread_mutex_unlock(&aQueue->iMutex);
57 return pthread_mutex_destroy(&aQueue->iMutex);
63 This internal function atomically adds a element
66 bool _QueueAdd(_CondQueue* aQueue, _CondNode* aNode)
68 if( (!aQueue) || (!aNode) )
73 pthread_mutex_lock(&aQueue->iMutex);
76 aQueue->iHead = aQueue->iTail = aNode;
80 aQueue->iTail->iNext = aNode;
81 aQueue->iTail = aNode;
83 pthread_mutex_unlock(&aQueue->iMutex);
89 This internal function atomically removes the pased element
92 bool _QueueRemove(_CondQueue* aQueue, _CondNode* aNode)
94 if( (!aQueue) || (!aNode) )
98 pthread_mutex_lock(&aQueue->iMutex);
100 _CondNode* prev = NULL;
101 _CondNode* node = aQueue->iHead;
102 for(; node; node = node->iNext)
112 if(node == aQueue->iHead)
114 aQueue->iHead = node->iNext;
116 if(node == aQueue->iTail)
118 aQueue->iTail = prev;
122 prev->iNext = node->iNext;
125 pthread_mutex_unlock(&aQueue->iMutex);
126 return (node) ? true : false;
130 This internal function atomically removes the head of the queue, and
131 returns a pointer to this node
133 _CondNode* _QueueRemoveHead(_CondQueue* aQueue)
135 _CondNode* retNode = NULL;
136 pthread_mutex_lock(&aQueue->iMutex);
137 retNode = aQueue->iHead;
140 aQueue->iHead = retNode->iNext;
141 if(aQueue->iTail == retNode)
143 aQueue->iTail = aQueue->iHead = NULL;
146 pthread_mutex_unlock(&aQueue->iMutex);
152 This internal function removes the head of the queue, and
153 returns a pointer to this node WITHOUT locking the associated mutex
155 _CondNode* _QueueRemoveHeadNoLock(_CondQueue* aQueue)
157 _CondNode* retNode = NULL;
158 retNode = aQueue->iHead;
161 aQueue->iHead = retNode->iNext;
162 if(aQueue->iTail == retNode)
164 aQueue->iTail = aQueue->iHead = NULL;
171 This internal function locks the queue mutex
173 void _QueueLock(_CondQueue* aQueue)
175 pthread_mutex_lock(&aQueue->iMutex);
179 This internal function unlocks the queue mutex
181 void _QueueUnlock(_CondQueue* aQueue)
183 pthread_mutex_unlock(&aQueue->iMutex);
187 This internal function atomically resolves the race to dynamically initialize a static cond var
189 bool _staticCondInit(pthread_cond_t* cond)
195 if(cond->iState == _EInitialized)
201 if(cond->iState != _ENeedsNormalInit)
207 #ifndef NOUSE_INTERNALS
210 // Get the TLS pointer
211 tlsPtr = _pthread_getTls();
216 _pthread_atomicMutexLock(tlsPtr);
219 //another thread might win race
220 if(cond->iState != _EInitialized)
222 retval = pthread_cond_init(cond,NULL);
225 #ifndef NOUSE_INTERNALS
226 _pthread_atomicMutexUnlock(tlsPtr);
239 This internal function provides the functionality to wait on a condition variable,
241 int _internalCondWait(pthread_cond_t *cond, pthread_mutex_t *mutex,const struct timespec *abstime)
243 if(!_staticCondInit(cond))
248 _CondNode* newNode = new _CondNode;
253 sem_init(&newNode->iSemaphore,0,0);
255 _QueueAdd(&cond->iQueue,newNode);
259 //unlock passed mutex
260 retval = pthread_mutex_unlock(mutex);
263 _QueueRemove(&cond->iQueue,newNode);
264 sem_destroy(&newNode->iSemaphore);
266 errno = 0; // Condition variables should not set errno
270 //node removed from queue by pthread_cond_signal or pthread_cond_broadcast
274 retval = sem_timedwait(&newNode->iSemaphore,abstime);
277 _QueueRemove(&cond->iQueue,newNode);
278 }//timed_wait timedout
282 retval = sem_wait(&newNode->iSemaphore);
288 sem_destroy(&newNode->iSemaphore);
290 /* This is a cancellation point */
292 pthread_testcancel();
294 //lock the passed mutex
295 pthread_mutex_lock(mutex);
297 errno = 0; // Condition variables should not set errno