2017-01-20 08:36:52 -05:00
|
|
|
#pragma once
|
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
namespace Utils
|
|
|
|
{
|
|
|
|
template <typename T>
|
|
|
|
class Chain
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
class Entry
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
std::shared_ptr<T> object;
|
|
|
|
std::shared_ptr<Entry> next;
|
|
|
|
|
|
|
|
public:
|
|
|
|
bool hasNext()
|
|
|
|
{
|
|
|
|
return (this->next.use_count() > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isValid()
|
|
|
|
{
|
2017-01-20 16:41:03 -05:00
|
|
|
return (this->object.use_count() > 0);
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void set(T object)
|
|
|
|
{
|
2017-01-20 16:41:03 -05:00
|
|
|
this->object = std::make_shared<T>();
|
2017-01-19 16:23:59 -05:00
|
|
|
*this->object.get() = object;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<T> get()
|
|
|
|
{
|
|
|
|
return this->object;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry getNext()
|
|
|
|
{
|
|
|
|
if (this->hasNext())
|
|
|
|
{
|
|
|
|
return *(this->next.get());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Entry();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<Entry> getNextEntry()
|
|
|
|
{
|
|
|
|
return this->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setNextEntry(std::shared_ptr<Entry> entry)
|
|
|
|
{
|
|
|
|
this->next = entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
T *operator->()
|
|
|
|
{
|
|
|
|
return (this->object.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry& operator++ ()
|
|
|
|
{
|
|
|
|
*this = this->getNext();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry operator++ (int)
|
|
|
|
{
|
|
|
|
Entry result = *this;
|
|
|
|
this->operator++();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::mutex mutex;
|
|
|
|
Entry object;
|
|
|
|
|
|
|
|
public:
|
|
|
|
void add(T object)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> _(this->mutex);
|
|
|
|
|
2017-01-20 16:41:03 -05:00
|
|
|
if (!this->empty())
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
// Create new chain entry
|
2017-01-20 16:41:03 -05:00
|
|
|
std::shared_ptr<Entry> currentObject = std::make_shared<Entry>();
|
2017-01-19 16:23:59 -05:00
|
|
|
*currentObject.get() = this->object;
|
|
|
|
|
|
|
|
// Add it to the chain
|
|
|
|
this->object = Entry();
|
|
|
|
this->object.setNextEntry(currentObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->object.set(object);
|
|
|
|
}
|
|
|
|
|
|
|
|
void remove(std::shared_ptr<T> object)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> _(this->mutex);
|
|
|
|
|
|
|
|
if (!this->empty())
|
|
|
|
{
|
|
|
|
if (this->object.get().get() == object.get())
|
|
|
|
{
|
|
|
|
this->object = this->object.getNext();
|
|
|
|
}
|
2017-06-14 06:06:04 -04:00
|
|
|
else if (this->object.hasNext())
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
for (auto entry = this->object; entry.isValid(); ++entry)
|
|
|
|
{
|
|
|
|
auto next = entry.getNext();
|
|
|
|
|
|
|
|
if (next.isValid() && next.get().get() == object.get())
|
|
|
|
{
|
|
|
|
*entry.getNextEntry().get() = next.getNext();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void remove(Entry entry)
|
|
|
|
{
|
|
|
|
if (entry.isValid())
|
|
|
|
{
|
|
|
|
this->remove(entry.Get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty()
|
|
|
|
{
|
|
|
|
return !this->object.isValid();
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry begin()
|
|
|
|
{
|
|
|
|
return this->object;
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
this->object = Entry();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|