summaryrefslogtreecommitdiff
path: root/o3tl
diff options
context:
space:
mode:
authorThorsten Behrens <thb@openoffice.org>2006-03-23 14:25:00 +0000
committerThorsten Behrens <thb@openoffice.org>2006-03-23 14:25:00 +0000
commit93b0a13d2de166c48ba7e182c306df1806b05eec (patch)
treec4c81e25b2b84af58b28cd866a5f444903df603f /o3tl
parent6d036b06fa079f04cd16cbb4b243fa7b5be3ebc3 (diff)
#i63310# Made cow_wrapper refcounting behaviour configurable via policy class (otherwise, code like basegfx, which previously hadn't used thread-safe refcounting, would now been hit by the performance penalty); added compile-test for ThreadSafeRefCountingPolicy to unit tests; removed cruft from unit tests
Diffstat (limited to 'o3tl')
-rw-r--r--o3tl/inc/o3tl/cow_wrapper.hxx79
-rw-r--r--o3tl/qa/cow_wrapper_clients.cxx71
-rw-r--r--o3tl/qa/cow_wrapper_clients.hxx33
3 files changed, 154 insertions, 29 deletions
diff --git a/o3tl/inc/o3tl/cow_wrapper.hxx b/o3tl/inc/o3tl/cow_wrapper.hxx
index 2596c0743f10..f633fc57e438 100644
--- a/o3tl/inc/o3tl/cow_wrapper.hxx
+++ b/o3tl/inc/o3tl/cow_wrapper.hxx
@@ -4,9 +4,9 @@
*
* $RCSfile: cow_wrapper.hxx,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: thb $ $Date: 2006-03-17 16:50:18 $
+ * last change: $Author: thb $ $Date: 2006-03-23 15:25:00 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
@@ -45,6 +45,31 @@
namespace o3tl
{
+ /** Thread-unsafe refcounting
+
+ This is the default locking policy for cow_wrapper. No
+ locking/guarding against concurrent access is performed
+ whatsoever.
+ */
+ struct UnsafeRefCountingPolicy
+ {
+ typedef sal_uInt32 ref_count_t;
+ static ref_count_t incrementCount( ref_count_t& rCount ) { return ++rCount; }
+ static ref_count_t decrementCount( ref_count_t& rCount ) { return --rCount; }
+ };
+
+ /** Thread-safe refcounting
+
+ Use this to have the cow_wrapper refcounting mechanisms employ
+ the thread-safe oslInterlockedCount .
+ */
+ struct ThreadSafeRefCountingPolicy
+ {
+ typedef oslInterlockedCount ref_count_t;
+ static ref_count_t incrementCount( ref_count_t& rCount ) { return osl_incrementInterlockedCount(&rCount); }
+ static ref_count_t decrementCount( ref_count_t& rCount ) { return osl_decrementInterlockedCount(&rCount); }
+ };
+
/** Copy-on-write wrapper.
This template provides copy-on-write semantics for the wrapped
@@ -70,10 +95,13 @@ namespace o3tl
thread-safe per se, because cow_wrapper has no way of
syncronizing the potentially many different cow_wrapper
instances, that reference a single shared value_type
- instance. Accessing a thread-safe pointee through multiple
- cow_wrapper instances might be thread-safe, if the individual
- pointee methods are thread-safe, <em>including</em> pointee's
- copy constructor. Any wrapped object that needs external
+ instance. That said, when passing
+ <code>ThreadSafeRefCountingPolicy</code> as the
+ <code>MTPolicy</code> parameter, accessing a thread-safe
+ pointee through multiple cow_wrapper instances might be
+ thread-safe, if the individual pointee methods are
+ thread-safe, <em>including</em> pointee's copy
+ constructor. Any wrapped object that needs external
synchronisation (e.g. via an external mutex, which arbitrates
access to object methods, and can be held across multiple
object method calls) cannot easily be dealt with in a
@@ -144,9 +172,9 @@ void cow_wrapper_client::queryUnmodified() const
}
</pre>
*/
- template<typename T> class cow_wrapper
+ template<typename T, class MTPolicy=UnsafeRefCountingPolicy> class cow_wrapper
{
- /** shared value object - gets copied before cow_wrapper hands
+ /** shared value object - gets cloned before cow_wrapper hands
out a non-const reference to it
*/
struct impl_t : private boost::noncopyable
@@ -163,19 +191,20 @@ void cow_wrapper_client::queryUnmodified() const
{
}
- T m_value;
- oslInterlockedCount m_ref_count;
+ T m_value;
+ typename MTPolicy::ref_count_t m_ref_count;
};
void release()
{
- if( osl_decrementInterlockedCount(&m_pimpl->m_ref_count) == 0 )
+ if( MTPolicy::decrementCount(m_pimpl->m_ref_count) == 0 )
boost::checked_delete(m_pimpl), m_pimpl=0;
}
public:
- typedef T value_type;
- typedef T* pointer;
+ typedef T value_type;
+ typedef T* pointer;
+ typedef MTPolicy mt_policy;
/** Default-construct wrapped type instance
*/
@@ -196,7 +225,7 @@ void cow_wrapper_client::queryUnmodified() const
explicit cow_wrapper( const cow_wrapper& rSrc ) : // nothrow
m_pimpl( rSrc.m_pimpl )
{
- osl_incrementInterlockedCount( &m_pimpl->m_ref_count );
+ MTPolicy::incrementCount( m_pimpl->m_ref_count );
}
~cow_wrapper() // nothrow, if ~T does not throw
@@ -208,7 +237,7 @@ void cow_wrapper_client::queryUnmodified() const
cow_wrapper& operator=( const cow_wrapper& rSrc ) // nothrow
{
// this already guards against self-assignment
- osl_incrementInterlockedCount( &rSrc.m_pimpl->m_ref_count );
+ MTPolicy::incrementCount( rSrc.m_pimpl->m_ref_count );
release();
m_pimpl = rSrc.m_pimpl;
@@ -236,7 +265,7 @@ void cow_wrapper_client::queryUnmodified() const
}
/// return number of shared instances (1 for unique object)
- oslInterlockedCount use_count() const // nothrow
+ typename MTPolicy::ref_count_t use_count() const // nothrow
{
return m_pimpl->m_ref_count;
}
@@ -265,32 +294,32 @@ void cow_wrapper_client::queryUnmodified() const
};
- template<class A, class B> inline bool operator==( const cow_wrapper<A>& a,
- const cow_wrapper<B>& b )
+ template<class A, class B, class P> inline bool operator==( const cow_wrapper<A,P>& a,
+ const cow_wrapper<B,P>& b )
{
return *a == *b;
}
- template<class A, class B> inline bool operator!=( const cow_wrapper<A>& a,
- const cow_wrapper<B>& b )
+ template<class A, class B, class P> inline bool operator!=( const cow_wrapper<A,P>& a,
+ const cow_wrapper<B,P>& b )
{
return *a != *b;
}
- template<class A, class B> inline bool operator<( const cow_wrapper<A>& a,
- const cow_wrapper<B>& b )
+ template<class A, class B, class P> inline bool operator<( const cow_wrapper<A,P>& a,
+ const cow_wrapper<B,P>& b )
{
return *a < *b;
}
- template<class T> inline void swap( cow_wrapper<T>& a,
- cow_wrapper<T>& b )
+ template<class T, class P> inline void swap( cow_wrapper<T,P>& a,
+ cow_wrapper<T,P>& b )
{
a.swap(b);
}
// to enable boost::mem_fn on cow_wrapper
- template<class T> inline T * get_pointer( const cow_wrapper<T>& r )
+ template<class T, class P> inline T * get_pointer( const cow_wrapper<T,P>& r )
{
return r.get();
}
diff --git a/o3tl/qa/cow_wrapper_clients.cxx b/o3tl/qa/cow_wrapper_clients.cxx
index c389b7d8dd79..37d71061b258 100644
--- a/o3tl/qa/cow_wrapper_clients.cxx
+++ b/o3tl/qa/cow_wrapper_clients.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: cow_wrapper_clients.cxx,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: thb $ $Date: 2006-02-01 10:55:36 $
+ * last change: $Author: thb $ $Date: 2006-03-23 15:25:00 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -144,4 +144,71 @@ bool cow_wrapper_client2::operator<( const cow_wrapper_client2& rRHS ) const
return maImpl < rRHS.maImpl;
}
+// ---------------------------------------------------------------------------
+
+cow_wrapper_client3::cow_wrapper_client3() : maImpl()
+{
+}
+
+cow_wrapper_client3::cow_wrapper_client3( int nVal ) :
+ maImpl( cow_wrapper_client2_impl(nVal) )
+{
+}
+
+cow_wrapper_client3::~cow_wrapper_client3()
+{
+}
+
+cow_wrapper_client3::cow_wrapper_client3( const cow_wrapper_client3& rSrc ) :
+ maImpl(rSrc.maImpl)
+{
+}
+
+cow_wrapper_client3& cow_wrapper_client3::operator=( const cow_wrapper_client3& rSrc )
+{
+ maImpl = rSrc.maImpl;
+
+ return *this;
+}
+
+void cow_wrapper_client3::modify( int nVal )
+{
+ maImpl->setValue( nVal );
+}
+
+int cow_wrapper_client3::queryUnmodified() const
+{
+ return maImpl->getValue();
+}
+
+void cow_wrapper_client3::makeUnique()
+{
+ maImpl.make_unique();
+}
+bool cow_wrapper_client3::is_unique() const
+{
+ return maImpl.is_unique();
+}
+oslInterlockedCount cow_wrapper_client3::use_count() const
+{
+ return maImpl.use_count();
+}
+void cow_wrapper_client3::swap( cow_wrapper_client3& r )
+{
+ o3tl::swap(maImpl, r.maImpl);
+}
+
+bool cow_wrapper_client3::operator==( const cow_wrapper_client3& rRHS ) const
+{
+ return maImpl == rRHS.maImpl;
+}
+bool cow_wrapper_client3::operator!=( const cow_wrapper_client3& rRHS ) const
+{
+ return maImpl != rRHS.maImpl;
+}
+bool cow_wrapper_client3::operator<( const cow_wrapper_client3& rRHS ) const
+{
+ return maImpl < rRHS.maImpl;
+}
+
} // namespace o3tltests
diff --git a/o3tl/qa/cow_wrapper_clients.hxx b/o3tl/qa/cow_wrapper_clients.hxx
index 49a9cb5023d5..013414d477ec 100644
--- a/o3tl/qa/cow_wrapper_clients.hxx
+++ b/o3tl/qa/cow_wrapper_clients.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: cow_wrapper_clients.hxx,v $
*
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
*
- * last change: $Author: thb $ $Date: 2006-01-25 16:17:38 $
+ * last change: $Author: thb $ $Date: 2006-03-23 15:25:00 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -128,6 +128,35 @@ private:
o3tl::cow_wrapper< cow_wrapper_client2_impl > maImpl;
};
+/** test MT-safe cow_wrapper - basically the same as
+ cow_wrapper_client2, only with different refcounting policy
+ */
+class cow_wrapper_client3
+{
+public:
+ cow_wrapper_client3();
+ explicit cow_wrapper_client3( int nVal );
+ ~cow_wrapper_client3();
+
+ cow_wrapper_client3( const cow_wrapper_client3& );
+ cow_wrapper_client3& operator=( const cow_wrapper_client3& );
+
+ void modify( int nVal );
+ int queryUnmodified() const;
+
+ void makeUnique();
+ bool is_unique() const;
+ oslInterlockedCount use_count() const;
+ void swap( cow_wrapper_client3& r );
+
+ bool operator==( const cow_wrapper_client3& rRHS ) const;
+ bool operator!=( const cow_wrapper_client3& rRHS ) const;
+ bool operator<( const cow_wrapper_client3& rRHS ) const;
+
+private:
+ o3tl::cow_wrapper< cow_wrapper_client2_impl, o3tl::ThreadSafeRefCountingPolicy > maImpl;
+};
+
} // namespace o3tltests
#endif /* INCLUDED_COW_WRAPPER_CLIENTS_HXX */