Click here to Skip to main content
15,891,674 members
Articles / Programming Languages / C++

Writing Win32 Apps with C++: V2 - part 1

Rate me:
Please Sign up or sign in to vote.
4.70/5 (34 votes)
20 Jun 2005CPOL14 min read 107.9K   1.2K   73  
An independent framework to handle Win32 objects inside C++ classes.
//Wrp.h 
// generic wrappers
#pragma once

namespace GE_{ namespace stdx1 {


	//apply copy and assing functionality to a RefcountableValue class
	//	also support comparisons through a compare function
	template<class Handable>
	class Handle: 
		public Handable
	{
		//function that must be inherited
		//	void _init() // required by the constructor
		//  void _clear() // required by the destructor
		// template<class U> void _set(const U& u) //required for copy and assignments
		// template<class U> int _compare(const U& u) const //required for comparisons

	public:
		typedef Handle Handle_type; //ourself
		Handle() { _init();	}
		virtual ~Handle() { _clear(); }
		//copy
		Handle(const Handle& _c) { _init(); _set(static_cast<const Handable&>(_c)); }
		template<class U> Handle(const U& _u) {_init(); _set(_u); }
		//assign
		Handle& operator=(const Handle& _c) { _set(static_cast<const Handable&>(_c)); return *this; }
		template<class U> Handle& operator=(const U& _u) { _set(_u); return *this; }
		//compare
		bool operator<(const Handle& _c) const { return _compare(static_cast<const Handable&>(_c)) <0; }
		template<class U> bool operator<(const U& _u) const { return _compare(_u) <0; }
		bool operator==(const Handle& _c) const { return _compare(static_cast<const Handable&>(_c)) ==0; }
		template<class U> bool operator==(const U& _u) const { return _compare(_u) ==0; }

		//note: homogeneous type operators are delegated to the correponding bases, passing the base object.
		//	eterogeneous operators are delegated as they are, letting the base specialization to define the behaviour
	};


	//implement a referece counter copy / assign
	template<class Refcountable>
	class HandableRefcounter:  //NOTE: CANNOT BE STATIC - or the g_countmap will be destroyed anticipaing causing corruption
		public Refcountable
	{
		//provisioning expected from Refcountable
		//  typedef value_type // the type we are listening
		//	typedef stored_type //the RefcountableValue we are storing
		//	typedef key_type //the type we use as reverse searc key
		//	
		//	static key_type _key(const stored_type&) //get the key
		//	static key_type _nullkey() //get a null key
		//	void _init()
		//	void _clear()
		//	void _set(const Refcountable&)
		//	value_type _convert<U>(const U& u) const
		//	void on_addref()	//called if we are the first recout for the object
		//	void on_firstref()	//called when assigning us to an object
		//  void on_release()	//called when deassigning us from an object
		//	void on_lastrelease() //called if we are the last refocunt for the object
		//  template<class U> int _compare(const U& u) const //required for comparisons
	public:
		typedef HandableRefcounter Handable_type;
	private:
		// internal helper functions
        void addref()
		{
			if(prefcnt)
			{
				if(*prefcnt == -1) return; //return immediatly if locked
				++(*prefcnt);	//increment
				if(!*prefcnt) throw std::overflow_error("v_refcnt::add_ref: overflow");
				if(*prefcnt == 1) on_firstref(); //do callbacks
				on_addref();
			}
		}
		void release()
		{
			if(prefcnt)
			{
				if(*prefcnt == -1) return; //return immediatly if locked
				--(*prefcnt);
				if(!*prefcnt) *prefcnt = -1; //lock when zero: will be no more incremented / decremented
				on_release(); //do callbacks
				if(*prefcnt == -1) //if we have locked
				{
					g_r().erase(_key(*this)); //cleanup the map
					on_lastrelease();
				}
			}
		}
		unsigned int* prefcnt;	//the reference conting associated to the value
		friend class HandableRefcounter;
	protected:
		typedef Global<std::map<typename Refcountable::key_type, unsigned int> > g_countmap; //the reference counters map
		g_countmap::ref g_r;

		void _init() { g_r = g_countmap::get(); prefcnt = NULL; Refcountable::_init(); }
		void _set(const typename Refcountable::stored_type& _v) 
		{
			//seek for the reference counter
			typename Refcountable::key_type k = _key(_v);
			unsigned int* pnewrefcnt = (k == _nullkey())? NULL: &(g_r()[k]);
			if(pnewrefcnt == prefcnt) return; //nothing to set ! (we are already referring the same entity)
			release();	//release the actual object
			Refcountable::_set(_v);
			prefcnt = pnewrefcnt;
			addref(); //increment the new object references
		}
		void _set(const HandableRefcounter& _r)
		{
			if(prefcnt == _r.prefcnt) return; //nothig to set
			release();
			prefcnt = _r.prefcnt;
			Refcountable::_set(static_cast<const Refcountable&>(_r));
			addref();
		}
		
		template<class U>
		void _set(const U& _u)
		{
			_set(_convert(_u));
		}
		void _clear()
		{
			if(prefcnt)
				release();
			prefcnt = NULL;
			Refcountable::_clear();
		}

	public:
		unsigned int getrefcount() const { return (prefcnt)? *prefcnt: 0; }
	};


	//implement a HandableOwner copy / assign (like HandableRefcounter, but ... without refcounting, but like std::auto_ptr)
	template<class Refcountable>
	class HandableOwner: 
		public Refcountable
	{
		//provisioning expected from Refcountable
		//  typedef value_type // the type we are listening
		//	typedef stored_type //the RefcountableValue we are storing
		//	typedef key_type //the type we use as reverse searc key
		//	
		//	static key_type _key(const stored_type&) //get the key
		//	static key_type _nullkey() //get a null key
		//	void _init()
		//	void _clear()
		//	void _set(const value_type&)
		//	void _set(const Refcountable&)
		//	value_type _convert<U>(const U& u) const
		//	void on_addref()
		//	void on_firstref()
		//  void on_release()
		//	void on_lastrelease()
		//  template<class U> int _compare(const U& u) const//required for comparisons
		friend class HandableOwner;
	public:
		typedef HandableOwner Handable_type;
	private:
		mutable bool bOwn;
	private:
        void addref()
		{
			if(bOwn)
				on_firstref();
			on_addref();
		}
		void release()
		{
			on_release();
			if(bOwn)
				on_lastrelease();
		}
	protected:

		void _init() { Refcountable::_init(); bOwn = false; }
		void _set(const typename Refcountable::stored_type& _v) 
		{
			release();
			bOwn = true;
			Refcountable::_set(_v);
			addref();
		}
		void _set(const HandableOwner& _r)
		{
			release();
			bOwn = _r.bOwn;
			Refcountable::_set(static_cast<const Refcountable&>(_r));
			addref();
			_r.bOwn = false;
		}
		
		template<class U>
		void _set(const U& _u)
		{
			bOwn = true;
			_set(_convert(_u));
		}
		void _clear()
		{
			release();
			Refcountable::_clear();
			bOwn = false;
		}
	};


	/// refcountable classes:
	//	provides value and RefcountablePointer semantics
	//


	//RefcountableValue wrapper
	template<class V, V nullvalue = NULL >
	class RefcountableValue
	{
	protected:
		typedef V value_type; //the RefcountableValue we are referring
		typedef V stored_type; //the RefcountableValue we are storing
		typedef V key_type; //the type we use as reverse search key
	public:
		typedef RefcountableValue Refcountable_type;
	private:
		stored_type MyVal;
	protected:
		static key_type _key(const stored_type& _v) { return _v; } //get the key
		static key_type _nullkey() { return nullvalue; } //get a null key
		void _init() { MyVal = nullvalue; }
		void _clear() { MyVal = nullvalue; }
		void _set(const stored_type& _v) { MyVal = _v; }
		void _set(const RefcountableValue& _v) { MyVal = _v; }
		template<class U>
			static value_type _convert(const U& u) { return static_cast<value_type>(u); }
		virtual void on_addref() {}
		virtual void on_firstref() {}
		virtual void on_release() {}
		virtual void on_lastrelease() {}
		template<class U> int _compare(const U& u) const
		{ value_type v = _convert(u); return (MyVal==v)? 0:(MyVal<v)? -1: 1; }
	public:
		operator value_type() const { return MyVal; }
		value_type operator()() const { MyVal; }
		bool operator!() const { return MyVal == nullvalue; }
	};

	//RefcountableValue wrapper
	template<class PointerCaster>
	class RefcountablePointer: public PointerCaster
	{
		//functionalities to be provided by PointerCaster
		//	typedef V value_type; //the RefcountableValue we are referring
		//  value_type _convert<U>(const U& u) 
		//  typedef LPVOID key_type; //the type we use as reverse searc key
		//	key_type _key(const stored_type& _v) { return _v; } //get the key
		//	typedef value_type* stored_type; //the RefcountableValue we are storing
	protected:
		typedef typename PointerCaster::value_type value_type; //the RefcountableValue we are referring
		typedef typename PointerCaster::key_type key_type; //the type we use as reverse searc key
		typedef typename PointerCaster::stored_type stored_type; //the RefcountableValue we are storing
	public:
		typedef RefcountablePointer Refcountable_type;
	private:
		stored_type MyPtr;
	protected:
		static key_type _nullkey() { return NULL; } //get a null key
		void _init() { MyPtr = NULL; }
		void _clear() { MyPtr = NULL; }
		void _set(const stored_type& _v) { MyPtr = _v; }
		void _set(const RefcountablePointer& _v) { MyPtr = _v; }
		virtual void on_addref() {}
		virtual void on_firstref() {}
		virtual void on_release() {}
		virtual void on_lastrelease() { delete MyPtr; }
		template<class U> int _compare(const U& u) const
		{ value_type v = _convert(u); return (MyPtr==v)? 0:(MyPtr<v)? -1: 1; }
	public:
		operator value_type*() const { return MyPtr; }
		value_type* operator->() const { if(!MyPtr) throw std::domain_error("stdx1::ptr::accessmember: null dereference"); return MyPtr; }
		value_type& operator*() const { if(!MyPtr) throw std::domain_error("stdx1::ptr::dereference: null dereference"); return *MyPtr; }
		operator value_type&() const { **this; }
		bool operator !() const { return MyPtr == NULL; }	
	};

	
	
	//RefcountablePointer casters (use as P parameter for RefcountablePointer)

	template<class V> //value type
	class Caster_static
	{
	public:
		typedef Caster_static Pointer_type;
	protected:
		typedef V value_type; //the RefcountableValue we are referring
		typedef value_type* stored_type; //the RefcountableValue we are storing
		typedef void* key_type; //the type we use as reverse searc key
		
		template<class U>
		static value_type* _convert(const U& u) 
		{ return static_cast<value_type*>(&*u);	}

		static key_type _key(const stored_type& _v) { return static_cast<key_type>(_v); } //get the key
	};

	template<class V> //value type
	class Caster_dynamic
	{
	public:
		typedef Caster_dynamic Pointer_type;
	protected:
		typedef V value_type; //the RefcountableValue we are referring
		typedef value_type* stored_type; //the RefcountableValue we are storing
		typedef void* key_type; //the type we use as reverse searc key
		
		template<class U>
		static value_type* _convert(const U& u) 
		{ return dynamic_cast<value_type*>(&*u);	}

		static key_type _key(const stored_type& _v) { return dynamic_cast<key_type>(_v); } //get the key
	};

	template<class V> //value type
	class Caster_c_style
	{
	public:
		typedef Caster_c_style Pointer_type;
	protected:
		typedef V value_type; //the RefcountableValue we are referring
		typedef value_type* stored_type; //the RefcountableValue we are storing
		typedef void* key_type; //the type we use as reverse searc key
		
		template<class U>
		static value_type* _convert(const U& u) 
		{ return (value_type*)&*u;	}

		static key_type _key(const stored_type& _v) { return (key_type)(_v); } //get the key
	};


}}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Italy Italy
Born and living in Milan (Italy), I'm an engineer in electronics actually working in the ICT department of an important oil/gas & energy company as responsible for planning and engineering of ICT infrastructures.
Interested in programming since the '70s, today I still define architectures for the ICT, deploying dedicated specific client application for engineering purposes, working with C++, MFC, STL, and recently also C# and D.

Comments and Discussions