I have created a class which wraps pointers and behaves like a pointer would behave, minus a few cases. It is a lock wrapper class which simply locks before usage of the pointer and unlocks once the pointer usage is done.
It must behave exactly like a pointer EXCEPT in the following cases:
- It cannot be implicitly converted to the pointer type it is pointing to
- It does not handle any memory allocation/deallocation (it provides access to the base pointer when that time comes)
- When compared to another wrapper object, it compares their pointers to see if they are the same
Here is what I have so far:
template <class PtrType, class LockType>
class ELockWrapper {
public:
class Proxy {
public:
Proxy(PtrType* p, LockType* lock) : ptr(p), mLock(lock) { mLock->Lock(); }
~Proxy() { mLock->Unlock(); }
PtrType* operator->() { return ptr; }
PtrType operator*() { return *ptr; }
private:
PtrType* ptr;
LockType* mLock;
};
ELockWrapper() : ptr(nullptr), lock(nullptr) {}
ELockWrapper(nullptr_t t) : ELockWrapper() {}
ELockWrapper(PtrType *p, LockType* l) : ptr(p), lock(l) {}
ELockWrapper(PtrType *p, LockType& l) : ptr(p), lock(&l) {}
ELockWrapper(const ELockWrapper& copy) = default;
ELockWrapper& operator=(const ELockWrapper& x) = default;
bool operator==(const ELockWrapper& cmp) { return cmp.ptr == ptr; }
bool operator!=(const ELockWrapper& cmp) { return !operator==(cmp); }
bool operator==(PtrType* t) { return ptr == t; }
bool operator!=(PtrType* t) { return ptr != t; }
bool operator==(bool b) { return (ptr && b) || (!ptr && !b); }
bool operator!=(bool b) { return !operator==(b); }
operator bool() const { return ptr; }
Proxy operator->() {
return Proxy(ptr, lock);
}
PtrType operator*() {
return *Proxy(ptr, lock);
}
PtrType* GetPointer() {
Proxy(ptr, lock);
return ptr;
}
private:
PtrType* ptr;
LockType* lock;
};
Here is it in action with some test cases.
Any mistakes/suggestions would be much appreciated.