summaryrefslogtreecommitdiffstats
path: root/mmc_updater/depends/win32cpp/shared_ptr.h
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2013-12-02 00:55:24 +0100
committerPetr Mrázek <peterix@gmail.com>2013-12-02 00:55:24 +0100
commit6aa9bd0f77dcb5128167fae62e32aa5252fe85c6 (patch)
tree632994a61888929af9289927d338bd19a2b3f32c /mmc_updater/depends/win32cpp/shared_ptr.h
parent613699b3626aea750093ab7eaaeccaa28c0e87c6 (diff)
downloadMultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar
MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.gz
MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.lz
MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.xz
MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.zip
Renew the updater branch
Now with some actual consensus on what the updater will do!
Diffstat (limited to 'mmc_updater/depends/win32cpp/shared_ptr.h')
-rw-r--r--mmc_updater/depends/win32cpp/shared_ptr.h199
1 files changed, 199 insertions, 0 deletions
diff --git a/mmc_updater/depends/win32cpp/shared_ptr.h b/mmc_updater/depends/win32cpp/shared_ptr.h
new file mode 100644
index 00000000..0d2f8b0c
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/shared_ptr.h
@@ -0,0 +1,199 @@
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// This software was developed from code available in the public domain
+// and has no copyright.
+
+
+// About Shared_Ptr:
+// Shared_Ptr wraps a reference-counted smart pointer around a dynamically
+// allocated object. Unlike auto_ptr, the Shared_Ptr can be used as a smart
+// pointer for objects stored in containers like std::vector. Do not use
+// Shared_Ptr (or shared_ptr or auto_ptr) for dynamically allocated arrays.
+// See below for advice on how to wrap dynamically allocated arrays in a
+// vector.
+//
+// The next standard of C++ will also contain a shared_ptr. Some modern
+// compilers already have a shared_ptr available as std::tr1::shared_ptr. If
+// your compiler already provides a shared_ptr, or if you have Boost, you
+// should use that smart pointer instead. This class has been provided for
+// those users who don't have easy access to an "official" shared_ptr.
+// Note that this class is "Shared_Ptr", a slightly different name to the
+// future "shared_ptr" to avoid naming conflicts.
+
+// Advantages of Shared_Ptr (or shared_ptr where available):
+// - Shared_Ptr can be safely copied. This makes then suitable for containers.
+// - Shared_Ptr automatically calls delete for the wrapped pointer when
+// its last copy goes out of scope.
+// - Shared_Ptr simplifies exception safety.
+//
+// Without smart pointers, it can be quite challenging to ensure that every
+// dynamically allocated pointer (i.e. use of new) is deleted in the event of
+// all possible exceptions. In addition to the exceptions we throw ourselves,
+// "new" itself will throw an exception it it fails, as does the STL (Standard
+// Template Library which includes vector and string). Without smart pointers
+// we often need to resort to additional try/catch blocks simply to avoid
+// memory leaks when exceptions occur.
+
+// Examples:
+// Shared_Ptr<CWnd> w1(new CWnd);
+// or
+// Shared_Ptr<CWnd> w1 = new CWnd;
+// or
+// typedef Shared_Ptr<CWnd> CWndPtr;
+// CWndPtr w1 = new CWnd;
+// or
+// typedef Shared_Ptr<CWnd> CWndPtr;
+// CWndPtr w1(new CWnd);
+//
+// And with a vector
+// typedef Shared_Ptr<CWnd> CWndPtr;
+// std::vector<CWndPtr> MyVector;
+// MyVector.push_back(new CWnd);
+// or
+// typedef Shared_Ptr<CWnd> CWndPtr;
+// CWnd* pWnd = new CWnd;
+// std::vector<CWndPtr> MyVector;
+// MyVector.push_back(pWnd);
+//
+
+// How to handle dynamically allocated arrays:
+// While we could create a smart pointer for arrays, we don't need to because
+// std::vector already handles this for us. Consider the following example:
+// int nLength = ::GetWindowTextLength(m_hWnd);
+// pTChar = new TCHAR[nLength+1];
+// memset(pTChar, 0, (nLength+1)*sizeof(TCHAR));
+// ::GetWindowText(m_hWnd, m_pTChar, nLength+1);
+// ....
+// delete[] pTChar;
+//
+// This can be improved by using a vector instead of an array
+// int nLength = ::GetWindowTextLength(m_hWnd);
+// std::vector<TCHAR> vTChar( nLength+1, _T('\0') );
+// TCHAR* pTCharArray = &vTChar.front();
+// ::GetWindowText(m_hWnd, pTCharArray, nLength+1);
+//
+// This works because the memory in a vector is always contiguous. Note that
+// this is NOT always true of std::string.
+
+
+// Summing up:
+// In my opinion, "naked" pointers for dynamically created objects should be
+// avoided in modern C++ code. That's to say that calls to "new" should be
+// wrapped in some sort of smart pointer wherever possible. This eliminates
+// the possibility of memory leaks (particularly in the event of exceptions).
+// It also elminiates the need for delete in user's code.
+
+#ifndef _WIN32XX_SHARED_PTR_
+#define _WIN32XX_SHARED_PTR_
+
+namespace Win32xx
+{
+
+ template <class T1>
+ class Shared_Ptr
+ {
+ public:
+ Shared_Ptr() : m_ptr(NULL), m_count(NULL) { }
+ Shared_Ptr(T1 * p) : m_ptr(p), m_count(NULL)
+ {
+ try
+ {
+ if (m_ptr) m_count = new long(0);
+ inc_ref();
+ }
+ // catch the unlikely event of 'new long(0)' throwing an exception
+ catch (const std::bad_alloc&)
+ {
+ delete m_ptr;
+ throw;
+ }
+ }
+ Shared_Ptr(const Shared_Ptr& rhs) : m_ptr(rhs.m_ptr), m_count(rhs.m_count) { inc_ref(); }
+ ~Shared_Ptr()
+ {
+ if(m_count && 0 == dec_ref())
+ {
+ // Note: This code doesn't handle a pointer to an array.
+ // We would need delete[] m_ptr to handle that.
+ delete m_ptr;
+ delete m_count;
+ }
+ }
+
+ T1* get() const { return m_ptr; }
+ long use_count() const { return m_count? *m_count : 0; }
+ bool unique() const { return (m_count && (*m_count == 1)); }
+
+ void swap(Shared_Ptr& rhs)
+ {
+ std::swap(m_ptr, rhs.m_ptr);
+ std::swap(m_count, rhs.m_count);
+ }
+
+ Shared_Ptr& operator=(const Shared_Ptr& rhs)
+ {
+ Shared_Ptr tmp(rhs);
+ this->swap(tmp);
+ return *this;
+ }
+
+ T1* operator->() const
+ {
+ assert(m_ptr);
+ return m_ptr;
+ }
+
+ T1& operator*() const
+ {
+ assert (m_ptr);
+ return *m_ptr;
+ }
+
+ bool operator== (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr == *rhs.m_ptr);
+ }
+
+ bool operator!= (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr != *rhs.m_ptr);
+ }
+
+ bool operator< (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr < *rhs.m_ptr );
+ }
+
+ bool operator> (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr > *rhs.m_ptr );
+ }
+
+ private:
+ void inc_ref()
+ {
+ if(m_count)
+ InterlockedIncrement(m_count);
+ }
+
+ int dec_ref()
+ {
+ assert (m_count);
+ return InterlockedDecrement(m_count);
+ }
+
+ T1* m_ptr;
+ long* m_count;
+ };
+
+}
+
+#endif // _WIN32XX_SHARED_PTR_