86 lines
3.2 KiB
C++

#pragma once
#include "starlight/_global.h"
#include <string>
#include <memory>
#include "starlight/ThemeManager.h"
namespace starlight {
namespace gfx {
template <class T> class ThemeRef;
template <class T>
class ThemeRefContainer {
friend class starlight::ThemeManager;
friend class ThemeRef<T>;
protected:
const std::string name;
std::shared_ptr<T> ptr = nullptr;
ThemeRefContainer* redir = nullptr;
unsigned int lastAccess = 0; // how many gc sweeps since last use
volatile int refCount = 0;
void Unload(bool full = false) {
ptr.reset();
if (full) redir = nullptr;
}
ThemeRefContainer(std::string name, std::shared_ptr<T> ptr) : name(name), ptr(ptr) { }
ThemeRefContainer(std::string name, T* ptr) : name(name), ptr(ptr) { }
ThemeRefContainer(std::string name) : name(name) { }
inline std::shared_ptr<T>& _getptr() {
lastAccess = 0;
if (!redir && !ptr) ThemeManager::Fulfill(*this); // call thememanager to grab things
if (redir) return redir->_getptr();
return ptr;
}
inline std::shared_ptr<T>& getptr() const { return const_cast<ThemeRefContainer<T>&>(*this)._getptr(); }
public:
~ThemeRefContainer() { }
T* operator ->() const {
return &*(getptr());
}
/*T& operator *() const {
if (ptr == nullptr) {
ThemeManager::Fulfill(const_cast<ThemeRef<T>&>(*this)); // call thememanager to grab things
}
return *ptr;
}*/
};
template <class T>
class ThemeRef {
friend class starlight::ThemeManager;
protected:
ThemeRefContainer<T>* cptr;
public:
ThemeRef() : cptr(nullptr) { }
ThemeRef(ThemeRefContainer<T>* c) : cptr(c) { if (cptr) cptr->refCount++; }
ThemeRef(ThemeRef<T>& o) : cptr(o.cptr) { if (cptr) cptr->refCount++; }
ThemeRef(ThemeRef<T>&& o) : cptr(o.cptr) { if (cptr) cptr->refCount++; }
~ThemeRef() { if (cptr) cptr->refCount--; }
ThemeRef<T>& operator =(const ThemeRef<T>& o) {
if (cptr) cptr->refCount--;
cptr = o.cptr;
if (cptr) cptr->refCount++;
return *this;
}
ThemeRef<T>& operator =(const ThemeRef<T>&& o) {
if (cptr) cptr->refCount--;
cptr = o.cptr;
if (cptr) cptr->refCount++;
return *this;
}
inline const ThemeRefContainer<T>& operator ->() const { return const_cast<const ThemeRefContainer<T>&>(*cptr); }
inline explicit operator bool() const { return cptr != nullptr; }
inline std::shared_ptr<T> GetShared() const { return (*cptr).getptr(); }
inline const std::string& GetName() const { return (*cptr).name; }
};
}
}