Home > Software design >  C Is there any fast way to detect how many std::vector elements has been updated/modified?
C Is there any fast way to detect how many std::vector elements has been updated/modified?

Time:02-24

I'm currently implementing a caching system that has a similar API to std::vector, but it has a member function called Flush, which is for transferring elements to somewhere(e.g. hardware, network, etc.).

What I want to do is to make the caching system be able to minimize the transfer overhead through flushing, by just transferring the modified elements instead of the entire array, and also the frequency of transfer should be limited because it needs time cost to initiate a transfer.

What I've tried to do is to inherit std::vector, then try to find out if there are any interfaces like on_element_modified or on_element_updated for me to use to detect if the user modified any of the elements (via operator[], iterators, or push_back insert remove, etc.) then when flushing, I can just transfer these modified elements, but it looks like std::vector doesn't have such interfaces for me to use.

template<typename Ty, typename Allocator = std::allocator<Ty>>
class MyFlushableVector : public std::vector
{
protected:
    using size_type = typename std::vector::size_type;
    std::vector<bool> updated;
    // These imagined functions is what I need
    void on_element_modified(size_type index) override
    {
        updated[index] = true;
    }
    void on_new_element() override
    {
        updated.push_back(true);
    }
    void on_popped_element() override
    {
        updated.pop_back();
    }
    void Transfer(Ty *Pointer, size_type count)
    {
        // Do some transfer
    }

public:
    void Flush()
    {
        // Minimize the frequency of transfer by finding the updated blocks to transfer.
        size_type i, first_updated = 0;
        bool is_modified = false;
        for (i = 0; i < size(); i  )
        {
            if (is_modified == false)
            {
                if (updated[i])
                {
                    first_updated = i;
                    is_modified = true;
                }
            }
            else
            {
                if (!updated[i])
                {
                    Transfer(data()   first_updated, i - first_updated);
                    is_modified = false;
                }
            }
        }
        if (is_modified)
        {
            Transfer(data()   first_updated, i - first_updated);
        }
    }
};

As I couldn't find these imagination interfaces to use, I'm now trying to implement a new class that isn't inherited from std::vector but it has the same interfaces as std::vector and I implemented each of them except it doesn't support iterators (because I don't know how to implement an iterator that can detect any write operations to the vector and set the corresponding updated element to true). I'm not sure this is the true way to do it in modern C .

CodePudding user response:

The short answer to the question that's contained in the title of this question is simply "no", there's nothing like that, neither in vector nor any other C library container. If you need to track changes to the values in the container it will be up to you to implement the entire scaffolding that does so.

Other than that, the only other thing you appear to be asking, indirectly, is in the last paragraph which I'll address in the rest of my answer:

I don't know how to implement an iterator that can detect any write operations to the vector and set the corresponding updated element to true)

I am presuming you're asking how to do that. Well, you can use the same approach that already happens to be used in the C library by std::ostreambuf_iterator, which you can simply appropriate for your own purposes.

    std::ostreambuf_iteraor<char> iter{std::cout};

    *iter   = 'H';
    *iter   = 'e';

    // and so on, for the remainder of "Hello world!", which will get written
    // to C  

The key factor here is that iterators are not pointers. They are just objects that implement * and several other operators (depending on the requirements of the iterator's declared category).

std::ostreambuf_iterator implements the * and the operator that do ...absolutely nothing. They return the iterator itself. Then, std::ostreambuf_iterator also implements the = operator, that takes the char given to it, and writes it to the output stream buffer.

So, the expression *iter is a big-fat-nothing, it's only there to meet the requirements for this iterator's category, and all the action happens in the = operator overload. *iter ='H'; only actual work that happens is in the invoked operator= overload.

Your custom iterator class simply needs to do the same thing: implement an operator Ty and operator=(const Ty&). The former hands over the actual Ty value that your iterator is referencing. The latter assigns a new value to it, and then sets the corresponding modified flag. Your container hands over these iterators, to iterate itself over. The End. Mission accomplished.

  • Related