Thread: Reference Counting

  1. #1
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034

    Smile Reference Counting

    I've a program where I'm using pointers all over the place. It's starting to run up to 750mb ram so I need to work on the memory management. Currently I'm not deleting any data after using it (just letting it build up). So my options are either use temporary objects which delete at the end of the scope and copy-construct, or use shared_ptr for auto reference counting, or use an internal reference counter?

    I like the idea of not using pointers, but feel copy-constructing everywhere may be inefficient when I could just pass a pointer or reference. If I pass a reference, the object has to guarantee to exist, but I'm using a lot of asynchronous events, so I can't guarantee that. Even if I keep a list or vector, and want to remove the object, I can't know if it's still required for an asynchronous event out there. So I could have it copied for async, or just use reference counting.

    Which leads me to boost::shared_ptr. It's great and all, common, standard. I'm not really fond (syntactically) of wrapping all my classes with it. I could typedef it, but it still requires you use the wrapped class and the typedef at the same time.

    Seems like many custom implementations use internal reference counts, build into the class or superclass, and from what I can assume a global variable. So the syntax doesn't need to be altered or increase complexity, but you still gain the benefits of memory management. Is there a boost or std way of doing this? or play it safe and stick with shared_ptr?

    P.S. I'm taking out a lot of rows (1000) out of a database, converting them to objects, using them asynchronously, then ignoring them for the rest of the program and fetching 1000 more.

    Thanks, sorry for tl;dr;

    Edit: Okay so I've never seriously used smart pointers, but what's to stop me from doing something like this?

    Code:
    #include <boost/shared_ptr.hpp>
    #include <boost/lexical_cast.hpp>
    
    #include <iostream>
    #include <vector>
    #include <string>
    
    #include <windows.h>
    
    class impl_name
    {
        public: std::string first;
        public: std::string last;
    
        public: impl_name() : first("john"), last("doe")
        {
    		
        }
    
        public: impl_name(std::string const& first, std::string const& last) : first(first), last(last)
        {
    		
        }
    };
    
    class name
    {
        private: boost::shared_ptr<impl_name> data;
    
        public: name() : data(new impl_name())
        {
            
        }
    
        public: name(std::string const& first, std::string const& last) : data(new impl_name(first, last))
        {
           
        }
    
        //copy constructor
        public: name(const name& n) : data(n.data)
        {
            
        }
    
        public: impl_name* operator->()
        {
            return data.get();
        }
    };
    
    void x()
    {
        std::vector<name> names;
    
        Sleep(5000);
    
        std::cout << "Creating..." << std::endl << std::endl;
    
        for(int i = 0; i < 1000000; ++i)
            names.push_back(name("john" + boost::lexical_cast<std::string>(i), "doe"));
    
        Sleep(5000);
    
        std::cout << "Displaying 10..." << std::endl << std::endl;
    
        for(std::vector<name>::iterator i = names.begin(), l = names.end(); i != names.begin() + 10; ++i)
            std::cout << (*i)->first << " " << (*i)->last << std::endl;
    
        std::cout << std::endl;
    
        Sleep(5000);
    
        std::cout << "Erasing..." << std::endl << std::endl;
    
        for(int i = 0; i < 1000000; ++i)
            names.pop_back();
    
        names.empty();
    }
    
    int main()
    {
        x();
    
        std::cin.get();
    }
    Yeah, all I did was wrap the real "impl_name" class with "name" and relay the constructors/operators to the intrusive_ptr of impl_name. That way I can use the class normally, without having to worry about intrusive_ptr or shared_ptr or anything in the usage code. Or is that just asking too much? Seems like all signs point to being REQUIRED to use smart pointers EVERYWHERE in usage code no matter what. It's the only way? Without a garbage collector like Java. I remember seeing source code from Half-Life that overloaded operator new/delete and some other stuff, maybe that was for smart pointers, or maybe just controlling it's memory allocation stack/heap/etc. I dunno.
    Last edited by Dae; 08-13-2009 at 06:30 AM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Smart pointers carry very little overhead and they work just like normal pointers. All you have to do is use the smart pointer class as the type and away you go. It couldn't be simpler.
    And your code is a pretty big failure. The idea of a reference counted pointer is that it automatically increases/decreases the ref count as needed. Your code does no such thing, since it doesn't even have any constructors or destructors.

    Try the smart pointers first.
    And honestly, not freeing the resources you were using is just plain sloppy and stupid. There is no excuse for not doing it. If you don't want to do it manually, you can always use smart pointers.
    Last edited by Elysia; 08-13-2009 at 05:39 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Elysia View Post
    Smart pointers carry very little overhead and they work just like normal pointers. All you have to do is use the smart pointer class as the type and away you go. It couldn't be simpler.
    And your code is a pretty big failure. The idea of a reference counted pointer is that it automatically increases/decreases the ref count as needed. Your code does no such thing, since it doesn't even have any constructors or destructors.

    Try the smart pointers first.
    And honestly, not freeing the resources you were using is just plain sloppy and stupid. There is no excuse for not doing it. If you don't want to do it manually, you can always use smart pointers.
    I know Elysia. You're right. I was just writing down a bunch of classes as they came into my head and didn't want to bother with smart pointers until I actually had something that worked. It was sort of like pseudo-code, and you don't need smart pointers when you write pseudo-code.

    Also how is my code failure? I am using smart pointers. I'm using boost::intrusive_ptr, which calls intrusive_ptr_add_ref/intrusive_ptr_release, which reference counts and destroys the object when it's finished. I checked in the task manager (all columns enabled). The example works. Run it. It probably has a lot of gotchas (issues) though. Maybe I should just give into the power of using smart pointers normally. It's not that bad. It's actually simple. Just not as simple as it could be (in say, a different language). I did manage to find a project which uses almost the same thing as me using boost::intrusive_ptr: Second Life Viewer: llhttpclient.cpp Source File
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Dae View Post
    Also how is my code failure? I am using smart pointers. I'm using boost::intrusive_ptr, which calls intrusive_ptr_add_ref/intrusive_ptr_release, which reference counts and destroys the object when it's finished. I checked in the task manager (all columns enabled). The example works. Run it. It probably has a lot of gotchas (issues) though. Maybe I should just give into the power of using smart pointers normally. It's not that bad. It's actually simple. Just not as simple as it could be (in say, a different language). I did manage to find a project which uses almost the same thing as me using boost::intrusive_ptr: Second Life Viewer: llhttpclient.cpp Source File
    Ah, sorry, I missed that. I was mostly looking at the reference classes you had, which doesn't do much.

    But the main point is that you don't have to do a lot of extra engineering to get your pointers to behave like normal pointers, because smart pointers behave like normal pointers.
    You just have to pass around the actual container and not raw pointers and it works
    But is that answer enough to your question?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Elysia View Post
    Ah, sorry, I missed that. I was mostly looking at the reference classes you had, which doesn't do much.

    But the main point is that you don't have to do a lot of extra engineering to get your pointers to behave like normal pointers, because smart pointers behave like normal pointers.
    You just have to pass around the actual container and not raw pointers and it works
    But is that answer enough to your question?
    I revisited boost::shared_ptr, and after I got it worked it turns out it's exactly what I already had -- but simpler. Recheck it, it's easier to see what I'm saying, and do you still think there's anything wrong with using smart pointers exactly how you said, but instead.. wrapping them so usage code is easier to... use, and read?
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Typedefing something like
    typedef boost::shared_ptr sptr;
    and using that type instead of boost::shared_ptr to make it it easier to type and read? I don't think there's anything wrong with that. It doesn't interfere with the code in any way either.

    I think your updated example will work, too.
    No memory leaks. No hassle.
    Last edited by Elysia; 08-13-2009 at 06:33 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Elysia View Post
    Typedefing something like
    typedef boost::shared_ptr sptr;
    and using that type instead of boost::shared_ptr to make it it easier to type and read? I don't think there's anything wrong with that. It doesn't interfere with the code in any way either.
    I was just gonna reply about that. It only interferes in one way: instead of name(first, last) it's pname(new name(first, last)) and using pname everywhere instead of name. In a perfect world, every pointer * (or new operator) would be a smart pointer (compiler flag).

    I noticed you can do something interesting this way though. Make the impl_name constructors private, and a friend of name. So the only way to use the class is the smart way. Kind of dumb to prohibit access to the real class though, I assume?

    And yes, your answer is good. I was actually curious if there was an existing smart pointer to magically convert any class into a smart pointer class. I wasn't trying to implement my own. I very much appreciate the work that goes into these libraries, and very much know that they are much better than what I could write.
    Last edited by Dae; 08-13-2009 at 06:44 AM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Dae View Post
    I was just gonna reply about that. It only interferes in one way: instead of name(first, last) it's pname(new name(first, last)) and using pname everywhere instead of name. In a perfect world, every pointer * (or new operator) would be a smart pointer (compiler flag).
    Ah yes, this is actually something that bugs me - the constructors for pointers (T*) is actually explicit! This is rather annoying since you'd have to construct a temporary object explicitly in order to make it work.
    If it interests you, though, I actually made my own smart pointer that is supposed to be exception safe and has all the features you'd expect of a smart pointer (including some nice things the boost pointer doesn't have).
    And most importantly, it removes the annoying explicit constructor. I could show it to you if you want. I think at least one thing might not work properly (operator bool), but it's no big deal.

    I noticed you can do something interesting this way though. Make the impl_name constructors private, and a friend of name. So the only way to use the class is the smart way. Kind of dumb to prohibit access to the real class though, I assume?
    I think I would consider hiding impl_name inside name and make it private. That way you don't need friends and the outside world can't access it. Perfect, right?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Elysia View Post
    Ah yes, this is actually something that bugs me - the constructors for pointers (T*) is actually explicit! This is rather annoying since you'd have to construct a temporary object explicitly in order to make it work.
    If it interests you, though, I actually made my own smart pointer that is supposed to be exception safe and has all the features you'd expect of a smart pointer (including some nice things the boost pointer doesn't have).
    And most importantly, it removes the annoying explicit constructor. I could show it to you if you want. I think at least one thing might not work properly (operator bool), but it's no big deal.
    That's what I was getting at - the temporary object (which to me looks like over-complication, given you're constructing 2 objects pname/name). I guess they could get around that with a bunch of templates/macros (for arguments) like with boost::tuples. Maybe (I don't know). I'd be most interested in seeing if your smart pointers are a better fit.

    Quote Originally Posted by Elysia View Post
    I think I would consider hiding impl_name inside name and make it private. That way you don't need friends and the outside world can't access it. Perfect, right?
    Ya, I think if you were to do something like that it would be a bit of extra work (I just realized boost::bind/boost::function/functors would require some additional redirecting - needs more planning), but in the long run it would pay off. Good stuff.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Alright, here goes:
    Code:
    #ifndef MAD_SHARED_PTR_175451_H
    #define MAD_SHARED_PTR_175451_H
    
    #include <boost/cstdint.hpp>
    #include <memory>
    #include <assert.h>
    
    #if defined(THREAD_SAFE) || defined(THREAD_STORAGE)
    // Requirements: Windows Vista
    #undef _WIN32_WINNT
    #undef WINVER
    #define _WIN32_WINNT 0x600
    #define WINVER 0x600
    #include <Windows.h>
    #endif
    
    const int nullptr = NULL;
    #pragma warning(push)
    #pragma warning(disable: 4355)
    
    template<typename T> T* mad_ptr_clone(const T* pOld) { return smad_ptr_int<T, boost::is_polymorphic<T>::value>::Clone(pOld); }
    
    template<typename T, bool Polymorphic> struct smad_ptr_int
    {
    	static T* Clone(const T* pOld) { return pOld->Clone(); } // IsPolymorphic = yes
    };
    template<typename T> struct smad_ptr_int<T, false>
    {
    	static T* Clone(const T* pOld) { return new T(*pOld); } // IsPolymorphic = no
    };
    
    template<int N> struct ptr_bits { /*typedef current_amount_of_bits_not_supported rf_type;*/ };
    template<> struct ptr_bits<32> { typedef boost::uint32_t rf_type; };
    template<> struct ptr_bits<64> { typedef boost::uint64_t rf_type; };
    
    #ifdef THREAD_SAFE
    template<int Bits> class ptr_thread_safe { };
    template<> class ptr_thread_safe<32> 
    {
    public:
    	static void Increment(void* p) { InterlockedIncrement((LONG*)p); }
    	static void Decrement(void* p) { InterlockedDecrement((LONG*)p); }
    };
    template<> class ptr_thread_safe<64> 
    {
    public:
    	static void Increment(void* p) { InterlockedIncrement64((LONGLONG*)p); }
    	static void Decrement(void* p) { InterlockedDecrement64((LONGLONG*)p); }
    };
    #endif
    
    template<int Bits> class ptr_thread_dangerous
    {
    public:
    	template<typename T> static void Increment(T* p) { (*p)++; }
    	template<typename T> static void Decrement(T* p) { (*p)--; }
    };
    
    template<typename T, template<int> class thread_safety = ptr_thread_dangerous, int Bits = 32>
    class mad_shared_ptr
    {
    protected:
    	typedef void (mad_shared_ptr::* bool_type)() const;
    	template<typename T, int Bits> struct sptr
    	{
    		template<typename T> class deleter_base { public: virtual void destroy(T* p) = 0; };
    		template<typename T, typename deleter_t> class deleter: public deleter_base<T>
    		{
    		public:
    			deleter(deleter_t delete_fnc): m_delete_fnc(delete_fnc) { }
    			virtual void destroy(T* p) { m_delete_fnc(p); }
    
    		private:
    			deleter_t m_delete_fnc;
    		};
    
    		sptr(): p(nullptr), RefCount(0), pDeleter(nullptr) { }
    
    		T* p;
    		typename ptr_bits<Bits>::rf_type RefCount;
    		deleter_base<T>* pDeleter;
    	};
    	typedef sptr<T, Bits> ptr_t;
    
    public:
    	mad_shared_ptr(): m_ptr(nullptr) { }
    	template<typename Other> mad_shared_ptr(Other* p): m_ptr(nullptr) { *this = p; }
    	template<typename Other, typename Deleter> mad_shared_ptr(Other* p, Deleter delete_fnc): m_ptr(nullptr) { ConstructWithDeleter(p, delete_fnc); }
    	mad_shared_ptr(const mad_shared_ptr& rhs): m_ptr(nullptr) { *this = rhs; }
    	template<typename Other> mad_shared_ptr(const mad_shared_ptr<Other>& rhs): m_ptr(nullptr) { *this = rhs; }
    
    protected:
    	mad_shared_ptr(ptr_t* ptr): m_ptr(ptr) { }
    	template<typename Other> mad_shared_ptr(Other* p, ptr_t* ptr): m_ptr(ptr) { *this = p; }
    	template<typename Other, typename Deleter> mad_shared_ptr(Other* p, Deleter delete_fnc, ptr_t* ptr): m_ptr(ptr) { ConstructWithDeleter(p, delete_fnc); }
    
    	template<typename Other, typename Deleter> void ConstructWithDeleter(Other* p, Deleter delete_fnc)
    	{
    		std::auto_ptr< ptr_t::deleter_base<T> > pDeleter( new ptr_t::deleter<T, Deleter>(delete_fnc) );
    		//*this = p;
    		if (m_ptr)
    			Assign(p, m_ptr, nullptr);
    		else
    			Assign(p, new ptr_t, m_ptr);
    		m_ptr->pDeleter = pDeleter.release();
    	}
    
    public:
    	~mad_shared_ptr() { DecRefCount(m_ptr); }
    	bool empty() { return (m_ptr == nullptr || m_ptr->p == nullptr); }
    	bool unique() const { return (m_ptr->RefCount == 1); }
    	void make_unique()
    	{
    		if (unique())
    			return;
    		
    		std::auto_ptr<ptr_t> pNewPtr(new ptr_t);
    		pNewPtr->p = mad_ptr_clone(m_ptr->p);
    		pNewPtr->RefCount = 1;
    		pNewPtr->pDeleter = m_ptr->pDeleter;
    		DecRefCount(m_ptr);
    		m_ptr = pNewPtr.release();
    	}
    	void release()
    	{
    		DecRefCount();
    		m_p = nullptr;
    		m_RefCount = nullptr;
    		m_deleter = nullptr;
    	}
    	template<typename Other> mad_shared_ptr& operator = (Other* rhs)
    	{
    		if (m_ptr && rhs == m_ptr->p)
    			return *this;
    
    		/*std::auto_ptr<ptr_t>*/ptr_t* pNewPtr( AllocPtr() );
    		Assign(rhs, pNewPtr, m_ptr);
    
    		//pNewPtr->p = rhs;
    		//pNewPtr->RefCount++;
    		//m_ptr = pNewPtr.release();
    
    		//DecRefCount(pOldPtr);
    		return *this;
    	}
    	template<typename Other>
    	void Assign(Other* rhs, ptr_t* NewPtr, ptr_t* OldPtr)
    	{
    		std::auto_ptr<ptr_t> pNewPtr(NewPtr);
    
    		pNewPtr->p = rhs;
    		pNewPtr->RefCount++;
    		m_ptr = pNewPtr.release();
    
    		DecRefCount(OldPtr);
    	}
    	mad_shared_ptr& operator = (const mad_shared_ptr& rhs)
    	{
    		return operator = <T>(rhs);
    	}
    	template<typename Other> mad_shared_ptr& operator = (const mad_shared_ptr<Other>& rhs)
    	{
    		if (rhs == *this)
    			return *this;
    		DecRefCount(m_ptr);
    		m_ptr = rhs.m_ptr;
    		IncRefCount(m_ptr);
    		return *this;
    	}
    	virtual T& operator * () const { assert(m_ptr); return *m_ptr->p; }
    	T* operator -> () const { assert(m_ptr); return m_ptr->p; }
    
    	template<typename rhs_t>
    	friend bool operator == (const mad_shared_ptr& lhs, const mad_shared_ptr<rhs_t>& rhs)
    	{
    		return (lhs.m_ptr == rhs.m_ptr);
    	}
    
    	template<typename rhs_t>
    	friend bool operator != (const mad_shared_ptr& lhs, const mad_shared_ptr<rhs_t>& rhs)
    	{
    		return !(lhs == rhs);
    	}
    
    	operator bool_type() const 
    	{
    		return m_ptr && m_ptr->p ? &mad_shared_ptr::this_type_does_not_support_comparisons : nullptr;
    	}
    
    protected:
    	void IncRefCount(sptr<T, Bits>* ptr)
    	{
    		thread_safety<Bits>::Increment(&ptr->RefCount);
    	}
    
    	void DecRefCount(sptr<T, Bits>*& ptr)
    	{
    		if (ptr == nullptr)
    			return;
    		thread_safety<Bits>::Decrement(&ptr->RefCount);
    		if (ptr->RefCount == 0)
    		{
    			if (ptr->pDeleter)
    				ptr->pDeleter->destroy(ptr->p);
    			else
    				delete ptr->p;
    			delete ptr;
    			ptr = nullptr;
    		}
    	}
    
    	void this_type_does_not_support_comparisons() const {}
    
    	ptr_t* AllocPtr() { return new ptr_t; }
    	ptr_t* m_ptr;
    };
    
    #ifdef THREAD_STORAGE
    template<typename T, template<int> class thread_safety = ptr_thread_dangerous, int Bits = 32>
    class mad_thread_storage_ptr: public mad_shared_ptr<T, thread_safety, Bits>
    {
    public:
    	mad_thread_storage_ptr(): mad_shared_ptr(new T, boost::bind(&mad_thread_storage_ptr::DeleteTlsStorage, this), AllocPtr()) { }
    	mad_thread_storage_ptr(T Value): mad_shared_ptr(new T(Value), boost::bind(&mad_thread_storage_ptr::DeleteTlsStorage, this), AllocPtr()) { }
    	virtual T& operator * () { return *GetTlsStorage()->p; }
    	
    protected:
    #ifdef _DEBUG
    #define MAD_ASSERT(x) assert(x)
    #else
    #define MAD_ASSERT(x) x
    #endif
    	ptr_t* AllocPtr()
    	{
    		ptr_t* p = new ptr_t; 
    		NewTlsStorage();
    		SetTlsStorage(p);
    		return p;
    	}
    	void NewTlsStorage() { m_StorageId = TlsAlloc(); MAD_ASSERT(m_StorageId != TLS_OUT_OF_INDEXES); }
    	void SetTlsStorage(ptr_t* p) { MAD_ASSERT( TlsSetValue(m_StorageId, p) ); }
    	void DeleteTlsStorage() { MAD_ASSERT( TlsFree(m_StorageId) ); }
    	ptr_t* GetTlsStorage() 
    	{
    		ptr_t* p = static_cast<ptr_t*>(TlsGetValue(m_StorageId)); 
    		MAD_ASSERT(p != NULL && GetLastError() == ERROR_SUCCESS);
    		return p;
    	}
    	DWORD m_StorageId;
    };
    #endif
    
    #pragma warning(pop)
    
    //#define sptr mad_shared_ptr
    
    #endif // MAD_SHARED_PTR_175451_H
    It currently relies on boost. Is that okay?
    I like the cstdint header. I might get rid of it in the future. I don't know.

    As a side note, it contains the smart pointer and a thread storage class. The smart pointer can be thread safe or thread dangerous. Thread safety requires Windows Vista. The thread storage class also requires Windows.
    Both are optional and can be included or not through two macros, as you can see.

    And it removes the explicit constructors, so this is possible:
    Code:
    mad_shared_ptr<int> myfunc()
    {
        return new int;
    }
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Elysia View Post
    It currently relies on boost. Is that okay?
    I think I jumped on the boost bandwagon a long time ago.


    Quote Originally Posted by Elysia View Post
    As a side note, it contains the smart pointer and a thread storage class. The smart pointer can be thread safe or thread dangerous. Thread safety requires Windows Vista. The thread storage class also requires Windows.

    Both are optional and can be included or not through two macros, as you can see.
    Oh yes, I see, increment/decrement unprotected. I'd probably want thread safety eventually, but I don't need it now.

    Quote Originally Posted by Elysia View Post
    And it removes the explicit constructors, so this is possible:
    Code:
    mad_shared_ptr<int> myfunc()
    {
        return new int;
    }
    Nice. Well, it's bed for me, tomorrow I'm gonna try something out. Now I have a few ideas on where to go from here.

    Thanks
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. C OpenGL Compiler Error?
    By Matt3000 in forum C Programming
    Replies: 12
    Last Post: 07-07-2006, 04:42 PM
  5. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 10:18 AM