os/ossrv/genericopenlibs/openenvcore/libpthread/src/condvar.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericopenlibs/openenvcore/libpthread/src/condvar.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,301 @@
     1.4 +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// Name        : condvar.cpp
    1.18 +// Part of     : pthread
    1.19 +// Interface   : POSIX, pthread
    1.20 +// POSIX implementation of pthread on Symbian
    1.21 +// Version     :
    1.22 +//
    1.23 +
    1.24 +
    1.25 +
    1.26 +#include "condvartypes.h"
    1.27 +
    1.28 +/*
    1.29 +This internal function initializes the passed queue to be an empty queue
    1.30 +*/
    1.31 +bool _QueueInit(_CondQueue* aQueue)
    1.32 +{
    1.33 +    if(!aQueue)
    1.34 +    {
    1.35 +        return false;
    1.36 +    }
    1.37 +    pthread_mutex_init(&aQueue->iMutex,NULL);
    1.38 +    aQueue->iHead = aQueue->iTail = NULL;
    1.39 +    return true;
    1.40 +}
    1.41 +
    1.42 +/*
    1.43 +This internal function destroys the passed 
    1.44 +*/
    1.45 +int _QueueDestroy(_CondQueue* aQueue)
    1.46 +{
    1.47 +    if(!aQueue)
    1.48 +    {
    1.49 +        return EINVAL;
    1.50 +    }
    1.51 +    pthread_mutex_lock(&aQueue->iMutex);
    1.52 +    _CondNode* head = aQueue->iHead;
    1.53 +    pthread_mutex_unlock(&aQueue->iMutex);
    1.54 +    if (head) 
    1.55 +    {
    1.56 +        return EBUSY;   
    1.57 +    }
    1.58 +    else
    1.59 +    {
    1.60 +        return pthread_mutex_destroy(&aQueue->iMutex);
    1.61 +    }
    1.62 +}
    1.63 +
    1.64 +
    1.65 +/*
    1.66 +This internal function atomically adds a element
    1.67 +to the passed queue
    1.68 +*/
    1.69 +bool _QueueAdd(_CondQueue* aQueue, _CondNode* aNode)
    1.70 +{
    1.71 +    if( (!aQueue) || (!aNode) )
    1.72 +    {
    1.73 +        return false;
    1.74 +    }
    1.75 +    aNode->iNext = NULL;
    1.76 +    pthread_mutex_lock(&aQueue->iMutex);
    1.77 +    if(!(aQueue->iHead))
    1.78 +    {
    1.79 +        aQueue->iHead = aQueue->iTail = aNode;
    1.80 +    }
    1.81 +    else
    1.82 +    {
    1.83 +        aQueue->iTail->iNext = aNode;
    1.84 +        aQueue->iTail = aNode;
    1.85 +    }
    1.86 +    pthread_mutex_unlock(&aQueue->iMutex);
    1.87 +    return true;
    1.88 +}
    1.89 +  
    1.90 +    
    1.91 +/*
    1.92 +This internal function atomically removes the pased element
    1.93 +from the queue
    1.94 +*/
    1.95 +bool _QueueRemove(_CondQueue* aQueue, _CondNode* aNode)
    1.96 +{
    1.97 +    if( (!aQueue) || (!aNode) )
    1.98 +    {
    1.99 +        return false;
   1.100 +    }
   1.101 +    pthread_mutex_lock(&aQueue->iMutex);
   1.102 +        
   1.103 +    _CondNode* prev = NULL;
   1.104 +    _CondNode* node = aQueue->iHead;
   1.105 +    for(; node; node = node->iNext)
   1.106 +    {
   1.107 +        if(node == aNode)
   1.108 +        {
   1.109 +            break;
   1.110 +        }
   1.111 +        prev = node;
   1.112 +    }
   1.113 +    if(node)
   1.114 +    {
   1.115 +        if(node == aQueue->iHead)
   1.116 +        {
   1.117 +            aQueue->iHead = node->iNext;
   1.118 +        }
   1.119 +        if(node == aQueue->iTail)
   1.120 +        {
   1.121 +            aQueue->iTail = prev;
   1.122 +        }
   1.123 +        if(prev)
   1.124 +        {
   1.125 +            prev->iNext = node->iNext;
   1.126 +        }
   1.127 +    }// node found
   1.128 +    pthread_mutex_unlock(&aQueue->iMutex);
   1.129 +    return (node) ? true : false;
   1.130 +}
   1.131 +
   1.132 +/*
   1.133 +This internal function atomically removes the head of the queue, and
   1.134 +returns a pointer to this node
   1.135 +*/
   1.136 +_CondNode* _QueueRemoveHead(_CondQueue* aQueue)
   1.137 +{
   1.138 +    _CondNode* retNode = NULL;
   1.139 +    pthread_mutex_lock(&aQueue->iMutex);
   1.140 +    retNode = aQueue->iHead;
   1.141 +    if(retNode)
   1.142 +    {
   1.143 +        aQueue->iHead = retNode->iNext;
   1.144 +        if(aQueue->iTail == retNode)
   1.145 +        {
   1.146 +            aQueue->iTail = aQueue->iHead = NULL;
   1.147 +        }
   1.148 +    }
   1.149 +    pthread_mutex_unlock(&aQueue->iMutex);
   1.150 +    return retNode;
   1.151 +}
   1.152 +
   1.153 +
   1.154 +/*
   1.155 +This internal function  removes the head of the queue, and
   1.156 +returns a pointer to this node WITHOUT locking the associated mutex
   1.157 +*/
   1.158 +_CondNode* _QueueRemoveHeadNoLock(_CondQueue* aQueue)
   1.159 +{
   1.160 +    _CondNode* retNode = NULL;
   1.161 +    retNode = aQueue->iHead;
   1.162 +    if(retNode)
   1.163 +    {
   1.164 +        aQueue->iHead = retNode->iNext;
   1.165 +        if(aQueue->iTail == retNode)
   1.166 +        {
   1.167 +            aQueue->iTail = aQueue->iHead = NULL;
   1.168 +        }
   1.169 +    }
   1.170 +    return retNode;
   1.171 +}
   1.172 +
   1.173 +/*
   1.174 +This internal function  locks the queue mutex
   1.175 +*/
   1.176 +void  _QueueLock(_CondQueue* aQueue)
   1.177 +{
   1.178 +    pthread_mutex_lock(&aQueue->iMutex);
   1.179 +}
   1.180 +
   1.181 +/*
   1.182 +This internal function  unlocks the queue mutex
   1.183 +*/
   1.184 +void  _QueueUnlock(_CondQueue* aQueue)
   1.185 +{
   1.186 +    pthread_mutex_unlock(&aQueue->iMutex);
   1.187 +}
   1.188 +
   1.189 +/*
   1.190 +This internal function atomically resolves the race to dynamically initialize a static cond var
   1.191 +*/
   1.192 +bool _staticCondInit(pthread_cond_t* cond)
   1.193 +{
   1.194 +    if(!cond)
   1.195 +    {
   1.196 +        return false;
   1.197 +    }
   1.198 +    if(cond->iState == _EInitialized)
   1.199 +    {
   1.200 +        return true;
   1.201 +    }
   1.202 +
   1.203 +
   1.204 +    if(cond->iState != _ENeedsNormalInit)
   1.205 +    {
   1.206 +        return false;
   1.207 +    }
   1.208 +    int retval=0;
   1.209 +
   1.210 +    #ifndef NOUSE_INTERNALS
   1.211 +    void* tlsPtr;
   1.212 +
   1.213 +    // Get the TLS pointer
   1.214 +    tlsPtr = _pthread_getTls();  
   1.215 +    if(NULL == tlsPtr)
   1.216 +    {
   1.217 +        return false;
   1.218 +    }
   1.219 +    _pthread_atomicMutexLock(tlsPtr);
   1.220 +    #endif
   1.221 +
   1.222 +    //another thread might win race
   1.223 +    if(cond->iState != _EInitialized)
   1.224 +    {
   1.225 +        retval = pthread_cond_init(cond,NULL);
   1.226 +    }
   1.227 +
   1.228 +    #ifndef NOUSE_INTERNALS
   1.229 +    _pthread_atomicMutexUnlock(tlsPtr);
   1.230 +    #endif
   1.231 +    if(retval == 0)
   1.232 +    {
   1.233 +        return true;
   1.234 +    }
   1.235 +    else
   1.236 +    {
   1.237 +        return false;
   1.238 +    }
   1.239 +}
   1.240 +
   1.241 +/*
   1.242 +This internal function provides the functionality to wait on a condition variable,
   1.243 +*/
   1.244 +int _internalCondWait(pthread_cond_t *cond, pthread_mutex_t *mutex,const struct timespec *abstime)
   1.245 +{
   1.246 +    if(!_staticCondInit(cond))
   1.247 +    {
   1.248 +        return EINVAL;
   1.249 +    }
   1.250 +    
   1.251 +    _CondNode* newNode = new _CondNode;  
   1.252 +    if(!newNode)
   1.253 +    {
   1.254 +        return ENOMEM;
   1.255 +    }
   1.256 +    sem_init(&newNode->iSemaphore,0,0);
   1.257 +      
   1.258 +    _QueueAdd(&cond->iQueue,newNode);
   1.259 +
   1.260 +    int retval=0;
   1.261 +    
   1.262 +    //unlock passed mutex
   1.263 +    retval = pthread_mutex_unlock(mutex);
   1.264 +    if(retval != 0)
   1.265 +    {
   1.266 +        _QueueRemove(&cond->iQueue,newNode);
   1.267 +        sem_destroy(&newNode->iSemaphore);
   1.268 +        delete newNode; 
   1.269 +        errno = 0; // Condition variables should not set errno
   1.270 +        return retval;
   1.271 +    }    
   1.272 +
   1.273 +    //node removed from queue by pthread_cond_signal or pthread_cond_broadcast
   1.274 +    //by timeout below
   1.275 +    if(abstime)
   1.276 +    {
   1.277 +        retval = sem_timedwait(&newNode->iSemaphore,abstime);   
   1.278 +        if(retval != 0)
   1.279 +        {
   1.280 +            _QueueRemove(&cond->iQueue,newNode);
   1.281 +        }//timed_wait timedout
   1.282 +    }
   1.283 +    else
   1.284 +    {
   1.285 +        retval = sem_wait(&newNode->iSemaphore);    
   1.286 +    }
   1.287 +    if(retval != 0)
   1.288 +    {
   1.289 +        retval = errno;
   1.290 +    }
   1.291 +    sem_destroy(&newNode->iSemaphore);
   1.292 +    delete newNode; 
   1.293 +    /* This is a cancellation point */
   1.294 +    //test for cancel
   1.295 +    pthread_testcancel();
   1.296 +
   1.297 +    //lock the passed mutex
   1.298 +    pthread_mutex_lock(mutex);
   1.299 +
   1.300 +    errno = 0; // Condition variables should not set errno
   1.301 +    return retval;
   1.302 +}
   1.303 +
   1.304 +//End of File