Commit before breaking everything
[matches/honours.git] / research / transmission_spectroscopy / TOF / Win32++ / include / shared_ptr.h
1 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF\r
2 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\r
3 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\r
4 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\r
5 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
6 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
7 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
8 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\r
9 // OR OTHER DEALINGS IN THE SOFTWARE.\r
10 //\r
11 // This software was developed from code available in the public domain\r
12 // and has no copyright.\r
13 \r
14 \r
15 // About Shared_Ptr:\r
16 // Shared_Ptr wraps a reference-counted smart pointer around a dynamically\r
17 // allocated object. Unlike auto_ptr, the Shared_Ptr can be used as a smart\r
18 // pointer for objects stored in containers like std::vector. Do not use\r
19 // Shared_Ptr (or shared_ptr or auto_ptr) for dynamically allocated arrays.\r
20 // See below for advice on how to wrap dynamically allocated arrays in a\r
21 // vector.\r
22 //\r
23 // The next standard of C++ will also contain a shared_ptr. Some modern\r
24 // compilers already have a shared_ptr available as std::tr1::shared_ptr. If\r
25 // your compiler already provides a shared_ptr, or if you have Boost, you\r
26 // should use that smart pointer instead. This class has been provided for\r
27 // those users who don't have easy access to an "official" shared_ptr.\r
28 // Note that this class is "Shared_Ptr", a slightly different name to the\r
29 // future "shared_ptr" to avoid naming conflicts.\r
30 \r
31 // Advantages of Shared_Ptr (or shared_ptr where available):\r
32 //  - Shared_Ptr can be safely copied. This makes then suitable for containers.\r
33 //  - Shared_Ptr automatically calls delete for the wrapped pointer when\r
34 //     its last copy goes out of scope.\r
35 //  - Shared_Ptr simplifies exception safety.\r
36 //\r
37 // Without smart pointers, it can be quite challenging to ensure that every\r
38 // dynamically allocated pointer (i.e. use of new) is deleted in the event of\r
39 // all possible exceptions. In addition to the exceptions we throw ourselves,\r
40 // "new" itself will throw an exception it it fails, as does the STL (Standard\r
41 // Template Library which includes vector and string). Without smart pointers\r
42 // we often need to resort to additional try/catch blocks simply to avoid\r
43 // memory leaks when exceptions occur.\r
44 \r
45 // Examples:\r
46 //  Shared_Ptr<CWnd> w1(new CWnd);\r
47 //   or\r
48 //  Shared_Ptr<CWnd> w1 = new CWnd;\r
49 //   or\r
50 //  typedef Shared_Ptr<CWnd> CWndPtr;\r
51 //  CWndPtr w1 = new CWnd;\r
52 //   or\r
53 //  typedef Shared_Ptr<CWnd> CWndPtr;\r
54 //  CWndPtr w1(new CWnd);\r
55 //\r
56 //  And with a vector\r
57 //  typedef Shared_Ptr<CWnd> CWndPtr;\r
58 //  std::vector<CWndPtr> MyVector;\r
59 //  MyVector.push_back(new CWnd);\r
60 //   or\r
61 //  typedef Shared_Ptr<CWnd> CWndPtr;\r
62 //  CWnd* pWnd = new CWnd;\r
63 //  std::vector<CWndPtr> MyVector;\r
64 //  MyVector.push_back(pWnd);\r
65 //\r
66 \r
67 // How to handle dynamically allocated arrays:\r
68 // While we could create a smart pointer for arrays, we don't need to because\r
69 // std::vector already handles this for us. Consider the following example:\r
70 //    int nLength = ::GetWindowTextLength(m_hWnd);\r
71 //        pTChar = new TCHAR[nLength+1];\r
72 //        memset(pTChar, 0, (nLength+1)*sizeof(TCHAR));\r
73 //        ::GetWindowText(m_hWnd, m_pTChar, nLength+1);\r
74 //    ....\r
75 //    delete[] pTChar;\r
76 //\r
77 // This can be improved by using a vector instead of an array\r
78 //    int nLength = ::GetWindowTextLength(m_hWnd);\r
79 //    std::vector<TCHAR> vTChar( nLength+1, _T('\0') );\r
80 //    TCHAR* pTCharArray = &vTChar.front();\r
81 //    ::GetWindowText(m_hWnd, pTCharArray, nLength+1);\r
82 //\r
83 // This works because the memory in a vector is always contiguous. Note that\r
84 // this is NOT always true of std::string.\r
85 \r
86 \r
87 // Summing up:\r
88 // In my opinion, "naked" pointers for dynamically created objects should be \r
89 // avoided in modern C++ code. That's to say that calls to "new" should be \r
90 // wrapped in some sort of smart pointer wherever possible. This eliminates \r
91 // the possibility of memory leaks (particularly in the event of exceptions). \r
92 // It also elminiates the need for delete in user's code.\r
93 \r
94 #ifndef _WIN32XX_SHARED_PTR_\r
95 #define _WIN32XX_SHARED_PTR_\r
96 \r
97 namespace Win32xx\r
98 {\r
99 \r
100         template <class T1>\r
101         class Shared_Ptr\r
102         {\r
103         public:\r
104                 Shared_Ptr() : m_ptr(NULL), m_count(NULL) { }\r
105                 Shared_Ptr(T1 * p) : m_ptr(p), m_count(NULL)\r
106                 {\r
107                         try\r
108                         {\r
109                                 if (m_ptr) m_count = new long(0);\r
110                 inc_ref();\r
111                         }\r
112                         // catch the unlikely event of 'new long(0)' throwing an exception\r
113                         catch (const std::bad_alloc&)\r
114                         {\r
115                                 delete m_ptr;\r
116                                 throw;\r
117                         }\r
118                 }\r
119                 Shared_Ptr(const Shared_Ptr& rhs) : m_ptr(rhs.m_ptr), m_count(rhs.m_count) { inc_ref(); }\r
120                 ~Shared_Ptr()\r
121                 {\r
122                         if(m_count && 0 == dec_ref())\r
123                         {\r
124                                 // Note: This code doesn't handle a pointer to an array.\r
125                                 //  We would need delete[] m_ptr to handle that.\r
126                                 delete m_ptr;\r
127                                 delete m_count;\r
128                         }\r
129                 }\r
130 \r
131                 T1* get() const { return m_ptr; }\r
132                 long use_count() const { return m_count? *m_count : 0; }\r
133                 bool unique() const { return (m_count && (*m_count == 1)); }\r
134 \r
135                 void swap(Shared_Ptr& rhs)\r
136                 {\r
137                    std::swap(m_ptr, rhs.m_ptr);\r
138                    std::swap(m_count, rhs.m_count);\r
139                 }\r
140 \r
141                 Shared_Ptr& operator=(const Shared_Ptr& rhs)\r
142                 {\r
143                          Shared_Ptr tmp(rhs);\r
144                          this->swap(tmp);\r
145                          return *this;\r
146                 }\r
147 \r
148                 T1* operator->() const\r
149                 {\r
150                         assert(m_ptr);\r
151                         return m_ptr;\r
152                 }\r
153 \r
154                 T1& operator*() const\r
155                 {\r
156                         assert (m_ptr);\r
157                         return *m_ptr;\r
158                 }\r
159 \r
160                 bool operator== (const Shared_Ptr& rhs) const\r
161                 {\r
162                         return ( *m_ptr == *rhs.m_ptr);\r
163                 }\r
164 \r
165                 bool operator!= (const Shared_Ptr& rhs) const\r
166                 {\r
167                         return ( *m_ptr != *rhs.m_ptr);\r
168                 }\r
169 \r
170                 bool operator< (const Shared_Ptr& rhs) const\r
171                 {\r
172                         return ( *m_ptr < *rhs.m_ptr );\r
173                 }\r
174 \r
175                 bool operator> (const Shared_Ptr& rhs) const\r
176                 {\r
177                         return ( *m_ptr > *rhs.m_ptr );\r
178                 }\r
179 \r
180         private:\r
181                 void inc_ref()\r
182                 {\r
183                         if(m_count)\r
184                                 InterlockedIncrement(m_count);\r
185                 }\r
186 \r
187                 int  dec_ref()\r
188                 {\r
189                         assert (m_count);\r
190                         return InterlockedDecrement(m_count);\r
191                 }\r
192 \r
193                 T1* m_ptr;\r
194                 long* m_count;\r
195         };\r
196 \r
197 }\r
198 \r
199 #endif  // _WIN32XX_SHARED_PTR_\r

UCC git Repository :: git.ucc.asn.au