[Alephmodular-devel] For the curious a template class for scoped resources
Status: Pre-Alpha
Brought to you by:
brefin
|
From: Br'fin <br...@ma...> - 2003-03-03 21:52:36
|
Some of you might have noticed the stuff in my design document about
working with scoped resources. For instance:
> Locking pixels. (std::auto_ptr<CBuffer::PixelLock> get_pixel_lock)
> When dealing with buffers on Macintosh, one must lock down pixels
> before doing certain operations. Such as rendering onto the bitmap or
> using copybits. With an auto_ptr based mechanism, the lock is
> automatically freed once out of scope. A corrolary of this is that
> directly requesting a buffer's bitmap should make sure the
> corresponding bitmap has locked the buffer and has control of the
> lock. Trying to double lock or doubly unlock a buffer should assert.
I though I'd show off the sort of thing I'm setting up to actually do
this.
A common trait that all these locks share is a scope. Mostly along the
lines of 'lock this resource until the scope is done and then call this
other private method to revert the lock' Since my design just for the
CDisplay has this in 2-4 different spots so far, I worked up a template
class to handle this.
It is defined with a class and is instantiated with a specific instance
of the class and the address of of member function. The member function
can be any member function with no arguments and no return value ( void
(*class::memberfunc)() )
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
template<class T>
class ScopedLock
{
typedef void (T::*TMemberFn)();
T& origin;
TMemberFn release_method;
public:
ScopedLock(T& _origin, TMemberFn _method): origin(_origin),
release_method(_method) {}
~ScopedLock() { CALL_MEMBER_FN(origin, release_method)(); }
};
As an example of how to use it, here is a very incomplete version of
CBuffer. The typedefs breakdown the complexity of the definition.
Though it's not perfect, hence alloc_pixels_lock which both sets up the
PixelLock and passes in the actual terminating function that really
makes it a PixelLock.
/* Abstract base class for interfacing with the platform specific way
of handling
a drawing surface. For instance a CGrafPort under MacOS
*/
class CBuffer
{
public:
typedef ScopedLock<CBuffer> _CBufferLock;
typedef std::auto_ptr<_CBufferLock> PixelLock;
private:
bool pixels_locked;
virtual void _lock_pixels() = 0;
virtual void _unlock_pixels() = 0;
void unlock_pixels() { assert(pixels_locked); _unlock_pixels();
pixels_locked= false; }
PixelLock alloc_pixel_lock() { return PixelLock(new
_CBufferLock(*this, &CBuffer::unlock_pixels)); }
protected:
CBuffer(): pixels_locked(false) {}
public:
PixelLock get_pixel_lock();
virtual ~CBuffer() {}
};
...
CBuffer::PixelLock CBuffer::get_pixel_lock()
{
assert(!pixels_locked);
_lock_pixels();
pixels_locked= true;
return alloc_pixel_lock();
}
If one class needed multiple locks of some kind, then it could use one
defined form of ScopedLock, and simply setup typedefs and appropriate
alloc_funcs to name versions instantiated with different
release_methods.
-Jeremy Parsons
|