VirtualBox

Changeset 28983 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
May 3, 2010 2:55:34 PM (15 years ago)
Author:
vboxsync
Message:

VBoxService/PropCache: Make it thread safe (for a global cache later).

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r28968 r28983  
    2525#endif
    2626
    27 #ifdef VBOX_WITH_GUEST_CONTROL
    28 # include <iprt/list.h>
    29 # include <iprt/semaphore.h>
    30 #endif
     27#include <iprt/list.h>
     28#include <iprt/semaphore.h>
    3129
    3230/**
     
    222220{   
    223221    /** The client ID for HGCM communication. */
    224     uint32_t uClientID;
     222    uint32_t   uClientID;
    225223    RTLISTNODE Node;
     224    RTSEMMUTEX Mutex;
    226225} VBOXSERVICEVEPROPCACHE;
    227226/** Pointer to a guest property cache. */
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.cpp

    r28981 r28983  
    3636{
    3737    AssertPtr(pCache);
     38    /** @todo Prevent init the cache twice! */
    3839    RTListInit(&pCache->Node);
    3940    pCache->uClientID = u32ClientId;
    40     return VINF_SUCCESS;
     41    return RTSemMutexCreate(&pCache->Mutex);
    4142}
    4243
     
    4849    AssertPtr(pszName);
    4950    /* This is a O(n) lookup, maybe improve this later to O(1) using a map. */
    50     PVBOXSERVICEVEPROPCACHEENTRY pNode;
    51     RTListForEach(&pCache->Node, pNode, VBOXSERVICEVEPROPCACHEENTRY, Node)
    52     {
    53         if (strcmp(pNode->pszName, pszName) == 0)
    54             return pNode;
    55     }
    56     return NULL;
     51    PVBOXSERVICEVEPROPCACHEENTRY pNodeIt, pNode = NULL;
     52    if (RT_SUCCESS(RTSemMutexRequest(pCache->Mutex, RT_INDEFINITE_WAIT)))
     53    {   
     54        RTListForEach(&pCache->Node, pNodeIt, VBOXSERVICEVEPROPCACHEENTRY, Node)
     55        {
     56            if (strcmp(pNodeIt->pszName, pszName) == 0)
     57            {
     58                pNode = pNodeIt;
     59                break;
     60            }
     61        }
     62        RTSemMutexRelease(pCache->Mutex);
     63    }
     64    return pNode;
    5765}
    5866
     
    6573    AssertPtr(pszName);
    6674    PVBOXSERVICEVEPROPCACHEENTRY pNode = VBoxServicePropCacheFind(pCache, pszName, 0);
     75    int rc;
    6776    if (pNode != NULL)
    6877    {
    69         pNode->uFlags = u32Flags;
    70         if (pszValueReset)
    71         {
     78        rc = RTSemMutexRequest(pCache->Mutex, RT_INDEFINITE_WAIT);
     79        if (RT_SUCCESS(rc))
     80        {
     81            pNode->uFlags = u32Flags;
    7282            if (pszValueReset)
    73                 RTStrFree(pNode->pszValueReset);
    74             pNode->pszValueReset = RTStrDup(pszValueReset);
    75         }
    76         return VINF_SUCCESS;
    77     }
    78     return VERR_NOT_FOUND;
     83            {
     84                if (pszValueReset)
     85                    RTStrFree(pNode->pszValueReset);
     86                pNode->pszValueReset = RTStrDup(pszValueReset);
     87            }
     88            rc = RTSemMutexRelease(pCache->Mutex);
     89        }
     90    }
     91    else
     92        rc = VERR_NOT_FOUND;
     93    return rc;
    7994}
    8095
     
    136151
    137152    PVBOXSERVICEVEPROPCACHEENTRY pNode = VBoxServicePropCacheFind(pCache, pszName, 0);
    138     if (pNode == NULL)
    139     {         
    140         pNode = (PVBOXSERVICEVEPROPCACHEENTRY)RTMemAlloc(sizeof(VBOXSERVICEVEPROPCACHEENTRY));
    141         AssertPtrReturn(pNode, VERR_NO_MEMORY);
    142 
    143         pNode->pszName = RTStrDup(pszName);
    144         pNode->pszValue = NULL;
    145         pNode->uFlags = 0;
    146         pNode->pszValueReset = NULL;
    147 
    148         /*rc =*/ RTListAppend(&pCache->Node, &pNode->Node);
    149     }
    150 
    151     int rc;
    152     AssertPtr(pNode);
    153     if (pszValue) /* Do we have a value to check for? */
    154     {
    155         bool fUpdate = false;
    156         /* Always update this property, no matter what? */
    157         if (pNode->uFlags & VBOXSERVICEPROPCACHEFLAG_ALWAYS_UPDATE)
    158             fUpdate = true;
    159         /* Did the value change so we have to update? */
    160         else if (pNode->pszValue && strcmp(pNode->pszValue, pszValue) != 0)
    161             fUpdate = true;
    162         /* No value stored at the moment but we have a value now? */
    163         else if (pNode->pszValue == NULL)
    164             fUpdate = true;
    165 
    166         if (fUpdate)
    167         {
    168             /* Write the update. */
    169             rc = VBoxServiceWritePropF(pCache->uClientID, pNode->pszName, pszValue);
    170             if (pNode->pszValue)
     153
     154    /* Lock the cache. */
     155    int rc = RTSemMutexRequest(pCache->Mutex, RT_INDEFINITE_WAIT);
     156    if (RT_SUCCESS(rc))
     157    {
     158   
     159        if (pNode == NULL)
     160        {         
     161            pNode = (PVBOXSERVICEVEPROPCACHEENTRY)RTMemAlloc(sizeof(VBOXSERVICEVEPROPCACHEENTRY));
     162            AssertPtrReturn(pNode, VERR_NO_MEMORY);
     163   
     164            pNode->pszName = RTStrDup(pszName);
     165            pNode->pszValue = NULL;
     166            pNode->uFlags = 0;
     167            pNode->pszValueReset = NULL;
     168   
     169            /*rc =*/ RTListAppend(&pCache->Node, &pNode->Node);
     170        }
     171   
     172        AssertPtr(pNode);
     173        if (pszValue) /* Do we have a value to check for? */
     174        {
     175            bool fUpdate = false;
     176            /* Always update this property, no matter what? */
     177            if (pNode->uFlags & VBOXSERVICEPROPCACHEFLAG_ALWAYS_UPDATE)
     178                fUpdate = true;
     179            /* Did the value change so we have to update? */
     180            else if (pNode->pszValue && strcmp(pNode->pszValue, pszValue) != 0)
     181                fUpdate = true;
     182            /* No value stored at the moment but we have a value now? */
     183            else if (pNode->pszValue == NULL)
     184                fUpdate = true;
     185   
     186            if (fUpdate)
     187            {
     188                /* Write the update. */
     189                rc = VBoxServiceWritePropF(pCache->uClientID, pNode->pszName, pszValue);
     190                if (pNode->pszValue)
     191                    RTStrFree(pNode->pszValue);
     192                pNode->pszValue = RTStrDup(pszValue);
     193            }
     194            else
     195                rc = VINF_ALREADY_INITIALIZED; /* No update needed. */
     196        }
     197        else
     198        {
     199            /* No value specified. Deletion (or no action required). */
     200            if (pNode->pszValue) /* Did we have a value before? Then the value needs to be deleted. */
     201            {
     202                /* Delete property (but do not remove from cache) if not deleted yet. */
     203                rc = VBoxServiceWritePropF(pCache->uClientID, pNode->pszName, NULL);
    171204                RTStrFree(pNode->pszValue);
    172             pNode->pszValue = RTStrDup(pszValue);
    173         }
    174         else
    175             rc = VINF_ALREADY_INITIALIZED; /* No update needed. */
    176     }
    177     else
    178     {
    179         /* No value specified. Deletion (or no action required). */
    180         if (pNode->pszValue) /* Did we have a value before? Then the value needs to be deleted. */
    181         {
    182             /* Delete property (but do not remove from cache) if not deleted yet. */
    183             rc = VBoxServiceWritePropF(pCache->uClientID, pNode->pszName, NULL);
    184             RTStrFree(pNode->pszValue);
    185             pNode->pszValue = NULL;
    186         }
    187         else
    188             rc = VINF_ALREADY_INITIALIZED; /* No update needed. */
    189     }
    190 
    191     /* Update rest of the fields. */
    192     if (pszValueReset)
    193     {
    194         if (pNode->pszValueReset)
    195             RTStrFree(pNode->pszValueReset);
    196         pNode->pszValueReset = RTStrDup(pszValueReset);
    197     }
    198     if (u32Flags)
    199         pNode->uFlags = u32Flags;
    200  
    201     /* Delete temp stuff. */
    202     if (pszValue)
    203         RTStrFree(pszValue);   
     205                pNode->pszValue = NULL;
     206            }
     207            else
     208                rc = VINF_ALREADY_INITIALIZED; /* No update needed. */
     209        }
     210   
     211        /* Update rest of the fields. */
     212        if (pszValueReset)
     213        {
     214            if (pNode->pszValueReset)
     215                RTStrFree(pNode->pszValueReset);
     216            pNode->pszValueReset = RTStrDup(pszValueReset);
     217        }
     218        if (u32Flags)
     219            pNode->uFlags = u32Flags;
     220     
     221        /* Delete temp stuff. */
     222        if (pszValue)
     223            RTStrFree(pszValue);   
     224   
     225        /* Release cache. */
     226        int rc2 = RTSemMutexRelease(pCache->Mutex);
     227        if (RT_SUCCESS(rc))
     228            rc2 = rc;
     229    }
    204230    return rc;
    205231}
     
    242268        pNode = pNext;
    243269    }
     270    /* Destroy mutex. */
     271    RTSemMutexDestroy(pCache->Mutex);
    244272}
    245273#endif /* VBOX_WITH_GUEST_PROPS */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette