find a element in a vector from one of its arguments - c++

How would i find a element in a vector from one of its arguments set with emplace_back
Trying to detach thread then delete it from vector.
std::vector<std::thread> vTimerThreads;
void SetTimer(UINT ID, DWORD dwMilliseconds)
{
// timerThreadProc is my thread that handles my timers
vTimerThreads.emplace_back(timerThreadProc, ID, dwMilliseconds);
}
void DeleteTimer(UINT ID)
{
//Find thread by ID?
// thread.detach();
// then delete
}
SetTimer(TIMER1, 5000);

std::find_if sounds like what you want if you're just going to remove based on id.
void DeleteTimer(std::thread::id ID)
{
std::vector<std::thread>::iterator itr = std::find_if(vTimerThreads.begin(), vTimerThreads.end(), [&](const std::thread& t) { return t.get_id() == ID; });
if( itr != vTimerThreads.end() )
vTimerThreads.erase(itr);
}
I've used a lambda here but it's not necessary.
If you're thinking of using a large number of threads, maybe a different data structure would suit you better. Have you considered an std::set for faster searching? Perhaps even a map or hash_map would be good for you, where the id is the key? You could put the threads into these containers with move semantics instead of emplace_back without having copying (as I suspect is motivating you to use emplace).
Check out the std::algorithm library though, there's some great stuff in there
EDIT:
I see in one of the comments OP says that ID is not in fact the thread id. Unless we can get clarification on what member of T for std::vector<T> we are meant to be searching on, an explicit solution cannot be provided.
As long as I'm doing an edit, here's some code for adding threads to a std::map without copying. With the following code it'll be trivial to find an element by std::thread::id or whatever else you want to use as a key and then delete it.
std::map<std::thread::id, std::thread> mapTimerThreads;
void AddNewThreadToMap()
{
std::thread t;
mapTimerThreads[t.get_id()] = std::move(t);
}

If you want to do a simple linear search (which makes sense if the number of threads is not large) you can just do
void DeleteTimer(UINT ID)
{
for(int i = 0; i < vTimerThreads.size(); i++)
if(vTimerThreads[i].get_id() == ID)
{
vTimerThreads.erase(vTimerThreads.begin()+i);
break;
}
}
If your number of threads is large, arbitrary deletion like this is expensive - you might want to consider something like forward_list instead of vector in that case.

Related

Std::forward_list thread safety

With reference to the following code:
#include <iostream>
#include <vector>
#include <mutex>
#include <forward_list>
using std::cout;
using std::endl;
class Cache {
// thread safe, only 1 writer, thanks to mutex
int add(int val)
{
std::lock_guard<std::mutex> lk(mtx);
if(flSize == 0)
{
fl.push_front(val);
backIt = fl.begin();
}
else
{
backIt = fl.insert_after(backIt,val);
}
++flSize;
return flSize - 1;
}
// allow concurrent readers (with other readers and writer)
// get the element at idx into the forward linked list
// the thread calling get() will never try to index past the last
// index/value it pushed to list. It uses the return value from add() as
// the arg to get
// a.k.a get will never be called before an add() has been called, and
// if add has been called N times, the index to get will be [0, N)
int get(int idx)
{
int num = 0;
auto it = fl.cbegin();
while(num < idx)
{
++num;
++it;
}
return *it;
}
private:
std::forward_list<int> fl;
size_t flSize {0};
std::forward_list<int>::iterator backIt;
std::mutex mtx;
};
The goal is to have readers read from any node in the linked list that has been constructed fully.
Thoughts:
This seems to be thread safe(under the aforementioned constraints). I think am relying on the implementation details to achieve this behavior. I am not sure if something can go wrong here or if any of my assumptions are incorrect. Is this code portable (across compilers) and is this future proof? Might break if future implementation changes.
Question:
can I access the data for a node in a std::forward_list in a thread while another thread is performing std::forward_list::insert_after on the same node?
Does the standard provide any guidelines for such a scenario?
Of course you can access a node in one thread while adding another in another thread. You only get in trouble if you try to access data that is being modified, but insert_after doesn't modify the data in existing nodes nor does it move any node around. No iterators or references are invalidated.
As long as you don't expose a "remove" function or access to iterators (so no thread can iterate through the list while something is being inserted), this is fine. However, I don't see the point of the member backIt: it is only accessed (and modified) when the mutex is locked, so it is effectively the same as fl.end(). If std::forward_list had a size method, flSize would also be redundant.
A couple suggestions to end with. First, I would suggest against using a linked list to begin with. If you can reserve enough elements or if you can deal with resizing (while locked for readers) when necessary, I would just use a vector or perhaps a vector of pointers if the items are very big. If the reserve or resize cannot be done, I would use a std::deque. Second, if you really want to use a std::forward_list, I would use push_front instead, and return an iterator (possibly const) in add that the user can later pass to get. That way, no need any complex logic in either of these functions, and flSize can also be removed. Though get could also be removed since the iterator provides access to the data. Unless there is something more to your comment "It uses the return value from add() as the arg to get".

C++ N-last added items container

I try to find optimal data structure for next simple task: class which keeps N last added item values in built-in container. If object obtain N+1 item it should be added at the end of the container and first item should be removed from it. It like a simple queue, but class should have a method GetAverage, and other methods which must have access to every item. Unfortunately, std::queue doesn't have methods begin and end for this purpose.
It's a part of simple class interface:
class StatItem final
{
static int ITEMS_LIMIT;
public:
StatItem() = default;
~StatItem() = default;
void Reset();
void Insert(int val);
int GetAverage() const;
private:
std::queue<int> _items;
};
And part of desired implementation:
void StatItem::Reset()
{
std::queue<int> empty;
std::swap(_items, empty);
}
void StatItem::Insert(int val)
{
_items.push(val);
if (_items.size() == ITEMS_LIMIT)
{
_items.pop();
}
}
int StatItem::GetAverage() const
{
const size_t itemCount{ _items.size() };
if (itemCount == 0) {
return 0;
}
const int sum = std::accumulate(_items.begin(), _items.end(), 0); // Error. std::queue doesn't have this methods
return sum / itemCount;
}
Any ideas?
I'm not sure about std::deque. Does it work effective and should I use it for this task or something different?
P.S.: ITEMS_LIMIT in my case about 100-500 items
The data structure you're looking for is a circular buffer. There is an implementation in the Boost library, however in this situation since it doesn't seem you need to remove items you can easily implement one using a std::vector or std::array.
You will need to keep track of the number of elements in the vector so far so that you can average correctly until you reach the element limit, and also the current insertion index which should just wrap when you reach that limit.
Using an array or vector will allow you to benefit from having a fixed element limit, as the elements will be stored in a single block of memory (good for fast memory access), and with both data structures you can make space for all elements you need on construction.
If you choose to use a std::vector, make sure to use the 'fill' constructor (http://www.cplusplus.com/reference/vector/vector/vector/), which will allow you to create the right number of elements from the beginning and avoid any extra allocations.

remove element from std::list by reference

std::list<Reader> readers;
readers.push_back(Reader());
Reader& r = *(readers.begin());
/* at this point, the exact place in list, where the reader was picked out, is forgotten.
Only 'r' shows which element of the list it is. */
readers.erase(r); //<---how to do this?
Clients get the new instances 'reader' objects from a manager/dispatcher. The manager maintains an internal list of whatever was dispatched and invalidates/frees up a cached data if "everyone interested" picked it up by observing the pool of readers dispatched.
When the client is no longer interested in the data, it should return the reader to the manager for removal from the pool. But I don't want the client to keep an iterator - it's absolutely uninterested in guts of the manager and the pool of the readers; only needs this one own reader it got, not an iterator pointing to it. So, for deletion, it calls the manager's cleanup function, with the reference to that single reader.
Is there a nicer way to erase that reader from the list than to iterate through the whole list in search of that one reader the reference leads to?
you can compare the pointers to check if they are same object
readers.remove_if([r=&r](auto& x){return &x==r;});
Your options if you only have a reference to the object is to use std::list::remove
readers.remove(r);
or std::find in conjunction with std::list::erase
readers.erase(std::find(readers.begin(), readers.end(), r));
The former has to iterate the entire list while the latter will stop when it finds the first element and then removes it. For large list this can make a big difference.
Both of these options only work when the items are unique. If you have non unique elements then you can use std::find_if and provide a functor that compares the address of the items. That way you can guarantee you only delete the object the reference actually refers to instead of compares equal to.
readers.erase(std::find_if(readers.begin(), readers.end(), [&](const auto& e) {return &r == &e;}));
Use std::remove in combination with erase
readers.erase(std::remove(readers.begin(), readers.end(), r), readers.end());
Also, u can't delete element from list by value, without iterating it. If you think about it, it doesn't even make sense, because pointers inside the list have to be updated.
If the list can contain equal values then you can do something like the following
#include <iostream>
#include <list>
int main()
{
struct Reader { std::pair<char, int> p; };
std::list<Reader> readers;
readers.push_back({{ 'A', 1 } });
readers.push_back({ { 'A', 2 } });
Reader &rr = readers.back();
readers.push_back({ { 'A', 3 } });
readers.remove_if([&rr](const Reader &r) { return &r == &rr; });
for (const auto &r : readers)
{
std::cout << r.p.first << ' ' << r.p.second << std::endl;
}
return 0;
}
The program output is
A 1
A 3

for(auto e : elements) may cause one of elements to be wanted to be removed from vector

I have some classes:
struct Listenable{
virtual void removeListener(Listener * listener) = 0;
};
class Listener{
public: //that way example is simpler
unsigned myCode = 0;
Listenable * subject = 0;
Listener(unsigned myCode, Listenable * subject)
: myCode(myCode), subject(subject){}
void notify(unsigned value){
if(value == myCode){
a->removeListener(this);
}
}
};
class A : public Listenable{
public: //that way example is simpler
std::vector<Listener*> listeners;
void fun(unsigned value){
for(auto listener : listeners){
b->notify(value);
}
}
void removeListener(Listener * listener){
auto it = std::find(listeners.begin(), listeners.end(), listener);
if(it != listeners.end()){
listeners.erase(it);
}
}
};
and the code:
A a;
Listener * l1 = new Listener(5, a);
Listener * l2 = new Listener(7, a);
a.listeners.push_back(l1);
a.listeners.push_back(l2);
a.notify(3); //OK
a.notify(5); //error
I get the vector iterator not incrementable error in a.notify(5).
I know that it's because when I notify the l1 listener (inside of for loop of A::fun(5)), it decides to unsubscribe (call to A::removeListener).
But how to solve this? I want to iterate throw all the listeners and notify them about an event. I cannot assume if any of them (or how many of them) will want to remove itself from the list (it can happens as a reaction to event or somewhere else). I also cannot assume which circumstances will force specific Listener to call A::removeListener(this) and when.
I could change void notify(...) to bool notify(...) where return true would mean "please, remove me". But I cannot be sure that user won't call A::removeListener(this) inside of his custom notify(...){...} (from the class that inherit from Listener) anyway.
There's only one way to go if the vector might be changed while you iterate over it:
Iterate over a copy!
Unless, of course, you can just change the data-structure.
This seems like a probable use case for std::list, where iterators don't become invalidated when the list is changed (unless the thing they refer to is removed).
If you had a std::list<Listener*>, you could step through the list with two iterators current and next (for example), keep next one ahead of current, notify *current in every iteration and be sure that next will still be a valid iterator afterwards. Then set current = next; ++next;, and the issue is neatly sidestepped.
An alternative is to mark the element to suppress, and remove it after the loop, something like:
class A : public Listenable{
public: //that way example is simpler
std::vector<Listener*> listeners;
void fun(unsigned value){
for (auto listener : listeners){
if (listener) { // not marked as deleted
listener->notify(value);
}
}
// remove 'mark_as_deleted' listeners
listeners.erase(std::remove(listeners.begin(), listeners.end(), nullptr),
listeners.end();
}
void removeListener(Listener* listener){
auto it = std::find(listeners.begin(), listeners.end(), listener);
if (it != listeners.end()){
*it = nullptr; // mark as deleted.
}
}
};
If you can't control whether your listeners may try to remove themselves from thew collection, you should consider using a container with stable iterators. One good example would be stable_vector class from Boost (see the documentation here: http://www.boost.org/doc/libs/release/doc/html/container/non_standard_containers.html#container.non_standard_containers.stable_vector).
Its memory footprint is of course bigger than one of std::vector, but overall algorithmic complexity is same. A good feature you get is particular element iterator stays valid as long as element is present in the container. You can rewrite your iteration like this to make it tolerate removals:
for (auto iter = listeners.begin(); iter != listeners.end(); ) // note we don't auto increment here
auto next_iter = iter + 1; // remember the next element
iter->do_something(); // may remove itself from the container
iter = next_iter;
}
EDIT: Or, as wintermute suggested, you may use std::list as the stable container, although it has pretty worse performance when it comes to iteration, and its memory usage is way less efficient than one of any vector.
Add a boolean flag isNotifying to the class A.
Set this flag to true at the beginning of fun and to false at the end of fun.
Inside removeListener, check the flag. If it is false, simply remove the listener as you are doing now. Otherwise, add the listener to a second vector of listeners to be removed in the future.
At the very end of fun, remove all listeners from said vector of listeners. Then clear said vector.
If fun needs to be re-entrant, use an int instead of a boolean flag and count up/down.

C++ Marking objects for removal in STD list via nullptrs

I was wondering if this is an accaptable practice:
struct Item { };
std::list<std::shared_ptr<Item>> Items;
std::list<std::shared_ptr<Item>> RemovedItems;
void Update()
{
Items.push_back(std::make_shared<Item>()); // sample item
for (auto ItemIterator=Items.begin();ItemIterator!=Items.end();ItemIterator++)
{
if (true) { // a complex condition, (true) is for demo purposes
RemovedItems.push_back(std::move(*ItemIterator)); // move ownership
*ItemIterator=nullptr; // set current item to nullptr
}
// One of the downsides, is that we have to always check if
// the current iterator value is not a nullptr
if (*ItemIterator!=nullptr) {
// A complex loop where Items collection could be modified
}
}
// After the loop is done, we can now safely remove our objects
RemovedItems.clear(); // calls destructors on objects
//finally clear the items that are nullptr
Items.erase( std::remove_if( Items.begin(), Items.end(),
[](const std::shared_ptr<Item>& ItemToCheck){
return ItemToCheck==nullptr;
}), Items.end() );
}
The idea here is that we're marking Items container could be effected by outside sources. When an item is removed from the container, it's simply set to nullptr but moved to RemovedItems before that.
Something like an event might effect the Items and add/remove items, so I had to come up with this solution.
Does this seem like a good idea?
I think you are complicating things too much. If you are a in multi-threaded situation (you didn't mention it in your question), you would certainly need some locks guarding reads from other threads that access your modified lists. Since there are no concurrent data structures in the Standard Library, you would need to add such stuff yourself.
For single-threaded code, you can simply call the std:list member remove_if with your predicate. There is no need to set pointers to null, store them and do multiple passes over your data.
#include <algorithm>
#include <list>
#include <memory>
#include <iostream>
using Item = int;
int main()
{
auto lst = std::list< std::shared_ptr<Item> >
{
std::make_shared<int>(0),
std::make_shared<int>(1),
std::make_shared<int>(2),
std::make_shared<int>(3),
};
// shared_ptrs to even elements
auto x0 = *std::next(begin(lst), 0);
auto x2 = *std::next(begin(lst), 2);
// erase even numbers
lst.remove_if([](std::shared_ptr<int> p){
return *p % 2 == 0;
});
// even numbers have been erased
for (auto it = begin(lst); it != end(lst); ++it)
std::cout << **it << ",";
std::cout << "\n";
// shared pointers to even members are still valid
std::cout << *x0 << "," << *x2;
}
Live Example.
Note that the elements have been really erased from the list, not just put at the end of the list. The latter effect is what the standard algorithm std::remove_if would do, and after which you would have to call the std::list member function erase. This two-step erase-remove idiom looks like this
// move even numbers to the end of the list in an unspecified state
auto res = std::remove_if(begin(lst), end(lst), [](std::shared_ptr<int> p){
return *p % 2 == 0;
});
// erase even numbers
lst.erase(res, end(lst));
Live Example.
However, in both cases, the underlying Item elements have not been deleted, since they each still have a shared pointer associated to them. Only if the refence counts would drop to zero, would those former list elements actually be deleted.
If I was reviewing this code I would say it's not acceptable.
What is the purpose of the two-stage removal? An unusual decision like that needs comments explaining its purpose. Despite repeated requests you have failed to explain the point of it.
The idea here is that we're marking Items container could be effected by outside sources.
Do you mean "The idea here is that while we're marking Items container could be effected by outside sources." ? Otherwise that sentence doesn't make sense.
How could it be affected? Your explanation isn't clear:
Think of a Root -> Parent -> Child relationship. An event might trigger in a Child that could remove Parent from Root. So the loop might break in the middle and iterator will be invalid.
That doesn't explain anything, it's far too vague, using very broad terms. Explain what you mean.
A "parent-child relationship" could mean lots of different things. Do you mean the types are related, by inheritance? Objects are related, by ownership? What?
What kind of "event"? Event can mean lots of things, I wish people on StackOverflow would stop using the word "event" to mean specific things and assuming everyone else knows what meaning they intend. Do you mean an asynchronous event, e.g. in another thread? Or do you mean destroying an Item could cause the removal of other elements from the Items list?
If you mean an asynchronous event, your solution completely fails to address the problem. You cannot safely iterate over any standard container if that container can be modidifed at the same time. To make that safe you must do something (e.g. lock a mutex) to ensure exclusive access to the container while modifying it.
Based on this comment:
// A complex loop where Items collection could be modified
I assume you don't mean an asynchronous event (but then why do you say "outside sources" could alter the container) in which case your solution does ensure that iterators remain valid while the "complex loop" iterates over the list, but why do need the actual Item objects to remain valid, rather than just keeping iterators valid? Couldn't you just set the element to nullptr without putting it in RemovedItems, then do Items.remove_if([](shared_ptr<Item> const& p) { return !p; } at the end? You need to explain a bit more about what your "complex loop" can do to the container or to the items.
Why is RemovedItems not a local variable in the Update() function? It doesn't seem to be needed outside that function. Why not use the new C++11 range-based for loop to iterate over the list?
Finally, why is everything named with a capital letter?! Naming local variables and functions with a capital letter is just weird, and if everything is named that way then it's pointless because the capitalisation doesn't help distinguish different types of names (e.g. using a capital letter just for types makes it clear which names are types and which are not ... using it for everything is useless.)
I feel like this only complicates things a lot by having to check for nullptr everywhere. Also, moving a shared_ptr is a little bit silly.
edit:
I think I understand the problem now and this is how I would solve it:
struct Item {
std::list<std::shared_ptr<Item>> Children;
std::set < std::shared_ptr<Item>, std::owner_less < std::shared_ptr<Item >> > RemovedItems;
void Update();
void Remove(std::shared_ptr<Item>);
};
void Item::Update()
{
for (auto child : Children){
if (true) { // a complex condition, (true) is for demo purposes
RemovedItems.insert(child);
}
// A complex loop where children collection could be modified but
// only by calling Item::remove, Item::add or similar
}
auto oless = std::owner_less < std::shared_ptr < Item >>();
std::sort(Children.begin(), Children.end(), oless ); //to avoid use a set
auto newEnd = std::set_difference(Children.begin(),
Children.end(),
RemovedItems.begin(),
RemovedItems.end(),
Children.begin(),
oless);
Children.erase(newEnd, Children.end());
RemovedItems.clear(); // may call destructors on objects
}
void Item::Remove(std::shared_ptr<Item> element){
RemovedItems.insert(element);
}