diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp new file mode 100644 index 0000000..0a22e64 --- /dev/null +++ b/include/boost/detail/atomic_count.hpp @@ -0,0 +1,122 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/atomic_count.hpp - thread/SMP safe reference counter +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// typedef boost::detail::atomic_count; +// +// atomic_count a(n); +// +// (n is convertible to long) +// +// Effects: Constructs an atomic_count with an initial value of n +// +// a; +// +// Returns: (long) the current value of a +// +// ++a; +// +// Effects: Atomically increments the value of a +// Returns: nothing +// +// --a; +// +// Effects: Atomically decrements the value of a +// Returns: (long) zero if the new value of a is zero, +// unspecified non-zero value otherwise (usually the new value) +// +// Important note: when --a returns zero, it must act as a +// read memory barrier (RMB); i.e. the calling thread must +// have a synchronized view of the memory +// +// On Intel IA-32 (x86) memory is always synchronized, so this +// is not a problem. +// +// On many architectures the atomic instructions already act as +// a memory barrier. +// +// This property is necessary for proper reference counting, since +// a thread can update the contents of a shared object, then +// release its reference, and another thread may immediately +// release the last reference causing object destruction. +// +// The destructor needs to have a synchronized view of the +// object to perform proper cleanup. +// +// Original example by Alexander Terekhov: +// +// Given: +// +// - a mutable shared object OBJ; +// - two threads THREAD1 and THREAD2 each holding +// a private smart_ptr object pointing to that OBJ. +// +// t1: THREAD1 updates OBJ (thread-safe via some synchronization) +// and a few cycles later (after "unlock") destroys smart_ptr; +// +// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization +// with respect to shared mutable object OBJ; OBJ destructors +// are called driven by smart_ptr interface... +// + + +#include + +#ifndef BOOST_HAS_THREADS + +namespace boost +{ + +namespace detail +{ + +typedef long atomic_count; + +} + +} + +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + +#include "atomic_count_win32.hpp" + +#elif defined(linux) || defined(__linux) || defined(__linux__) + +#include "atomic_count_linux.hpp" + +#elif defined(BOOST_HAS_PTHREADS) + +#include "atomic_count_pthreads.hpp" + +#else + +// #warning Unrecognized platform, detail::atomic_count will not be thread safe + +namespace boost +{ + +namespace detail +{ + +typedef long atomic_counter; + +} + +} + +#endif + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_linux.hpp b/include/boost/detail/atomic_count_linux.hpp new file mode 100644 index 0000000..8fd5346 --- /dev/null +++ b/include/boost/detail/atomic_count_linux.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED + +// +// boost/detail/atomic_count_linux.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +// +// On Linux, atomic.h is usually located in /usr/include/asm +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count(long v) + { + atomic_t init = ATOMIC_INIT(v); + value_ = init; + } + + void operator++() + { + atomic_inc(&value_); + } + + long operator--() + { + return !atomic_dec_and_test(&value_); + } + + operator long() const + { + return atomic_read(&value_); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + atomic_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_pthreads.hpp b/include/boost/detail/atomic_count_pthreads.hpp new file mode 100644 index 0000000..eb1dd97 --- /dev/null +++ b/include/boost/detail/atomic_count_pthreads.hpp @@ -0,0 +1,99 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED + +// +// boost/detail/atomic_count_pthreads.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +// +// The generic pthread_mutex-based implementation sometimes leads to +// inefficiencies. Example: a class with two atomic_count members +// can get away with a single mutex. +// +// Define a macro so that users can detect the situation and optimize. +// + +#define BOOST_ATOMIC_COUNT_USES_PTHREADS + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +private: + + class scoped_lock + { + public: + + scoped_lock(pthread_mutex_t & m): m_(m) + { + pthread_mutex_lock(&m_); + } + + ~scoped_lock() + { + pthread_mutex_unlock(&m_); + } + + private: + + pthread_mutex_t & m_; + }; + +public: + + explicit atomic_count(long v): value_(v) + { + pthread_mutex_init(&mutex_, 0); + } + + ~atomic_count() + { + pthread_mutex_destroy(&mutex_); + } + + void operator++() + { + scoped_lock lock(mutex_); + ++value_; + } + + long operator--() + { + scoped_lock lock(mutex_); + return --value_; + } + + operator long() const + { + scoped_lock lock(mutex_); + return value_; + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable pthread_mutex_t mutex_; + long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/detail/atomic_count_win32.hpp new file mode 100644 index 0000000..163a26d --- /dev/null +++ b/include/boost/detail/atomic_count_win32.hpp @@ -0,0 +1,68 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/atomic_count_win32.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +namespace boost +{ + +namespace detail +{ + +// Avoid #including + +namespace win32 +{ +extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement(long volatile *); +extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *); +} + +class atomic_count +{ +public: + + explicit atomic_count(long v): value_(v) + { + } + + long operator++() + { + return win32::InterlockedIncrement(&value_); + } + + long operator--() + { + return win32::InterlockedDecrement(&value_); + } + + operator long() const + { + return value_; + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + volatile long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED diff --git a/include/boost/detail/shared_array_nmt.hpp b/include/boost/detail/shared_array_nmt.hpp new file mode 100644 index 0000000..e5137a3 --- /dev/null +++ b/include/boost/detail/shared_array_nmt.hpp @@ -0,0 +1,135 @@ +#ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED + +// +// detail/shared_array_nmt.hpp - shared_array.hpp without member templates +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include +#include +#include + +#include // for std::ptrdiff_t +#include // for std::swap +#include // for std::less + +namespace boost +{ + +template class shared_array +{ +private: + + typedef detail::atomic_count count_type; + +public: + + typedef T element_type; + + explicit shared_array(T * p = 0): px(p) + { + try // prevent leak if new throws + { + pn = new count_type(1); + } + catch(...) + { + checked_array_delete(p); + throw; + } + } + + ~shared_array() + { + if(--*pn == 0) + { + checked_array_delete(px); + delete pn; + } + } + + shared_array(shared_array const & r) : px(r.px) // never throws + { + pn = r.pn; + ++*pn; + } + + shared_array & operator=(shared_array const & r) + { + shared_array(r).swap(*this); + return *this; + } + + void reset(T * p = 0) + { + shared_array(p).swap(*this); + } + + T * get() const // never throws + { + return px; + } + + T & operator[](std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(px != 0); + BOOST_ASSERT(i >= 0); + return px[i]; + } + + long use_count() const // never throws + { + return *pn; + } + + bool unique() const // never throws + { + return *pn == 1; + } + + void swap(shared_array & other) // never throws + { + std::swap(px, other.px); + std::swap(pn, other.pn); + } + +private: + + T * px; // contained pointer + count_type * pn; // ptr to reference counter + +}; // shared_array + +template inline bool operator==(shared_array const & a, shared_array const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_array const & a, shared_array const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_array const & a, shared_array const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_array & a, shared_array & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp new file mode 100644 index 0000000..46ceaf5 --- /dev/null +++ b/include/boost/detail/shared_count.hpp @@ -0,0 +1,250 @@ +#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// detail/shared_count.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +namespace boost +{ + +namespace detail +{ + +class counted_base +{ +public: + + typedef atomic_count count_type; + + explicit counted_base(long initial_use_count, long initial_weak_count): + use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete) + { + } + + virtual ~counted_base() + { + } + + virtual void dispose() + { + } + + void add_ref() + { + ++use_count_; + ++weak_count_; + } + + void release() + { + if(--use_count_ == 0) + { + dispose(); + } + + if(--weak_count_ == 0) + { + // not a direct 'delete this', because the inlined + // release() may use a different heap manager + self_deleter_(this); + } + } + + void weak_add_ref() + { + ++weak_count_; + } + + void weak_release() + { + if(--weak_count_ == 0) + { + self_deleter_(this); + } + } + + long use_count() const + { + return use_count_; + } + +private: + + counted_base(counted_base const &); + counted_base & operator= (counted_base const &); + + static void self_delete(counted_base * p) + { + delete p; + } + + count_type use_count_; + count_type weak_count_; + + void (*self_deleter_) (counted_base *); +}; + +template class counted_base_impl: public counted_base +{ +private: + + P ptr; // copy constructor must not throw + D del; // copy constructor must not throw + + counted_base_impl(counted_base_impl const &); + counted_base_impl & operator= (counted_base_impl const &); + +public: + + counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count): + counted_base(initial_use_count, initial_weak_count), ptr(p), del(d) + { + } + + virtual void dispose() + { + del(ptr); + } +}; + + +class shared_count +{ +private: + + counted_base * pi_; + + friend class weak_count; + +public: + + template shared_count(P p, D d): pi_(0) + { + try + { + pi_ = new counted_base_impl(p, d, 1, 1); + } + catch(...) + { + d(p); // delete p + throw; + } + } + + ~shared_count() // nothrow + { + pi_->release(); + } + + shared_count(shared_count const & r): pi_(r.pi_) // nothrow + { + pi_->add_ref(); + } + + shared_count & operator= (shared_count const & r) // nothrow + { + counted_base * tmp = r.pi_; + tmp->add_ref(); + pi_->release(); + pi_ = tmp; + + return *this; + } + + void swap(shared_count & r) // nothrow + { + counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_->use_count(); + } + + bool unique() const // nothrow + { + return pi_->use_count() == 1; + } +}; + +class weak_count +{ +private: + + counted_base * pi_; + +public: + + weak_count(): pi_(new counted_base(0, 1)) // can throw + { + } + + weak_count(shared_count const & r): pi_(r.pi_) // nothrow + { + pi_->weak_add_ref(); + } + + weak_count(weak_count const & r): pi_(r.pi_) // nothrow + { + pi_->weak_add_ref(); + } + + ~weak_count() // nothrow + { + pi_->weak_release(); + } + + weak_count & operator= (shared_count const & r) // nothrow + { + counted_base * tmp = r.pi_; + tmp->weak_add_ref(); + pi_->weak_release(); + pi_ = tmp; + + return *this; + } + + weak_count & operator= (weak_count const & r) // nothrow + { + counted_base * tmp = r.pi_; + tmp->weak_add_ref(); + pi_->weak_release(); + pi_ = tmp; + + return *this; + } + + void swap(weak_count & r) // nothrow + { + counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_->use_count(); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/shared_ptr_nmt.hpp b/include/boost/detail/shared_ptr_nmt.hpp new file mode 100644 index 0000000..8b268a2 --- /dev/null +++ b/include/boost/detail/shared_ptr_nmt.hpp @@ -0,0 +1,165 @@ +#ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED + +// +// detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include +#include +#include + +#ifndef BOOST_NO_AUTO_PTR +#include // for std::auto_ptr +#endif + +#include // for std::swap +#include // for std::less + +namespace boost +{ + +template class shared_ptr +{ +private: + + typedef detail::atomic_count count_type; + +public: + + typedef T element_type; + + explicit shared_ptr(T * p = 0): px(p) + { + try // prevent leak if new throws + { + pn = new count_type(1); + } + catch(...) + { + checked_delete(p); + throw; + } + } + + ~shared_ptr() + { + if(--*pn == 0) + { + checked_delete(px); + delete pn; + } + } + + shared_ptr(shared_ptr const & r): px(r.px) // never throws + { + pn = r.pn; + ++*pn; + } + + shared_ptr & operator=(shared_ptr const & r) + { + shared_ptr(r).swap(*this); + return *this; + } + +#ifndef BOOST_NO_AUTO_PTR + + explicit shared_ptr(std::auto_ptr & r) + { + pn = new count_type(1); // may throw + px = r.release(); // fix: moved here to stop leak if new throws + } + + shared_ptr & operator=(std::auto_ptr & r) + { + shared_ptr(r).swap(*this); + return *this; + } + +#endif + + void reset(T * p = 0) + { + shared_ptr(p).swap(*this); + } + + T & operator*() const // never throws + { + BOOST_ASSERT(px != 0); + return *px; + } + + T * operator->() const // never throws + { + BOOST_ASSERT(px != 0); + return px; + } + + T * get() const // never throws + { + return px; + } + + long use_count() const // never throws + { + return *pn; + } + + bool unique() const // never throws + { + return *pn == 1; + } + + void swap(shared_ptr & other) // never throws + { + std::swap(px, other.px); + std::swap(pn, other.pn); + } + +private: + + T * px; // contained pointer + count_type * pn; // ptr to reference counter +}; + +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_ptr & a, shared_ptr & b) +{ + a.swap(b); +} + +// get_pointer() enables boost::mem_fn to recognize shared_ptr + +template inline T * get_pointer(shared_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp new file mode 100644 index 0000000..3fcce8d --- /dev/null +++ b/include/boost/scoped_array.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED +#define BOOST_SCOPED_ARRAY_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. + +#include +#include // in case ptrdiff_t not in std +#include // for std::ptrdiff_t + +namespace boost +{ + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template class scoped_array // noncopyable +{ +private: + + T* ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + +public: + + typedef T element_type; + + explicit scoped_array( T* p = 0 ): ptr(p) // never throws + { + } + + ~scoped_array() + { + typedef char type_must_be_complete[sizeof(T)]; + delete [] ptr; + } + + void reset( T* p = 0 ) + { + typedef char type_must_be_complete[sizeof(T)]; + + if ( ptr != p ) + { + delete [] ptr; + ptr = p; + } + } + + T& operator[](std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(ptr != 0); + BOOST_ASSERT(i >= 0); + return ptr[i]; + } + + T* get() const // never throws + { + return ptr; + } + + void swap(scoped_array & rhs) + { + T * tmp = rhs.ptr; + rhs.ptr = ptr; + ptr = tmp; + } + +}; + +template inline void swap(scoped_array & a, scoped_array & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp new file mode 100644 index 0000000..b920a72 --- /dev/null +++ b/include/boost/scoped_ptr.hpp @@ -0,0 +1,90 @@ +#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED +#define BOOST_SCOPED_PTR_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. + +#include + +namespace boost +{ + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +template class scoped_ptr // noncopyable +{ +private: + + T* ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + +public: + + typedef T element_type; + + explicit scoped_ptr( T* p = 0 ): ptr(p) // never throws + { + } + + ~scoped_ptr() + { + typedef char type_must_be_complete[sizeof(T)]; + delete ptr; + } + + void reset( T* p = 0 ) + { + typedef char type_must_be_complete[sizeof(T)]; + + if ( ptr != p ) + { + delete ptr; + ptr = p; + } + } + + T& operator*() const // never throws + { + BOOST_ASSERT(ptr != 0); + return *ptr; + } + + T* operator->() const // never throws + { + BOOST_ASSERT(ptr != 0); + return ptr; + } + + T* get() const // never throws + { + return ptr; + } + + void swap(scoped_ptr & rhs) + { + T * tmp = rhs.ptr; + rhs.ptr = ptr; + ptr = tmp; + } +}; + +template inline void swap(scoped_ptr & a, scoped_ptr & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp new file mode 100644 index 0000000..85741b2 --- /dev/null +++ b/include/boost/shared_array.hpp @@ -0,0 +1,136 @@ +#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED +#define BOOST_SHARED_ARRAY_HPP_INCLUDED + +// +// shared_array.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include +#else + +#include +#include + +#include + +#include // for std::ptrdiff_t +#include // for std::swap +#include // for std::less + +namespace boost +{ + +// +// shared_array +// +// shared_array extends shared_ptr to arrays. +// The array pointed to is deleted when the last shared_array pointing to it +// is destroyed or reset. +// + +template class shared_array +{ +private: + + // Borland 5.5.1 specific workarounds + typedef checked_array_deleter deleter; + typedef shared_array this_type; + +public: + + typedef T element_type; + + explicit shared_array(T * p = 0): px(p), pn(p, deleter()) + { + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_array will release p by calling d(p) + // + + template shared_array(T * p, D d): px(p), pn(p, d) + { + } + +// generated copy constructor, assignment, destructor are fine + + void reset(T * p = 0) + { + this_type(p).swap(*this); + } + + T & operator[] (std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(px != 0); + BOOST_ASSERT(i >= 0); + return px[i]; + } + + T * get() const // never throws + { + return px; + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + bool unique() const // never throws + { + return pn.unique(); + } + + void swap(shared_array & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +private: + + T * px; // contained pointer + detail::shared_count pn; // reference counter + +}; // shared_array + +template inline bool operator==(shared_array const & a, shared_array const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_array const & a, shared_array const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_array const & a, shared_array const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_array & a, shared_array & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp new file mode 100644 index 0000000..996a1b5 --- /dev/null +++ b/include/boost/shared_ptr.hpp @@ -0,0 +1,246 @@ +#ifndef BOOST_SHARED_PTR_HPP_INCLUDED +#define BOOST_SHARED_PTR_HPP_INCLUDED + +// +// shared_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include +#else + +#include +#include + +#include + +#include // for std::auto_ptr +#include // for std::swap +#include // for std::less + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +namespace detail +{ + +struct static_cast_tag {}; +struct dynamic_cast_tag {}; + +template struct shared_ptr_traits +{ + typedef T & reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +} // namespace detail + + +// +// shared_ptr +// +// An enhanced relative of scoped_ptr with reference counted copy semantics. +// The object pointed to is deleted when the last shared_ptr pointing to it +// is destroyed or reset. +// + +template class weak_ptr; + +template class shared_ptr +{ +private: + + // Borland 5.5.1 specific workarounds + typedef checked_deleter deleter; + typedef shared_ptr this_type; + +public: + + typedef T element_type; + + explicit shared_ptr(T * p = 0): px(p), pn(p, deleter()) + { + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_ptr will release p by calling d(p) + // + + template shared_ptr(T * p, D d): px(p), pn(p, d) + { + } + +// generated copy constructor, assignment, destructor are fine + + template + shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws + { + } + + template + shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) + { + } + + template + shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if(px == 0) // need to allocate new counter -- the cast failed + { + pn = detail::shared_count(static_cast(0), deleter()); + } + } + +#ifndef BOOST_NO_AUTO_PTR + + template + explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn(r.release(), checked_deleter()) + { + } + +#endif + + template + shared_ptr & operator=(shared_ptr const & r) // nothrow? + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#ifndef BOOST_NO_AUTO_PTR + + template + shared_ptr & operator=(std::auto_ptr & r) + { + this_type(r).swap(*this); + return *this; + } + +#endif + + void reset(T * p = 0) + { + this_type(p).swap(*this); + } + + typename detail::shared_ptr_traits::reference operator* () const // never throws + { + BOOST_ASSERT(px != 0); + return *px; + } + + T * operator-> () const // never throws + { + BOOST_ASSERT(px != 0); + return px; + } + + T * get() const // never throws + { + return px; + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + bool unique() const // never throws + { + return pn.unique(); + } + + void swap(shared_ptr & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class shared_ptr; + template friend class weak_ptr; + + +#endif + + T * px; // contained pointer + detail::shared_count pn; // reference counter + +}; // shared_ptr + +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template shared_ptr shared_static_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::static_cast_tag()); +} + +template shared_ptr shared_dynamic_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::dynamic_cast_tag()); +} + +template void swap(shared_ptr & a, shared_ptr & b) +{ + a.swap(b); +} + +// get_pointer() enables boost::mem_fn to recognize shared_ptr + +template inline T * get_pointer(shared_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp new file mode 100644 index 0000000..87231c3 --- /dev/null +++ b/include/boost/weak_ptr.hpp @@ -0,0 +1,175 @@ +#ifndef BOOST_WEAK_PTR_HPP_INCLUDED +#define BOOST_WEAK_PTR_HPP_INCLUDED + +// +// weak_ptr.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include + +#include // for broken compiler workarounds +#include + +#include + +#include // for std::swap +#include // for std::less + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +template class weak_ptr +{ +private: + + // Borland 5.5.1 specific workarounds + typedef weak_ptr this_type; + +public: + + typedef T element_type; + + weak_ptr(): px(0), pn() + { + } + +// generated copy constructor, assignment, destructor are fine + + template + weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws + { + } + + template + weak_ptr(weak_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) + { + } + + template + weak_ptr(weak_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if(px == 0) // need to allocate new counter -- the cast failed + { + pn = detail::weak_count(); + } + } + + template + weak_ptr & operator=(weak_ptr const & r) // nothrow? + { + px = r.px; + pn = r.pn; + return *this; + } + + void reset() + { + this_type().swap(*this); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + T * get() const // never throws + { + return use_count() == 0? 0: px; + } + + typename detail::shared_ptr_traits::reference operator* () const // never throws + { + T * p = get(); + + BOOST_ASSERT(p != 0); + return *p; + } + + T * operator-> () const // never throws + { + T * p = get(); + + BOOST_ASSERT(p != 0); + return p; + } + + void swap(weak_ptr & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class weak_ptr; + +#endif + + T * px; // contained pointer + detail::weak_count pn; // reference counter + +}; // weak_ptr + +template inline bool operator==(weak_ptr const & a, weak_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(weak_ptr const & a, weak_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(weak_ptr const & a, weak_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template weak_ptr shared_static_cast(weak_ptr const & r) +{ + return weak_ptr(r, detail::static_cast_tag()); +} + +template weak_ptr shared_dynamic_cast(weak_ptr const & r) +{ + return weak_ptr(r, detail::dynamic_cast_tag()); +} + +template void swap(weak_ptr & a, weak_ptr & b) +{ + a.swap(b); +} + +// get_pointer() enables boost::mem_fn to recognize weak_ptr + +template inline T * get_pointer(weak_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED