|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r56018 - in sandbox/stm/branches/vbe: boost/stm boost/stm/detail libs/stm/example libs/stm/test
From: vicente.botet_at_[hidden]
Date: 2009-09-04 12:07:39
Author: viboes
Date: 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
New Revision: 56018
URL: http://svn.boost.org/trac/boost/changeset/56018
Log:
TBoost.Stm vbe deep changes on smart pointers + list example
Added:
sandbox/stm/branches/vbe/libs/stm/example/counter.cpp (contents, props changed)
Text files modified:
sandbox/stm/branches/vbe/boost/stm/base_transaction.hpp | 77 +++-
sandbox/stm/branches/vbe/boost/stm/detail/config.hpp | 4
sandbox/stm/branches/vbe/boost/stm/detail/transaction_impl.hpp | 15
sandbox/stm/branches/vbe/boost/stm/detail/tx_ptr.hpp | 346 ++++++++++++++++-----
sandbox/stm/branches/vbe/boost/stm/transaction.hpp | 421 ++++++++++++++++++--------
sandbox/stm/branches/vbe/libs/stm/example/bank.cpp | 210 +++++++++++--
sandbox/stm/branches/vbe/libs/stm/example/list.cpp | 621 +++++++++------------------------------
sandbox/stm/branches/vbe/libs/stm/test/Jamfile.v2 | 3
sandbox/stm/branches/vbe/libs/stm/test/testLinkedList.h | 9
9 files changed, 944 insertions(+), 762 deletions(-)
Modified: sandbox/stm/branches/vbe/boost/stm/base_transaction.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/base_transaction.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/base_transaction.hpp 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -50,6 +50,9 @@
//-----------------------------------------------------------------------------
namespace boost { namespace stm {
+template <class T> void cache_deallocate(T*);
+template <class T> void cache_restore(const T* const ori, T* target);
+template <class T> inline T* cache_new_copy_constructor(const T&);
#ifndef BOOST_STM_USE_BOOST_MUTEX
typedef pthread_mutex_t PLOCK;
@@ -206,9 +209,7 @@
#endif
virtual ~base_transaction_object() {};
#ifdef BOOST_STM_USE_UNASIGNED_COPY
-#if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER)
- virtual void return_this_mem()=0;
-#endif
+ virtual void cache_deallocate()=0;
#endif
void transaction_thread(size_t rhs) const { transactionThread_ = rhs; }
@@ -289,15 +290,6 @@
};
-
-template <class T> void cache_restore(const T* const ori, T* target) {
-#ifdef BOOST_STM_USE_UNASIGNED_COPY
- std::uninitialized_copy(ori,ori+1, target);
-#else
- *target=*ori;
-#endif
-}
-
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
template <class Derived>
@@ -319,10 +311,11 @@
}
#endif
-#ifdef BOOST_STM_USE_UNASIGNED_COPY
-#if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER)
- void return_this_mem() {base_transaction_object::return_mem(this,sizeof(Derived));};
-#endif
+#ifdef BOOST_STM_USE_UNASIGNED_COPY
+ virtual void cache_deallocate() {
+ boost::stm::cache_deallocate(this);
+ }
+
#endif
#if USE_STM_MEMORY_MANAGER
@@ -396,25 +389,31 @@
//-----------------------------------------------------------------------------
// transactional object wrapper
+// A transactional_object<T> is a base_transaction_object wrapping an instance of type T
+//
+// If a class D inherits from B we have that transactional_object<D> dont inherits from transactional_object<B>, but
+// we can static/dynamic cast them robustly.
+// Evidently the std::static_cast/std::dynamic_cast do not works. We need to define the specific cast
+//
+// transactional_object<D>* d=...;
+// transactional_object<B>* b=tx_static_cast<B>(d);
+//
+// transactional_object<B>* b=...;
+// transactional_object<D>* d=tx_dynamic_cast<B>(b);
+//
//-----------------------------------------------------------------------------
+
template <typename T>
class transactional_object : public base_transaction_object {
public:
T value;
-
- static transactional_object<T>* up_cast(T* ptr) {
- return reinterpret_cast<transactional_object<T>*>(reinterpret_cast<char*>(ptr)-offsetof(transactional_object<T>, value));
- }
+
transactional_object() {}
transactional_object(const T*ptr)
: base_transaction_object()
, value(*ptr) {}
- transactional_object(transaction*tx, const T*ptr)
- : base_transaction_object(tx)
- , value(*ptr) {}
-
transactional_object(transactional_object<T> const & r)
: base_transaction_object(r)
, value(r.value) {}
@@ -424,6 +423,11 @@
: base_transaction_object()
, value(p1) {}
+ template <typename T1, typename T2>
+ transactional_object(T1 const &p1, T2 const &p2)
+ : base_transaction_object()
+ , value(p1,p2) {}
+
transactional_object & operator=(transactional_object const & r) // never throws
{
this->transaction_=r.transaction_;
@@ -437,9 +441,9 @@
}
#ifdef BOOST_STM_USE_UNASIGNED_COPY
-#if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER)
- void return_this_mem() {return_mem(this,sizeof(transactional_object<T>));};
-#endif
+ virtual void cache_deallocate() {
+ boost::stm::cache_deallocate(this);
+ }
#endif
#if USE_STM_MEMORY_MANAGER
@@ -456,6 +460,25 @@
};
+// gets the transactional_object<T> pointer wrapping the T pointer
+template <typename T>
+static transactional_object<T>* up_cast(T* ptr) {
+ return reinterpret_cast<transactional_object<T>*>(reinterpret_cast<char*>(ptr)-offsetof(transactional_object<T>, value));
+}
+
+//
+template <typename T, typename U>
+static transactional_object<T>* tx_static_cast(transactional_object<U>* ptr) {
+ return up_cast(static_cast<T*>(&ptr->value));
+}
+
+template <typename T, typename U>
+static transactional_object<T>* tx_dynamic_cast(transactional_object<U>* ptr) {
+ T* p = dynamic_cast<T*>(&ptr->value);
+ if (p==0) return 0;
+ return up_cast(p);
+}
+
//-----------------------------------------------------------------------------
class base_contention_manager
Modified: sandbox/stm/branches/vbe/boost/stm/detail/config.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/detail/config.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/detail/config.hpp 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -26,7 +26,7 @@
#define PERFORMING_WRITE_BLOOM 1
//#define ALWAYS_ALLOW_ABORT 1
//#define LOGGING_BLOCKS 1
-//#define USE_SINGLE_THREAD_CONTEXT_MAP 1
+#define USE_SINGLE_THREAD_CONTEXT_MAP 1
//#define BOOST_STM_HAVE_SINGLE_TSS_CONTEXT_MAP 1
#define BOOST_STM_TX_CONTAINS_REFERENCES_TO_TSS_FIELDS 1
@@ -61,6 +61,8 @@
//#define BOOST_STM_USE_BOOST_THREAD_ID 1
//#define BOOST_STM_USE_BOOST_MUTEX 1
+#define BOOST_STM_NO_PARTIAL_SPECIALIZATION 1
+
#endif // BOOST_STM_DETAIL_CONFIG_H
Modified: sandbox/stm/branches/vbe/boost/stm/detail/transaction_impl.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/detail/transaction_impl.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/detail/transaction_impl.hpp 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -1666,7 +1666,20 @@
tx_type_ref() = eNormalTx;
#if PERFORMING_LATM
- get_tx_conflicting_locks().clear();
+ get_tx_conflicting_locks().clear();
+ /* BACKTRACE
+#2 0x00459309 in std::set<__pthread_mutex_t**, std::less<__pthread_mutex_t**>,
+std::allocator<__pthread_mutex_t**> >::clear (this=0x0)
+ at /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_set.h:413
+#3 0x0041e8c1 in boost::stm::transaction::invalidating_deferred_commit (
+ this=0x191ccc40) at ../../../boost/stm/detail/transaction_impl.hpp:1593
+#4 0x0041f707 in boost::stm::transaction::invalidating_deferred_end_transaction
+ (this=0x191ccc40) at ../../../boost/stm/detail/transaction_impl.hpp:1002
+#5 0x0041fa0c in boost::stm::transaction::end (this=0x191ccc40)
+ at ../../../boost/stm/detail/transaction_impl.hpp:796
+#6 0x0040142e in account_withdraw_thr ()
+ at C:\cygwin\sandbox\stm\branches\vbe\libs\stm\example\bank.cpp:144
+ */
clear_latm_obtained_locks();
#endif
state_ = e_committed;
Modified: sandbox/stm/branches/vbe/boost/stm/detail/tx_ptr.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/detail/tx_ptr.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/detail/tx_ptr.hpp 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -16,6 +16,7 @@
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
+#include <assert.h>
#include <boost/stm/transaction.hpp>
//-----------------------------------------------------------------------------
@@ -23,87 +24,92 @@
namespace boost { namespace stm {
template <typename T>
+class rd_ptr;
+template <typename T>
+class wr_ptr;
+template <typename T>
+class upgrd_ptr;
+
+
+//-----------------------------------------------------------------------------
+// a tx_ptr<T> is an smart pointer to a transactional_object<T> (which contains an instance of T).
+// Reference fields in linked structures should always be tx_ptrs.
+// The result of derreferencing it will be the pointer to the T instance
+// When this pointer is derreference on a transaction the transactional_object<T> is set a written and
+// the transaction specific storage will be used
+// Otherwise the shared storage is used.
+// Used to initialize a rd_ptr<T>, wr_ptr<T>, or upgrd_ptr<T>.
+//-----------------------------------------------------------------------------
+
+template <typename T>
class tx_ptr {
public:
typedef tx_ptr<T> this_type;
- mutable transactional_object<T> * ptr_;
+ transactional_object<T> * ptr_;
tx_ptr() : ptr_(0) {}
- //explicit tx_ptr(T* ptr) : ptr_(new transactional_object<T>(ptr)) {}
template<class Y>
explicit tx_ptr(Y * ptr) : ptr_(new transactional_object<Y>(ptr)) {}
explicit tx_ptr(transactional_object<T>* ptr) : ptr_(ptr) {}
template<class Y>
- tx_ptr(tx_ptr<Y> const & r) : ptr_(r.ptr_) {}// never throws
+ tx_ptr(tx_ptr<Y> const& r) : ptr_(r.ptr_) {}// never throws
template<class Y>
- tx_ptr & operator=(tx_ptr<Y> const & r) // never throws
- {
- this_type(r).swap(*this);
+ tx_ptr(rd_ptr<Y> const & r) : ptr_(r.ptr_) {}// never throws
+
+ template<class Y>
+ tx_ptr(wr_ptr<Y> const & r) : ptr_(r.ptr_) {}// never throws
+
+ template<class Y>
+ tx_ptr(upgrd_ptr<Y> const & r) : ptr_(r.ptr_) {}// never throws
+
+ template<class Y>
+ tx_ptr & operator=(tx_ptr<Y> const & r) { // never throws
+ //this_type(r).swap(*this);
+ ptr_=r.ptr_;
return *this;
}
-
+ template<class Y>
+ tx_ptr & operator=(transactional_object<Y>* ptr) { // never throws
+ ptr_=ptr;
+ return *this;
+ }
+
+ // two transactional pointers are equal if they point to the same cache on the current transaction.
bool operator==(const tx_ptr<T>& rhs) {
- return this->get()==rhs.get();
+ return ptr_==rhs.ptr_ || this->get()==rhs.ptr_ || ptr_==rhs.get();
}
+
T* operator->() const {
return this->get();
}
T& operator*() const {
return *this->get();
}
- #if 0
- T const & operator*() const {
- return *this->get();
- }
- T const * operator->() const {
- return this->get();
- }
- #endif
T* get() const {
if (0==ptr_) return 0;
- if (0==ptr_->transaction_) {
- transaction* tx=transaction::current_transaction();
- if (tx!=0) {
- if (tx->forced_to_abort()) {
- tx->lock_and_abort();
- throw aborted_transaction_exception("aborting transaction");
- }
- ptr_=tx->write_ptr(ptr_);
- }
- }
- return &ptr_->value;
- }
- T const * get2() const {
- if (0==ptr_) return 0;
- if (0==ptr_->transaction_) {
- transaction* tx=transaction::current_transaction();
- if (tx!=0) {
- if (tx->forced_to_abort()) {
- tx->lock_and_abort();
- throw aborted_transaction_exception("aborting transaction");
- }
- ptr_=const_cast<transactional_object<T>*>(tx->read_ptr(ptr_));
+ transaction* tx=transaction::current_transaction();
+ if (tx!=0) {
+ if (tx->forced_to_abort()) {
+ tx->lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
}
+ return &(tx->write_ptr(ptr_)->value);
}
return &ptr_->value;
}
- operator T*() const { return this->get(); }
- //operator T const*() const { return this->get(); }
+ operator T*() const { return this->get(); }
typedef transactional_object<T>* this_type::*unspecified_bool_type;
+ #if 0
operator unspecified_bool_type() const
{
return ptr_ == 0? 0: &this_type::ptr_;
}
- // operator! is redundant, but some compilers need it
- bool operator! () const // never throws
- {
- return ptr_ == 0;
- }
+ #endif
void swap(tx_ptr & other) // never throws
{
std::swap(ptr_, other.ptr_);
@@ -136,6 +142,32 @@
return tx_ptr<T>(new transactional_object<T>(a1));
}
+
+template <typename T>
+void delete_ptr(tx_ptr<T> ptr) {
+ if (ptr.ptr_==0) return;
+ if (ptr.ptr_->transaction_==0) delete ptr.ptr_;
+ ptr.ptr_->transaction_->delete_tx_ptr(ptr.ptr_);
+}
+
+
+template <typename T>
+void delete_ptr(transaction& tx, tx_ptr<T> ptr) {
+ if (ptr.ptr_==0) return;
+ tx.delete_tx_ptr(ptr.ptr_);
+}
+
+template <typename T, typename U>
+static tx_ptr<T> tx_static_cast(tx_ptr<U> ptr) {
+ return tx_ptr<T>(tx_static_cast<T>(ptr->ptr_));
+}
+
+template <typename T, typename U>
+static tx_ptr<T>* tx_dynamic_cast(tx_ptr<U>* ptr) {
+ return tx_ptr<T>(tx_dynamic_cast<T>(ptr->ptr_));
+}
+
+
template <typename T>
class tx_obj {
public:
@@ -170,123 +202,259 @@
}
};
+//-----------------------------------------------------------------------------
+// A rd_ptr<T> ("read pointer") points to an object that the current
+// transaction has opened for read only access.
+// You can only call a const method through a read pointer.
+// A rd_ptr<T> is constructed from an tx_ptr<T> through an explicit constructor.
+// Once a rd_ptr<T> has been constructed, an tx_ptr<T> can be opened for
+// reading simply by assignment (operator=()) into the constructed rd_ptr<T>.
+// It is not safe to derreference a rd_ptr<T> after having assigned the same
+// tx_ptr<T> to a wr_ptr<T>. If this is the case the readen value do not match
+// the writen one. If it is possible to write on the same transaction use
+// upgrd_ptr instead which is safe.
+//-----------------------------------------------------------------------------
+
template <typename T>
class rd_ptr {
+ typedef tx_ptr<T> this_type;
public:
- inline rd_ptr(transaction &t, tx_ptr<T> const & tx_obj) :
- //tx_obj_p_(t.read_ptr(tx_obj.ptr_))
- tx_obj_p_(&t.insert_and_return_read_memory(*tx_obj.ptr_))
-
-{}
+ inline rd_ptr(transaction &t, tx_ptr<T> tx_obj) :
+ ptr_(&t.insert_and_return_read_memory(*tx_obj.ptr_))
+ {}
+ template<class Y>
+ rd_ptr & operator=(tx_ptr<Y> const & r) { // never throws
+ //this_type(r).swap(*this);
+ ptr_=r.ptr_;
+ return *this;
+ }
+
const T* get() const {
- //if (tx_obj_p_->transaction_->forced_to_abort()) {
- // tx_obj_p_->transaction_->lock_and_abort();
+ //if (ptr_->transaction_->forced_to_abort()) {
+ // ptr_->transaction_->lock_and_abort();
// throw aborted_transaction_exception("aborting transaction");
//}
- return &tx_obj_p_->value;
+ return &ptr_->value;
}
inline const T & operator*() const { return *get(); }
- inline const T* operator->() const { return &tx_obj_p_->value; }
-private:
- const transactional_object<T> * tx_obj_p_;
+ inline const T* operator->() const { return get(); }
+
+ operator const T*() const { return get(); }
+
+ typedef transactional_object<T>* this_type::*unspecified_bool_type;
+
+ #if 0
+ operator unspecified_bool_type() const
+ {
+ return ptr_ == 0? 0: &this_type::ptr_;
+ }
+ #endif
+//private:
+ mutable transactional_object<T>* ptr_;
};
+template <typename T>
+rd_ptr<T> make_rd_ptr(transaction& tx, tx_ptr<T>& ptr) {
+ return rd_ptr<T>(tx, ptr);
+}
+
+template <typename T>
+rd_ptr<T> make_rd_ptr(tx_ptr<T>& ptr) {
+ transaction* tx = transaction::current_transaction();
+ assert(tx==0);
+ return rd_ptr<T>(*tx, ptr);
+}
+
+template <typename T>
+void delete_ptr(rd_ptr<T> ptr) {
+ if (ptr.ptr_==0) return;
+ if (ptr.ptr_->transaction_==0) delete ptr.ptr_;
+ ptr.ptr_->transaction_->delete_tx_ptr(ptr.ptr_);
+}
+
+template <typename T>
+void delete_ptr(transaction& tx, rd_ptr<T> ptr) {
+ if (ptr.ptr_==0) return;
+ tx.delete_tx_ptr(ptr.ptr_);
+}
+
+//-----------------------------------------------------------------------------
+// A upgrd_ptr<T> ("upgradable pointer") points to an object that the current
+// transaction has opened for read only access.
+// You can only call a const method through a read pointer.
+// A upgrd_ptr<T> is constructed from an tx_ptr<T> through a constructor
+// having also the transaction as parameter.
+// Once a rd_ptr<T> has been constructed, an tx_ptr<T> can be opened for
+// reading simply by assignment (operator=()) into the constructed rd_ptr<T>.
+// It is safe to derreference a rd_ptr<T> after having assigned the same
+// tx_ptr<T> to a wr_ptr<T>.
+// A upgrd_ptr<T> can be upgraded to a wr_ptr<T> through a constructor.
+//-----------------------------------------------------------------------------
+
template <typename T>
class upgrd_ptr {
+ typedef tx_ptr<T> this_type;
public:
- inline upgrd_ptr(transaction &t, tx_ptr<T> const &tx_obj) :
- tx_ptr_(t.read_ptr(tx_obj.ptr_)), written_(false)
- {}
+ inline upgrd_ptr() : tx_(0) {}
+ inline upgrd_ptr(transaction &t, tx_ptr<T> tx_obj) : tx_(&t),
+ ptr_(const_cast<transactional_object<T>*>(t.read_ptr(tx_obj.ptr_))), written_(false) {}
+
+ template<class Y>
+ upgrd_ptr & operator=(tx_ptr<Y> const& r) { // never throws
+ //this_type(r).swap(*this);
+ ptr_=r.ptr_;
+ written_=false;
+ return *this;
+ }
const T* get() const {
- if (tx_ptr_->transaction_->forced_to_abort()) {
- tx_ptr_->transaction_->lock_and_abort();
+ if (tx_->forced_to_abort()) {
+ tx_->lock_and_abort();
throw aborted_transaction_exception("aborting transaction");
}
// we don't hold the written object and
// we have alrerady written an object on this transaction maybe is this one
- if (!written_ && tx_ptr_->transaction_->written()) {
- transactional_object<T>* temp = tx_ptr_->transaction_->get_written(*tx_ptr_);
+ if (!written_ && tx_->written()) {
+ transactional_object<T>* temp = tx_->get_written(*ptr_);
// if we found something, store this as the tx_ptr_
if (0 != temp) {
- tx_ptr_ = temp;
+ ptr_ = temp;
written_ = true;
}
}
- return &tx_ptr_->value;
+ return &ptr_->value;
}
inline T const & operator*() const { return *get(); }
inline T const * operator->() const { return get(); }
- //inline transaction &trans() { return t_; }
+ //operator const T*() const { return get(); }
+
+ typedef transactional_object<T>* this_type::*unspecified_bool_type;
+
+ #if 1
+ operator unspecified_bool_type() const
+ {
+ return ptr_ == 0? 0: &this_type::ptr_;
+ }
+ #endif
+ void write_ptr(transactional_object<T>* ptr) {
+ ptr_ = ptr;
+ written_ = true;
+ }
T* write_ptr() {
- if (tx_ptr_->transaction_->forced_to_abort()) {
- tx_ptr_->transaction_->lock_and_abort();
+ if (tx_->forced_to_abort()) {
+ tx_->lock_and_abort();
throw aborted_transaction_exception("aborting transaction");
}
// we are already holding the written object
- if (written_) return tx_ptr_;
+ if (written_) return ptr_;
- transactional_object<T>* temp = tx_ptr_->transaction_->get_written(*tx_ptr_);
+ transactional_object<T>* temp = tx_->get_written(ptr_);
// if we found something, store this as the tx_ptr_
if (0 != temp) {
- tx_ptr_ = temp;
+ ptr_ = temp;
written_ = true;
} else {
- tx_ptr_ = &tx_ptr_->transaction_->write(*tx_ptr_);
+ ptr_ = tx_->write_ptr(ptr_);
written_ = true;
}
- return tx_ptr_;
+ return ptr_;
}
-private:
- mutable transactional_object<T> const *tx_ptr_;
+//private:
+ mutable transaction* tx_;
+ mutable transactional_object<T>* ptr_;
mutable bool written_;
};
+template <typename T>
+void delete_ptr(upgrd_ptr<T> ptr) {
+ if (ptr.ptr_==0) return;
+ if (ptr.ptr_->transaction_==0) delete ptr.ptr_;
+ ptr.ptr_->transaction_->delete_tx_ptr(ptr.ptr_);
+}
+
//-----------------------------------------------------------------------------
+// A wr_ptr<T> ("write pointer") points to a shared object that the current transaction has opened for writing.
+// A wr_ptr<T> is initialized explicitly from an sh_ptr<T>.
+// A wr_ptr<T> can also be explicitly constructed from a upgrd_ptr<T> as an upgrade-to-writable operation.
//-----------------------------------------------------------------------------
+
template <typename T>
class wr_ptr {
+ typedef tx_ptr<T> this_type;
public:
- inline wr_ptr(transaction &t, tx_ptr<T> & tx_obj) :
- tx_obj_(t.write(*tx_obj.ptr_))
+ inline wr_ptr(transaction &t, tx_ptr<T> tx_obj) :
+ ptr_(t.write_ptr(tx_obj.ptr_))
{}
- inline T& operator*() {
- if (tx_obj_.transaction_->forced_to_abort()) {
- tx_obj_.transaction_->lock_and_abort();
- throw aborted_transaction_exception("aborting transaction");
- }
- return tx_obj_.value;
+ inline wr_ptr(transaction &t, upgrd_ptr<T> tx_obj) :
+ ptr_(t.write_ptr(tx_obj.ptr_))
+ {
+ tx_obj.write_ptr(ptr_);
}
- inline T* operator->() {
- if (tx_obj_.transaction_->forced_to_abort()) {
- tx_obj_.transaction_->lock_and_abort();
+ T* get() {
+ if (ptr_->transaction_->forced_to_abort()) {
+ ptr_->transaction_->lock_and_abort();
throw aborted_transaction_exception("aborting transaction");
}
- return &tx_obj_.value;
+ return &ptr_->value;
}
+
+ inline T& operator*() { return *get(); }
+ inline T* operator->() { return get(); }
-private:
- mutable transactional_object<T> &tx_obj_;
+ operator const T*() const { return get(); }
+
+ typedef transactional_object<T>* this_type::*unspecified_bool_type;
+
+ #if 0
+ operator unspecified_bool_type() const
+ {
+ return ptr_ == 0? 0: &this_type::ptr_;
+ }
+ #endif
+//private:
+ mutable transactional_object<T>* ptr_;
};
+template <typename T>
+wr_ptr<T> make_wr_ptr(transaction& tx, tx_ptr<T>& ptr) {
+ return wr_ptr<T>(tx, ptr);
+}
+
+
+template <typename T>
+wr_ptr<T> make_wr_ptr(tx_ptr<T>& ptr) {
+ transaction* tx = transaction::current_transaction();
+ if (tx==0) throw "error";
+ return wr_ptr<T>(*tx, ptr);
+}
+
+template <typename T>
+void delete_ptr(wr_ptr<T> ptr) {
+ if (ptr.ptr_==0) return;
+ if (ptr.ptr_->transaction_==0) delete ptr.ptr_;
+ ptr.ptr_->transaction_->delete_tx_ptr(ptr.ptr_);
+}
+
+
+//=========================
template <typename T>
class read_ptr
Modified: sandbox/stm/branches/vbe/boost/stm/transaction.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/transaction.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/transaction.hpp 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -70,6 +70,7 @@
//-----------------------------------------------------------------------------
namespace boost { namespace stm {
+
#if defined(BOOST_STM_CM_STATIC_CONF)
#if defined(BOOST_STM_CM_STATIC_CONF_ExceptAndBackOffOnAbortNoticeCM)
typedef except_and_back_off_on_abort_notice_cm contention_manager_type;
@@ -171,39 +172,32 @@
typedef std::multimap<size_t, MemoryContainerList > DeletionBuffer;
-#if 0
-#ifndef BOOST_STM_USE_BOOST_MUTEX
- typedef pthread_mutex_t Mutex;
-#else
- typedef boost::mutex Mutex;
-#endif
-#endif
- typedef std::set<Mutex*> MutexSet;
+ typedef std::set<Mutex*> MutexSet;
typedef std::set<size_t> ThreadIdSet;
typedef std::map<size_t, MemoryContainerList*> ThreadMemoryContainerList;
typedef std::pair<size_t, Mutex*> thread_mutex_pair;
-#ifndef MAP_THREAD_MUTEX_CONTAINER
- typedef vector_map<size_t, Mutex*> ThreadMutexContainer;
-#else
- typedef std::map<size_t, Mutex*> ThreadMutexContainer;
-#endif
+ #ifndef MAP_THREAD_MUTEX_CONTAINER
+ typedef vector_map<size_t, Mutex*> ThreadMutexContainer;
+ #else
+ typedef std::map<size_t, Mutex*> ThreadMutexContainer;
+ #endif
typedef std::map<size_t, MutexSet* > ThreadMutexSetContainer;
typedef std::map<size_t, bloom_filter*> ThreadBloomFilterList;
-#ifdef BOOST_STM_BLOOM_FILTER_USE_DYNAMIC_BITSET
-typedef std::map<size_t, boost::dynamic_bitset<>*> ThreadBitVectorList;
-#else
-typedef std::map<size_t, bit_vector*> ThreadBitVectorList;
-#endif
+ #ifdef BOOST_STM_BLOOM_FILTER_USE_DYNAMIC_BITSET
+ typedef std::map<size_t, boost::dynamic_bitset<>*> ThreadBitVectorList;
+ #else
+ typedef std::map<size_t, bit_vector*> ThreadBitVectorList;
+ #endif
typedef std::pair<size_t, int*> thread_bool_pair;
-#ifndef MAP_THREAD_BOOL_CONTAINER
+ #ifndef MAP_THREAD_BOOL_CONTAINER
typedef vector_map<size_t, int*> ThreadBoolContainer;
-#else
+ #else
typedef std::map<size_t, int*> ThreadBoolContainer;
-#endif
+ #endif
typedef std::map<Mutex*, ThreadIdSet > MutexThreadSetMap;
typedef std::map<Mutex*, size_t> MutexThreadMap;
@@ -213,24 +207,24 @@
typedef InflightTxes in_flight_transaction_container;
typedef in_flight_transaction_container in_flight_trans_cont;
-#ifdef USE_SINGLE_THREAD_CONTEXT_MAP
- struct tx_context
- {
-#if defined(BOOST_STM_USE_UNASIGNED_COPY) && defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
+ #ifdef USE_SINGLE_THREAD_CONTEXT_MAP
+ struct tx_context
+ {
+ #if defined(BOOST_STM_USE_UNASIGNED_COPY) && defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
monotonic_storage<6*1000*1000> mstorage_;
-#endif
- MemoryContainerList newMem;
- MemoryContainerList delMem;
- WriteContainer writeMem;
- bloom_filter wbloom;
- bloom_filter bloom;
- TxType txType;
+ #endif
+ MemoryContainerList newMem;
+ MemoryContainerList delMem;
+ WriteContainer writeMem;
+ bloom_filter wbloom;
+ bloom_filter bloom;
+ TxType txType;
- int abort;
- };
+ int abort;
+ };
-#ifdef BOOST_STM_HAVE_SINGLE_TSS_CONTEXT_MAP
+ #ifdef BOOST_STM_HAVE_SINGLE_TSS_CONTEXT_MAP
// thread specific data
struct tss_context
@@ -238,23 +232,23 @@
inline tss_context()
: tx_()
, transactions()
-#ifndef BOOST_STM_USE_BOOST_MUTEX
-#if WIN32
+ #ifndef BOOST_STM_USE_BOOST_MUTEX
+ #if WIN32
, mutex_(PTHREAD_MUTEX_INITIALIZER)
-#endif
-#else
+ #endif
+ #else
, mutex_()
-#endif
+ #endif
-#if PERFORMING_LATM
+ #if PERFORMING_LATM
, blocked_(false)
-#endif
+ #endif
{
// the current transaction is 0
transactions.push(0);
-#ifndef BOOST_STM_USE_BOOST_MUTEX
+ #ifndef BOOST_STM_USE_BOOST_MUTEX
pthread_mutex_init(&mutex_, 0);
-#endif
+ #endif
}
inline ~tss_context() {
pthread_mutex_destroy(&mutex_);
@@ -263,26 +257,26 @@
tx_context tx_;
TransactionStack transactions;
Mutex mutex_;
-#if PERFORMING_LATM
+ #if PERFORMING_LATM
int blocked_;
-#endif
-#if PERFORMING_LATM
-#if USING_TRANSACTION_SPECIFIC_LATM
+ #endif
+ #if PERFORMING_LATM
+ #if USING_TRANSACTION_SPECIFIC_LATM
MutexSet conflictingMutex_;
-#endif
+ #endif
MutexSet obtainedLocks_;
MutexSet currentlyLockedLocks_;
-#endif
- };
+ #endif
+ };
-#endif
+ #endif
-#ifndef BOOST_STM_HAVE_SINGLE_TSS_CONTEXT_MAP
- typedef std::map<size_t, tx_context*> tss_context_map_type;
-#else
- typedef std::map<size_t, tss_context*> tss_context_map_type;
-#endif
-#endif
+ #ifndef BOOST_STM_HAVE_SINGLE_TSS_CONTEXT_MAP
+ typedef std::map<size_t, tx_context*> tss_context_map_type;
+ #else
+ typedef std::map<size_t, tss_context*> tss_context_map_type;
+ #endif
+ #endif
//--------------------------------------------------------------------------
// transaction static methods
@@ -290,7 +284,7 @@
static void initialize();
static void initialize_thread();
static void terminate_thread();
-#if defined(BOOST_STM_CM_STATIC_CONF)
+ #if defined(BOOST_STM_CM_STATIC_CONF)
//static contention_manager_type cm_;
//inline static void contention_manager(base_contention_manager *rhs) { delete cm_; cm_ = rhs; }
inline static contention_manager_type* get_contention_manager() {
@@ -319,7 +313,7 @@
static void cm_perform_isolated_tx_wait_priority_promotion(transaction &t) {return contention_manager_type::perform_isolated_tx_wait_priority_promotion(t); }
static void cm_perform_irrevocable_tx_wait_priority_promotion(transaction &t) {return contention_manager_type::perform_irrevocable_tx_wait_priority_promotion(t); }
-#else
+ #else
static base_contention_manager *cm_;
inline static void contention_manager(base_contention_manager *rhs) { delete cm_; cm_ = rhs; }
inline static base_contention_manager* get_contention_manager() { return cm_; }
@@ -346,7 +340,7 @@
static void cm_perform_isolated_tx_wait_priority_promotion(transaction &t) {return cm_->perform_isolated_tx_wait_priority_promotion(t); }
static void cm_perform_irrevocable_tx_wait_priority_promotion(transaction &t) {return cm_->perform_irrevocable_tx_wait_priority_promotion(t); }
-#endif
+ #endif
inline static void enableLoggingOfAbortAndCommitSetSize() { bookkeeping_.setIsLoggingAbortAndCommitSize(true); }
inline static void disableLoggingOfAbortAndCommitSetSize() { bookkeeping_.setIsLoggingAbortAndCommitSize(false); }
@@ -407,9 +401,9 @@
inline static bool validating()
{
-#ifdef PERFORMING_VALIDATION
+ #ifdef PERFORMING_VALIDATION
return true;
-#endif
+ #endif
return false;
}
@@ -458,7 +452,7 @@
static bool doing_tx_lock_protection();
-#ifdef WIN32
+ #ifdef WIN32
template <typename T>
inline static int lock_(T *lock) { throw "unsupported lock type"; }
@@ -485,7 +479,7 @@
template <>
inline static int unlock_(Mutex *lock) { return pthread_unlock(lock); }
-#else
+ #else
inline static int lock_(PLOCK &lock) { return pthread_lock(&lock); }
inline static int lock_(PLOCK *lock) { return pthread_lock(lock); }
@@ -494,7 +488,7 @@
inline static int unlock_(PLOCK &lock) { return pthread_unlock(&lock); }
inline static int unlock_(PLOCK *lock) { return pthread_unlock(lock); }
-#endif
+ #endif
static int pthread_lock(Mutex *lock);
static int pthread_trylock(Mutex *lock);
@@ -503,7 +497,7 @@
//--------------------------------------------------------------------------
-#if PERFORMING_LATM
+ #if PERFORMING_LATM
//--------------------------------------------------------------------------
inline static void tm_lock_conflict(Mutex &lock)
{
@@ -517,7 +511,7 @@
void must_be_in_conflicting_lock_set(Mutex *inLock);
static void must_be_in_tm_conflicting_lock_set(Mutex *inLock);
-#if USING_TRANSACTION_SPECIFIC_LATM
+ #if USING_TRANSACTION_SPECIFIC_LATM
void see_if_tx_must_block_due_to_tx_latm();
inline void lock_conflict(Mutex &lock)
@@ -534,7 +528,7 @@
void clear_tx_conflicting_locks();
//MutexSet get_tx_conflicting_locks() { return conflictingMutexRef_; }
-#endif
+ #endif
void add_to_obtained_locks(Mutex* );
static void unblock_conflicting_threads(Mutex *mutex);
@@ -546,7 +540,7 @@
void remove_from_currently_locked_locks(Mutex *m);
bool is_currently_locked_lock(Mutex *m);
bool is_on_obtained_locks_list(Mutex *m);
-#endif
+ #endif
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
@@ -624,9 +618,9 @@
// transaction is direct or deferred.
//
//--------------------------------------------------------------------------
-#ifndef DISABLE_READ_SETS
+ #ifndef DISABLE_READ_SETS
inline size_t const read_set_size() const { return readListRef_.size(); }
-#endif
+ #endif
inline size_t const writes() const { return write_list()->size(); }
inline bool written() const {return !write_list()->empty();}
@@ -660,21 +654,21 @@
}
}
- //--------------------------------------------------------------------------
- template <typename T>
- inline bool has_been_read(T const & in)
- {
-#ifndef DISABLE_READ_SETS
- ReadContainer::iterator i = readList().find
- (static_cast<base_transaction_object*>(&in));
- //----------------------------------------------------------------
- // if this object is already in our read list, bail
- //----------------------------------------------------------------
- return i != readList().end();
-#else
- return bloom().exists((size_t)&in);
-#endif
- }
+ //--------------------------------------------------------------------------
+ template <typename T>
+ inline bool has_been_read(T const & in)
+ {
+ #ifndef DISABLE_READ_SETS
+ ReadContainer::iterator i = readList().find
+ (static_cast<base_transaction_object*>(&in));
+ //----------------------------------------------------------------
+ // if this object is already in our read list, bail
+ //----------------------------------------------------------------
+ return i != readList().end();
+ #else
+ return bloom().exists((size_t)&in);
+ #endif
+ }
//--------------------------------------------------------------------------
template <typename T>
@@ -738,6 +732,11 @@
}
}
+ template <typename T>
+ inline void delete_tx_ptr(T *in) {
+ delete_memory(*in);
+ }
+
//--------------------------------------------------------------------------
// allocation of new memory behaves the same for both deferred and direct
// transaction implementations
@@ -906,50 +905,7 @@
inline size_t const & thread_id() const { return threadId_; }
private:
-
-template <class T> T* cache_allocate() {
-#if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER)
- return reinterpret_cast<T*>(T::retrieve_mem(sizeof(T)));
-#elif defined(BOOST_STM_CACHE_USE_MALLOC)
- return reinterpret_cast<T*>(malloc(sizeof(T)));
-#elif defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
- return reinterpret_cast<T*>(context_.mstorage_.allocate<T>());
-#else
- #error "BOOST_STM_CACHE_USE_MEMORY_MANAGER or BOOST_STM_CACHE_USE_MALLOC must be defined"
-#endif
-}
-
-inline void cache_release(base_transaction_object* ptr) {
-#ifdef BOOST_STM_USE_UNASIGNED_COPY
- if (ptr) {
- #if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER)
- ptr->return_this_mem();
-#elif defined(BOOST_STM_CACHE_USE_MALLOC)
- free(ptr);
-#elif defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
-#else
- #error "BOOST_STM_CACHE_USE_MEMORY_MANAGER or BOOST_STM_CACHE_USE_MALLOC must be defined"#endif
-#endif
- }
-#else
- delete ptr;
-#endif
-}
-template <class T> T* cache_new_copy(const T& val) {
-#ifdef BOOST_STM_USE_UNASIGNED_COPY
- T* p = cache_allocate<T>();
- if (p==0) {
- //std::cout << __LINE__ << " malloc ERROR" << std::endl;
- throw std::bad_alloc();
- }
- std::uninitialized_copy(&val,(&val)+1, p);
- return p;
-#else
- return new T(val);
-#endif
-}
-
-
+
#ifdef LOGGING_BLOCKS
static std::string outputBlockedThreadsAndLockedLocks();
@@ -2056,16 +2012,213 @@
inline transaction_state const & state() const { return state_; }
inline WriteContainer& writeList() { return *write_list(); }
-#ifndef DISABLE_READ_SETS
+ #ifndef DISABLE_READ_SETS
inline ReadContainer& readList() { return readListRef_; }
-#endif
+ #endif
public:
- inline static transaction* transaction::current_transaction() {return transactions(THREAD_ID).top();}
+ inline static transaction* current_transaction() {return transactions(THREAD_ID).top();}
+
+
+};
+
+#ifdef BOOST_STM_USE_UNASIGNED_COPY
+template <class T> T* cache_allocate() {
+ #if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER)
+ return reinterpret_cast<T*>(T::retrieve_mem(sizeof(T)));
+ #elif defined(BOOST_STM_CACHE_USE_MALLOC)
+ return reinterpret_cast<T*>(malloc(sizeof(T)));
+ #elif defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
+ return reinterpret_cast<T*>(context_.mstorage_.allocate<T>());
+ #else
+ #error "BOOST_STM_CACHE_USE_MEMORY_MANAGER, BOOST_STM_CACHE_USE_MALLOC or BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER must be defined"
+ #endif
+}
+
+// this function must be specialized for objects that are non transactional
+// by deleting the object
+
+#ifdef BOOST_STM_NO_PARTIAL_SPECIALIZATION
+namespace partial_specialization_workaround {
+template <class T>
+struct cache_deallocate;
+
+template <class T>
+struct cache_deallocate {
+ static void apply(T* ptr) {
+ if (ptr) {
+ #if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER)
+ //ptr->return_this_mem();
+ base_transaction_object::return_mem(ptr,sizeof(T));
+ #elif defined(BOOST_STM_CACHE_USE_MALLOC)
+ free(ptr);
+ #elif defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
+ #else
+ #error "BOOST_STM_CACHE_USE_MEMORY_MANAGER, BOOST_STM_CACHE_USE_MALLOC or BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER must be defined"
+ #endif
+ }
+ }
+};
+template <class T>
+struct cache_deallocate<transactional_object<std::vector<T> > > {
+ static void apply(transactional_object<std::vector<T> >* ptr) {
+ delete ptr;
+ }
+};
+
+}
+
+template <class T> void cache_deallocate(T*ptr) {
+ partial_specialization_workaround::cache_deallocate<T>::apply(ptr);
+}
+
+#else //!BOOST_STM_NO_PARTIAL_SPECIALIZATION
+
+template <class T>
+inline void cache_deallocate(transactional_object<std::vector<T> >* ptr) {
+ delete ptr;
+}
+
+template <class T>
+inline void cache_deallocate(T* ptr) {
+ if (ptr) {
+ #if defined(BOOST_STM_CACHE_USE_MEMORY_MANAGER)
+ //ptr->return_this_mem();
+ base_transaction_object::return_mem(ptr,sizeof(T));
+ #elif defined(BOOST_STM_CACHE_USE_MALLOC)
+ free(ptr);
+ #elif defined(BOOST_STM_CACHE_USE_TSS_MONOTONIC_MEMORY_MANAGER)
+ #else
+ #error "BOOST_STM_CACHE_USE_MEMORY_MANAGER or BOOST_STM_CACHE_USE_MALLOC must be defined"#endif
+ #endif
+ }
+}
+#endif //BOOST_STM_NO_PARTIAL_SPECIALIZATION
+
+// this function must be specialized for objects that are non transactional,
+// by calling to new of the copy constructor
+
+#ifdef BOOST_STM_NO_PARTIAL_SPECIALIZATION
+namespace partial_specialization_workaround {
+template <class T>
+struct cache_new_copy_constructor;
+template <class T>
+struct cache_new_copy_constructor {
+ static inline T* apply(const T& val) {
+ T* p = cache_allocate<T>();
+ if (p==0) {
+ //std::cout << __LINE__ << " malloc ERROR" << std::endl;
+ throw std::bad_alloc();
+ }
+ boost::stm::cache_restore(&val, p);
+ //std::uninitialized_copy(&val,(&val)+1, p);
+ return p;
+ }
+};
+
+template <class T, class A>
+struct cache_new_copy_constructor<transactional_object<std::vector<T,A> > > {
+ static inline transactional_object<std::vector<T,A> >* apply(const transactional_object<std::vector<T,A> >& val) {
+ return new transactional_object<std::vector<T,A> >(val);
+ }
+};
+} // partial_specialization_workaround
+
+template <class T>
+inline T* cache_new_copy_constructor(const T& val) {
+ return partial_specialization_workaround::cache_new_copy_constructor<T>::apply(val);
+}
+#else //BOOST_STM_NO_PARTIAL_SPECIALIZATION
+
+template <class T>
+inline transactional_object<std::vector<T> >* cache_new_copy_constructor(const transactional_object<std::vector<T> >& val) {
+ return new transactional_object<std::vector<T> >(val);
+}
+
+template <class T>
+inline T* cache_new_copy_constructor(const T& val) {
+ T* p = cache_allocate<T>();
+ if (p==0) {
+ //std::cout << __LINE__ << " malloc ERROR" << std::endl;
+ throw std::bad_alloc();
+ }
+ cache_restore(&val, p);
+ //std::uninitialized_copy(&val,(&val)+1, p);
+ return p;
+}
+#endif // BOOST_STM_NO_PARTIAL_SPECIALIZATION
+#endif // BOOST_STM_USE_UNASIGNED_COPY
+
+inline void cache_release(base_transaction_object* ptr) {
+#ifdef BOOST_STM_USE_UNASIGNED_COPY
+ //cache_deallocate(ptr);
+ ptr->cache_deallocate();
+#else
+ delete ptr;
+#endif
+}
+
+template <class T>
+inline T* cache_new_copy(const T& val) {
+#ifdef BOOST_STM_USE_UNASIGNED_COPY
+ return cache_new_copy_constructor(val);
+#else
+ return new T(val);
+#endif
+}
+
+template <class T> void cache_restore(const T* const ori, T* target);
+// When BOOST_STM_USE_UNASIGNED_COPY is defined
+// this function must be specialized for objects that are non transactional by deleting the object, e.g.
+
+#ifdef BOOST_STM_NO_PARTIAL_SPECIALIZATION
+#ifdef BOOST_STM_USE_UNASIGNED_COPY
+namespace partial_specialization_workaround {
+template <class T> struct cache_restore;
+
+
+template <class T>
+struct cache_restore {
+ static inline void apply(const T* const ori, T* target) {
+ std::uninitialized_copy(ori,ori+1, target);
+ }
+};
+template <class T>
+struct cache_restore<transactional_object<std::vector<T> > > {
+ static inline void apply(const transactional_object<std::vector<T> >* const ori, transactional_object<std::vector<T> >* target) {
+ *target=*ori;
+ }
};
+} // partial_specialization_workaround
+#endif
+
+template <class T> void cache_restore(const T* const ori, T* target) {
+#ifdef BOOST_STM_USE_UNASIGNED_COPY
+ partial_specialization_workaround::cache_restore<T>::apply(ori, target);
+#else
+ *target=*ori;
+#endif
+}
+
+#else
+#ifdef BOOST_STM_USE_UNASIGNED_COPY
+template <class T> void cache_restore(const transactional_object<std::vector<T> >* const ori, transactional_object<std::vector<T> >* target) {
+ *target=*ori;
+}
+#endif
+
+template <class T> void cache_restore(const T* const ori, T* target) {
+#ifdef BOOST_STM_USE_UNASIGNED_COPY
+ std::uninitialized_copy(ori,ori+1, target);
+#else
+ *target=*ori;
+#endif
+}
+#endif
+
struct thread_initializer {
thread_initializer() {transaction::initialize_thread();}
Modified: sandbox/stm/branches/vbe/libs/stm/example/bank.cpp
==============================================================================
--- sandbox/stm/branches/vbe/libs/stm/example/bank.cpp (original)
+++ sandbox/stm/branches/vbe/libs/stm/example/bank.cpp 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -49,6 +49,8 @@
}
};
+typedef BankAccount account;
+
struct bank{ //persistent object
vector<tx_ptr<BankAccount> > accounts;
int overall_balance() const{
@@ -61,83 +63,208 @@
void print_balance() const{
foreach(BankAccount const* a,this->accounts){
cerr << a->Nb() << "=" << a->Balance() << endl;
-
}
}
};
struct teller {
- teller(tx_ptr<bank> const &b)
- : bank_(b){}
+ teller(bank* b)
+ : bank_(b){
+ cerr << "teller this=" <<this<< endl;
+ cerr << "ptr=" <<bank_<< endl;
+ cerr << "size=" <<bank_->accounts.size()<< endl;
+ }
+ ~teller() {
+ cerr << "~this=" <<this<< endl;
+ }
void operator()(){ //thread start
- //thread_initializer thi;
- transaction::initialize_thread();
+ cerr << "this=" <<this<< endl;
+ cerr << "start"<< endl;
+ thread_initializer thi;
+ cerr << "initialize_thread"<< endl;
//while(!exit)
- for(int i=100; i>0;--i)
+ for(int i=10; i>0;--i)
{
+ cerr << "c="<< i<<endl;
atomic(_) {
int amount=random() % 1000;
#if 0
tx_ptr<bank> rd_bank(bank_);
#else
- rd_ptr<bank> rd_bank(_,bank_);
+ //rd_ptr<bank> rd_bank(_,bank_);
+ bank* rd_bank = bank_;
+ //cerr << "rd_bank"<< endl;
#endif
+ //cerr << "ptr=" <<rd_bank<< endl;
+ //cerr << "size=" <<rd_bank->accounts.size()<< endl;
int acc1=random() % rd_bank->accounts.size();
int acc2=random() % rd_bank->accounts.size();
rd_bank->accounts[acc1]->Withdraw(amount);
- rd_bank->accounts[acc2]->Deposit(amount);
+ rd_bank->accounts[acc2]->Deposit(amount+1);
} catch(...) {
cerr << "aborted"<< endl;
}
}
- transaction::terminate_thread();
+ cerr << "ptr=" <<bank_<< endl;
+ cerr << "size=" <<bank_->accounts.size()<< endl;
+ cerr << "balance=" <<bank_->overall_balance()<< endl;
+ cerr << "end"<< endl;
}
- tx_ptr<bank> const & bank_;
+ bank* bank_;
static bool volatile exit;
};
bool volatile teller::exit=false;
-void create_db(tx_ptr<bank> &mybank, int nr_of_accounts){
- use_atomic(_) {
+void create_db(bank* b, int nr_of_accounts){
+ //use_atomic(_)
+ {
for(int c=0;c<nr_of_accounts;++c){
+ //cerr << "c=" <<c<< endl;
tx_ptr<BankAccount> acc(make_tx_ptr<BankAccount>(c));
- mybank->accounts.push_back(acc);
+ //cerr << "ptr=" <<acc.ptr_<< endl;
+ b->accounts.push_back(acc);
+ //cerr << "size=" <<mybank->accounts.size()<< endl;
}
}
}
-
-int main() {
- transaction::enable_dynamic_priority_assignment();
- transaction::do_deferred_updating();
- transaction::initialize();
- transaction::initialize_thread();
- //thread_initializer thi;
- srand(time(0));
+tx_ptr<BankAccount> a;
+void account_withdraw_thr_basic() {
+ thread_initializer thi;
+ use_atomic(_) {
+ a->Withdraw(10);
+ }
+}
+void account_withdraw_thr() {
+ thread_initializer thi;
+ use_atomic(_) {
+ make_wr_ptr(_,a)->Withdraw(10);
+ }
+}
+
+void account_deposit_thr_basic() {
+ thread_initializer thi;
+ use_atomic(_) {
+ a->Deposit(10);
+ }
+}
+void account_deposit_thr() {
+ thread_initializer thi;
+ use_atomic(_) {
+ make_wr_ptr(_,a)->Deposit(10);
+ }
+}
+
+int test_account() {
+ a=make_tx_ptr<account>(1);
+ thread th1(account_withdraw_thr);
+ thread th2(account_deposit_thr);
+ thread th3(account_withdraw_thr_basic);
+ thread th4(account_deposit_thr_basic);
+
+ th1.join();
+ th2.join();
+ th3.join();
+ th4.join();
+ cerr << "ptr=" << a.ptr_ << " nb=" << a->Nb() << " bal=" << a->Balance() << endl;
+ int res = (a->Balance()==0?0:1);
+ //boost::stm::delete_ptr(a);
+ return res;
+}
+
+tx_ptr<std::vector<int> > v;
+
+void vector_int_assign_basic() {
+ thread_initializer thi;
+ use_atomic(_) {
+ (*v)[0]+=10;
+ }
+}
+
+void vector_int_assign() {
+ thread_initializer thi;
+ use_atomic(_) {
+ wr_ptr<std::vector<int> > wrv(_,v);
+ (*wrv)[0]+=10;
+ }
+}
+
+int test_vector_int() {
+ v=make_tx_ptr<std::vector<int> >();
+ cerr << "ptr=" << v.ptr_ << endl;
+ v->push_back(10);
+ cerr << "ptr=" << v.ptr_ << " v[0]=" << v.ptr_->value[0] << endl;
+
+ thread th1(vector_int_assign);
+ thread th2(vector_int_assign_basic);
+ thread th3(vector_int_assign);
+
+ th1.join();
+ th2.join();
+ th3.join();
+ cerr << "ptr=" << v.ptr_ << " v[0]=" << (*v)[0] << endl;
+ //cerr << "ptr=" << v.ptr_ << " v[0]=" << v.ptr_->value[0] << endl;
+ //cerr << "ptr=" << v.ptr_ << " v[0]=" << 0 << endl;
+ int res = ((*v)[0]==40?0:1);
+
+ //boost::stm::delete_ptr(v);
+ return res;
+}
+
+
+int test_xxxx() {
+ string wait;
- int nr_of_threads=10;
+ //int nr_of_threads=10;
int nr_of_accounts=200;
- tx_ptr<bank> mybank(make_tx_ptr<bank>());
+ cerr << __LINE__ << endl;
+ //cin >> wait;teller::exit=true;
+ bank abank;
+ bank* mybank=&abank;
create_db(mybank,nr_of_accounts);
-
- cerr << "overall balance before: " << mybank->overall_balance() << endl;
- string wait;
-#if 0
- thread* th1= new thread(teller(mybank));
- thread* th2= new thread(teller(mybank));
+ cerr << __LINE__ << endl;
+ //cin >> wait;teller::exit=true;
+ //use_atomic(_)
+ {
+
+ //cerr << "size=" <<mybank.ptr_->value.accounts.size()<< endl;
+ cerr << __LINE__ << " size=" <<mybank->accounts.size()<< endl;
+ cerr << __LINE__ << " overall balance before: " << mybank->overall_balance() << endl;
+ }
+
+#if 0
+ mybank->accounts[0]->Withdraw(10);
+ mybank->accounts[1]->Deposit(100);
+#endif
+#if 0
+ teller t(mybank);
+ t();
+ //cerr << "size=" <<mybank->accounts.size()<< endl;
+ //cerr << "overall balance before: " << mybank->overall_balance() << endl;
+ cerr << __LINE__ << endl;
+#endif
+#if 1
+ teller t(mybank);
+ cerr << "t=" <<&t<< endl;
+ thread* th1= new thread(boost::ref(t));
+ //thread* th2= new thread(teller(mybank));
cin >> wait;teller::exit=true;
+ cerr << __LINE__ << endl;
th1->join();
delete th1;
- th2->join();
- delete th2;
-#endif
+ //th2->join();
+ //delete th2;
+ use_atomic(_) {
cerr << "overall balance after: " << mybank->overall_balance() << endl;
cerr << "balances after: " <<endl;
mybank->print_balance();
+ }
+#endif
+#if 0
list<shared_ptr<thread> > threads;
@@ -156,9 +283,22 @@
cerr << "overall balance after: " << mybank->overall_balance() << endl;
cerr << "balances after: " << endl;
mybank->print_balance();
+#endif
- transaction::terminate_thread();
- return 0;
-
+ return 0;
}
+int main() {
+ transaction::enable_dynamic_priority_assignment();
+ transaction::do_deferred_updating();
+ transaction::initialize();
+ thread_initializer thi;
+ srand(time(0));
+
+ int res=0;
+ res+=test_account();
+ res+=test_vector_int();
+
+ return res;
+
+}
Added: sandbox/stm/branches/vbe/libs/stm/example/counter.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/branches/vbe/libs/stm/example/counter.cpp 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -0,0 +1,74 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Justin E. Gottchlich 2009.
+// (C) Copyright Vicente J. Botet Escriba 2009.
+// Distributed under the Boost
+// Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/synchro for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/stm.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread.hpp>
+#include <boost/shared_ptr.hpp>
+//#include <string>
+#include <vector>
+#include <list>
+//#include <iostream>
+#include <stdlib.h>
+#define foreach BOOST_FOREACH
+
+using namespace std;
+using namespace boost;
+using namespace boost::stm;
+
+stm::tx_ptr<int> counter;
+
+void inc() {
+ thread_initializer thi;
+
+ use_atomic(_) {
+ *counter+=*counter;
+ }
+}
+void check() {
+ //thread_initializer thi;
+
+ use_atomic(_) {
+ assert(*counter==4);
+ }
+}
+int test_counter() {
+ counter=make_tx_ptr<int>(0);
+
+ thread th1(inc);
+ thread th2(inc);
+ thread th3(inc);
+ thread th4(inc);
+
+ th1.join();
+ th2.join();
+ th3.join();
+ th4.join();
+
+ check();
+ boost::stm::delete_ptr(counter);
+ return 0;
+}
+
+int main() {
+ transaction::enable_dynamic_priority_assignment();
+ transaction::do_deferred_updating();
+ transaction::initialize();
+ thread_initializer thi;
+ srand(time(0));
+
+ test_counter();
+
+ return 0;
+
+}
Modified: sandbox/stm/branches/vbe/libs/stm/example/list.cpp
==============================================================================
--- sandbox/stm/branches/vbe/libs/stm/example/list.cpp (original)
+++ sandbox/stm/branches/vbe/libs/stm/example/list.cpp 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -1,72 +1,4 @@
-
-
-class BankAccount
-{
-protected:
- int nb_;
- int balance_;
-public:
- BankAccount(int bnb) : nb_(nb), balance_(0) {}
- BankAccount(const BankAccount &rhs) {
- atomic(_) balance_=rhs.balance_;
- }
-
- BankAccount& operator=(BankAccount &rhs)
- {
- if(&rhs == this) return *this;
-
- atomic(_) {
- balance_=rhs.balance_;
- return *this;
- }
- }
-
- void Deposit(int amount) {
- atomic(_) balance_ += amount;
- }
- int Withdraw(int amount) {
- atomic(_) {
- balance_ -= amount;
- return amount;
- }
- }
- int GetBalance() {
- atomic(_) return balance_;
- }
-};
-
-tx_ptr<BankAccount> JoesAccount(new transactional_object<BankAccount>(0));
-tx_ptr<BankAccount> A(new transactional_object<BankAccount>(1));
-tx_ptr<BankAccount> B(new transactional_object<BankAccount>(2));
-
-void bankAgent()
-{
- for (int i =10; i>0; --i) {
- //...
- atomic(_) JoesAccount->Deposit(500);
- //...
- }
-}
-
-void Joe() {
- for (int i =10; i>0; --i) {
- //...
- int myPocket;
- atomic(_) {
- myPocket= JoesAccount->Withdraw(100);
- }
- std::cout << myPocket << std::endl;
- //...
- }
-}
-
- atomic(_) {
- *B = *A;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Justin E. Gottchlich 2009.
// (C) Copyright Vicente J. Botet Escriba 2009.
@@ -80,432 +12,185 @@
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-#ifndef TEST_LINKED_LIST_H
-#define TEST_LINKED_LIST_H
-
-//#define BOOST_STM_USES_AS_NEW 1
-//#define BOOST_STM_USES_PARAM 1
-#define BOOST_STM_LL_USES_NODE 1
-#include "main.h"
-#include <boost/stm/transaction.hpp>
+#include <boost/stm.hpp>
+#include <boost/thread.hpp>
+#include <stdlib.h>
+
+using namespace std;
+using namespace boost;
+using namespace boost::stm;
+
+#define BOOST_STM_NEW(T, P) \
+ ((T).throw_if_forced_to_abort_on_new(), \
+ (T).as_new(new P))
-#include <fstream>
+#define BOOST_STM_NEW_1(P) \
+ ((boost::stm::transaction::current_transaction()!=0)?BOOST_STM_NEW(*boost::stm::transaction::current_transaction(), P):new P)
-#define BIG_SIZE 1000
///////////////////////////////////////////////////////////////////////////////
+namespace test {
template <typename T>
class list_node
{
public:
- list_node() : value_(0), next_(0) {
- }
- explicit list_node(T const &rhs) : value_(rhs), next_(NULL) {
- }
+ list_node() : value_(), next_() {}
+ explicit list_node(T const &rhs) : value_(rhs), next_() {}
+ list_node(T const &rhs, tx_ptr<list_node<T> > next) : value_(rhs), next_(next) {}
// zero initialization for native types
- void clear() { value_ = T(); next_ = NULL; }
-
- T &value() { return value_; }
- T const &value() const { return value_; }
+ void clear() { value_ = T(); next_ = 0; }
- list_node const *next() const { return next_->get(); }
-
- void next(list_node const *rhs, boost::stm::transaction &t)
- {
- if (NULL == rhs) next_ = NULL;
- else {
- tx_ptr<list_node> tmp(rhs);
- next_ = tmp;
- }
- }
-
-private:
T value_;
- tx_ptr<list_node> next_;
-
+ tx_ptr<list_node<T> > next_;
};
////////////////////////////////////////////////////////////////////////////
template <typename T>
-class LinkedList
+class list
{
public:
typedef tx_ptr<list_node<T> > node_type;
- LinkedList() { head_->value() = T(); }
-
- ~LinkedList() { quick_clear(); }
-
- void move(node_type const &node1, node_type const &node2)
- {
- using namespace boost::stm;
- bool succeeded1 = true, succeeded2 = true;
- transaction_state state = e_no_state;
-
- do
- {
- try
- {
- transaction t;
- succeeded1 = internal_remove(node1);
- succeeded2 = internal_insert(node2);
- t.end();
- }
- catch (aborted_transaction_exception&) {}
-
- if (!succeeded1 || !succeeded2)
- {
- return false; // auto abort of t
- }
-
- } while (e_committed != state);
-
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- bool insert(list_node<T> const &node)
- {
- atomic(_) { return internal_insert(node, t); }
- }
-#ifdef BOOST_STM_USES_PARAM
- bool insert(T val)
-#else
- bool insert(const T& val)
-#endif
- {
- atomic(_) { return internal_insert(val, t); }
- }
- ////////////////////////////////////////////////////////////////////////////
-#ifdef BOOST_STM_USES_PARAM
- bool lookup(T val)
-#else
- bool lookup(T const &val)
-#endif
- {
- atomic(_) { return internal_lookup(val, t); }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- bool remove(list_node<T> const &node)
- {
- atomic(_) { return internal_remove(node, t); }
- }
-
-#ifdef BOOST_STM_USES_PARAM
- bool remove(T val)
-#else
- bool remove(T const &val)
-#endif
- {
- atomic(_) { return internal_remove(val, t); }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- void outputList(std::ofstream &o)
- {
- int i = 0;
- for (list_node<T> const *cur = head_->next(); cur != NULL; cur = cur->next())
- {
- o << "element [" << i++ << "]: " << cur->value() << std::endl;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- int walk_size()
- {
- int i = 0;
- for (list_node<T> const *cur = head_.next(); cur != NULL; cur = cur->next())
- {
- ++i;
- }
-
- return i;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- void quick_clear()
- {
- for (list_node<T> const *cur = head_.next(); cur != NULL;)
- {
- list_node<T> const *prev = cur;
- cur = cur->next();
- delete prev;
- }
-
- head_.clear();
- }
-
- ////////////////////////////////////////////////////////////////////////////
- boost::stm::transaction_state clear()
- {
- atomic(_) {
-
- for (list_node<T> const *cur = head_->next(); cur != NULL;)
- {
- list_node<T> const *prev = cur;
- cur = cur->next();
- prev.delete_memory();
- }
-
- head_->clear();
-
- return t.end();
- }
-
-private:
-
- //--------------------------------------------------------------------------
- // find the location to insert the node. if the value already exists, fail
- //--------------------------------------------------------------------------
- bool internal_insert(node_type n)
- {
- if (0 != head_->next_)
- {
- node_type prev = head_;
- node_type cur = head_->next_;
- T val = n->value_;
-
- while (true)
- {
- if (cur->value_ == val) return false;
- else if (cur->value_ > val || !cur->next_) break;
-
- prev = cur;
-
- node_type curNext = cur->next_;
-
- if (!curNext) break;
-
- cur = curNext;
- }
-
- //--------------------------------------------------------------------
- // if cur->next() is null it means our newNode value is greater than
- // cur, so insert ourselves after cur.
- //--------------------------------------------------------------------
- if (val > cur->value()) cur->next=n;
- //--------------------------------------------------------------------
- // otherwise, we are smaller than cur, so insert between prev and cur
- //--------------------------------------------------------------------
- else
- {
- n->next=cur;
- prev->next_=n;
- }
- }
- else
- {
- head_.next_=n;
- }
-
- return true;
- }
-
-#ifdef BOOST_STM_USES_PARAM
- bool internal_insert(T val, boost::stm::transaction &t)
-#else
- bool internal_insert(const T& val, boost::stm::transaction &t)
-#endif
- {
- //T val = valr;
- if (0 != head_->next())
- {
- node_type_ptr const prev = &head_;
- node_type_ptr const cur = head_->next_;
-
- while (true)
- {
- if (cur->value() == val) return false;
- else if (cur->value() > val || !cur->next()) break;
-
- prev = cur;
-
- node_type_ptr curNext = cur->next();
-
- if (0 == curNext) break;
-
- cur = curNext;
- }
- t.throw_if_forced_to_abort_on_new();
- node_type_ptr newNode(new transactional_object<list_node<T> >(val)));
- //--------------------------------------------------------------------
- // if cur->next() is null it means our newNode value is greater than
- // cur, so insert ourselves after cur.
- //--------------------------------------------------------------------
- if (val > cur->value()) cur->next_ = newNode;
- //--------------------------------------------------------------------
- // otherwise, we are smaller than cur, so insert between prev and cur
- //--------------------------------------------------------------------
- else
- {
- newNode->next= cur;
- prev->next_=newNode;
- }
- }
- else
- {
- t.throw_if_forced_to_abort_on_new();
- node_type_ptr newNode(new transactional_object<list_node<T> >(val)));
- head_->next_ = newNode;
- }
-
- t.end();
- return true;
- }
- //--------------------------------------------------------------------------
- // find the location to insert the node. if the value already exists, bail
- //--------------------------------------------------------------------------
-#ifdef BOOST_STM_USES_PARAM
- bool internal_lookup(T val, boost::stm::transaction &t)
-#else
- bool internal_lookup(T const &val, boost::stm::transaction &t)
-#endif
- {
- node_type_ptr cur = head_;
-
- for (; true ; cur = cur->next() )
- {
- if (cur->value() == val)
- {
- return true;
- }
-
- if (0 == cur->next()) break;
- }
-
- return false;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- bool internal_remove(list_node<T> const &rhs, boost::stm::transaction &t)
- {
- for (rd_ptr<list_node<T> > prev(head_), rd_ptr<list_node<T> > cur(t, prev->next_);
- 0!=cur;
- prev = cur, cur=cur->next_) {
- if (cur->value_ == rhs.value_) {
- wr_ptr<list_node<T> > wr_prev(t, prev);
- wr_prev->next_=cur->next();
- cur.delete_memory();
- return true;
- }
- }
-
- return false;
- }
-
-#ifdef BOOST_STM_USES_PARAM
- bool internal_remove(T value, boost::stm::transaction &t)
-#else
- bool internal_remove(T const &value, boost::stm::transaction &t)
-#endif
- {
- list_node<T> const *prev = &t.read(head_);
-
- for (list_node<T> const *cur = prev; cur != NULL; prev = cur)
- {
- cur = t.read(*cur).next();
-
- if (NULL == cur) break;
-
- if (cur->value() == value)
- {
- list_node<T> const *curNext = t.read(*cur).next();
-
- t.delete_memory(*cur);
- t.write(*(list_node<T>*)prev).next(curNext, t);
- t.end();
- return true;
- }
- }
-
- return false;
- }
- //--------------------------------------------------------------------------
- // find the location to insert the node. if the value already exists, bail
- //--------------------------------------------------------------------------
- bool internal_insert(list_node<T> const &rhs)
- {
- using namespace boost::stm;
- transaction t;
-
- list_node<T> const *headP = &t.read(head_);
-
- if (NULL != headP->next())
- {
- list_node<T> const *prev = headP;
- list_node<T> const *cur = t.read_ptr(headP->next());
- T val = rhs.value();
-
- while (true)
- {
- if (cur->value() == val) return false;
- else if (cur->value() > val || !cur->next()) break;
-
- prev = cur;
-
- list_node<T> const *curNext = t.read_ptr(cur->next());
-
- if (NULL == curNext) break;
-
- cur = curNext;
- }
-
- list_node<T> *newNode = t.new_memory_copy(rhs);
-
- //--------------------------------------------------------------------
- // if cur->next() is null it means our newNode value is greater than
- // cur, so insert ourselves after cur.
- //--------------------------------------------------------------------
- if (NULL == cur->next()) t.write_ptr((list_node<T>*)cur)->next_for_new_mem(newNode, t);
- //--------------------------------------------------------------------
- // otherwise, we are smaller than cur, so insert between prev and cur
- //--------------------------------------------------------------------
- else
- {
- newNode->next(cur, t);
- t.write_ptr((list_node<T>*)prev)->next_for_new_mem(newNode, t);
- }
- }
- else
- {
- list_node<T> *newNode = t.new_memory_copy(rhs);
- t.write(head_).next_for_new_mem(newNode, t);
- }
+ tx_ptr<list_node<T> > head_;
+ tx_ptr<std::size_t> size_;
+ list()
+ : head_(BOOST_STM_NEW_1(transactional_object<list_node<T> >()))
+ , size_(BOOST_STM_NEW_1(transactional_object<std::size_t>(0)))
+ { }
+
+ ~list() { }
+
+ std::size_t size() {
+ std::size_t res=0;
+ use_atomic(_) {
+ rd_ptr<std::size_t> s(_, size_);
+ res=*s;
+ }
+ return res;
+ }
- t.end();
- return true;
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, fail
+ //--------------------------------------------------------------------------
+ void insert(const T& val) {
+ use_atomic(_) {
+ upgrd_ptr<list_node<T> > prev(_, head_);
+ upgrd_ptr<list_node<T> > curr(_, head_->next_);
+ while (curr) {
+ if (curr->value_ == val) return;
+ else if (curr->value_ > val) break;
+ prev = curr;
+ curr = curr->next_;
+ }
+ if (!curr || (curr->value_ > val)) {
+ wr_ptr<list_node<T> > insert_point(_,prev);
+ insert_point->next_=BOOST_STM_NEW(_,transactional_object<list_node<T> >(val, curr));
+ ++(*size_);
+
+ }
+ }
}
- ////////////////////////////////////////////////////////////////////////////
- bool internal_remove(list_node<T> const &rhs)
- {
- using namespace boost::stm;
- transaction t;
-
- list_node<T> const *prev = &t.read(head_);
-
- for (list_node<T> const *cur = prev; cur != NULL;
- prev = cur, cur = t.read(*cur).next())
- {
- if (cur->value() == rhs.value())
- {
- t.write(*(list_node<T>*)prev).next(t.read_ptr(cur)->next(), t);
- t.delete_memory(*cur);
- t.end();
- return true;
- }
- }
+ // search function
+ bool lookup(const T& val) const {
+ bool found = false;
+ use_atomic(_) {
+ rd_ptr<list_node<T> > curr(_, head_);
+ curr = curr->next_;
+ while (curr) {
+ if (curr->value_ >= val) break;
+ curr = curr->next_;
+ }
- return false;
- }
+ found = ((curr) && (curr->value_ == val));
+ }
+ return found;
+ }
- tx_obj<list_node<T> > head_;
+ // remove a node if its value == val
+ void remove(const T& val)
+ {
+ use_atomic(_) {
+ // find the node whose val matches the request
+ upgrd_ptr<list_node<T> > prev(_,head_);
+ upgrd_ptr<list_node<T> > curr(_,prev->next_);
+ while (curr) {
+ // if we find the node, disconnect it and end the search
+ if (curr->value_ == val) {
+ wr_ptr<list_node<T> > mod_point(_,prev);
+ mod_point->next_=curr->next_;
+ // delete curr...
+ delete_ptr(_,curr);
+ --(*size_);
+ break;
+ } else if (curr->value_ > val) {
+ // this means the search failed
+ break;
+ }
+ prev = curr;
+ curr = prev->next_;
+ }
+ }
+ }
+
};
+}
+tx_ptr<test::list<int> > l;
+void insert1() {
+ thread_initializer thi;
+ use_atomic(_) {
+ //wr_ptr<test::list<int> > w(_,l);
+ //w->insert(1);
+ make_wr_ptr(_,l)->insert(1);
+ }
+}
+void insert2() {
+ thread_initializer thi;
+ use_atomic(_) {
+ //wr_ptr<test::list<int> > w(_,l);
+ //w->insert(2);
+ make_wr_ptr(_,l)->insert(2);
+ }
+}
+
+void insert3() {
+ thread_initializer thi;
+ use_atomic(_) {
+ //wr_ptr<test::list<int> > w(_,l);
+ //w->insert(3);
+ make_wr_ptr(_,l)->insert(3);
+ }
+}
+int test1() {
+ l=boost::stm::make_tx_ptr<test::list<int> >();
+ thread th1(insert1);
+ //thread th2(insert2);
+ //thread th3(insert2);
+ //thread th4(insert3);
+
+ th1.join();
+ //th2.join();
+ //th3.join();
+ //th4.join();
+ int res = (l->size()==1?0:1);
+ //boost::stm::delete_ptr(l);
+ return res;
+}
-#endif // TEST_LINKED_LIST_H
-
\ No newline at end of file
+int main() {
+ transaction::enable_dynamic_priority_assignment();
+ transaction::do_deferred_updating();
+ transaction::initialize();
+ thread_initializer thi;
+ srand(time(0));
+
+ int res=0;
+ res+=test1();
+
+ return res;
+
+}
Modified: sandbox/stm/branches/vbe/libs/stm/test/Jamfile.v2
==============================================================================
--- sandbox/stm/branches/vbe/libs/stm/test/Jamfile.v2 (original)
+++ sandbox/stm/branches/vbe/libs/stm/test/Jamfile.v2 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -41,11 +41,10 @@
# ;
#}
- exe t : ../example/bank.cpp
- ;
test-suite "tests"
:
#[ run stm.cpp testatom.cpp pointer_test.cpp smart.cpp globalIntArr.cpp testHashMapAndLinkedListsWithLocks.cpp irrevocableInt.cpp testHashMapWithLocks.cpp isolatedComposedIntLockInTx.cpp testInt.cpp isolatedComposedIntLockInTx2.cpp testLL_latm.cpp isolatedInt.cpp testLinkedList.cpp isolatedIntLockInTx.cpp testLinkedListWithLocks.cpp litExample.cpp testPerson.cpp lotExample.cpp testRBTree.cpp transferFun.cpp nestedTxs.cpp txLinearLock.cpp testHT_latm.cpp usingLockTx.cpp testHashMap.cpp ]
#[ run ../example/bank.cpp ]
+ [ run ../example/list.cpp ]
;
Modified: sandbox/stm/branches/vbe/libs/stm/test/testLinkedList.h
==============================================================================
--- sandbox/stm/branches/vbe/libs/stm/test/testLinkedList.h (original)
+++ sandbox/stm/branches/vbe/libs/stm/test/testLinkedList.h 2009-09-04 12:07:36 EDT (Fri, 04 Sep 2009)
@@ -15,9 +15,9 @@
#ifndef TEST_LINKED_LIST_H
#define TEST_LINKED_LIST_H
-//#define BOOST_STM_USES_AS_NEW 1
-//#define BOOST_STM_USES_PARAM 1
-#define BOOST_STM_LL_USES_NODE 1
+#define BOOST_STM_USES_AS_NEW 1
+#define BOOST_STM_USES_PARAM 1
+//#define BOOST_STM_LL_USES_NODE 1
#include "main.h"
#include <boost/stm/transaction.hpp>
@@ -335,8 +335,7 @@
list_node<T> node(val);
list_node<T> *newNode = t.new_memory_copy(node);
#else
- t.throw_if_forced_to_abort_on_new();
- list_node<T> *newNode = t.as_new(new list_node<T>(val));
+ list_node<T> *newNode = (t.throw_if_forced_to_abort_on_new(),t.as_new(new list_node<T>(val)));
#endif
//--------------------------------------------------------------------
// if cur->next() is null it means our newNode value is greater than
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk