[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 |