|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r57630 - in sandbox/stm/branches/vbe: boost/stm boost/stm/detail boost/stm/tx libs/stm/example/tx libs/stm/test
From: vicente.botet_at_[hidden]
Date: 2009-11-13 02:27:36
Author: viboes
Date: 2009-11-13 02:27:34 EST (Fri, 13 Nov 2009)
New Revision: 57630
URL: http://svn.boost.org/trac/boost/changeset/57630
Log:
TBoost.STM vbe:
*Added missing delete_non_tx and associated deleters.
* Changed embedeeds by binds
* Added tx/list.hpp
Added:
sandbox/stm/branches/vbe/libs/stm/example/tx/list.cpp (contents, props changed)
Text files modified:
sandbox/stm/branches/vbe/boost/stm/base_transaction_object.hpp | 2
sandbox/stm/branches/vbe/boost/stm/detail/deleters.hpp | 28 +++++++++-
sandbox/stm/branches/vbe/boost/stm/transaction.hpp | 104 ++++++++++++++++++++++++++++++++++++++-
sandbox/stm/branches/vbe/boost/stm/tx/mixin.hpp | 34 ++++++++++--
sandbox/stm/branches/vbe/boost/stm/tx/object.hpp | 18 +++++-
sandbox/stm/branches/vbe/boost/stm/tx/pointer.hpp | 24 ++++++--
sandbox/stm/branches/vbe/libs/stm/test/Jamfile.v2 | 3
7 files changed, 188 insertions(+), 25 deletions(-)
Modified: sandbox/stm/branches/vbe/boost/stm/base_transaction_object.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/base_transaction_object.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/base_transaction_object.hpp 2009-11-13 02:27:34 EST (Fri, 13 Nov 2009)
@@ -104,7 +104,7 @@
#endif
#if BOOST_STM_ALLOWS_EMBEDEEDS
- std::list<base_transaction_object*>& embeddeds() {return embeddeds_;}
+ std::list<base_transaction_object*>& binds() {return embeddeds_;}
void bind(base_transaction_object* bto) {embeddeds_.push_back(bto);}
#endif
Modified: sandbox/stm/branches/vbe/boost/stm/detail/deleters.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/detail/deleters.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/detail/deleters.hpp 2009-11-13 02:27:34 EST (Fri, 13 Nov 2009)
@@ -71,8 +71,8 @@
template <typename T>
struct non_transaction_object_deleter : deleter {
T* ptr_;
- typedef typename T::binds_list binds_type;
- typedef typename T::binds_list::iterator binds_iterator;
+ typedef typename std::list<base_transaction_object*> binds_type;
+ typedef typename binds_type::iterator binds_iterator;
non_transaction_object_deleter(T* ptr) : ptr_(ptr){}
virtual void reset() {
@@ -95,8 +95,8 @@
struct non_transaction_object_array_deleter : deleter {
T* ptr_;
std::size_t size_;
- typedef typename T::binds_list binds_type;
- typedef typename T::binds_list::iterator binds_iterator;
+ typedef typename std::list<base_transaction_object*> binds_type;
+ typedef typename binds_type::iterator binds_iterator;
non_transaction_object_array_deleter(T* ptr, std::size_t size) : ptr_(ptr), size_(size) {}
virtual void reset() {
@@ -204,6 +204,26 @@
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
template <typename T>
+ inline deleter_type* make_non_tx(T* p) {
+ return new non_transaction_object_deleter<T>(p);
+ }
+ template <typename T>
+ inline deleter_type* make_non_tx(T& r) {
+ return new non_transaction_object_deleter<T>(&r);
+ }
+ template <typename T>
+ inline deleter_type* make_non_tx(T const* p) {
+ return new non_transaction_object_deleter<T>(const_cast<T*>(p));
+ }
+ template <typename T>
+ inline deleter_type* make_non_tx(T const& r) {
+ return new non_transaction_object_deleter<T>(const_cast<T*>(&r));
+ }
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+ template <typename T>
inline deleter_type* make_array(T* p, std::size_t size) {
return new base_transaction_object_array_deleter<T>(p, size);
}
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-11-13 02:27:34 EST (Fri, 13 Nov 2009)
@@ -570,7 +570,18 @@
//--------------------------------------------------------------------------
template <typename T>
inline void delete_non_tx_ptr(T *in) {
- delete_memory(*in);
+ if (direct_updating())
+ {
+#if PERFORMING_VALIDATION
+ throw "direct updating not implemented for validation yet";
+#else
+ direct_delete_non_tx_ptr(in);
+#endif
+ }
+ else
+ {
+ deferred_delete_non_tx_ptr(in);
+ }
}
#ifdef BOOST_STM_USE_BOOST
template <int> struct dummy { dummy(int) {} };
@@ -667,6 +678,15 @@
return newNode;
}
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T* as_new_non_tx(T *newNode)
+ {
+ newMemoryList().push_back(detail::make_non_tx(newNode));
+
+ return newNode;
+ }
+
#ifdef BOOST_STM_USE_BOOST
//--------------------------------------------------------------------------
template <typename T>
@@ -1004,6 +1024,39 @@
//--------------------------------------------------------------------------
template <typename T>
+ void direct_delete_non_tx_ptr(T *in)
+ {
+ //if (in.transaction_thread() == threadId_)
+ //{
+ // deletedMemoryList().push_back(detail::make(in));
+ // return;
+ //}
+
+ //-----------------------------------------------------------------------
+ // if we're here this item isn't in our writeList - get the global lock
+ // and see if anyone else is writing to it. if not, we add the item to
+ // our write list and our deletedList
+ //-----------------------------------------------------------------------
+ synchro::unique_lock<Mutex> lock_m(transactionMutex_);
+
+ //if (in.transaction_thread() != invalid_thread_id())
+ //{
+ // cm_abort_on_write(*this, (base_transaction_object&)(in));
+ //}
+ //else
+ {
+ //in.transaction_thread(threadId_);
+ lock_m.unlock();
+ // is this really necessary? in the deferred case it is, but in direct it
+ // doesn't actually save any time for anything
+ //writeList()[(base_transaction_object*)&in] = 0;
+
+ deletedMemoryList().push_back(detail::make_non_tx(in));
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
void direct_delete_tx_array(T *in, std::size_t size)
{
bool all_in_this_thread = true;
@@ -1144,8 +1197,6 @@
#if USE_BLOOM_FILTER
bloom().insert((std::size_t)&in);
lock.unlock();
-#else
-
#endif
#if PERFORMING_WRITE_BLOOM
wbloom().set_bv1(bloom().h1());
@@ -1211,6 +1262,53 @@
//--------------------------------------------------------------------------
template <typename T>
+ void deferred_delete_non_tx_ptr(T *in)
+ {
+ if (forced_to_abort())
+ {
+ deferred_abort(true);
+ throw aborted_tx("");
+ }
+ //-----------------------------------------------------------------------
+ // if this memory is true memory, not transactional, we add it to our
+ // deleted list and we're done
+ //-----------------------------------------------------------------------
+ //if (in.transaction_thread() != invalid_thread_id())
+ //{
+ // {
+ // synchro::lock_guard<Mutex> lock(*mutex());
+ // bloom().insert((std::size_t)&in);
+ // }
+ // writeList().insert(tx_pair((base_transaction_object*)&in, 0));
+ //}
+ //-----------------------------------------------------------------------
+ // this isn't real memory, it's transactional memory. But the good news is,
+ // the real version has to be in our write list somewhere, find it, add
+ // both items to the deletion list and exit
+ //-----------------------------------------------------------------------
+ //else
+ //{
+ // {
+ // synchro::lock_guard<Mutex> lock(*mutex());
+ // bloom().insert((std::size_t)&in);
+ // }
+ // // check the ENTIRE write container for this piece of memory in the
+ // // second location. If it's there, it means we made a copy of a piece
+ // for (WriteContainer::iterator j = writeList().begin(); writeList().end() != j; ++j)
+ // {
+ // if (j->second == (base_transaction_object*)&in)
+ // {
+ // writeList().insert(tx_pair(j->first, 0));
+ // deletedMemoryList().push_back(detail::make(j->first));
+ // }
+ // }
+ //}
+
+ deletedMemoryList().push_back(detail::make_non_tx(in));
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
void deferred_delete_tx_array(T *in, std::size_t size)
{
if (forced_to_abort())
Modified: sandbox/stm/branches/vbe/boost/stm/tx/mixin.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/tx/mixin.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/tx/mixin.hpp 2009-11-13 02:27:34 EST (Fri, 13 Nov 2009)
@@ -32,21 +32,36 @@
class mixin : public transaction_object< Final, Base >
{
protected:
- T val_;
public:
+ T val_;
+ typedef mixin<Final, T, Base> this_type;
typedef Final final_type;
typedef T value_type;
//-----------------------------------------------------------------------------
- mixin() : val_() {}
+ mixin() : val_() {
+ std::cerr << __LINE__ << " mixin val_=" << val_ << std::endl;
+ }
//
- template<typename F, typename U>
- mixin(mixin<F,U> const& r) : val_(r.value()) {}
+ //template<typename F, typename U>
+ //mixin(mixin<F,U> const& r) : val_(r.value()) {
+ // std::cerr << __LINE__ << " mixin val_=" << val_ << std::endl;
+ //}
+
+ //template<typename F, typename U>
+ mixin(mixin const& r) : val_(r.value()) {
+ std::cerr << __LINE__ << " mixin val_=" << val_ << std::endl;
+ }
// contructor from a convertible to T
- template <typename U>
- mixin(U v) : val_(v) {}
-
+ //template <typename U>
+ //mixin(U v) : val_(v) {
+ // std::cerr << __LINE__ << " mixin val_=" << v << std::endl;
+ //}
+ mixin(T v) : val_(v) {
+ std::cerr << __LINE__ << " mixin val_=" << v << std::endl;
+ }
+
operator T() const { return value(); }
operator T&() { return ref(); }
@@ -73,6 +88,11 @@
tx->lock_and_abort();
throw aborted_transaction_exception("aborting transaction");
}
+ this_type const * r=tx->read_ptr(this);
+ std::cerr << __LINE__ << " mixin this=" << this << std::endl;
+ std::cerr << __LINE__ << " mixin this.val_=" << this->val_ << std::endl;
+ std::cerr << __LINE__ << " mixin read=" << r << std::endl;
+ std::cerr << __LINE__ << " mixin val_=" << r->val_ << std::endl;
return tx->read(*this).val_;
}
return val_;
Modified: sandbox/stm/branches/vbe/boost/stm/tx/object.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/tx/object.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/tx/object.hpp 2009-11-13 02:27:34 EST (Fri, 13 Nov 2009)
@@ -33,12 +33,24 @@
public:
typedef mixin< object<T>, T > base_type;
//-----------------------------------------------------------------------------
- object() : base_type() {}
+ object() : base_type() {
+ std::cerr << __LINE__ << " object" << std::endl;
+ }
template<typename U>
- object(object<U> const& r) : base_type(r) {}
+ object(object<U> const& r) : base_type(r) {
+ std::cerr << __LINE__ << " object" << std::endl;
+ }
+ object(object const& r) : base_type(r) {
+ std::cerr << __LINE__ << " object" << std::endl;
+ }
// contructor from a convertible to T
template <typename U>
- object(U v) : base_type(v) {}
+ object(U v) : base_type(v) {
+ std::cerr << __LINE__ << " object" << std::endl;
+ }
+ object(T v) : base_type(v) {
+ std::cerr << __LINE__ << " object" << std::endl;
+ }
};
}}}
Modified: sandbox/stm/branches/vbe/boost/stm/tx/pointer.hpp
==============================================================================
--- sandbox/stm/branches/vbe/boost/stm/tx/pointer.hpp (original)
+++ sandbox/stm/branches/vbe/boost/stm/tx/pointer.hpp 2009-11-13 02:27:34 EST (Fri, 13 Nov 2009)
@@ -34,12 +34,24 @@
public:
//-----------------------------------------------------------------------------
- pointer() : base_type(static_cast<T*>(0)) {}
- template<class U>
- pointer(pointer<U> const& r) : base_type(r) {}
- template <typename U>
- pointer(U* v) : base_type(v) {}
- //pointer(T* v) : base_type(v) {}
+ pointer() : base_type(static_cast<T*>(0)) {
+ std::cerr << __LINE__ << " pointer" << std::endl;
+ }
+ //template<class U>
+ //pointer(pointer<U> const& r) : base_type(r) {
+ // std::cerr << __LINE__ << " pointer" << std::endl;
+ //}
+ //pointer(pointer const& r) : base_type(r) {
+ pointer(pointer const& r) : base_type(*((base_type const*)(&r))) {
+ std::cerr << __LINE__ << " pointer" << std::endl;
+ }
+ //template <typename U>
+ //pointer(U* v) : base_type(v) {
+ // std::cerr << __LINE__ << " pointer" << std::endl;
+ //}
+ pointer(T* v) : base_type(v) {
+ std::cerr << __LINE__ << " pointer" << std::endl;
+ }
T* operator->() const {
return this->value();
Added: sandbox/stm/branches/vbe/libs/stm/example/tx/list.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/branches/vbe/libs/stm/example/tx/list.cpp 2009-11-13 02:27:34 EST (Fri, 13 Nov 2009)
@@ -0,0 +1,237 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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/stm for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/stm.hpp>
+#include <boost/thread.hpp>
+#include <stdlib.h>
+
+using namespace std;
+using namespace boost;
+using namespace boost::stm;
+
+//--------------------------------------------------------------------------
+
+namespace test {
+template <typename T>
+class list_node
+{
+public:
+
+ list_node() : value_(), next_()
+ , embeddeds_()
+{}
+ explicit list_node(T const &rhs)
+ : value_(rhs), next_() {}
+ list_node(T const &rhs, tx::pointer<list_node<T> > next)
+ : value_(rhs), next_(next) {}
+
+ // zero initialization for native types
+ void clear() { value_ = T(); next_ = 0; }
+
+ std::list<base_transaction_object*>& binds() {return embeddeds_;}
+ void bind(base_transaction_object* bto) {embeddeds_.push_back(bto);}
+
+ tx::object<T> value_;
+ tx::pointer<list_node<T> > next_;
+ std::list<base_transaction_object*> embeddeds_;
+};
+
+template <typename OSTREAM, typename T>
+OSTREAM& operator<<(OSTREAM& os, list_node<T>& v) {
+ os << v.value_;
+ return os;
+}
+
+//--------------------------------------------------------------------------
+template <typename T>
+class list
+{
+public:
+
+ typedef tx::pointer<list_node<T> > node_type;
+ tx::pointer<list_node<T> > head_;
+ tx::uint_t size_;
+ list()
+ : head_(BOOST_STM_NEW_PTR(list_node<T>()))
+ , size_(0)
+ {
+ std::cout << "list().head=" << head_ << std::endl;
+ std::cout << "list().size=" << size_ << std::endl;
+ }
+
+ ~list() { }
+
+ std::size_t size() const {
+ BOOST_STM_ATOMIC(_) {
+ BOOST_STM_RETURN(size_);
+ } BOOST_STM_END_ATOMIC
+ return 0;
+ }
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, fail
+ //--------------------------------------------------------------------------
+ void insert(const T& val) {
+ cerr << __LINE__ << " insert" << endl;
+ BOOST_STM_ATOMIC(_) {
+ //for (boost::stm::transaction _; !_.committed() && _.restart(); _.end()) {
+ cerr << __LINE__ << " insert head=" << head_.value() << endl;
+ //tx::pointer<list_node<T> > prev(head_);
+ list_node<T>* prev(head_);
+ //tx::pointer<list_node<T> > curr(head_->next_);
+ list_node<T> * curr(head_->next_);
+ while (curr!=0) {
+ cerr << __LINE__ << " curr" << curr << endl;
+ if (curr->value_ == val) return;
+ else if (curr->value_ > val) break;
+ prev = curr;
+ curr = curr->next_;
+ }
+ cerr << __LINE__ << " insert" << endl;
+ if (curr==0 || (curr->value_ > val)) {
+ tx::pointer<list_node<T> > mod(prev);
+ mod->next_=BOOST_STM_TX_NEW_PTR(_,list_node<T>(val, curr));
+ ++size_;
+ cerr << __LINE__ << " inserting" << endl;
+
+ }
+ } BOOST_STM_END_ATOMIC
+ catch (...) {
+ cerr << __LINE__ << " insert" << endl;
+ }
+ cerr << __LINE__ << " insert" << endl;
+ }
+
+ // search function
+ bool lookup(const T& val) const {
+ bool found = false;
+ BOOST_STM_ATOMIC(_) {
+ tx::pointer<list_node<T> > curr=head_;
+ curr = curr->next_;
+ while (curr) {
+ if (curr->value_ >= val) break;
+ curr = curr->next_;
+ }
+
+ BOOST_STM_RETURN((curr) && (curr->value_ == val));
+ } BOOST_STM_END_ATOMIC
+ catch (...) {
+ cerr << __LINE__ << " lookup" << endl;
+ }
+ return false;
+ }
+
+ // remove a node if its value == val
+ void remove(const T& val)
+ {
+ BOOST_STM_ATOMIC(_) {
+ // find the node whose val matches the request
+ tx::pointer<list_node<T> > prev=head_;
+ tx::pointer<list_node<T> > curr=prev->next_;
+ while (curr) {
+ // if we find the node, disconnect it and end the search
+ if (curr->value_ == val) {
+ prev->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_;
+ }
+ } BOOST_STM_END_ATOMIC
+ }
+
+};
+}
+//--------------------------------------------------------------------------
+
+test::list<int> l;
+
+void create() {
+ BOOST_STM_ATOMIC(_) {
+ cerr << __LINE__ << " create" << endl;
+ cerr << " create size " << l.size() << endl;
+ } BOOST_STM_END_ATOMIC
+ catch (...) {
+ cerr << "aborted" << endl;
+ }
+}
+void insert1() {
+ //thread_initializer thi;
+ //BOOST_STM_ATOMIC(_) {
+ cerr << __LINE__ << " try" << endl;
+ cerr << __LINE__ << " insert1 size " << l.size() << endl;
+ int val = 1;
+ l.insert(val);
+ cerr << __LINE__ << " insert1 size " << l.size() << endl;
+ //} BOOST_STM_END_ATOMIC
+ //catch(...) {
+ // cerr << __LINE__ << " aborted" << endl;
+ //}
+}
+void insert2() {
+ thread_initializer thi;
+ BOOST_STM_ATOMIC(_) {
+ l.insert(2);
+ } BOOST_STM_END_ATOMIC
+}
+
+void insert3() {
+ thread_initializer thi;
+ BOOST_STM_ATOMIC(_) {
+ l.insert(3);
+ } BOOST_STM_END_ATOMIC
+}
+bool check_size(std::size_t val) {
+ BOOST_STM_ATOMIC(_) {
+ BOOST_STM_RETURN(l.size()==val);
+ } BOOST_STM_END_ATOMIC
+ return false;
+}
+int test_all() {
+ //create();
+ insert1();
+ bool fails=false;
+ //fails= fails || !check_size(0);
+ #if 0
+ thread th1(insert1);
+ thread th2(insert2);
+ thread th3(insert2);
+ thread th4(insert3);
+
+ th1.join();
+ th2.join();
+ th3.join();
+ th4.join();
+ bool fails=false;
+ //fails= !check_size(1);
+ //boost::stm::delete_ptr(l);
+ #endif
+ SLEEP(2);
+ return fails;
+}
+
+int main() {
+ transaction::enable_dynamic_priority_assignment();
+ transaction::do_deferred_updating();
+ transaction::initialize();
+ thread_initializer thi;
+
+ return test_all();
+
+}
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-11-13 02:27:34 EST (Fri, 13 Nov 2009)
@@ -192,7 +192,7 @@
########### fails
# /bin/sh: line 4: 2656 Segmentation fault (core dumped) "bin/list.test/gcc-3.4.4/debug/threading-multi/list.exe" > "bin/list.test/gcc-3.4.4/debug/threading-multi/list.output" 2>&1
- [ link ../example/list.cpp ]
+ #[ link ../example/list.cpp ]
[ run ../example/counter.cpp ]
# fails sometimes
@@ -200,6 +200,7 @@
[ run ../example/tx/numeric.cpp ]
[ run ../example/tx/array.cpp ]
[ run ../example/tx/pointer.cpp ]
+ [ run ../example/tx/list.cpp ]
[ run ../example/counter_ptr.cpp ]
# fails sometimes
# assertion "res==0" failed: file "../../../boost/synchro/pthread/mutex.hpp", line 52
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