0

I'm trying to find all the processes in the blockedProcess list with the specified event number, copy them into a transferList, and then remove them. Copying and moving the Process objects works fine, but I can't figure out how to remove those Process objects from blockedProcess afterwards.

ProcessQueue findEventFlag(int eventnum)
{
    ProcessQueue transferProcess;
    Process process;
    list<Process>::iterator it;



    for (it = blockedProcess.begin(); it != blockedProcess.end(); it++)
    {
        process = *it;

        if (process.getEvent() == eventnum)
        {
            process.setState("READY");
            process.setEvent(-1);
            transferProcess.enqueue(process);
        }

    }

    return transferProcess;

}
  • Is `blockedProcess` `std::list`? If so: https://stackoverflow.com/questions/596162/can-you-remove-elements-from-a-stdlist-while-iterating-through-it – Algirdas Preidžius Oct 03 '18 at 21:46
  • @AlgirdasPreidžius Would `list.remove()` also work? Just doing it once at end. – Rivasa Oct 03 '18 at 21:48
  • @Rivasa `list.remove ()` would also need to iterate through the list to remove the elements, effectively needing 2 iterations through the list. While the technique described in the linked question, would require just one iteration through the list, due to the fact that removal from the list, via the iterator, is O(1) operation. – Algirdas Preidžius Oct 03 '18 at 21:52
  • You could do use erase-remove thinking, but I agree with Algirdas. The main cost of removing an item from a linked list is finding it. [Since it's already found...](https://www.youtube.com/watch?v=iONsYGTu_UA) – user4581301 Oct 03 '18 at 21:57
  • Right, knew something was escaping me on this point. Thank you. – Rivasa Oct 03 '18 at 21:58

1 Answers1

0

Building on the comments, try this (which relies on the fact that std::list::erase conveniently returns an iterator to the next item in the list):

ProcessQueue findEventFlag(int eventnum)
{
    ProcessQueue transferProcess;
    Process process;
    list<Process>::iterator it = blockedProcess.begin();

    while (it != blockedProcess.end())
    {
        process = *it;

        if (process.getEvent() == eventnum)
        {
            process.setState("READY");
            process.setEvent(-1);
            transferProcess.enqueue(process);
            it = process.Erase (it);
        }
        else
            it++;
    }

    return transferProcess;
}

You can also transfer an element from one list to another with std::list::splice which would avoid copying your process object and might therefore be more efficient, something like:

ProcessQueue findEventFlag(int eventnum)
{
    ProcessQueue transferProcess;
    Process process;
    list<Process>::iterator it = blockedProcess.begin();

    while (it != blockedProcess.end())
    {
        process = *it;
        list<Process>::iterator next = std::next (it);

        if (process.getEvent() == eventnum)
        {
            process.setState("READY");
            process.setEvent(-1);
            transferProcess.splice(transferProcess.begin (), blockedProcess, it);
        }

        it = next;
    }

    return transferProcess;
}
Paul Sanders
  • 24,133
  • 4
  • 26
  • 48