VirtualBox

Changeset 95714 in vbox


Ignore:
Timestamp:
Jul 18, 2022 4:13:16 PM (3 years ago)
Author:
vboxsync
Message:

Recording/Main: Object sharing fixes for the per-screen settings by using an internal refcount. This is needed as a peer object could share the same per-screen object when saving / committing settings. bugref:9286

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/RecordingScreenSettingsImpl.h

    r95639 r95714  
    5959
    6060    settings::RecordingScreenSettings &i_getData(void);
     61
     62    int32_t i_reference(void);
     63    int32_t i_release(void);
     64    int32_t i_getReferences(void);
    6165
    6266private:
  • trunk/src/VBox/Main/src-server/RecordingScreenSettingsImpl.cpp

    r95639 r95714  
    4242    Data()
    4343        : pParent(NULL)
     44        , cRefs(0)
    4445    { }
    4546
     
    4748    const ComObjPtr<RecordingScreenSettings> pPeer;
    4849    uint32_t                                 uScreenId;
     50    /** Internal reference count to track sharing of this screen settings object among
     51     *  other recording settings objects. */
     52    int32_t                                  cRefs;
    4953
    5054    // use the XML settings structure in the members for simplicity
     
    146150    m->bd.share(aThat->m->bd);
    147151
    148     HRESULT rc = S_OK;
     152    HRESULT hrc = S_OK;
    149153
    150154    int vrc = i_initInternal();
     
    156160    {
    157161        autoInitSpan.setFailed();
    158         rc = E_UNEXPECTED;
     162        hrc = E_UNEXPECTED;
    159163    }
    160164
    161165    LogFlowThisFuncLeave();
    162     return rc;
     166    return hrc;
    163167}
    164168
     
    214218void RecordingScreenSettings::uninit()
    215219{
    216     LogFlowThisFuncEnter();
     220    LogThisFunc(("%p\n", this));
    217221
    218222    /* Enclose the state transition Ready->InUninit->NotReady */
     
    221225        return;
    222226
     227    /* Make sure nobody holds an internal reference to it anymore. */
     228    AssertReturnVoid(m->cRefs == 0);
     229
    223230    m->bd.free();
    224231
     
    930937{
    931938    AssertPtrReturn(m, VERR_INVALID_POINTER);
     939
     940    i_reference();
    932941
    933942    int vrc = i_parseOptionsString(m->bd->strOptions, *m->bd.data());
     
    983992HRESULT RecordingScreenSettings::i_saveSettings(settings::RecordingScreenSettings &data)
    984993{
     994    LogThisFunc(("%p: Screen %RU32\n", this, m ? m->uScreenId : UINT32_MAX));
     995
    985996    /* sanity */
    986997    AutoCaller autoCaller(this);
     
    10711082    AssertPtr(m);
    10721083    return *m->bd.data();
     1084}
     1085
     1086/**
     1087 * Increments the reference count.
     1088 *
     1089 * @returns New reference count.
     1090 *
     1091 * @note    Internal reference count, to track object sharing across different recording settings objects
     1092 *          which share the same screen recording data.
     1093 */
     1094int32_t RecordingScreenSettings::i_reference(void)
     1095{
     1096    int cNewRefs = ASMAtomicIncS32(&m->cRefs); RT_NOREF(cNewRefs);
     1097    LogThisFunc(("%p: cRefs -> %RI32\n", this, cNewRefs));
     1098    return cNewRefs;
     1099}
     1100
     1101/**
     1102 * Decrements the reference count.
     1103 *
     1104 * @returns New reference count.
     1105 *
     1106 * @note    Internal reference count, to track object sharing across different recording settings objects
     1107 *          which share the same screen recording data.
     1108 */
     1109int32_t RecordingScreenSettings::i_release(void)
     1110{
     1111    int32_t cNewRefs = ASMAtomicDecS32(&m->cRefs); RT_NOREF(cNewRefs);
     1112    LogThisFunc(("%p: cRefs -> %RI32\n", this, cNewRefs));
     1113    AssertReturn(cNewRefs >= 0, 0);
     1114    return cNewRefs;
     1115}
     1116
     1117/**
     1118 * Returns the current reference count.
     1119 *
     1120 * @returns Current reference count.
     1121 *
     1122 * @note    Internal reference count, to track object sharing across different recording settings objects
     1123 *          which share the same screen recording data.
     1124 */
     1125int32_t RecordingScreenSettings::i_getReferences(void)
     1126{
     1127    return ASMAtomicReadS32(&m->cRefs);
    10731128}
    10741129
  • trunk/src/VBox/Main/src-server/RecordingSettingsImpl.cpp

    r95663 r95714  
    127127
    128128    m->bd.share(aThat->m->bd);
     129
     130    /* Make sure to add a reference when sharing the screen objects with aThat. */
     131    for (RecordingScreenSettingsObjMap::const_iterator itScreenThat  = aThat->m->mapScreenObj.begin();
     132                                                       itScreenThat != aThat->m->mapScreenObj.end();
     133                                                     ++itScreenThat)
     134        itScreenThat->second->i_reference();
     135
    129136    m->mapScreenObj = aThat->m->mapScreenObj;
    130137
     
    202209        return;
    203210
    204     /* Note: Do *not* call i_reset() here, as the shared recording configuration
    205      *       otherwise gets destructed when this object goes out of scope or is destroyed. */
     211    /* Make sure to destroy screen objects attached to this object.
     212     * Note: This also decrements the refcount of a screens object, in case it's shared among other recording settings. */
     213    i_destroyAllScreenObj(m->mapScreenObj);
    206214
    207215    m->bd.free();
     
    369377    AssertReturn(screenSettingsMap.find(idScreen) == screenSettingsMap.end(), VERR_ALREADY_EXISTS);
    370378
    371     LogFlowThisFunc(("Screen %RU32\n", idScreen));
    372 
    373379    int vrc = VINF_SUCCESS;
    374380
     
    391397    }
    392398
     399    LogThisFunc(("%p: Screen %RU32 -> %Rrc\n", recordingScreenSettings.m_p, idScreen, vrc));
    393400    return vrc;
    394401}
     
    397404 * Removes a screen settings object from a particular map.
    398405 *
    399  * @returns IPRT status code. VERR_NOT_FOUND if specified screen was not found.
     406 * If the internal reference count hits 0, the screen settings object will be destroyed.
     407 * This means that this screen settings object is not being used anymore by other recording settings (as shared data).
     408 *
     409 * @returns IPRT status code.
     410 * @retval  VERR_NOT_FOUND if specified screen was not found.
    400411 * @param   screenSettingsMap   Map to remove screen settings from.
    401412 * @param   idScreen            ID of screen to remove.
     
    403414int RecordingSettings::i_destroyScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap, uint32_t idScreen)
    404415{
    405     LogFlowThisFunc(("Screen %RU32\n", idScreen));
    406 
    407     AssertReturn(idScreen > 0, VERR_INVALID_PARAMETER); /* Removing screen 0 isn't a good idea. */
    408416    AssertReturn(screenSettingsMap.find(idScreen) != screenSettingsMap.end(), VERR_NOT_FOUND);
    409417
     
    416424    screenSettingsMap.erase(itScreen);
    417425
    418     pScreenSettings.setNull();
     426    LogThisFunc(("%p: Screen %RU32, cRefs=%RI32\n", pScreenSettings.m_p, idScreen, pScreenSettings->i_getReferences()));
     427
     428    pScreenSettings->i_release();
     429
     430    /* Only destroy the object if nobody else keeps a reference to it anymore. */
     431    if (pScreenSettings->i_getReferences() == 0)
     432    {
     433        LogThisFunc(("%p: Screen %RU32 -> Null\n", pScreenSettings.m_p, idScreen));
     434        pScreenSettings.setNull();
     435    }
    419436
    420437    return VINF_SUCCESS;
     
    431448    LogFlowThisFuncEnter();
    432449
    433     RecordingScreenSettingsObjMap::iterator itScreenObj = screenSettingsMap.begin();
    434     while (itScreenObj != screenSettingsMap.end())
    435     {
    436         /* Make sure to consume the pointer before the one of the
    437          * iterator gets released. */
    438         ComObjPtr<RecordingScreenSettings> pScreenSettings = itScreenObj->second;
    439 
    440         screenSettingsMap.erase(itScreenObj);
    441 
    442         pScreenSettings->uninit();
    443         pScreenSettings.setNull();
    444 
    445         itScreenObj = screenSettingsMap.begin();
     450    int vrc = VINF_SUCCESS;
     451
     452    RecordingScreenSettingsObjMap::iterator itScreen = screenSettingsMap.begin();
     453    while (itScreen != screenSettingsMap.end())
     454    {
     455        vrc = i_destroyScreenObj(screenSettingsMap, itScreen->first);
     456        if (RT_FAILURE(vrc))
     457            break;
     458
     459        itScreen = screenSettingsMap.begin();
    446460    }
    447461
    448462    Assert(screenSettingsMap.size() == 0);
    449     return VINF_SUCCESS;
     463    return vrc;
    450464}
    451465
     
    748762    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    749763
     764    LogThisFunc(("%p: cDisplays=%RU32 vs. %zu\n", this, cDisplays, m->mapScreenObj.size()));
     765
    750766    /* If counts match, take a shortcut. */
    751767    if (cDisplays == m->mapScreenObj.size())
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