Std::forward_list thread safety - c++

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".

Related

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

find a element in a vector from one of its arguments

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.

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);
}

C++ buffer pool?

I have a strong use case for pre-allocating all the memory I need upfront and releasing it upon completion.
I have came out with this real simple buffer pool C++ implementation which I have to test but I am not sure that the pointer arithmetic I am trying to use will allow me to do that. Basically the bit where I do next and release. I would prefer some trick around this idea and not relying on any sort of memory handler which just makes the client code more convoluted.
#include <stdio.h>
#include <queue>
#include "utils_mem.h"
using namespace std;
template <class T>
class tbufferpool {
private:
const int m_initial;
const int m_size;
const int m_total;
T* m_buffer;
vector<T*> m_queue;
public:
// constructor
tbufferpool(int initial, int size) : m_initial(initial), m_size(size), m_total(initial*size*sizeof(T)) {
m_buffer = (T*) malloc(m_total);
T* next_buffer = m_buffer;
for (int i=0; i < initial; ++i, next_buffer += i*size) {
m_queue.push_back(next_buffer);
}
}
// get next buffer element from the pool
T* next() {
// check for pool overflow
if (m_queue.empty()) {
printf("Illegal bufferpool state, our bufferpool has %d buffers only.", m_initial);
exit(EXIT_FAILURE);
}
T* next_buffer = m_queue.back();
m_queue.pop_back();
return next_buffer;
}
// release element, make it available back in the pool
void release(T* buffer) {
assert(m_buffer <= buffer && buffer < (buffer + m_total/sizeof(T)));
m_queue.push_back(buffer);
}
void ensure_size(int size) {
if (size >= m_size) {
printf("Illegal bufferpool state, maximum buffer size is %d.", m_size);
exit(EXIT_FAILURE);
}
}
// destructor
virtual ~tbufferpool() {
free(m_buffer);
}
};
First, when you increase a pointer to T, it will point the next element of T in the memory.
m_queue.push(m_buffer + (i*size*sizeof(T)));
This should be like
m_buffer = (T*) malloc(m_total);
T* next = m_buffer;
for (int i=0; i < initial; ++i) {
m_queue.push(next++);
}
Second,
assert(m_buffer <= buffer && buffer < m_total);
It should be like
assert(m_buffer <= buffer && buffer <= m_buffer + m_total/sizeof(T));
Hope it helps!
I don't understand why you're "wrapping" the STL queue<> container. Just put your "buffers" in the queue, and pull the addresses as you need them. When you're done with a "segment" in the buffer, just pop it off of the queue and it's released automatically. So instead of pointers to buffers, you just have the actual buffer classes.
It just strikes me as re-inventing the wheel. Now since you need the whole thing allocated at once, I'd use vector not queue, because the vector<> type can be allocated all at once on construction, and the push_back() method doesn't re-allocate unless it needs to, the same with pop_back(). See here for the methods used.
Basically, though, here's my back-of-the-envelope idea:
#include <myType.h> // Defines BufferType
const int NUMBUFFERS = 30;
int main()
{
vector<BufferType> myBuffers(NUMBUFFERS);
BufferType* segment = &(myBuffers[0]); // Gets first segment
myBuffers.pop_back(); // Reduces size by one
return 0;
}
I hope that gives you the general idea. You can just use the buffers in the vector that way, and there's only one allocation or de-allocation, and you can use stack-like logic if you wish. The dequeue type may also be worth looking at, or other standard containers, but if it's just "I only want one alloc or de-alloc" I'd just use vector, or even a smart pointer to an array possibly.
Some stuff I've found out using object pools:
I'm not sure about allocating all the objects at once. I like to descend all my pooled objects from a 'pooledObject' class that contains a private reference to its own pool, so allowing a simple, parameterless 'release' method and I'm always absolutely sure that an object is always released back to its own pool. I'm not sure how to load up every instance with the pool reference with a static array ctor - I've always constructed the objects one-by-one in a loop.
Another useful private member is an 'allocated' boolean, set when an object is depooled and cleared when released. This allows the pool class to detect and except immediately if an object is released twice. 'Released twice' errors can be insanely nasty if not immediately detected - weird behaviour or a crash happens minutes later and, often, in another thread in another module. Best to detect double-releases ASAP!
I find it useful and reassuring to dump the level of my pools to a status bar on a 1s timer. If a leak occurs, I can see it happening and, often, get an idea of where the leak is by the activity I'm on when a number drops alarmingly. Who needs Valgrind:)
On the subject of threads, if you have to make your pools thread-safe, it helps to use a blocking queue. If the pool runs out, threads trying to get objects can wait until they are released and the app just slows down instead of crashing/deadlocking. Also, be careful re. false sharing. You may have to use a 'filler' array data member to ensure that no two objects share a cache line.

How do I avoid destructor stack overflow with deep nested data structure in C++?

int count;
class MyClass {
std::shared_ptr<void> p;
public:
MyClass(std::shared_ptr<void> f):p(f){
++count;
}
~MyClass(){
--count;
}
};
void test(int n){
std::shared_ptr<void> p;
for(int i=0;i<n;++i){
p = std::make_shared<MyClass>(p);
}
std::cout<<count<<std::endl;
}
int main(int argc, char* argv[])
{
test(200000);
std::cout<<count<<std::endl;
return 0;
}
The above program causes stack overflow under "release" build in Visual Studio 2010 IDE.
The question is: if you do need to create some data structure like the above, how to avoid this problem.
UPDATE: Now I have seen one meaningful answer. However this is not good enough. Please consider I have updated MyClass to contain two (or more) shared_ptrs, and each of them can be an instance of MyClass or some other data.
UPDATE: Somebody updated the title for me and saying "deep ref-counted data structure", which is not necessary related to this question. Actually, shared_ptr is only a convenient example; you can easily change to other data types with the same problem. I also removed the C++11 tag because it is not C++11 only problem as well.
Make the stack explicit (i.e. put it in a container on the heap).
Have non-opaque pointers (non-void) so that you can walk your structure.
Un-nest your deep recursive structure onto the heap container, making the structure non-recursive (by disconnecting it as you go along).
Deallocate everything by iterating over the pointers collected above.
Something like this, with the type of p changed so we can inspect it.
std::shared_ptr<MyClass> p;
~MyClass() {
std::stack<std::shared_ptr<MyClass>> ptrs;
std::shared_ptr<MyClass> current = p;
while(current) {
ptrs.push_back(current);
current = current->p;
ptrs.back()->p.reset(); // does not call the dtor, since we have a copy in current
}
--count;
// ptrs dtor deallocates every ptr here, and there's no recursion since the objects p member is null, and each object is destroyed by an iterative for-loop
}
Some final tips:
If you want to untangle any structure, your types should provide an interface that returns and releases all internal shared_ptr's, i.e something like: std::vector<shared_ptr<MyClass>> yieldSharedPtrs(), perhaps within a ISharedContainer interface or something if you can't restrict yourself to MyClass.
For recursive structures, you should check that you don't add the same object to your ptr-container twice.
Thanks to #Macke's tips, I have an improved solution like the following:
~MyClass(){
DEFINE_THREAD_LOCAL(std::queue< std::shared<void> >, q)
bool reentrant = !q.empty();
q.emplace(std::move(p)); //IMPORTANT!
if(reentrant) return;
while(!q.empty()){
auto pv = q.front();
q.pop();
}
}
DEFINE_THREAD_LOCAL is a macro that defines a variable (param 2) as specified type (param 1) with thread local storage type, which means there is no more than one instance for each running thread. Because thread_local keyword is still not available for mainstream compilers, I have to assume such a macro to make it work for compilers.
For single thread programs, DEFINE_THREAD_LOCAL(type, var) is simply
static type var;
The benefit of this solution is it do not require to change the class definition.
Unlike #Macke's solution, I use std::queue rather than std::stack in order to keep the destruction order.
In the given test case, q.size() will never be more than 1. However, it is just because this algorithm is breadth-first. If MyClass has more links to another instance of MyClass, q.size() will reach greater values.
NOTE: It is important to remember use std::move to pass p to the queue. You have not solved the problem if you forgotten to do so, you are just creating and destroying a new copy of p, and after the visible code the destruction will still be recursive.
UPDATE: the original posted code has a problem: q is going to be modified within pop() call. The solution is cache the value of q.front() for later destruction.
If you really have to work with such an odd code, you can increase the size of your stack. You should find this option in the project properties of Visual Studio.
As already suggested, I must tell you that this kind of code should be avoided when working with a large mole of data structures, and increasing the stack size is not a good solution if you plan to release your software. It may also terribly slow down your own computer if you abuse this feature, obviously.