iw4x-client/src/Utils/Chain.hpp

148 lines
2.4 KiB
C++
Raw Normal View History

2016-09-30 20:03:12 -04:00
namespace Utils
{
template <typename T>
class Chain
{
public:
class Entry
{
private:
std::shared_ptr<T> object;
std::shared_ptr<Entry> next;
2016-09-30 20:03:12 -04:00
public:
bool hasNext()
2016-09-30 20:03:12 -04:00
{
return (this->next.use_count() > 0);
2016-09-30 20:03:12 -04:00
}
bool isValid()
2016-09-30 20:03:12 -04:00
{
return (this->Object.use_count() > 0);
}
void set(T object)
2016-09-30 20:03:12 -04:00
{
this->object = std::shared_ptr<T>(new T());
*this->object.get() = object;
2016-09-30 20:03:12 -04:00
}
std::shared_ptr<T> get()
2016-09-30 20:03:12 -04:00
{
return this->object;
2016-09-30 20:03:12 -04:00
}
Entry getNext()
2016-09-30 20:03:12 -04:00
{
if (this->hasNext())
2016-09-30 20:03:12 -04:00
{
return *(this->next.get());
2016-09-30 20:03:12 -04:00
}
else
{
return Entry();
}
}
std::shared_ptr<Entry> getNextEntry()
2016-09-30 20:03:12 -04:00
{
return this->next;
2016-09-30 20:03:12 -04:00
}
void setNextEntry(std::shared_ptr<Entry> entry)
2016-09-30 20:03:12 -04:00
{
this->next = entry;
2016-09-30 20:03:12 -04:00
}
T *operator->()
{
return (this->object.get());
2016-09-30 20:03:12 -04:00
}
Entry& operator++ ()
{
*this = this->getNext();
2016-09-30 20:03:12 -04:00
return *this;
}
Entry operator++ (int)
{
Entry result = *this;
this->operator++();
return result;
}
};
private:
std::mutex mutex;
Entry object;
2016-09-30 20:03:12 -04:00
public:
void add(T object)
2016-09-30 20:03:12 -04:00
{
std::lock_guard<std::mutex> _(this->mutex);
2016-09-30 20:03:12 -04:00
if (!this->Empty())
{
// Create new chain entry
std::shared_ptr<Entry> currentObject = std::shared_ptr<Entry>(new Entry);
*currentObject.get() = this->object;
2016-09-30 20:03:12 -04:00
// Add it to the chain
this->object = Entry();
this->object.setNextEntry(currentObject);
2016-09-30 20:03:12 -04:00
}
this->object.set(object);
2016-09-30 20:03:12 -04:00
}
void remove(std::shared_ptr<T> object)
2016-09-30 20:03:12 -04:00
{
std::lock_guard<std::mutex> _(this->mutex);
2016-09-30 20:03:12 -04:00
if (!this->empty())
2016-09-30 20:03:12 -04:00
{
if (this->object.get().get() == object.get())
2016-09-30 20:03:12 -04:00
{
this->object = this->object.getNext();
2016-09-30 20:03:12 -04:00
}
else if(this->object.hasNext())
2016-09-30 20:03:12 -04:00
{
for (auto entry = this->object; entry.isValid(); ++entry)
2016-09-30 20:03:12 -04:00
{
auto next = entry.getNext();
2016-09-30 20:03:12 -04:00
if (next.isValid() && next.get().get() == object.get())
2016-09-30 20:03:12 -04:00
{
*entry.getNextEntry().get() = next.getNext();
2016-09-30 20:03:12 -04:00
}
}
}
}
}
void remove(Entry entry)
2016-09-30 20:03:12 -04:00
{
if (entry.isValid())
2016-09-30 20:03:12 -04:00
{
this->remove(entry.Get());
2016-09-30 20:03:12 -04:00
}
}
bool empty()
2016-09-30 20:03:12 -04:00
{
return !this->object.isValid();
2016-09-30 20:03:12 -04:00
}
Entry begin()
2016-09-30 20:03:12 -04:00
{
return this->object;
2016-09-30 20:03:12 -04:00
}
void clear()
2016-09-30 20:03:12 -04:00
{
this->object = Entry();
2016-09-30 20:03:12 -04:00
}
};
}