Using "mutable" for asynchronously populated cache in const method

It seems to me that I am breaking the contract mutablethat I use to cache information in a data model that executes requests on demand asynchronously. The data model is Qt, although this is not a particularly important fact.

class MyDataModel : public QAbstractItemModel
{
public:
    QVariant data( const QModelIndex & index, int role ) const override;

private:
    void SignalRowDataUpdated( int row ) const;
    mutable SimpleRowCache mCache;
};

When called data(), I check the cache to see if it has it. If not, I immediately return null data (to avoid blocking the user interface), and also send an asynchronous API request to fill the cache. Since it data()must be const, this requires that it be mCachemodified. Feelings data()look like this:

RowData row_data = mCache.Get( row );
if( !row_data )
{
    // Store empty data in cache, to avoid repeated API requests
    mCache.Set( row, RowData() );

    // Invoke API with a lambda to deliver async result.  Note: 'this' is const
    auto data_callback = [this, row]( RowData data )
    {
        mCache.Set( row, std::move(data) );
        SignalRowDataUpdated( row );
    };
    DataApi::GetRowData( row, data_callback );

    return QVariant::Invalid;
}
return row_data[ column ];

, . data() , .

? / ?


: SignalRowDataUpdated(). Qt: emit dataChanged( from, to ), . this , const. = (

+4
5

[class.this] ++,

- ​​const, const X *

, const this; ( ) " " . const MyDataModel, ? [decl.type.cv]

, , mutable, , const (3.8) undefined.

mCache data() , mutable.

, - const , , - -.

, (QVariant::Invalid, RowData , ), .

, . , RowData, .

SignalRowDataUpdated, , , const_cast on this?

+2

, -- . (. https://herbsutter.com/2013/01/01/video-you-dont-know-const-and-mutable/).

, - const, , , .

, , . mutable, - , :)

+3

. const. .

, (...) . , (...) const, , , .

, , .

, . (...) .

( API), , - , , , dataVersion2, .

0

MyDataModel::data() , . QVariant::Invalid, .

, data(), , , data() , : data() .

, MyDataModel , data() . const, , undefined, .


, data() . mCache, . , data() (, async_retrieve() ) . const, .

, , sync_retrieve(), , , .

, , MyDataModel .

0

, , data (...) , , (...) (, ?) ' Qt).

, , (...):

1) , if (! row_data), mCache.Get(row), , null if (! row_data)

2) After that, it is also possible that a call to SignalRowDataUpdated caused by the first data call (...) will be executed before the second data call (...) returned with QVariant :: Invalid. I think this is not what you wanted. In this case, you will also need to synchronize the data (...) and SignalRowDataUpdated.

0
source

Source: https://habr.com/ru/post/1661893/


All Articles