Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r52632 - in sandbox/stm: boost boost/stm boost/stm/detail doc/html doc/html/images doc/html/images/callouts libs/stm/build libs/stm/doc libs/stm/src libs/stm/test
From: vicente.botet_at_[hidden]
Date: 2009-04-27 15:36:47


Author: viboes
Date: 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
New Revision: 52632
URL: http://svn.boost.org/trac/boost/changeset/52632

Log:
Boost.Stm v0.1 import
Added:
   sandbox/stm/boost/stm.hpp (contents, props changed)
   sandbox/stm/boost/stm/base_transaction.hpp (contents, props changed)
   sandbox/stm/boost/stm/contention_manager.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/auto_lock.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/bit_vector.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/bloom_filter.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/config.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/datatypes.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/jenkins_hash.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/latm_def_full_impl.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/latm_def_tm_impl.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/latm_def_tx_impl.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/latm_dir_full_impl.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/latm_dir_tm_impl.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/latm_dir_tx_impl.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/latm_general_impl.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/memory_pool.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/transaction_bookkeeping.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/transaction_conflict.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/transaction_impl.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/vector_map.hpp (contents, props changed)
   sandbox/stm/boost/stm/detail/vector_set.hpp (contents, props changed)
   sandbox/stm/boost/stm/transaction.hpp (contents, props changed)
   sandbox/stm/doc/html/
   sandbox/stm/doc/html/boostbook.css (contents, props changed)
   sandbox/stm/doc/html/images/
   sandbox/stm/doc/html/images/Thumbs.db (contents, props changed)
   sandbox/stm/doc/html/images/alert.png (contents, props changed)
   sandbox/stm/doc/html/images/blank.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/
   sandbox/stm/doc/html/images/callouts/1.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/10.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/11.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/12.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/13.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/14.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/15.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/2.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/3.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/4.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/5.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/6.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/7.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/8.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/9.png (contents, props changed)
   sandbox/stm/doc/html/images/callouts/Thumbs.db (contents, props changed)
   sandbox/stm/doc/html/images/caution.png (contents, props changed)
   sandbox/stm/doc/html/images/draft.png (contents, props changed)
   sandbox/stm/doc/html/images/home.png (contents, props changed)
   sandbox/stm/doc/html/images/important.png (contents, props changed)
   sandbox/stm/doc/html/images/next.png (contents, props changed)
   sandbox/stm/doc/html/images/next_disabled.png (contents, props changed)
   sandbox/stm/doc/html/images/note.png (contents, props changed)
   sandbox/stm/doc/html/images/prev.png (contents, props changed)
   sandbox/stm/doc/html/images/prev_disabled.png (contents, props changed)
   sandbox/stm/doc/html/images/smiley.png (contents, props changed)
   sandbox/stm/doc/html/images/tip.png (contents, props changed)
   sandbox/stm/doc/html/images/toc-blank.png (contents, props changed)
   sandbox/stm/doc/html/images/toc-minus.png (contents, props changed)
   sandbox/stm/doc/html/images/toc-plus.png (contents, props changed)
   sandbox/stm/doc/html/images/up.png (contents, props changed)
   sandbox/stm/doc/html/images/up_disabled.png (contents, props changed)
   sandbox/stm/doc/html/images/warning.png (contents, props changed)
   sandbox/stm/doc/html/reference.css (contents, props changed)
   sandbox/stm/libs/stm/build/Jamfile.v2 (contents, props changed)
   sandbox/stm/libs/stm/doc/Jamfile.v2 (contents, props changed)
   sandbox/stm/libs/stm/doc/acknowledgements.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/appendices.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/boostbook.css (contents, props changed)
   sandbox/stm/libs/stm/doc/case_studies.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/getting_started.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/history.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/implementation.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/index.html (contents, props changed)
   sandbox/stm/libs/stm/doc/installation.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/introduction.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/introduction_traits_and_concepts.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/overview.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/rationale.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/reference.css (contents, props changed)
   sandbox/stm/libs/stm/doc/reference.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/references.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/stm.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/tests.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/tickets.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/tutorial.qbk (contents, props changed)
   sandbox/stm/libs/stm/doc/users_guide.qbk (contents, props changed)
   sandbox/stm/libs/stm/src/bloom_filter.cpp (contents, props changed)
   sandbox/stm/libs/stm/src/contention_manager.cpp (contents, props changed)
   sandbox/stm/libs/stm/src/transaction.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/Jamfile.v2 (contents, props changed)
   sandbox/stm/libs/stm/test/globalIntArr.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/globalIntArr.h (contents, props changed)
   sandbox/stm/libs/stm/test/irrevocableInt.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/irrevocableInt.h (contents, props changed)
   sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx.h (contents, props changed)
   sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx2.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx2.h (contents, props changed)
   sandbox/stm/libs/stm/test/isolatedInt.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/isolatedInt.h (contents, props changed)
   sandbox/stm/libs/stm/test/isolatedIntLockInTx.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/isolatedIntLockInTx.h (contents, props changed)
   sandbox/stm/libs/stm/test/litExample.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/litExample.h (contents, props changed)
   sandbox/stm/libs/stm/test/lotExample.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/lotExample.h (contents, props changed)
   sandbox/stm/libs/stm/test/main.h (contents, props changed)
   sandbox/stm/libs/stm/test/nestedTxs.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/nestedTxs.h (contents, props changed)
   sandbox/stm/libs/stm/test/smart.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/smart.h (contents, props changed)
   sandbox/stm/libs/stm/test/stm.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testHT_latm.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testHT_latm.h (contents, props changed)
   sandbox/stm/libs/stm/test/testHashMap.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testHashMap.h (contents, props changed)
   sandbox/stm/libs/stm/test/testHashMapAndLinkedListsWithLocks.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testHashMapAndLinkedListsWithLocks.h (contents, props changed)
   sandbox/stm/libs/stm/test/testHashMapWithLocks.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testHashMapWithLocks.h (contents, props changed)
   sandbox/stm/libs/stm/test/testInt.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testInt.h (contents, props changed)
   sandbox/stm/libs/stm/test/testLL_latm.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testLL_latm.h (contents, props changed)
   sandbox/stm/libs/stm/test/testLinkedList.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testLinkedList.h (contents, props changed)
   sandbox/stm/libs/stm/test/testLinkedListWithLocks.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testLinkedListWithLocks.h (contents, props changed)
   sandbox/stm/libs/stm/test/testPerson.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testPerson.h (contents, props changed)
   sandbox/stm/libs/stm/test/testRBTree.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/testRBTree.h (contents, props changed)
   sandbox/stm/libs/stm/test/transferFun.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/transferFun.h (contents, props changed)
   sandbox/stm/libs/stm/test/txLinearLock.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/txLinearLock.h (contents, props changed)
   sandbox/stm/libs/stm/test/usingLockTx.cpp (contents, props changed)
   sandbox/stm/libs/stm/test/usingLockTx.h (contents, props changed)

Added: sandbox/stm/boost/stm.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,44 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+
+
+#ifndef BOOST_STM__HPP
+#define BOOST_STM__HPP
+
+#include <boost/stm/transaction.hpp>
+#include <boost/stm/contention_manager.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+#endif // TRANSACTION_H
+
+

Added: sandbox/stm/boost/stm/base_transaction.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/base_transaction.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,471 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#ifndef BOOST_STM_BASE_TRANSACTION_H
+#define BOOST_STM_BASE_TRANSACTION_H
+
+
+#include <pthread.h>
+//#include <boost/thread/mutex.hpp>
+//#include <boost/thread/locks.hpp>
+
+#include <boost/stm/detail/memory_pool.hpp>
+#include <stdarg.h>
+#include <list>
+
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ typedef pthread_mutex_t Mutex;
+#else
+ typedef boost::mutex Mutex;
+#endif
+
+//-----------------------------------------------------------------------------
+namespace boost { namespace stm {
+
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+typedef pthread_mutex_t PLOCK;
+#else
+typedef boost::mutex PLOCK;
+#endif
+
+
+//-----------------------------------------------------------------------------
+// boolean which is used to invoke "begin_transaction()" upon transaction
+// object construction (so two lines of code aren't needed to make a
+// transaction start, in case the client wants to start the transaction
+// immediately).
+//-----------------------------------------------------------------------------
+bool const begin_transaction = true;
+
+unsigned const kInvalidThread = 0xffffffff;
+
+//-----------------------------------------------------------------------------
+// The possible states a transaction can be in:
+//
+// e_no_state - initial state of transaction.
+// e_aborted - aborted transaction.
+// e_committed - transaction has committed.
+// e_hand_off - transaction memory has been handed off to another
+// transaction. This is the vital state for in-flight
+// transactions which are composed.
+// e_in_flight - transaction currently in process.
+//-----------------------------------------------------------------------------
+enum transaction_state
+{
+ e_no_state = -1, // no state is -1
+ e_aborted, // ensure aborted = 0
+ e_committed, // committed is positive
+ e_hand_off, // so is handoff in case bool conversion
+ e_in_flight
+};
+
+#if BUILD_MOVE_SEMANTICS
+template <class T>
+inline typename std::remove_reference<T>::type&& draco_move(T &&t)
+{
+ return t;
+}
+
+bool const kDracoMoveSemanticsCompiled = true;
+#else
+bool const kDracoMoveSemanticsCompiled = false;
+#endif
+
+class aborted_transaction_exception_no_unlocks {};
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+class aborted_transaction_exception : public std::exception
+{
+public:
+ aborted_transaction_exception(char const * const what) : what_(what) {}
+
+ //virtual char const * what() const { return what_; }
+
+private:
+ char const * const what_;
+};
+
+typedef aborted_transaction_exception aborted_tx;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+
+#if 0
+ template <typename T>
+ inline int lock(T *lock) { throw "unsupported lock type"; }
+
+ template <typename T>
+ inline int trylock(T *lock) { throw "unsupported lock type"; }
+
+ template <typename T>
+ inline int unlock(T *lock) { throw "unsupported lock type"; }
+
+ template <>
+ inline int lock(Mutex &lock) { return pthread_mutex_lock(&lock); }
+
+ template <>
+ inline int lock(Mutex *lock) { return pthread_mutex_lock(lock); }
+
+ template <>
+ inline int trylock(Mutex &lock) { return pthread_mutex_trylock(&lock); }
+
+ template <>
+ inline int trylock(Mutex *lock) { return pthread_mutex_trylock(lock); }
+
+ template <>
+ inline int unlock(Mutex &lock) { return pthread_mutex_unlock(&lock); }
+
+ template <>
+ inline int unlock(Mutex *lock) { return pthread_unlock(lock); }
+#else
+ inline int lock(PLOCK &lock) { return pthread_mutex_lock(&lock); }
+ inline int lock(PLOCK *lock) { return pthread_mutex_lock(lock); }
+
+ inline int trylock(PLOCK &lock) { return pthread_mutex_trylock(&lock); }
+ inline int trylock(PLOCK *lock) { return pthread_mutex_trylock(lock); }
+
+ inline int unlock(PLOCK &lock) { return pthread_mutex_unlock(&lock); }
+ inline int unlock(PLOCK *lock) { return pthread_mutex_unlock(lock); }
+#endif
+#else
+ inline void lock(PLOCK &lock) { lock.lock(); }
+ inline void lock(PLOCK *lock) { lock->lock(); }
+
+ inline bool trylock(PLOCK &lock) { return lock.try_lock(); }
+ inline bool trylock(PLOCK *lock) { return lock->try_lock(); }
+
+ inline void unlock(PLOCK &lock) { lock.unlock(); }
+ inline void unlock(PLOCK *lock) { lock->unlock(); }
+#endif
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+class base_transaction_object
+{
+public:
+
+ base_transaction_object() : transactionThread_(boost::stm::kInvalidThread),
+ newMemory_(0)
+#if PERFORMING_VALIDATION
+ ,version_(0)
+#endif
+ {}
+
+ virtual void copy_state(base_transaction_object const * const rhs) = 0;
+#if BUILD_MOVE_SEMANTICS
+ virtual void move_state(base_transaction_object * rhs) = 0;
+#else
+ virtual void move_state(base_transaction_object * rhs) {};
+#endif
+ virtual ~base_transaction_object() {};
+
+ void transaction_thread(size_t rhs) const { transactionThread_ = rhs; }
+ size_t const & transaction_thread() const { return transactionThread_; }
+
+#if USE_STM_MEMORY_MANAGER
+ static void alloc_size(size_t size) { memory_.alloc_size(size); }
+#else
+ static void alloc_size(size_t size) { }
+#endif
+
+ void new_memory(size_t rhs) const { newMemory_ = rhs; }
+ size_t const & new_memory() const { return newMemory_; }
+
+#if PERFORMING_VALIDATION
+ size_t version_;
+#endif
+
+protected:
+
+#if USE_STM_MEMORY_MANAGER
+ static void return_mem(void *mem, size_t size)
+ {
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ lock(&transactionObjectMutex_);
+ memory_.returnChunk(mem, size);
+ unlock(&transactionObjectMutex_);
+#else
+ boost::lock_guard<boost::mutex> lock(transactionObjectMutex_);
+ memory_.returnChunk(mem, size);
+#endif
+ }
+
+ static void* retrieve_mem(size_t size)
+ {
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ lock(&transactionObjectMutex_);
+ void *mem = memory_.retrieveChunk(size);
+ unlock(&transactionObjectMutex_);
+#else
+ boost::lock_guard<boost::mutex> lock(transactionObjectMutex_);
+ void *mem = memory_.retrieveChunk(size);
+#endif
+
+ return mem;
+ }
+#endif
+
+private:
+
+ //--------------------------------------------------------------------------
+ // int instead of bool for architecture word-boundary alignment
+ //
+ // transactionThread_ means a transaction is writing to this memory.
+ //
+ // in direct environments, this flag means memory being written to directly
+ //
+ // in deferred environments, this flag means this is memory that was copied
+ // and being written to off to the side
+ //
+ // it's important to note the differences between as direct reads and writes
+ // and deferred reads and writes behave very differently when using this
+ // flag.
+ //--------------------------------------------------------------------------
+ mutable size_t transactionThread_;
+
+ mutable size_t newMemory_;
+
+#if USE_STM_MEMORY_MANAGER
+ static Mutex transactionObjectMutex_;
+ static MemoryPool<base_transaction_object> memory_;
+#endif
+};
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <class Derived>
+class transaction_object : public base_transaction_object
+{
+public:
+
+ //--------------------------------------------------------------------------
+ virtual void copy_state(base_transaction_object const * const rhs)
+ {
+ static_cast<Derived *>(this)->operator=
+ ( (Derived&) *(static_cast<Derived const * const>(rhs)));
+ }
+
+#if BUILD_MOVE_SEMANTICS
+ virtual void move_state(base_transaction_object * rhs)
+ {
+ static_cast<Derived &>(*this) = draco_move
+ (*(static_cast<Derived*>(rhs)));
+ }
+#endif
+
+#if USE_STM_MEMORY_MANAGER
+ void* operator new(size_t size) throw ()
+ {
+ return retrieve_mem(size);
+ }
+
+ void operator delete(void* mem)
+ {
+ static Derived elem;
+ static size_t elemSize = sizeof(elem);
+ return_mem(mem, elemSize);
+ }
+#endif
+
+};
+
+template <typename T> class native_trans :
+public transaction_object< native_trans<T> >
+{
+public:
+
+ native_trans() : value_(T()) {}
+ native_trans(T const &rhs) : value_(rhs) {}
+ native_trans(native_trans const &rhs) : value_(rhs.value_) {}
+
+ native_trans& operator=(T const &rhs) { value_ = rhs; return *this; }
+
+ native_trans& operator--() { --value_; return *this; }
+ native_trans operator--(int) { native_trans n = *this; --value_; return n; }
+
+ native_trans& operator++() { ++value_; return *this; }
+ native_trans operator++(int) { native_trans n = *this; ++value_; return n; }
+
+ native_trans& operator+=(T const &rhs)
+ {
+ value_ += rhs;
+ return *this;
+ }
+
+ native_trans operator+(native_trans const &rhs)
+ {
+ native_trans ret = *this;
+ ret.value_ += rhs.value_;
+ return ret;
+ }
+
+ //template <>
+ operator T() const
+ {
+ return this->value_;
+ }
+
+#if BUILD_MOVE_SEMANTICS
+ //--------------------------------------------------
+ // move semantics
+ //--------------------------------------------------
+ native_trans(native_trans &&rhs) { value_ = rhs.value_;}
+ native_trans& operator=(native_trans &&rhs)
+ { value_ = rhs.value_; return *this; }
+#endif
+
+ T& value() { return value_; }
+ T const & value() const { return value_; }
+
+private:
+ T value_;
+};
+
+//-----------------------------------------------------------------------------
+// forward declaration
+//-----------------------------------------------------------------------------
+class transaction;
+
+//-----------------------------------------------------------------------------
+class base_contention_manager
+{
+public:
+ virtual void abort_on_new(boost::stm::transaction const &t) = 0;
+ virtual void abort_on_delete(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in) = 0;
+
+ virtual void abort_on_read(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in) = 0;
+ virtual void abort_on_write(boost::stm::transaction &t,
+ boost::stm::base_transaction_object const &in) = 0;
+
+ virtual bool abort_before_commit(boost::stm::transaction const &t) = 0;
+
+ virtual bool permission_to_abort
+ (boost::stm::transaction const &lhs, boost::stm::transaction const &rhs) = 0;
+
+ virtual bool allow_lock_to_abort_tx(int const & lockWaitTime, int const &lockAborted,
+ bool txIsIrrevocable, boost::stm::transaction const &rhs) = 0;
+
+ virtual int lock_sleep_time() { return 10; }
+
+ virtual void perform_isolated_tx_wait_priority_promotion(boost::stm::transaction &) = 0;
+ virtual void perform_irrevocable_tx_wait_priority_promotion(boost::stm::transaction &) = 0;
+
+ virtual ~base_contention_manager() {};
+};
+
+//-----------------------------------------------------------------------------
+class DefaultContentionManager : public boost::stm::base_contention_manager
+{
+public:
+ //--------------------------------------------------------------------------
+ void abort_on_new(boost::stm::transaction const &t);
+ void abort_on_delete(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in);
+
+ void abort_on_read(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in);
+ void abort_on_write(boost::stm::transaction &t,
+ boost::stm::base_transaction_object const &in);
+
+ virtual bool abort_before_commit(boost::stm::transaction const &t)
+ {
+ return false;
+ }
+
+ virtual bool permission_to_abort
+ (boost::stm::transaction const &lhs, boost::stm::transaction const &rhs)
+ { return true; }
+
+ virtual bool allow_lock_to_abort_tx(int const & lockWaitTime, int const &lockAborted,
+ bool txIsIrrevocable, boost::stm::transaction const &rhs);
+
+ virtual void perform_isolated_tx_wait_priority_promotion(boost::stm::transaction &);
+ virtual void perform_irrevocable_tx_wait_priority_promotion(boost::stm::transaction &);
+};
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename T>
+class var_auto_lock
+{
+public:
+
+ //--------------------------------------------------------------------------
+ typedef T lock_type;
+ typedef std::list<lock_type*> lock_list;
+
+ //--------------------------------------------------------------------------
+ var_auto_lock(lock_type *l, ...)
+ {
+ va_list ap;
+ va_start(ap, l);
+
+ while (l)
+ {
+ lockList_.push_back(l);
+ l = va_arg(ap, lock_type*);
+ }
+
+ va_end(ap);
+
+ std::list<PLOCK*>::iterator i = lockList_.begin();
+
+ for (; i != lockList_.end(); ++i)
+ {
+ lock(*i);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ ~var_auto_lock()
+ {
+ for (std::list<PLOCK*>::iterator i = lockList_.begin(); i != lockList_.end(); ++i)
+ {
+ unlock(*i);
+ }
+ }
+
+private:
+ std::list<lock_type*> lockList_;
+
+};
+
+
+} // namespace core
+}
+#endif // BASE_TRANSACTION_H
+
+

Added: sandbox/stm/boost/stm/contention_manager.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/contention_manager.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,158 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#ifndef BOOST_STM_CONTENTION_MANAGER_H
+#define BOOST_STM_CONTENTION_MANAGER_H
+
+#include <boost/stm/transaction.hpp>
+
+////////////////////////////////////////////////////////////////////////////
+//
+// this class does nothing on abort notices for writes and reads
+//
+// this is an important concept as sometimes the overhead from the exception
+// handling is more severe than simply aborting at "commit" time.
+//
+////////////////////////////////////////////////////////////////////////////
+class NoExceptionOnAbortNoticeOnReadWritesCM : public boost::stm::base_contention_manager
+{
+public:
+ /////////////////////////////////////////////////////////////////////////
+ // do nothing for both of these interfaces
+ /////////////////////////////////////////////////////////////////////////
+ void abort_on_write(boost::stm::transaction &t,
+ boost::stm::base_transaction_object const &in) {}
+ void abort_on_read(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in) {}
+ void abort_on_delete(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in) {}
+ void abort_on_new(boost::stm::transaction const &t) {}
+};
+
+////////////////////////////////////////////////////////////////////////////
+//
+// this class backs off (and sleeps) when aborting. this is commonly known
+// as "exponential backoff" for locking mechanisms.
+//
+////////////////////////////////////////////////////////////////////////////
+class ExceptAndBackOffOnAbortNoticeCM : public boost::stm::base_contention_manager
+{
+public:
+
+ ExceptAndBackOffOnAbortNoticeCM(int const initialSleepTime, int const sleepIncrease,
+ int const maxIncreases)
+ : sleepTime_(initialSleepTime), kSleepFactorIncrease_(sleepIncrease),
+ kMaxIncreases_(maxIncreases), initialSleepTime_(initialSleepTime)
+ {
+ kMaxSleepTime_ = kSleepFactorIncrease_ * sleepTime_ * kMaxIncreases_;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ void abort_on_write(boost::stm::transaction &t,
+ boost::stm::base_transaction_object const &in);
+ void abort_on_read(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in);
+ void abort_on_delete(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in);
+ void abort_on_new(boost::stm::transaction const &t);
+
+ ////////////////////////////////////////////////////////////////////////////
+ void perform_isolated_tx_wait_priority_promotion(boost::stm::transaction &lhs)
+ {
+ lhs.raise_priority();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ void perform_irrevocable_tx_wait_priority_promotion(boost::stm::transaction &lhs)
+ {
+ lhs.raise_priority();
+ }
+
+ //--------------------------------------------------------------------------
+ // this code is only ever called if "validation" is on not "invalidation"
+ // so don't worry about this code EVER stopping invalidation from committing
+ //--------------------------------------------------------------------------
+ virtual bool abort_before_commit(boost::stm::transaction const &t)
+ {
+ using namespace boost::stm;
+
+ for (transaction::in_flight_trans_cont::const_iterator i =
+ transaction::in_flight_transactions().begin();
+ i != transaction::in_flight_transactions().end(); ++i)
+ {
+ if (t.priority() < (*i)->priority()) return true;
+ }
+
+ return false;
+ }
+
+ virtual bool permission_to_abort
+ (boost::stm::transaction const &lhs, boost::stm::transaction const &rhs)
+ {
+ return true;
+#if 0
+ if (lhs.priority() + 100 > rhs.priority()) return true;
+
+ rhs.set_priority(rhs.priority() + 1000);
+ return false;
+#endif
+ //return lhs.writes() * lhs.priority() >= rhs.writes() * rhs.priority();
+ //return lhs.writes() + lhs.reads() >= rhs.writes() + rhs.reads();
+ }
+
+ virtual bool allow_lock_to_abort_tx
+ (int const & lockWaitTime, int const &lockAborted,
+ bool txTryingToAbortIsIrrevocable, boost::stm::transaction const &rhs)
+ {
+ if (txTryingToAbortIsIrrevocable) return true;
+
+#ifndef DISABLE_READ_SETS
+ if ((size_t)lockWaitTime > rhs.read_set_size() + 100 * rhs.writes())
+#else
+ if ((size_t)lockWaitTime > 100 * rhs.writes())
+#endif
+ {
+ return true;
+ }
+ else return false;
+ }
+
+private:
+
+ int sleepTime_;
+ int const kSleepFactorIncrease_;
+ int kMaxSleepTime_;
+ int const kMaxIncreases_;
+ int const initialSleepTime_;
+};
+
+#endif // CONTENTION_MANAGER_H

Added: sandbox/stm/boost/stm/detail/auto_lock.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/auto_lock.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,264 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_STM_AUTO_LOCK_H
+#define BOOST_STM_AUTO_LOCK_H
+
+#include <pthread.h>
+#include <stdexcept>
+#include <string>
+#include <iostream>
+#include <map>
+#include <vector>
+#include <boost/stm/detail/datatypes.hpp>
+
+//# if 0 // TBR
+#ifdef WIN32
+#pragma warning (disable:4786)
+
+//#ifndef SLEEP
+#include <time.h>
+#define SLEEP(x) Sleep(x)
+//#endif
+
+#ifndef THREAD_ID
+#define THREAD_ID (size_t)pthread_self().p
+#endif
+
+#else // WIN32
+#include <unistd.h>
+#ifndef SLEEP
+#define SLEEP(x) usleep(x*1000)
+#endif
+
+#ifndef THREAD_ID
+#define THREAD_ID (size_t) pthread_self()
+#endif
+
+#endif // WIN32
+//#endif
+
+
+#ifdef PERFORMING_LATM
+#include <boost/stm/transaction.hpp>
+#define LOCK(a) boost::stm::transaction::lock_(a)
+#define UNLOCK(a) boost::stm::transaction::unlock_(a)
+#else
+#define LOCK(a) boost::stm::lock(a)
+#define UNLOCK(a) boost::stm::unlock(a)
+#endif
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+namespace boost { namespace stm {
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+class timer_lock_exception : public std::exception
+{
+public:
+ timer_lock_exception(char const * const what) : what_(what) {}
+
+ //virtual char const * what() const { return what_; }
+
+private:
+ char const * const what_;
+};
+
+
+typedef timer_lock_exception timer_err;
+
+class auto_lock
+{
+public:
+ typedef std::pair<size_t const, Mutex*> ThreadedLockPair;
+ typedef std::multimap<size_t const, Mutex*> ThreadedLockContainer;
+ typedef ThreadedLockContainer::iterator ThreadedLockIter;
+
+ auto_lock(Mutex &mutex) : donePostStep_(false), hasLock_(false), lock_(NULL)
+ {
+ do_auto_lock(&mutex);
+ }
+
+ auto_lock(Mutex *mutex) : donePostStep_(false), hasLock_(false), lock_(NULL)
+ {
+ do_auto_lock(mutex);
+ }
+
+
+ auto_lock(size_t timeOut, Mutex &mutex) : donePostStep_(false), hasLock_(false), lock_(NULL)
+ {
+ do_timed_auto_lock(timeOut, &mutex);
+ }
+
+ auto_lock(size_t timeOut, Mutex *mutex) : donePostStep_(false), hasLock_(false), lock_(NULL)
+ {
+ do_timed_auto_lock(timeOut, mutex);
+ }
+
+ ~auto_lock() { do_auto_unlock(); }
+
+ bool has_lock() { return hasLock_; }
+
+ void release_lock() { do_auto_unlock(); }
+
+ static int VC6_fix()
+ {
+ static int VC6_fix = 0;
+ return VC6_fix;
+ }
+
+ void post_step()
+ {
+ release_lock();
+ donePostStep_ = true;
+ }
+
+ bool done_post_step() const
+ {
+ return donePostStep_;
+ }
+
+private:
+
+ void do_timed_auto_lock(size_t timeOut, Mutex *mutex)
+ {
+ lock_ = mutex;
+
+ if (thread_has_lock(mutex)) return;
+
+ for (size_t i = 0; i < timeOut; ++i)
+ {
+ if (0 == trylock(lock_))
+ {
+ hasLock_ = true;
+ insert_into_threaded_lock_map(mutex);
+ return;
+ }
+
+ SLEEP(1);
+ }
+
+ throw timer_lock_exception( "lock timed out" );
+ }
+
+ void insert_into_threaded_lock_map(Mutex* mutex)
+ {
+ lock(global_lock());
+ threaded_locks().insert(ThreadedLockPair(THREAD_ID, mutex));
+ unlock(global_lock());
+ }
+
+ void do_auto_lock(Mutex *mutex)
+ {
+ lock_ = mutex;
+ if (thread_has_lock(mutex)) return;
+
+ LOCK(mutex);
+ hasLock_ = true;
+
+ insert_into_threaded_lock_map(mutex);
+ }
+
+ void do_auto_unlock()
+ {
+ if (hasLock_)
+ {
+ hasLock_ = false;
+ UNLOCK(lock_);
+ remove_thread_has_lock(lock_);
+ }
+ }
+
+ bool thread_has_lock(Mutex *rhs)
+ {
+ lock(global_lock());
+
+ for (ThreadedLockIter i = threaded_locks().begin();
+ i != threaded_locks().end(); ++i)
+ {
+ if (i->first == THREAD_ID && i->second == rhs)
+ {
+ unlock(global_lock());
+ return true;
+ }
+ }
+
+ unlock(global_lock());
+ return false;
+ }
+
+ void remove_thread_has_lock(Mutex *rhs)
+ {
+ lock(global_lock());
+
+ for (ThreadedLockIter i = threaded_locks().begin();
+ i != threaded_locks().end(); ++i)
+ {
+ if (i->first == THREAD_ID && i->second == rhs)
+ {
+ threaded_locks().erase(i);
+ break;
+ }
+ }
+
+ unlock(global_lock());
+ }
+
+ static Mutex *global_lock()
+ {
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ static Mutex globalLock = PTHREAD_MUTEX_INITIALIZER;
+#else
+ static Mutex globalLock;
+#endif
+ return &globalLock;
+ }
+
+ static ThreadedLockContainer &threaded_locks()
+ {
+ static ThreadedLockContainer localThreadedLocks;
+ return localThreadedLocks;
+ }
+
+ //auto_lock(auto_lock const &);
+ //auto_lock& operator=(auto_lock const &);
+
+ bool donePostStep_;
+ bool hasLock_;
+ Mutex *lock_;
+};
+
+#define use_lock(L) if (0 != rand()+1) for (boost::stm::auto_lock ___l(L); !___l.done_post_step(); ___l.post_step())
+#define use_timed_lock(T, L) if (0 != rand()+1) for (boost::stm::auto_lock ___l(T, L); !___l.done_post_step(); ___l.post_step())
+
+#define try_timed_lock(T, L) try { for (boost::stm::auto_lock ___l(T, L); !___l.done_post_step(); ___l.post_step())
+#define catch_lock_timeout(E) } catch (std::timer_lock_exception &E)
+#define lock_timeout } catch (std::timer_lock_exception &E)
+
+} // core namespace
+}
+
+
+
+#endif // AUTO_LOCK_H
+
+
+
+
+
+
+
+
+

Added: sandbox/stm/boost/stm/detail/bit_vector.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/bit_vector.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,136 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_STM_BIT_VECTOR_H
+#define BOOST_STM_BIT_VECTOR_H
+
+#include <string.h>
+#include <math.h>
+
+//#define def_bit_vector_size 4194304
+
+//---------------------------------------------------------------------------
+// smaller allocation size: potentially more conflicts but more chance to
+// fit into a single cache line
+//---------------------------------------------------------------------------
+//#define def_bit_vector_size 131072
+//#define def_bit_vector_size 2048
+//#define def_bit_vector_size 16384
+//#define def_bit_vector_size 32768
+#define def_bit_vector_size 65536
+//#define def_bit_vector_size 131072
+//#define def_bit_vector_size 1048576
+#define def_bit_vector_alloc_size def_bit_vector_size / 32
+#define def_bit_vector_byte_size def_bit_vector_alloc_size * 4
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+namespace boost { namespace stm {
+ typedef size_t chunk_type;
+ size_t const chunk_size = sizeof(chunk_type);
+ size_t const byte_size = 8;
+ size_t const chunk_bits = chunk_size * byte_size;
+ size_t const chunk_shift = 5;
+ size_t const chunk_shift_bits = (int)pow((double)2.0, (double)chunk_shift) - 1;
+
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+class bit_vector
+{
+public:
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ bit_vector()
+ {
+ memset(bits_, 0, def_bit_vector_byte_size);
+ }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ size_t operator[](size_t const rhs) const
+ {
+ //---------------------------------------------------------------------
+ // (1) select the correct chunk from the bits_ array.
+ // (2) select the right bit in the chunk ( rhs % chunk_size ) and turn
+ // that bit on ( 1 << ( correct bit ) )
+ // (3) perform bitwise AND, this'll return 1 if the bits_ array has
+ // a 1 in the specific bit location
+ // (4) shift it back to the first bit location so we return a 0 or 1
+ //---------------------------------------------------------------------
+ return ( bits_[(rhs >> chunk_shift)] & (1 << rhs & chunk_shift_bits) )
+ >> rhs % chunk_bits;
+ //return ( bits_[rhs / chunk_bits] & (1 << rhs % chunk_bits) )
+ // >> rhs % chunk_bits;
+ }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ void clear()
+ {
+ memset(bits_, 0, def_bit_vector_byte_size);
+ }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ size_t const size() const { return def_bit_vector_size; }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ size_t const alloc_size() const { return def_bit_vector_alloc_size; }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ void set(size_t rhs)
+ {
+ bits_[(rhs >> chunk_shift)] |= 1 << (rhs & chunk_shift_bits);
+ }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ void reset(size_t rhs)
+ {
+ bits_[(rhs >> chunk_shift)] &= 0 << (rhs & chunk_shift_bits);
+ }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ bool test(size_t rhs)
+ {
+ return ( bits_[(rhs >> chunk_shift)] & (1 << (rhs & chunk_shift_bits)) ) > 0 ? true : false;
+ }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ size_t intersects(bit_vector const & rhs) const
+ {
+ for (register size_t i = 0; i < def_bit_vector_alloc_size; ++i)
+ {
+ if (bits_[i] & rhs.bits_[i]) return 1;
+ }
+
+ return 0;
+ }
+
+private:
+
+ chunk_type bits_[def_bit_vector_alloc_size];
+};
+
+}
+}
+
+
+#endif // BIT_VECTOR_H
+

Added: sandbox/stm/boost/stm/detail/bloom_filter.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/bloom_filter.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,111 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#ifndef BOOST_STM_BLOOM_FILTER_H
+#define BOOST_STM_BLOOM_FILTER_H
+
+#ifdef WIN32
+#pragma warning (disable:4786)
+#endif
+
+#ifdef BOOST_STM_BLOOM_FILTER_USE_DYNAMIC_BITSET
+#include <boost/dynamic_bitset.hpp>
+#else
+#include <boost/stm/detail/bit_vector.hpp>
+#endif
+//#include <vector>
+#include <boost/stm/detail/jenkins_hash.hpp>
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+namespace boost { namespace stm {
+
+#ifdef BOOST_STM_BLOOM_FILTER_USE_DYNAMIC_BITSET
+ std::size_t const def_bit_vector_size = 65536;
+#endif
+ typedef std::size_t (*size_t_fun_ptr)(std::size_t rhs);
+ std::size_t const bitwiseAndOp = def_bit_vector_size-1;
+ std::size_t const size_of_size_t = sizeof(std::size_t);
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+class bloom_filter
+{
+public:
+ bloom_filter()
+#ifdef BOOST_STM_BLOOM_FILTER_USE_DYNAMIC_BITSET
+ : bit_vector1_(def_bit_vector_size)
+ , bit_vector2_(def_bit_vector_size)
+#else
+#endif
+ {}
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ void insert(std::size_t const &rhs)
+ {
+ h1_ = h2_ = 0;
+ hashlittle2((void*)&rhs, size_of_size_t, &h1_, &h2_);
+ bit_vector1_.set( h1_ & bitwiseAndOp );
+ bit_vector2_.set( h2_ & bitwiseAndOp );
+ }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ bool exists(std::size_t const &rhs)
+ {
+ h1_ = h2_ = 0;
+ hashlittle2((void*)&rhs, size_of_size_t, &h1_, &h2_);
+ return bit_vector1_.test( h1_ & bitwiseAndOp ) &&
+ bit_vector2_.test( h2_ & bitwiseAndOp );
+ }
+
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ std::size_t intersection(bloom_filter const &rhs)
+ {
+ return bit_vector1_.intersects(rhs.bit_vector1_)
+ && bit_vector2_.intersects(rhs.bit_vector2_);
+ }
+
+ std::size_t h1() const { return h1_; }
+ std::size_t h2() const { return h2_; }
+
+ void set_bv1(std::size_t rhs) { bit_vector1_.set( rhs & bitwiseAndOp ); }
+ void set_bv2(std::size_t rhs) { bit_vector2_.set( rhs & bitwiseAndOp ); }
+ //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
+ void clear()
+ {
+ bit_vector1_.clear();
+ bit_vector2_.clear();
+ }
+
+private:
+
+ std::size_t h1_, h2_;
+#ifdef BOOST_STM_BLOOM_FILTER_USE_DYNAMIC_BITSET
+ boost::dynamic_bitset<> bit_vector1_;
+ boost::dynamic_bitset<> bit_vector2_;
+#else
+ bit_vector bit_vector1_;
+ bit_vector bit_vector2_;
+#endif
+};
+
+
+} // end of core namespace
+}
+#endif // BLOOM_FILTER_H
+
+

Added: sandbox/stm/boost/stm/detail/config.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/config.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,68 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_STM_DETAIL_CONFIG_H
+#define BOOST_STM_DETAIL_CONFIG_H
+
+//#define DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+//#define LOGGING_COMMITS_AND_ABORTS 1
+//#define PERFORMING_VALIDATION 1
+#define PERFORMING_LATM 1
+#define PERFORMING_COMPOSITION 1
+#define USE_STM_MEMORY_MANAGER 1
+#define BUILD_MOVE_SEMANTICS 0
+#define USING_TRANSACTION_SPECIFIC_LATM 1
+#define USE_BLOOM_FILTER 1
+#define PERFORMING_WRITE_BLOOM 1
+//#define ALWAYS_ALLOW_ABORT 1
+//#define LOGGING_BLOCKS 1
+//#define USE_SINGLE_THREAD_CONTEXT_MAP 1
+
+#ifdef USE_BLOOM_FILTER
+#define DISABLE_READ_SETS 1
+#endif
+
+#define MAP_WRITE_CONTAINER 1
+//#define MAP_NEW_CONTAINER 1
+//#define MAP_THREAD_MUTEX_CONTAINER 1
+#define MAP_THREAD_BOOL_CONTAINER 1
+#define USING_SHARED_FORCED_TO_ABORT 1
+
+#define BOOST_STM_BLOOM_FILTER_USE_BITSET 1
+//#define BOOST_STM_USE_BOOST_SLEEP 1
+//#define BOOST_STM_USE_BOOST_THREAD_ID 1
+//#define BOOST_STM_USE_BOOST_MUTEX 1
+
+#endif // BOOST_STM_DETAIL_CONFIG_H
+
+
+
+
+
+
+
+
+

Added: sandbox/stm/boost/stm/detail/datatypes.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/datatypes.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,92 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#ifndef BOOST_STM_dataTypes_header_file
+#define BOOST_STM_dataTypes_header_file
+
+//#include <boost/thread/thread.hpp>
+
+/////////////////////////////////////////////////////////////////////////////
+#ifdef WIN32
+#define WINOS
+#elif WIN64
+#define WINOS
+#else
+#define UNIX
+#endif
+
+#include <stdlib.h>
+//#include <boost/thread/thread.hpp>
+#include <pthread.h>
+
+#ifndef BOOST_STM_USE_BOOST_THREAD_ID
+#ifdef WINOS
+#pragma warning (disable:4786)
+#define THREAD_ID (size_t)pthread_self().p
+#else
+#define THREAD_ID (size_t) pthread_self()
+#endif
+#else
+
+#define THREAD_ID boost::this_thread::get_id()
+#endif
+
+
+#ifndef BOOST_STM_USE_BOOST_SLEEP
+#ifdef WINOS
+#define SLEEP(x) Sleep(x)
+#else
+#include <unistd.h>
+#define SLEEP(x) usleep(x*1000)
+#endif
+#else
+#define SLEEP(x) boost::this_thread::sleep(boost::posix_time::milliseconds(x))
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// types
+/////////////////////////////////////////////////////////////////////////////
+typedef bool bool8;
+typedef char char8;
+
+typedef unsigned char uchar8;
+
+typedef char int8;
+typedef unsigned char uint8;
+
+typedef short int int16;
+typedef unsigned short int uint16;
+
+typedef long int int32;
+typedef unsigned long int uint32;
+
+#endif // dataTypes_header_file

Added: sandbox/stm/boost/stm/detail/jenkins_hash.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/jenkins_hash.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,1008 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+-------------------------------------------------------------------------------
+lookup3.c, by Bob Jenkins, May 2006, Public Domain.
+
+These are functions for producing 32-bit hashes for hash table lookup.
+hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
+are externally useful functions. Routines to test the hash are included
+if SELF_TEST is defined. You can use this free for any purpose. It's in
+the public domain. It has no warranty.
+
+You probably want to use hashlittle(). hashlittle() and hashbig()
+hash byte arrays. hashlittle() is is faster than hashbig() on
+little-endian machines. Intel and AMD are little-endian machines.
+On second thought, you probably want hashlittle2(), which is identical to
+hashlittle() except it returns two 32-bit hashes for the price of one.
+You could implement hashbig2() if you wanted but I haven't bothered here.
+
+If you want to find a hash of, say, exactly 7 integers, do
+ a = i1; b = i2; c = i3;
+ mix(a,b,c);
+ a += i4; b += i5; c += i6;
+ mix(a,b,c);
+ a += i7;
+ final(a,b,c);
+then use c as the hash value. If you have a variable length array of
+4-byte integers to hash, use hashword(). If you have a byte array (like
+a character string), use hashlittle(). If you have several byte arrays, or
+a mix of things, see the comments above hashlittle().
+
+Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
+then mix those integers. This is fast (you can do a lot more thorough
+mixing with 12*3 instructions on 3 integers than you can with 3 instructions
+on 1 byte), but shoehorning those bytes into integers efficiently is messy.
+-------------------------------------------------------------------------------
+*/
+
+#ifndef BOOST_STM_JENKINS_HAS__HPP
+#define BOOST_STM_JENKINS_HAS__HPP
+
+#define SELF_TEST 1
+
+#include <cstddef>
+#include <stdio.h> /* defines printf for tests */
+#include <time.h> /* defines time_t for timings in the test */
+//#include <sys/param.h> /* attempt to define endianness */
+#ifdef linux
+# include <endian.h> /* attempt to define endianness */
+#endif
+
+#if 1 // TBR ERROR_DO_NOT_COPILE_IN_CYGWIN
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+#else
+//# include <stdint.h> /* attempt to define endianness */
+#endif
+typedef std::size_t uint32_t_size_t;
+
+/*
+ * My best guess at if you are big-endian or little-endian. This may
+ * need adjustment.
+ */
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN) || \
+ (defined(i386) || defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
+# define HASH_LITTLE_ENDIAN 1
+# define HASH_BIG_ENDIAN 0
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
+ __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 1
+#else
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 0
+#endif
+
+#define hashsize(n) ((uint32_t_size_t)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+/*
+-------------------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+
+This is reversible, so any information in (a,b,c) before mix() is
+still in (a,b,c) after mix().
+
+If four pairs of (a,b,c) inputs are run through mix(), or through
+mix() in reverse, there are at least 32 bits of the output that
+are sometimes the same for one pair and different for another pair.
+This was tested for:
+* pairs that differed by one bit, by two bits, in any combination
+ of top bits of (a,b,c), or in any combination of bottom bits of
+ (a,b,c).
+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ is commonly produced by subtraction) look like a single 1-bit
+ difference.
+* the base values were pseudorandom, all zero but one bit set, or
+ all zero plus a counter that starts at zero.
+
+Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
+satisfy this are
+ 4 6 8 16 19 4
+ 9 15 3 18 27 15
+ 14 9 3 7 17 3
+Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
+for "differ" defined as + with a one-bit base and a two-bit delta. I
+used http://burtleburtle.net/bob/hash/avalanche.html to choose
+the operations, constants, and arrangements of the variables.
+
+This does not achieve avalanche. There are input bits of (a,b,c)
+that fail to affect some output bits of (a,b,c), especially of a. The
+most thoroughly mixed value is c, but it doesn't really even achieve
+avalanche in c.
+
+This allows some parallelism. Read-after-writes are good at doubling
+the number of bits affected, so the goal of mixing pulls in the opposite
+direction as the goal of parallelism. I did what I could. Rotates
+seem to cost as much as shifts on every machine I could lay my hands
+on, and rotates are much kinder to the top and bottom bits, so I used
+rotates.
+-------------------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+ a -= c; a ^= rot(c, 4); c += b; \
+ b -= a; b ^= rot(a, 6); a += c; \
+ c -= b; c ^= rot(b, 8); b += a; \
+ a -= c; a ^= rot(c,16); c += b; \
+ b -= a; b ^= rot(a,19); a += c; \
+ c -= b; c ^= rot(b, 4); b += a; \
+}
+
+/*
+-------------------------------------------------------------------------------
+final -- final mixing of 3 32-bit values (a,b,c) into c
+
+Pairs of (a,b,c) values differing in only a few bits will usually
+produce values of c that look totally different. This was tested for
+* pairs that differed by one bit, by two bits, in any combination
+ of top bits of (a,b,c), or in any combination of bottom bits of
+ (a,b,c).
+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ is commonly produced by subtraction) look like a single 1-bit
+ difference.
+* the base values were pseudorandom, all zero but one bit set, or
+ all zero plus a counter that starts at zero.
+
+These constants passed:
+ 14 11 25 16 4 14 24
+ 12 14 25 16 4 14 24
+and these came close:
+ 4 8 15 26 3 22 24
+ 10 8 15 26 3 22 24
+ 11 8 15 26 3 22 24
+-------------------------------------------------------------------------------
+*/
+#define final(a,b,c) \
+{ \
+ c ^= b; c -= rot(b,14); \
+ a ^= c; a -= rot(c,11); \
+ b ^= a; b -= rot(a,25); \
+ c ^= b; c -= rot(b,16); \
+ a ^= c; a -= rot(c,4); \
+ b ^= a; b -= rot(a,14); \
+ c ^= b; c -= rot(b,24); \
+}
+
+/*
+--------------------------------------------------------------------
+ This works on all machines. To be useful, it requires
+ -- that the key be an array of uint32_t_size_t's, and
+ -- that the length be the number of uint32_t_size_t's in the key
+
+ The function hashword() is identical to hashlittle() on little-endian
+ machines, and identical to hashbig() on big-endian machines,
+ except that the length has to be measured in uint32_t_size_ts rather than in
+ bytes. hashlittle() is more complicated than hashword() only because
+ hashlittle() has to dance around fitting the key bytes into registers.
+--------------------------------------------------------------------
+*/
+inline uint32_t_size_t hashword(
+const uint32_t_size_t *k, /* the key, an array of uint32_t_size_t values */
+std::size_t length, /* the length of the key, in uint32_t_size_ts */
+uint32_t_size_t initval) /* the previous hash, or an arbitrary value */
+{
+ uint32_t_size_t a,b,c;
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + (((uint32_t_size_t)length)<<2) + initval;
+
+ /*------------------------------------------------- handle most of the key */
+ while (length > 3)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 3;
+ k += 3;
+ }
+
+ /*------------------------------------------- handle the last 3 uint32_t_size_t's */
+ switch(length) /* all the case statements fall through */
+ {
+ case 3 : c+=k[2];
+ case 2 : b+=k[1];
+ case 1 : a+=k[0];
+ final(a,b,c);
+ case 0: /* case 0: nothing left to add */
+ break;
+ }
+ /*------------------------------------------------------ report the result */
+ return c;
+}
+
+
+/*
+--------------------------------------------------------------------
+hashword2() -- same as hashword(), but take two seeds and return two
+32-bit values. pc and pb must both be nonnull, and *pc and *pb must
+both be initialized with seeds. If you pass in (*pb)==0, the output
+(*pc) will be the same as the return value from hashword().
+--------------------------------------------------------------------
+*/
+inline void hashword2 (
+const uint32_t_size_t *k, /* the key, an array of uint32_t_size_t values */
+std::size_t length, /* the length of the key, in uint32_t_size_ts */
+uint32_t_size_t *pc, /* IN: seed OUT: primary hash value */
+uint32_t_size_t *pb) /* IN: more seed OUT: secondary hash value */
+{
+ uint32_t_size_t a,b,c;
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t_size_t)(length<<2)) + *pc;
+ c += *pb;
+
+ /*------------------------------------------------- handle most of the key */
+ while (length > 3)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 3;
+ k += 3;
+ }
+
+ /*------------------------------------------- handle the last 3 uint32_t_size_t's */
+ switch(length) /* all the case statements fall through */
+ {
+ case 3 : c+=k[2];
+ case 2 : b+=k[1];
+ case 1 : a+=k[0];
+ final(a,b,c);
+ case 0: /* case 0: nothing left to add */
+ break;
+ }
+ /*------------------------------------------------------ report the result */
+ *pc=c; *pb=b;
+}
+
+
+/*
+-------------------------------------------------------------------------------
+hashlittle() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ length : the length of the key, counting by bytes
+ initval : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Two keys differing by one or two bits will have
+totally different hash values.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (uint8_t **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
+
+By Bob Jenkins, 2006. bob_jenkins_at_burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial. It's free.
+
+Use for hash table lookup, or anything where one collision in 2^^32 is
+acceptable. Do NOT use for cryptographic purposes.
+-------------------------------------------------------------------------------
+*/
+
+inline uint32_t_size_t hashlittle( const void *key, std::size_t length, uint32_t_size_t initval)
+{
+ uint32_t_size_t a,b,c; /* internal state */
+ union { const void *ptr; std::size_t i; } u; /* needed for Mac Powerbook G4 */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t_size_t)length) + initval;
+
+ u.ptr = key;
+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
+ const uint32_t_size_t *k = (const uint32_t_size_t *)key; /* read 32-bit chunks */
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff; break;
+ case 2 : a+=k[0]&0xffff; break;
+ case 1 : a+=k[0]&0xff; break;
+ case 0 : return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+ const uint8_t *k8;
+
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t_size_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t_size_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t_size_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t_size_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t_size_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t_size_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : return c;
+ }
+
+#endif /* !valgrind */
+
+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t_size_t)k[1])<<16);
+ b += k[2] + (((uint32_t_size_t)k[3])<<16);
+ c += k[4] + (((uint32_t_size_t)k[5])<<16);
+ mix(a,b,c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[4]+(((uint32_t_size_t)k[5])<<16);
+ b+=k[2]+(((uint32_t_size_t)k[3])<<16);
+ a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 11: c+=((uint32_t_size_t)k8[10])<<16; /* fall through */
+ case 10: c+=k[4];
+ b+=k[2]+(((uint32_t_size_t)k[3])<<16);
+ a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[2]+(((uint32_t_size_t)k[3])<<16);
+ a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 7 : b+=((uint32_t_size_t)k8[6])<<16; /* fall through */
+ case 6 : b+=k[2];
+ a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 3 : a+=((uint32_t_size_t)k8[2])<<16; /* fall through */
+ case 2 : a+=k[0];
+ break;
+ case 1 : a+=k8[0];
+ break;
+ case 0 : return c; /* zero length requires no mixing */
+ }
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t_size_t)k[1])<<8;
+ a += ((uint32_t_size_t)k[2])<<16;
+ a += ((uint32_t_size_t)k[3])<<24;
+ b += k[4];
+ b += ((uint32_t_size_t)k[5])<<8;
+ b += ((uint32_t_size_t)k[6])<<16;
+ b += ((uint32_t_size_t)k[7])<<24;
+ c += k[8];
+ c += ((uint32_t_size_t)k[9])<<8;
+ c += ((uint32_t_size_t)k[10])<<16;
+ c += ((uint32_t_size_t)k[11])<<24;
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=((uint32_t_size_t)k[11])<<24;
+ case 11: c+=((uint32_t_size_t)k[10])<<16;
+ case 10: c+=((uint32_t_size_t)k[9])<<8;
+ case 9 : c+=k[8];
+ case 8 : b+=((uint32_t_size_t)k[7])<<24;
+ case 7 : b+=((uint32_t_size_t)k[6])<<16;
+ case 6 : b+=((uint32_t_size_t)k[5])<<8;
+ case 5 : b+=k[4];
+ case 4 : a+=((uint32_t_size_t)k[3])<<24;
+ case 3 : a+=((uint32_t_size_t)k[2])<<16;
+ case 2 : a+=((uint32_t_size_t)k[1])<<8;
+ case 1 : a+=k[0];
+ break;
+ case 0 : return c;
+ }
+ }
+
+ final(a,b,c);
+ return c;
+}
+
+
+/*
+ * hashlittle2: return 2 32-bit hash values
+ *
+ * This is identical to hashlittle(), except it returns two 32-bit hash
+ * values instead of just one. This is good enough for hash table
+ * lookup with 2^^64 buckets, or if you want a second hash if you're not
+ * happy with the first, or if you want a probably-unique 64-bit ID for
+ * the key. *pc is better mixed than *pb, so use *pc first. If you want
+ * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
+ */
+inline void hashlittle2(
+ const void *key, /* the key to hash */
+ std::size_t length, /* length of the key */
+ uint32_t_size_t *pc, /* IN: primary initval, OUT: primary hash */
+ uint32_t_size_t *pb) /* IN: secondary initval, OUT: secondary hash */
+{
+ uint32_t_size_t a,b,c; /* internal state */
+ union { const void *ptr; std::size_t i; } u; /* needed for Mac Powerbook G4 */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t_size_t)length) + *pc;
+ c += *pb;
+
+ u.ptr = key;
+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
+ const uint32_t_size_t *k = (const uint32_t_size_t *)key; /* read 32-bit chunks */
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff; break;
+ case 2 : a+=k[0]&0xffff; break;
+ case 1 : a+=k[0]&0xff; break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+ const uint8_t *k8;
+
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t_size_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t_size_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t_size_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t_size_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t_size_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t_size_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
+
+#endif /* !valgrind */
+
+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t_size_t)k[1])<<16);
+ b += k[2] + (((uint32_t_size_t)k[3])<<16);
+ c += k[4] + (((uint32_t_size_t)k[5])<<16);
+ mix(a,b,c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[4]+(((uint32_t_size_t)k[5])<<16);
+ b+=k[2]+(((uint32_t_size_t)k[3])<<16);
+ a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 11: c+=((uint32_t_size_t)k8[10])<<16; /* fall through */
+ case 10: c+=k[4];
+ b+=k[2]+(((uint32_t_size_t)k[3])<<16);
+ a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[2]+(((uint32_t_size_t)k[3])<<16);
+ a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 7 : b+=((uint32_t_size_t)k8[6])<<16; /* fall through */
+ case 6 : b+=k[2];
+ a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]+(((uint32_t_size_t)k[1])<<16);
+ break;
+ case 3 : a+=((uint32_t_size_t)k8[2])<<16; /* fall through */
+ case 2 : a+=k[0];
+ break;
+ case 1 : a+=k8[0];
+ break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t_size_t)k[1])<<8;
+ a += ((uint32_t_size_t)k[2])<<16;
+ a += ((uint32_t_size_t)k[3])<<24;
+ b += k[4];
+ b += ((uint32_t_size_t)k[5])<<8;
+ b += ((uint32_t_size_t)k[6])<<16;
+ b += ((uint32_t_size_t)k[7])<<24;
+ c += k[8];
+ c += ((uint32_t_size_t)k[9])<<8;
+ c += ((uint32_t_size_t)k[10])<<16;
+ c += ((uint32_t_size_t)k[11])<<24;
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=((uint32_t_size_t)k[11])<<24;
+ case 11: c+=((uint32_t_size_t)k[10])<<16;
+ case 10: c+=((uint32_t_size_t)k[9])<<8;
+ case 9 : c+=k[8];
+ case 8 : b+=((uint32_t_size_t)k[7])<<24;
+ case 7 : b+=((uint32_t_size_t)k[6])<<16;
+ case 6 : b+=((uint32_t_size_t)k[5])<<8;
+ case 5 : b+=k[4];
+ case 4 : a+=((uint32_t_size_t)k[3])<<24;
+ case 3 : a+=((uint32_t_size_t)k[2])<<16;
+ case 2 : a+=((uint32_t_size_t)k[1])<<8;
+ case 1 : a+=k[0];
+ break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
+ }
+
+ final(a,b,c);
+ *pc=c; *pb=b;
+}
+
+
+
+/*
+ * hashbig():
+ * This is the same as hashword() on big-endian machines. It is different
+ * from hashlittle() on all machines. hashbig() takes advantage of
+ * big-endian byte ordering.
+ */
+inline uint32_t_size_t hashbig( const void *key, std::size_t length, uint32_t_size_t initval)
+{
+ uint32_t_size_t a,b,c;
+ union { const void *ptr; std::size_t i; } u; /* to cast key to (std::size_t) happily */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t_size_t)length) + initval;
+
+ u.ptr = key;
+ if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) {
+ const uint32_t_size_t *k = (const uint32_t_size_t *)key; /* read 32-bit chunks */
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]<<8" actually reads beyond the end of the string, but
+ * then shifts out the part it's not allowed to read. Because the
+ * string is aligned, the illegal read is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff00; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff0000; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff000000; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff00; break;
+ case 2 : a+=k[0]&0xffff0000; break;
+ case 1 : a+=k[0]&0xff000000; break;
+ case 0 : return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+ const uint8_t *k8;
+
+ k8 = (const uint8_t *)k;
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t_size_t)k8[10])<<8; /* fall through */
+ case 10: c+=((uint32_t_size_t)k8[9])<<16; /* fall through */
+ case 9 : c+=((uint32_t_size_t)k8[8])<<24; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t_size_t)k8[6])<<8; /* fall through */
+ case 6 : b+=((uint32_t_size_t)k8[5])<<16; /* fall through */
+ case 5 : b+=((uint32_t_size_t)k8[4])<<24; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t_size_t)k8[2])<<8; /* fall through */
+ case 2 : a+=((uint32_t_size_t)k8[1])<<16; /* fall through */
+ case 1 : a+=((uint32_t_size_t)k8[0])<<24; break;
+ case 0 : return c;
+ }
+
+#endif /* !VALGRIND */
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += ((uint32_t_size_t)k[0])<<24;
+ a += ((uint32_t_size_t)k[1])<<16;
+ a += ((uint32_t_size_t)k[2])<<8;
+ a += ((uint32_t_size_t)k[3]);
+ b += ((uint32_t_size_t)k[4])<<24;
+ b += ((uint32_t_size_t)k[5])<<16;
+ b += ((uint32_t_size_t)k[6])<<8;
+ b += ((uint32_t_size_t)k[7]);
+ c += ((uint32_t_size_t)k[8])<<24;
+ c += ((uint32_t_size_t)k[9])<<16;
+ c += ((uint32_t_size_t)k[10])<<8;
+ c += ((uint32_t_size_t)k[11]);
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=k[11];
+ case 11: c+=((uint32_t_size_t)k[10])<<8;
+ case 10: c+=((uint32_t_size_t)k[9])<<16;
+ case 9 : c+=((uint32_t_size_t)k[8])<<24;
+ case 8 : b+=k[7];
+ case 7 : b+=((uint32_t_size_t)k[6])<<8;
+ case 6 : b+=((uint32_t_size_t)k[5])<<16;
+ case 5 : b+=((uint32_t_size_t)k[4])<<24;
+ case 4 : a+=k[3];
+ case 3 : a+=((uint32_t_size_t)k[2])<<8;
+ case 2 : a+=((uint32_t_size_t)k[1])<<16;
+ case 1 : a+=((uint32_t_size_t)k[0])<<24;
+ break;
+ case 0 : return c;
+ }
+ }
+
+ final(a,b,c);
+ return c;
+}
+
+
+#ifdef SELF_TEST
+
+/* used for timings */
+inline void driver1()
+{
+ uint8_t buf[256];
+ uint32_t_size_t i;
+ uint32_t_size_t h=0;
+ time_t a,z;
+
+ time(&a);
+ for (i=0; i<256; ++i) buf[i] = 'x';
+ for (i=0; i<1; ++i)
+ {
+ h = hashlittle(&buf[0],1,h);
+ }
+ time(&z);
+ //if (z-a > 0) printf("time %d %.8x\n", z-a, h);
+}
+
+/* check that every input bit changes every output bit half the time */
+#define HASHSTATE 1
+#define HASHLEN 1
+#define MAXPAIR 60
+#define MAXLEN 70
+inline void driver2()
+{
+ uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
+ uint32_t_size_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
+ uint32_t_size_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
+ uint32_t_size_t x[HASHSTATE],y[HASHSTATE];
+ uint32_t_size_t hlen;
+
+ printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
+ for (hlen=0; hlen < MAXLEN; ++hlen)
+ {
+ z=0;
+ for (i=0; i<hlen; ++i) /*----------------------- for each input byte, */
+ {
+ for (j=0; j<8; ++j) /*------------------------ for each input bit, */
+ {
+ for (m=1; m<8; ++m) /*------------ for serveral possible initvals, */
+ {
+ for (l=0; l<HASHSTATE; ++l)
+ e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((uint32_t_size_t)0);
+
+ /*---- check that every output bit is affected by that input bit */
+ for (k=0; k<MAXPAIR; k+=2)
+ {
+ uint32_t_size_t finished=1;
+ /* keys have one bit different */
+ for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (uint8_t)0;}
+ /* have a and b be two keys differing in only one bit */
+ a[i] ^= (k<<j);
+ a[i] ^= (k>>(8-j));
+ c[0] = hashlittle(a, hlen, m);
+ b[i] ^= ((k+1)<<j);
+ b[i] ^= ((k+1)>>(8-j));
+ d[0] = hashlittle(b, hlen, m);
+ /* check every bit is 1, 0, set, and not set at least once */
+ for (l=0; l<HASHSTATE; ++l)
+ {
+ e[l] &= (c[l]^d[l]);
+ f[l] &= ~(c[l]^d[l]);
+ g[l] &= c[l];
+ h[l] &= ~c[l];
+ x[l] &= d[l];
+ y[l] &= ~d[l];
+ if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
+ }
+ if (finished) break;
+ }
+ if (k>z) z=k;
+ if (k==MAXPAIR)
+ {
+ printf("Some bit didn't change: ");
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x ",
+ e[0],f[0],g[0],h[0],x[0],y[0]);
+ printf("i %d j %d m %d len %d\n", i, j, m, hlen);
+ }
+ if (z==MAXPAIR) goto done;
+ }
+ }
+ }
+ done:
+ if (z < MAXPAIR)
+ {
+ printf("Mix success %2d bytes %2d initvals ",i,m);
+ printf("required %d trials\n", z/2);
+ }
+ }
+ printf("\n");
+}
+
+/* Check for reading beyond the end of the buffer and alignment problems */
+inline void driver3()
+{
+ uint8_t buf[MAXLEN+20], *b;
+ uint32_t_size_t len;
+ uint8_t q[] = "This is the time for all good men to come to the aid of their country...";
+ uint32_t_size_t h;
+ uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country...";
+ uint32_t_size_t i;
+ uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country...";
+ uint32_t_size_t j;
+ uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country...";
+ uint32_t_size_t ref,x,y;
+ uint8_t *p;
+
+ printf("Endianness. These lines should all be the same (for values filled in):\n");
+ printf("%.8x %.8x %.8x\n",
+ hashword((const uint32_t_size_t *)q, (sizeof(q)-1)/4, 13),
+ hashword((const uint32_t_size_t *)q, (sizeof(q)-5)/4, 13),
+ hashword((const uint32_t_size_t *)q, (sizeof(q)-9)/4, 13));
+ p = q;
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
+ hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
+ hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
+ hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
+ hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
+ hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
+ hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
+ p = &qq[1];
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
+ hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
+ hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
+ hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
+ hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
+ hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
+ hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
+ p = &qqq[2];
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
+ hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
+ hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
+ hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
+ hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
+ hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
+ hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
+ p = &qqqq[3];
+ printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
+ hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
+ hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
+ hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
+ hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
+ hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
+ hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
+ printf("\n");
+
+ /* check that hashlittle2 and hashlittle produce the same results */
+ i=47; j=0;
+ hashlittle2(q, sizeof(q), &i, &j);
+ if (hashlittle(q, sizeof(q), 47) != i)
+ printf("hashlittle2 and hashlittle mismatch\n");
+
+ /* check that hashword2 and hashword produce the same results */
+ len = 0xdeadbeef;
+ i=47, j=0;
+ hashword2(&len, 1, &i, &j);
+ if (hashword(&len, 1, 47) != i)
+ printf("hashword2 and hashword mismatch %x %x\n",
+ i, hashword(&len, 1, 47));
+
+ /* check hashlittle doesn't read before or after the ends of the string */
+ for (h=0, b=buf+1; h<8; ++h, ++b)
+ {
+ for (i=0; i<MAXLEN; ++i)
+ {
+ len = i;
+ for (j=0; j<i; ++j) *(b+j)=0;
+
+ /* these should all be equal */
+ ref = hashlittle(b, len, (uint32_t_size_t)1);
+ *(b+i)=(uint8_t)~0;
+ *(b-1)=(uint8_t)~0;
+ x = hashlittle(b, len, (uint32_t_size_t)1);
+ y = hashlittle(b, len, (uint32_t_size_t)1);
+ if ((ref != x) || (ref != y))
+ {
+ printf("alignment error: %.8x %.8x %.8x %d %d\n",ref,x,y,
+ h, i);
+ }
+ }
+ }
+}
+
+/* check for problems with nulls */
+inline void driver4()
+{
+ uint8_t buf[1];
+ uint32_t_size_t h,i,state[HASHSTATE];
+
+
+ buf[0] = ~0;
+ for (i=0; i<HASHSTATE; ++i) state[i] = 1;
+ printf("These should all be different\n");
+ for (i=0, h=0; i<8; ++i)
+ {
+ h = hashlittle(buf, 0, h);
+ //printf("%2ld 0-byte strings, hash is %.8x\n", i, h);
+ }
+}
+
+
+#if 0
+int main()
+{
+ driver1(); /* test that the key is hashed: used for timings */
+ driver2(); /* test that whole key is hashed thoroughly */
+ driver3(); /* test that nothing but the key is hashed */
+ driver4(); /* test hashing multiple buffers (all buffers are null) */
+ return 1;
+}
+#endif
+
+#endif /* SELF_TEST */
+
+#endif

Added: sandbox/stm/boost/stm/detail/latm_def_full_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/latm_def_full_impl.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,274 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+//
+// TransactionLockAwareImpl.h
+//
+// This file contains method implementations for transaction.hpp (specifically for
+// enabling lock aware transactions). The main purpose of this file is to reduce
+// the complexity of the transaction class by separating its implementation into
+// a secondary .h file.
+//
+// Do NOT place these methods in a .cc/.cpp/.cxx file. These methods must be
+// inlined to keep DracoSTM performing fast. If these methods are placed in a
+// C++ source file they will incur function call overhead - something we need
+// to reduce to keep performance high.
+//
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_TRANSACTION_LOCK_AWARE_DEF_IMPL_H
+#define BOOST_STM_TRANSACTION_LOCK_AWARE_DEF_IMPL_H
+
+#if PERFORMING_LATM
+
+#include <boost/stm/detail/latm_def_tx_impl.hpp>
+#include <boost/stm/detail/latm_def_tm_impl.hpp>
+
+//-----------------------------------------------------------------------------
+//
+//
+//
+// FULL LATM PROTECTION METHODS
+//
+//
+//
+//-----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::def_do_core_full_pthread_lock_mutex
+(Mutex *mutex, int lockWaitTime, int lockAborted)
+{
+ //--------------------------------------------------------------------------
+ // if the lock-aware tm lock set is empty, lock the in-flight trans mutex
+ // so we can abort all the in-flight transactions
+ //--------------------------------------------------------------------------
+ if (0 == latmLockedLocks_.size())
+ {
+ lock_general_access();
+ lock_inflight_access();
+
+ std::list<transaction*> txList;
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction *t = (transaction*)*i;
+
+ if (!t->irrevocable() &&
+ cm_->allow_lock_to_abort_tx(lockWaitTime, lockAborted, false, *t))
+ {
+ txList.push_back(t);
+ }
+ else
+ {
+ unlock_general_access();
+ unlock_inflight_access();
+ return false;
+ }
+ }
+
+ for (std::list<transaction*>::iterator it = txList.begin(); txList.end() != it; ++it)
+ {
+ (*it)->force_to_abort();
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+ }
+
+ try { latmLockedLocks_.insert(mutex); }
+ catch (...)
+ {
+ unlock_inflight_access();
+ throw;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::def_full_pthread_lock_mutex(Mutex *mutex)
+{
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ t->make_isolated();
+
+ bool hadLock = t->is_currently_locked_lock(mutex);
+ t->add_to_currently_locked_locks(mutex);
+ t->add_to_obtained_locks(mutex);
+
+ t->commit_deferred_update_tx();
+ lock_latm_access();
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock_latm_access();
+
+ // TBR if (hadLock) return 0;
+ // TBR else return lock(mutex);
+ if (hadLock) return 0;
+ else lock(mutex);
+ return 0;
+ }
+
+ int waitTime = 0, aborted = 0;
+ for (;;)
+ {
+ // TBR int val = lock(mutex);
+ // TBR if (0 != val) return val;
+ lock(mutex);
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //--------------------------------------------------------------------
+ // if we are able to do the core lock work, break
+ //--------------------------------------------------------------------
+ if (def_do_core_full_pthread_lock_mutex(mutex, waitTime, aborted)) break;
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ //-----------------------------------------------------------------------
+ // we weren't able to do the core lock work, unlock our mutex and sleep
+ //-----------------------------------------------------------------------
+ unlock(mutex);
+ unlock(&latmMutex_);
+
+ SLEEP(cm_->lock_sleep_time());
+ waitTime += cm_->lock_sleep_time();
+ ++aborted;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::def_full_pthread_trylock_mutex(Mutex *mutex)
+{
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ t->make_isolated();
+
+ bool hadLock = t->is_currently_locked_lock(mutex);
+ t->add_to_currently_locked_locks(mutex);
+ t->add_to_obtained_locks(mutex);
+
+ t->commit_deferred_update_tx();
+ lock_latm_access();
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock_latm_access();
+
+ if (hadLock) return 0;
+ else return trylock(mutex);
+ }
+
+ int val = trylock(mutex);
+ if (0 != val) return val;
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //-----------------------------------------------------------------------
+ // if !core done, since trylock, we cannot stall & retry - just exit
+ //-----------------------------------------------------------------------
+ if (!def_do_core_full_pthread_lock_mutex(mutex, 0, 0))
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ return -1;
+ }
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+ // note: we do not release the transactionsInFlightMutex - this will prevents
+ // new transactions from starting until this lock is released
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::def_full_pthread_unlock_mutex(Mutex *mutex)
+{
+ lock(&latmMutex_);
+ bool hasLock = true;
+
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ if (!t->is_on_obtained_locks_list(mutex))
+ {
+ // this is illegal, it means the transaction is unlocking a lock
+ // it did not obtain (e.g., early release) while the transaction
+ // is still in-flight. Throw exception
+ throw "lock released for transaction that did not obtain it";
+ }
+
+ if (!t->is_currently_locked_lock(mutex)) hasLock = false;
+ t->remove_from_currently_locked_locks(mutex);
+ }
+
+ latmLockedLocks_.erase(mutex);
+
+ if (0 == latmLockedLocks_.size()) unlock_inflight_access();
+
+ latmLockedLocksOfThreadMap_.erase(mutex);
+ unlock(&latmMutex_);
+
+ // TBR if (hasLock) return unlock(mutex);
+ // TBR else return 0;
+ if (hasLock) unlock(mutex);
+ return 0;
+}
+
+#endif
+
+
+#endif // TRANSACTION_IMPL_H
+

Added: sandbox/stm/boost/stm/detail/latm_def_tm_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/latm_def_tm_impl.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,284 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+//
+// LatmDefTmImlp.h
+//
+// This file contains method implementations for transaction.hpp (specifically for
+// enabling lock aware transactions). The main purpose of this file is to reduce
+// the complexity of the transaction class by separating its implementation into
+// a secondary .h file.
+//
+// Do NOT place these methods in a .cc/.cpp/.cxx file. These methods must be
+// inlined to keep DracoSTM performing fast. If these methods are placed in a
+// C++ source file they will incur function call overhead - something we need
+// to reduce to keep performance high.
+//
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_LATM_DEF_TM_IMPL_H
+#define BOOST_STM_LATM_DEF_TM_IMPL_H
+
+#if PERFORMING_LATM
+
+//-----------------------------------------------------------------------------
+//
+//
+//
+// GLOBAL CONFLICTING LOCK LATM PROTECTION METHODS
+//
+//
+//
+//-----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+//
+// ASSUMPTION: latmMutex_ MUST BE OBTAINED BEFORE CALLING THIS METHOD
+//
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::def_do_core_tm_conflicting_lock_pthread_lock_mutex
+(Mutex *mutex, int lockWaitTime, int lockAborted)
+{
+ //--------------------------------------------------------------------------
+ // if this mutex is on the tmConflictingLocks_ set, then we need to stop
+ // transactions which are in-flight.
+ //
+ // if it isn't we don't interrupt any in-flight transactions
+ //--------------------------------------------------------------------------
+ if (tmConflictingLocks_.find(mutex) != tmConflictingLocks_.end())
+ {
+ // if the lock-aware tm lock set is empty, lock the in-flight trans mutex
+ // so we can abort all the in-flight transactions
+ if (0 == latmLockedLocks_.size())
+ {
+ var_auto_lock<PLOCK> autlock(general_lock(), inflight_lock(), 0);
+
+ std::list<transaction*> txList;
+
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction *t = (transaction*)*i;
+
+ if (!t->irrevocable() &&
+ cm_->allow_lock_to_abort_tx(lockWaitTime, lockAborted, false, *t))
+ {
+ txList.push_back(t);
+ }
+ else return false;
+ }
+
+ for (std::list<transaction*>::iterator it = txList.begin(); txList.end() != it; ++it)
+ {
+ (*it)->force_to_abort();
+ }
+ }
+
+ latmLockedLocks_.insert(mutex);
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::
+def_tm_conflicting_lock_pthread_lock_mutex(Mutex *mutex)
+{
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ transaction::must_be_in_tm_conflicting_lock_set(mutex);
+ t->make_isolated();
+ t->commit_deferred_update_tx();
+
+ bool hadLock = t->is_currently_locked_lock(mutex);
+ t->add_to_currently_locked_locks(mutex);
+
+ lock_latm_access();
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock_latm_access();
+
+ // TBR if (hadLock) return 0;
+ // TBR else return lock(mutex);
+ if (hadLock) return 0;
+ else lock(mutex);
+ return 0;
+ }
+
+ int waitTime = 0, aborted = 0;
+
+ for (;;)
+ {
+ // TRR int val = lock(mutex);
+ // TRR if (0 != val) return val;
+ lock(mutex);
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //--------------------------------------------------------------------
+ // if we are able to do the core lock work, break
+ //--------------------------------------------------------------------
+ if (def_do_core_tm_conflicting_lock_pthread_lock_mutex
+ (mutex, waitTime, aborted)) break;
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ //-----------------------------------------------------------------------
+ // we weren't able to do the core lock work, unlock our mutex and sleep
+ //-----------------------------------------------------------------------
+ unlock(mutex);
+ unlock(&latmMutex_);
+
+ SLEEP(cm_->lock_sleep_time());
+ waitTime += cm_->lock_sleep_time();
+ ++aborted;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::
+def_tm_conflicting_lock_pthread_trylock_mutex(Mutex *mutex)
+{
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ transaction::must_be_in_tm_conflicting_lock_set(mutex);
+ t->make_isolated();
+ t->commit_deferred_update_tx();
+
+ bool hadLock = t->is_currently_locked_lock(mutex);
+ t->add_to_currently_locked_locks(mutex);
+
+ lock_latm_access();
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock_latm_access();
+
+ if (hadLock) return 0;
+ else return trylock(mutex);
+ }
+
+ int val = trylock(mutex);
+ if (0 != val) return val;
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //-----------------------------------------------------------------------
+ // if !core done, since trylock, we cannot stall & retry - just exit
+ //-----------------------------------------------------------------------
+ if (!def_do_core_tm_conflicting_lock_pthread_lock_mutex(mutex, 0, 0))
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ return -1;
+ }
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+ // note: we do not release the transactionsInFlightMutex - this will prevents
+ // new transactions from starting until this lock is released
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::
+def_tm_conflicting_lock_pthread_unlock_mutex(Mutex *mutex)
+{
+ lock(&latmMutex_);
+ bool hasLock = true;
+
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ if (!t->is_on_obtained_locks_list(mutex))
+ {
+ // this is illegal, it means the transaction is unlocking a lock
+ // it did not obtain (e.g., early release) while the transaction
+ // is still in-flight. Throw exception
+ throw "lock released for transaction that did not obtain it";
+ }
+
+ if (!t->is_currently_locked_lock(mutex)) hasLock = false;
+ t->remove_from_currently_locked_locks(mutex);
+ }
+
+ //--------------------------------------------------------------------------
+ // if this mutex is on the tmConflictingLocks_ set, then we need to remove
+ // it from the latmLocks and check to see if we allow transactions to
+ // continue.
+ //--------------------------------------------------------------------------
+ if (tmConflictingLocks_.find(mutex) != tmConflictingLocks_.end())
+ {
+ latmLockedLocks_.erase(mutex);
+
+ if (0 == latmLockedLocks_.size()) unlock_inflight_access();
+ }
+
+ latmLockedLocksOfThreadMap_.erase(mutex);
+ unlock(&latmMutex_);
+
+ // TBR if (hasLock) return unlock(mutex);
+ // TBR else return 0;
+ if (hasLock) unlock(mutex);
+ return 0;
+}
+
+
+#endif
+
+#endif // LATM_DIR_TM_IMPL_H
+
+

Added: sandbox/stm/boost/stm/detail/latm_def_tx_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/latm_def_tx_impl.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,332 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+//
+// LatmDefTxImlp.h
+//
+// This file contains method implementations for transaction.hpp (specifically for
+// enabling lock aware transactions). The main purpose of this file is to reduce
+// the complexity of the transaction class by separating its implementation into
+// a secondary .h file.
+//
+// Do NOT place these methods in a .cc/.cpp/.cxx file. These methods must be
+// inlined to keep DracoSTM performing fast. If these methods are placed in a
+// C++ source file they will incur function call overhead - something we need
+// to reduce to keep performance high.
+//
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_LATM_DEF_TX_IMPL_H
+#define BOOST_STM_LATM_DEF_TX_IMPL_H
+
+#if PERFORMING_LATM
+
+#include <fstream>
+
+//----------------------------------------------------------------------------
+//
+// ASSUMPTION: latmMutex_ MUST BE OBTAINED BEFORE CALLING THIS METHOD
+//
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::def_do_core_tx_conflicting_lock_pthread_lock_mutex
+(Mutex *mutex, int lockWaitTime, int lockAborted, bool txIsIrrevocable)
+{
+ //--------------------------------------------------------------------------
+ // see if this mutex is part of any of the in-flight transactions conflicting
+ // mutex set. if it is, stop that transaction and add it to the latm conflicting
+ // set. do not keep in-flight transactions blocked once the transactions have
+ // been processed.
+ //--------------------------------------------------------------------------
+ var_auto_lock<PLOCK> autolock(general_lock(), inflight_lock(), 0);
+
+ std::list<transaction *> txList;
+ std::set<size_t> txThreadId;
+
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction *t = (transaction*)*i;
+
+ // if this tx is part of this thread, skip it (it's an LiT)
+ if (t->threadId_ == THREAD_ID) continue;
+
+ // if this mutex has a conflict with an inflight tx
+ if (t->conflictingMutexRef_.find(mutex) != t->conflictingMutexRef_.end())
+ {
+ if (txIsIrrevocable || (!t->irrevocable() &&
+ cm_->allow_lock_to_abort_tx(lockWaitTime, lockAborted, txIsIrrevocable, *t)))
+ {
+ txList.push_back(t);
+ }
+ else return false;
+ }
+ }
+
+ if (0 != txList.size())
+ {
+#if LOGGING_BLOCKS
+ logFile_ << "----------------------\nbefore locked mutex: " << mutex << endl << endl;
+ logFile_ << outputBlockedThreadsAndLockedLocks() << endl;
+#endif
+
+ for (std::list<transaction*>::iterator it = txList.begin(); txList.end() != it; ++it)
+ {
+ transaction *t = (transaction*)*it;
+
+ t->force_to_abort();
+ t->block();
+ txThreadId.insert(t->threadId_);
+ }
+
+ try {
+ latmLockedLocksAndThreadIdsMap_.insert
+ (std::make_pair<Mutex*, ThreadIdSet>(mutex, txThreadId));
+ }
+ catch (...)
+ {
+ for (std::set<size_t>::iterator it = txThreadId.begin();
+ txThreadId.end() != it; ++it)
+ {
+ if (0 == thread_id_occurance_in_locked_locks_map(*it))
+ {
+ *threadBlockedLists_.find(*it)->second = false;
+ }
+ }
+ throw;
+ }
+
+#if LOGGING_BLOCKS
+ logFile_ << "----------------------\nafter locked mutex: " << mutex << endl << endl;
+ logFile_ << outputBlockedThreadsAndLockedLocks() << endl;
+#endif
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::def_tx_conflicting_lock_pthread_lock_mutex(Mutex *mutex)
+{
+ int waitTime = 0, aborted = 0;
+
+ //--------------------------------------------------------------------------
+ // this is the most complex code in the entire system. it is highly order
+ // dependent.
+ //
+ // if an in-flight transaction is present when this lock is attempted to be
+ // obtained:
+ //
+ // (1) make sure the lock is in the conflicting set, otherwise throw
+ // (2) make the tx irrevocable - THIS MUST BE DONE BEFORE THE LOCK IS OBTAINED
+ // otherwise the system can deadlock by obtaining
+ // the lock and then failing to become irrevocable
+ // while another irrevocable tx needs the lock we
+ // took.
+ // (3) obtain the lock
+ // (4) add the lock to the tx's obtained locked list ONLY after it has been
+ // obtained. adding it before the lock is obtained can lead to deadlock
+ // as another thread which is releasing the lock will not unblock txs
+ // that it has blocked due to our claiming to have obtained the lock
+ // (5) abort all the in-flight conflicting txes and return
+ //--------------------------------------------------------------------------
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ t->must_be_in_conflicting_lock_set(mutex);
+ t->make_irrevocable();
+
+ if (!t->is_currently_locked_lock(mutex))
+ {
+ lock(mutex); // TBR if (0 != lock(mutex)) return -1;
+ }
+
+ t->add_to_currently_locked_locks(mutex);
+ t->add_to_obtained_locks(mutex);
+ t->commit_deferred_update_tx();
+
+ lock(&latmMutex_);
+ def_do_core_tx_conflicting_lock_pthread_lock_mutex
+ (mutex, 0, 0, true);
+ unlock(&latmMutex_);
+
+ return 0;
+ }
+
+ for (;;)
+ {
+ lock(mutex); // TBR int val = lock(mutex);
+ // TBR if (0 != val) return val;
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //--------------------------------------------------------------------
+ // if we are able to do the core lock work, break
+ //--------------------------------------------------------------------
+ if (def_do_core_tx_conflicting_lock_pthread_lock_mutex
+ (mutex, waitTime, aborted, false)) break;
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ //-----------------------------------------------------------------------
+ // we weren't able to do the core lock work, unlock our mutex and sleep
+ //-----------------------------------------------------------------------
+ unlock(mutex);
+ unlock(&latmMutex_);
+
+ SLEEP(cm_->lock_sleep_time());
+ waitTime += cm_->lock_sleep_time();
+ ++aborted;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+
+ // note: we do not release the transactionsInFlightMutex - this will prevents
+ // new transactions from starting until this lock is released
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::def_tx_conflicting_lock_pthread_trylock_mutex(Mutex *mutex)
+{
+ //--------------------------------------------------------------------------
+
+ throw "might not be possible to implement trylock for this";
+
+ bool txIsIrrevocable = false;
+
+ int val = trylock(mutex);
+ if (0 != val) return val;
+
+ lock(&latmMutex_);
+
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ txIsIrrevocable = true;
+ t->must_be_in_conflicting_lock_set(mutex);
+ t->make_irrevocable();
+ t->add_to_obtained_locks(mutex);
+ t->commit_deferred_update_tx();
+ }
+
+ try
+ {
+ //-----------------------------------------------------------------------
+ // if !core done, since trylock, we cannot stall & retry - just exit
+ //-----------------------------------------------------------------------
+ if (!def_do_core_tx_conflicting_lock_pthread_lock_mutex(mutex, 0, 0, txIsIrrevocable))
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ return -1;
+ }
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+
+ // note: we do not release the transactionsInFlightMutex - this will prevents
+ // new transactions from starting until this lock is released
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::def_tx_conflicting_lock_pthread_unlock_mutex(Mutex *mutex)
+{
+ var_auto_lock<PLOCK> autolock(latm_lock(), general_lock(), inflight_lock(), 0);
+ bool hasLock = true;
+
+ if (transaction* t = get_inflight_tx_of_same_thread(true))
+ {
+ if (!t->is_on_obtained_locks_list(mutex))
+ {
+ // this is illegal, it means the transaction is unlocking a lock
+ // it did not obtain (e.g., early release) while the transaction
+ // is still in-flight. Throw exception
+ throw "lock released for transaction that did not obtain it";
+ }
+
+ if (!t->is_currently_locked_lock(mutex)) hasLock = false;
+ t->remove_from_currently_locked_locks(mutex);
+ }
+
+ //--------------------------------------------------------------------------
+ // if this mutex is on the tmConflictingLocks_ set, then we need to remove
+ // it from the latmLocks and any txs on the full thread list that are
+ // blocked because of this lock being locked should be unblocked
+ //--------------------------------------------------------------------------
+ if (latmLockedLocksAndThreadIdsMap_.find(mutex) != latmLockedLocksAndThreadIdsMap_.end())
+ {
+#if LOGGING_BLOCKS
+ logFile_ << "----------------------\nbefore unlocked mutex: " << mutex << endl << endl;
+ logFile_ << outputBlockedThreadsAndLockedLocks() << endl;
+#endif
+ latmLockedLocksAndThreadIdsMap_.erase(mutex);
+ unblock_conflicting_threads(mutex);
+
+#if LOGGING_BLOCKS
+ logFile_ << "----------------------\nafter unlocked mutex: " << mutex << endl << endl;
+ logFile_ << outputBlockedThreadsAndLockedLocks() << endl;
+#endif
+ }
+
+ latmLockedLocksOfThreadMap_.erase(mutex);
+ unblock_threads_if_locks_are_empty();
+
+ // TBR if (hasLock) return unlock(mutex);
+ // TBR else return 0;
+ if (hasLock) unlock(mutex);
+ return 0;
+}
+
+#endif
+
+#endif // LATM_DEF_TX_IMPL_H
+

Added: sandbox/stm/boost/stm/detail/latm_dir_full_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/latm_dir_full_impl.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,301 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+//
+// TransactionLockAwareImpl.h
+//
+// This file contains method implementations for transaction.hpp (specifically for
+// enabling lock aware transactions). The main purpose of this file is to reduce
+// the complexity of the transaction class by separating its implementation into
+// a secondary .h file.
+//
+// Do NOT place these methods in a .cc/.cpp/.cxx file. These methods must be
+// inlined to keep DracoSTM performing fast. If these methods are placed in a
+// C++ source file they will incur function call overhead - something we need
+// to reduce to keep performance high.
+//
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_TRANSACTION_LOCK_AWARE_DIR_IMPL_H
+#define BOOST_STM_TRANSACTION_LOCK_AWARE_DIR_IMPL_H
+
+#if PERFORMING_LATM
+
+#include <boost/stm/detail/latm_dir_tx_impl.hpp>
+#include <boost/stm/detail/latm_dir_tm_impl.hpp>
+
+//-----------------------------------------------------------------------------
+//
+//
+//
+// FULL LATM PROTECTION METHODS
+//
+//
+//
+//-----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::dir_do_core_full_pthread_lock_mutex
+(Mutex *mutex, int lockWaitTime, int lockAborted)
+{
+ //--------------------------------------------------------------------------
+ // if the lock-aware tm lock set is empty, lock the in-flight trans mutex
+ // so we can abort all the in-flight transactions
+ //--------------------------------------------------------------------------
+ if (0 == latmLockedLocks_.size())
+ {
+ lock_general_access();
+ lock_inflight_access();
+
+ std::list<transaction*> txList;
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction *t = (transaction*)*i;
+
+ if (!t->irrevocable() &&
+ cm_->allow_lock_to_abort_tx(lockWaitTime, lockAborted, false, *t))
+ {
+ txList.push_back(t);
+ }
+ else
+ {
+ unlock_general_access();
+ unlock_inflight_access();
+ return false;
+ }
+ }
+
+ for (std::list<transaction*>::iterator it = txList.begin(); txList.end() != it; ++it)
+ {
+ (*it)->force_to_abort();
+ }
+
+ //-----------------------------------------------------------------------
+ // block all threads, since we have to unlock the in-flight mutex
+ //-----------------------------------------------------------------------
+ for (ThreadMutexSetContainer::iterator iter = threadConflictingMutexes_.begin();
+ threadConflictingMutexes_.end() != iter; ++iter)
+ {
+ // no more locked LATM locks, clear everyone
+ *threadBlockedLists_.find(iter->first)->second = true;
+ //*threadBlockedLists_[iter->first] = true;
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+
+ //-----------------------------------------------------------------------
+ // now we must stall until all in-flight transactions are gone, otherwise
+ // global memory may still be in an inconsistent state
+ //-----------------------------------------------------------------------
+ while (transactionsInFlight_.size() != 0) { SLEEP(10); }
+ }
+
+ try { latmLockedLocks_.insert(mutex); }
+ catch (...)
+ {
+ unlock_general_access();
+ unlock_inflight_access();
+ throw;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::dir_full_pthread_lock_mutex(Mutex *mutex)
+{
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ t->make_isolated();
+
+ bool hadLock = t->is_currently_locked_lock(mutex);
+ t->add_to_currently_locked_locks(mutex);
+ t->add_to_obtained_locks(mutex);
+
+ // this method locks LATM and keeps it locked upon returning if param true
+ wait_until_all_locks_are_released(true);
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock_latm_access();
+
+ if (hadLock) return 0;
+ else lock(mutex);
+ return 0;
+ }
+
+ int waitTime = 0, aborted = 0;
+ for (;;)
+ {
+ // TBR int val = lock(mutex);
+ // TBR if (0 != val) return val;
+ lock(mutex);
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //--------------------------------------------------------------------
+ // if we are able to do the core lock work, break
+ //--------------------------------------------------------------------
+ if (dir_do_core_full_pthread_lock_mutex(mutex, waitTime, aborted)) break;
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ //-----------------------------------------------------------------------
+ // we weren't able to do the core lock work, unlock our mutex and sleep
+ //-----------------------------------------------------------------------
+ unlock(mutex);
+ unlock(&latmMutex_);
+
+ SLEEP(cm_->lock_sleep_time());
+ waitTime += cm_->lock_sleep_time();
+ ++aborted;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::dir_full_pthread_trylock_mutex(Mutex *mutex)
+{
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ t->make_isolated();
+
+ bool hadLock = t->is_currently_locked_lock(mutex);
+ t->add_to_currently_locked_locks(mutex);
+ t->add_to_obtained_locks(mutex);
+
+ // this method locks LATM and keeps it locked upon returning if param true
+ wait_until_all_locks_are_released(true);
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock_latm_access();
+
+ if (hadLock) return 0;
+ else return trylock(mutex);
+ }
+
+ int val = trylock(mutex);
+ if (0 != val) return val;
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //-----------------------------------------------------------------------
+ // if !core done, since trylock, we cannot stall & retry - just exit
+ //-----------------------------------------------------------------------
+ if (!dir_do_core_full_pthread_lock_mutex(mutex, 0, 0))
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ return -1;
+ }
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+ // note: we do not release the transactionsInFlightMutex - this will prevents
+ // new transactions from starting until this lock is released
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::dir_full_pthread_unlock_mutex(Mutex *mutex)
+{
+ lock(&latmMutex_);
+ bool hasLock = true;
+
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ if (!t->is_on_obtained_locks_list(mutex))
+ {
+ // this is illegal, it means the transaction is unlocking a lock
+ // it did not obtain (e.g., early release) while the transaction
+ // is still in-flight. Throw exception
+ throw "lock released for transaction that did not obtain it";
+ }
+
+ if (!t->is_currently_locked_lock(mutex)) hasLock = false;
+ t->remove_from_currently_locked_locks(mutex);
+ }
+
+ latmLockedLocks_.erase(mutex);
+
+ if (0 == latmLockedLocks_.size())
+ {
+ lock_general_access();
+
+ for (ThreadMutexSetContainer::iterator iter = threadConflictingMutexes_.begin();
+ threadConflictingMutexes_.end() != iter; ++iter)
+ {
+ // no more locked LATM locks, clear everyone
+ *threadBlockedLists_.find(iter->first)->second = false;
+ }
+
+ unlock_general_access();
+ }
+
+ latmLockedLocksOfThreadMap_.erase(mutex);
+ unlock(&latmMutex_);
+
+ // TBR if (hasLock) return unlock(mutex);
+ // TBR else return 0;
+ if (hasLock) unlock(mutex);
+ return 0;
+}
+
+#endif
+
+#endif // TRANSACTION_LOCK_AWARE_DIR_IMPL_H
+

Added: sandbox/stm/boost/stm/detail/latm_dir_tm_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/latm_dir_tm_impl.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,306 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+//
+// LatmDirTmImlp.h
+//
+// This file contains method implementations for transaction.hpp (specifically for
+// enabling lock aware transactions). The main purpose of this file is to reduce
+// the complexity of the transaction class by separating its implementation into
+// a secondary .h file.
+//
+// Do NOT place these methods in a .cc/.cpp/.cxx file. These methods must be
+// inlined to keep DracoSTM performing fast. If these methods are placed in a
+// C++ source file they will incur function call overhead - something we need
+// to reduce to keep performance high.
+//
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_LATM_DIR_TM_IMPL_H
+#define BOOST_STM_LATM_DIR_TM_IMPL_H
+
+#if PERFORMING_LATM
+
+//-----------------------------------------------------------------------------
+//
+//
+//
+// GLOBAL CONFLICTING LOCK LATM PROTECTION METHODS
+//
+//
+//
+//-----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+//
+// ASSUMPTION: latmMutex_ MUST BE OBTAINED BEFORE CALLING THIS METHOD
+//
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::dir_do_core_tm_conflicting_lock_pthread_lock_mutex
+(Mutex *mutex, int lockWaitTime, int lockAborted)
+{
+ //--------------------------------------------------------------------------
+ // if this mutex is on the tmConflictingLocks_ set, then we need to stop
+ // transactions which are in-flight.
+ //
+ // if it isn't we don't interrupt any in-flight transactions
+ //--------------------------------------------------------------------------
+ if (tmConflictingLocks_.find(mutex) != tmConflictingLocks_.end())
+ {
+ //--------------------------------------------------------------------------
+ // if the lock-aware tm lock set is empty, lock the in-flight trans mutex
+ // so we can abort all the in-flight transactions
+ //--------------------------------------------------------------------------
+ if (0 == latmLockedLocks_.size())
+ {
+ lock_general_access();
+ lock_inflight_access();
+
+ std::list<transaction*> txList;
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction *t = (transaction*)*i;
+
+ if (!t->irrevocable() &&
+ cm_->allow_lock_to_abort_tx(lockWaitTime, lockAborted, false, *t))
+ {
+ txList.push_back(t);
+ }
+ else
+ {
+ unlock_general_access();
+ unlock_inflight_access();
+ return false;
+ }
+ }
+
+ for (std::list<transaction*>::iterator it = txList.begin(); txList.end() != it; ++it)
+ {
+ (*it)->force_to_abort();
+ }
+
+ //-----------------------------------------------------------------------
+ // block all threads, since we have to unlock the in-flight mutex
+ //-----------------------------------------------------------------------
+ for (ThreadMutexSetContainer::iterator iter = threadConflictingMutexes_.begin();
+ threadConflictingMutexes_.end() != iter; ++iter)
+ {
+ // no more locked LATM locks, clear everyone
+ *threadBlockedLists_.find(iter->first)->second = true;
+ //*threadBlockedLists_[iter->first] = true;
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+
+ //-----------------------------------------------------------------------
+ // now we must stall until all in-flight transactions are gone, otherwise
+ // global memory may still be in an inconsistent state
+ //-----------------------------------------------------------------------
+ while (transactionsInFlight_.size() != 0) { SLEEP(10); }
+ }
+
+ latmLockedLocks_.insert(mutex);
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::
+dir_tm_conflicting_lock_pthread_lock_mutex(Mutex *mutex)
+{
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ transaction::must_be_in_tm_conflicting_lock_set(mutex);
+ t->make_isolated();
+ lock_latm_access();
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock_latm_access();
+ lock(mutex);
+ return 0;
+ }
+
+ int waitTime = 0, aborted = 0;
+
+ for (;;)
+ {
+ // TBR int val = lock(mutex);
+ // TBR if (0 != val) return val;
+ lock(mutex);
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //--------------------------------------------------------------------
+ // if we are able to do the core lock work, break
+ //--------------------------------------------------------------------
+ if (dir_do_core_tm_conflicting_lock_pthread_lock_mutex
+ (mutex, waitTime, aborted)) break;
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ //-----------------------------------------------------------------------
+ // we weren't able to do the core lock work, unlock our mutex and sleep
+ //-----------------------------------------------------------------------
+ unlock(mutex);
+ unlock(&latmMutex_);
+
+ SLEEP(cm_->lock_sleep_time());
+ waitTime += cm_->lock_sleep_time();
+ ++aborted;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::
+dir_tm_conflicting_lock_pthread_trylock_mutex(Mutex *mutex)
+{
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ transaction::must_be_in_tm_conflicting_lock_set(mutex);
+ t->make_isolated();
+ lock_latm_access();
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock_latm_access();
+ return trylock(mutex);
+ }
+
+ int val = trylock(mutex);
+ if (0 != val) return val;
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //-----------------------------------------------------------------------
+ // if !core done, since trylock, we cannot stall & retry - just exit
+ //-----------------------------------------------------------------------
+ if (!dir_do_core_tm_conflicting_lock_pthread_lock_mutex(mutex, 0, 0))
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ return -1;
+ }
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+ // note: we do not release the transactionsInFlightMutex - this will prevents
+ // new transactions from starting until this lock is released
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::
+dir_tm_conflicting_lock_pthread_unlock_mutex(Mutex *mutex)
+{
+ lock(&latmMutex_);
+ bool hasLock = true;
+
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ if (!t->is_on_obtained_locks_list(mutex))
+ {
+ // this is illegal, it means the transaction is unlocking a lock
+ // it did not obtain (e.g., early release) while the transaction
+ // is still in-flight. Throw exception
+ throw "lock released for transaction that did not obtain it";
+ }
+
+ if (!t->is_currently_locked_lock(mutex)) hasLock = false;
+ t->remove_from_currently_locked_locks(mutex);
+ }
+
+ //--------------------------------------------------------------------------
+ // if this mutex is on the tmConflictingLocks_ set, then we need to remove
+ // it from the latmLocks and check to see if we allow transactions to
+ // continue.
+ //--------------------------------------------------------------------------
+ if (tmConflictingLocks_.find(mutex) != tmConflictingLocks_.end())
+ {
+ latmLockedLocks_.erase(mutex);
+
+ if (0 == latmLockedLocks_.size())
+ {
+ lock_general_access();
+
+ for (ThreadMutexSetContainer::iterator iter = threadConflictingMutexes_.begin();
+ threadConflictingMutexes_.end() != iter; ++iter)
+ {
+ // no more locked LATM locks, clear everyone
+ *threadBlockedLists_.find(iter->first)->second = false;
+ }
+
+ unlock_general_access();
+ }
+ }
+
+ latmLockedLocksOfThreadMap_.erase(mutex);
+ unlock(&latmMutex_);
+
+ //if (hasLock) return unlock(mutex);
+ //else return 0;
+ if (hasLock) unlock(mutex);
+ return 0;
+}
+
+#endif
+
+#endif // LATM_DIR_TM_IMPL_H
+
+

Added: sandbox/stm/boost/stm/detail/latm_dir_tx_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/latm_dir_tx_impl.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,358 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+//
+// LatmDirTxImlp.h
+//
+// This file contains method implementations for transaction.hpp (specifically for
+// enabling lock aware transactions). The main purpose of this file is to reduce
+// the complexity of the transaction class by separating its implementation into
+// a secondary .h file.
+//
+// Do NOT place these methods in a .cc/.cpp/.cxx file. These methods must be
+// inlined to keep DracoSTM performing fast. If these methods are placed in a
+// C++ source file they will incur function call overhead - something we need
+// to reduce to keep performance high.
+//
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_LATM_DIR_TX_IMPL_H
+#define BOOST_STM_LATM_DIR_TX_IMPL_H
+
+#if PERFORMING_LATM
+
+#include <fstream>
+
+
+
+
+//----------------------------------------------------------------------------
+//
+// ASSUMPTION: latmMutex_ MUST BE OBTAINED BEFORE CALLING THIS METHOD
+//
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::dir_do_core_tx_conflicting_lock_pthread_lock_mutex
+(Mutex *mutex, int lockWaitTime, int lockAborted, bool txIsIrrevocable)
+{
+ //--------------------------------------------------------------------------
+ // see if this mutex is part of any of the in-flight transactions conflicting
+ // mutex set. if it is, stop that transaction and add it to the latm conflicting
+ // set. do not keep in-flight transactions blocked once the transactions have
+ // been processed.
+ //--------------------------------------------------------------------------
+ lock_general_access();
+ lock_inflight_access();
+
+ std::list<transaction *> txList;
+ std::set<size_t> txThreadId;
+ //transaction *txToMakeIsolated = NULL;
+
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction *t = (transaction*)*i;
+
+ // if this tx is part of this thread, skip it (it's an LiT)
+ if (t->threadId_ == THREAD_ID) continue;
+
+ if (t->conflictingMutexRef_.find(mutex) != t->conflictingMutexRef_.end())
+ {
+ if (txIsIrrevocable || (!t->irrevocable() &&
+ cm_->allow_lock_to_abort_tx(lockWaitTime, lockAborted, txIsIrrevocable, *t)))
+ {
+ txList.push_back(t);
+ }
+ else
+ {
+ unlock_general_access();
+ unlock_inflight_access();
+ return false;
+ }
+ }
+ }
+
+ if (0 != txList.size())
+ {
+ for (std::list<transaction*>::iterator it = txList.begin(); txList.end() != it; ++it)
+ {
+ transaction *t = (transaction*)*it;
+
+ t->force_to_abort();
+ t->block();
+ txThreadId.insert(t->threadId_);
+ }
+
+ try
+ {
+ latmLockedLocksAndThreadIdsMap_.insert
+ (std::make_pair<Mutex*, ThreadIdSet>(mutex, txThreadId));
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ }
+ catch (...)
+ {
+ for (std::set<size_t>::iterator it = txThreadId.begin();
+ txThreadId.end() != it; ++it)
+ {
+ if (0 == thread_id_occurance_in_locked_locks_map(*it))
+ {
+ *threadBlockedLists_.find(*it)->second = false;
+ }
+ }
+ throw;
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+
+ //-----------------------------------------------------------------------
+ // now wait until all the txs which conflict with this mutex are no longer
+ // in-flight
+ //-----------------------------------------------------------------------
+ for (;;)
+ {
+ bool conflictingTxInFlight = false;
+
+ lock_general_access();
+ lock_inflight_access();
+
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction *t = (transaction*)*i;
+
+ if (t->conflictingMutexRef_.find(mutex) != t->conflictingMutexRef_.end())
+ {
+ conflictingTxInFlight = true;
+ }
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+
+ if (conflictingTxInFlight) SLEEP(10);
+ else return true;
+ }
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::dir_tx_conflicting_lock_pthread_lock_mutex(Mutex *mutex)
+{
+ int waitTime = 0, aborted = 0;
+
+ //--------------------------------------------------------------------------
+ // this is the most complex code in the entire system. it is highly order
+ // dependent.
+ //
+ // if an in-flight transaction is present when this lock is attempted to be
+ // obtained:
+ //
+ // (1) make sure the lock is in the conflicting set, otherwise throw
+ // (2) make the tx irrevocable - THIS MUST BE DONE BEFORE THE LOCK IS OBTAINED
+ // otherwise the system can deadlock by obtaining
+ // the lock and then failing to become irrevocable
+ // while another irrevocable tx needs the lock we
+ // took.
+ // (3) obtain the lock
+ // (4) add the lock to the tx's obtained locked list ONLY after it has been
+ // obtained. adding it before the lock is obtained can lead to deadlock
+ // as another thread which is releasing the lock will not unblock txs
+ // that it has blocked due to our claiming to have obtained the lock
+ // (5) abort all the in-flight conflicting txes and return
+ //--------------------------------------------------------------------------
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ t->must_be_in_conflicting_lock_set(mutex);
+ t->make_irrevocable();
+
+ if (!t->is_currently_locked_lock(mutex))
+ {
+ // TBR if (0 != lock(mutex)) return -1;
+ lock(mutex);
+ }
+
+ t->add_to_currently_locked_locks(mutex);
+ t->add_to_obtained_locks(mutex);
+
+ lock(&latmMutex_);
+ def_do_core_tx_conflicting_lock_pthread_lock_mutex
+ (mutex, 0, 0, true);
+ unlock(&latmMutex_);
+
+ return 0;
+ }
+
+ for (;;)
+ {
+ // TBR int val = lock(mutex);
+ // TBR if (0 != val) return val;
+ lock(mutex);
+
+ lock(&latmMutex_);
+
+ try
+ {
+ //--------------------------------------------------------------------
+ // if we are able to do the core lock work, break
+ //--------------------------------------------------------------------
+ if (dir_do_core_tx_conflicting_lock_pthread_lock_mutex
+ (mutex, waitTime, aborted, false)) break;
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ //-----------------------------------------------------------------------
+ // we weren't able to do the core lock work, unlock our mutex and sleep
+ //-----------------------------------------------------------------------
+ unlock(mutex);
+ unlock(&latmMutex_);
+
+ SLEEP(cm_->lock_sleep_time());
+ waitTime += cm_->lock_sleep_time();
+ ++aborted;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+
+ // note: we do not release the transactionsInFlightMutex - this will prevents
+ // new transactions from starting until this lock is released
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::dir_tx_conflicting_lock_pthread_trylock_mutex(Mutex *mutex)
+{
+ //--------------------------------------------------------------------------
+ throw "might not be possible to implement trylock for this";
+
+ bool txIsIrrevocable = false;
+
+ int val = trylock(mutex);
+ if (0 != val) return val;
+
+ lock(&latmMutex_);
+
+ if (transaction* t = get_inflight_tx_of_same_thread(false))
+ {
+ txIsIrrevocable = true;
+ t->must_be_in_conflicting_lock_set(mutex);
+ t->make_irrevocable();
+ t->add_to_obtained_locks(mutex);
+ }
+
+ try
+ {
+ //-----------------------------------------------------------------------
+ // if !core done, since trylock, we cannot stall & retry - just exit
+ //-----------------------------------------------------------------------
+ if (!dir_do_core_tx_conflicting_lock_pthread_lock_mutex(mutex, 0, 0, txIsIrrevocable))
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ return -1;
+ }
+ }
+ catch (...)
+ {
+ unlock(mutex);
+ unlock(&latmMutex_);
+ throw;
+ }
+
+ latmLockedLocksOfThreadMap_[mutex] = THREAD_ID;
+ unlock(&latmMutex_);
+
+ // note: we do not release the transactionsInFlightMutex - this will prevents
+ // new transactions from starting until this lock is released
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// only allow one thread to execute any of these methods at a time
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::dir_tx_conflicting_lock_pthread_unlock_mutex(Mutex *mutex)
+{
+ var_auto_lock<PLOCK> autolock(latm_lock(), general_lock(), inflight_lock(), 0);
+ bool hasLock = true;
+
+ if (transaction* t = get_inflight_tx_of_same_thread(true))
+ {
+ if (!t->is_on_obtained_locks_list(mutex))
+ {
+ // this is illegal, it means the transaction is unlocking a lock
+ // it did not obtain (e.g., early release) while the transaction
+ // is still in-flight. Throw exception
+ throw "lock released for transaction that did not obtain it";
+ }
+
+ if (!t->is_currently_locked_lock(mutex)) hasLock = false;
+ t->remove_from_currently_locked_locks(mutex);
+ }
+
+ //--------------------------------------------------------------------------
+ // if this mutex is on the tmConflictingLocks_ set, then we need to remove
+ // it from the latmLocks and any txs on the full thread list that are
+ // blocked because of this lock being locked should be unblocked
+ //--------------------------------------------------------------------------
+ if (latmLockedLocksAndThreadIdsMap_.find(mutex) != latmLockedLocksAndThreadIdsMap_.end())
+ {
+ latmLockedLocksAndThreadIdsMap_.erase(mutex);
+ unblock_conflicting_threads(mutex);
+ }
+
+ latmLockedLocksOfThreadMap_.erase(mutex);
+ unblock_threads_if_locks_are_empty();
+
+ // TBR if (hasLock) return unlock(mutex);
+ // TBR else return 0;
+ if (hasLock) unlock(mutex);
+ return 0;
+}
+
+#endif
+
+#endif // LATM_DIR_TX_IMPL_H
+

Added: sandbox/stm/boost/stm/detail/latm_general_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/latm_general_impl.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,587 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+//
+// TransactionLockAwareImpl.h
+//
+// This file contains method implementations for transaction.hpp (specifically for
+// enabling lock aware transactions). The main purpose of this file is to reduce
+// the complexity of the transaction class by separating its implementation into
+// a secondary .h file.
+//
+// Do NOT place these methods in a .cc/.cpp/.cxx file. These methods must be
+// inlined to keep DracoSTM performing fast. If these methods are placed in a
+// C++ source file they will incur function call overhead - something we need
+// to reduce to keep performance high.
+//
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_TRANSACTION_LOCK_AWARE_GENERAL_IMPL_H
+#define BOOST_STM_TRANSACTION_LOCK_AWARE_GENERAL_IMPL_H
+
+#if PERFORMING_LATM
+
+//-----------------------------------------------------------------------------
+//
+//
+//
+// GENERAL LATM INTERFACES
+//
+//
+//
+//-----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::wait_until_all_locks_are_released(bool keepLatmLocked)
+{
+ while (true)
+ {
+ lock_latm_access();
+ if (0 == latmLockedLocks_.size()) break;
+ unlock_latm_access();
+ SLEEP(10);
+ }
+
+ if (!keepLatmLocked) unlock_latm_access();
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::add_to_obtained_locks(Mutex* m)
+{
+ obtainedLocksRef_.insert(m);
+
+#if LOGGING_BLOCKS
+ logFile_ << "----------------------\ntx has obtained mutex: " << m << endl << endl;
+#endif
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::is_on_obtained_locks_list(Mutex *m)
+{
+ return obtainedLocksRef_.find(m) != obtainedLocksRef_.end();
+}
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::is_currently_locked_lock(Mutex *m)
+{
+ return currentlyLockedLocksRef_.find(m) != currentlyLockedLocksRef_.end();
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::add_to_currently_locked_locks(Mutex* m)
+{
+ currentlyLockedLocksRef_.insert(m);
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::remove_from_currently_locked_locks(Mutex *m)
+{
+ currentlyLockedLocksRef_.erase(m);
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::clear_latm_obtained_locks()
+{
+ for (MutexSet::iterator i = obtainedLocksRef_.begin(); i != obtainedLocksRef_.end();)
+ {
+ Mutex* m = *i;
+ obtainedLocksRef_.erase(i);
+ i = obtainedLocksRef_.begin();
+
+#if LOGGING_BLOCKS
+ logFile_ << "----------------------\nbefore tx release unlocked mutex: " << m << endl << endl;
+ logFile_ << outputBlockedThreadsAndLockedLocks() << endl;
+#endif
+
+ unblock_conflicting_threads(m);
+
+#if LOGGING_BLOCKS
+ logFile_ << "----------------------\nafter tx release unlocked mutex: " << m << endl << endl;
+ logFile_ << outputBlockedThreadsAndLockedLocks() << endl;
+#endif
+ }
+
+ unblock_threads_if_locks_are_empty();
+
+ currentlyLockedLocksRef_.clear();
+}
+
+//----------------------------------------------------------------------------
+//
+// PRE-CONDITION: latm_lock(), general_lock() and inflight_lock() are obtained
+// prior to calling this method.
+//
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::mutex_is_on_obtained_tx_list(Mutex *mutex)
+{
+ for (ThreadMutexSetContainer::iterator iter = threadObtainedLocks_.begin();
+ threadObtainedLocks_.end() != iter; ++iter)
+ {
+ if (iter->second->find(mutex) != iter->second->end())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+//
+// PRE-CONDITION: latm_lock(), general_lock() and inflight_lock() are obtained
+// prior to calling this method.
+//
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::unblock_conflicting_threads(Mutex *mutex)
+{
+ // if the mutex is on the latm locks map, we can't unblock yet
+ if (latmLockedLocksAndThreadIdsMap_.find(mutex) != latmLockedLocksAndThreadIdsMap_.end())
+ {
+#if LOGGING_BLOCKS
+ logFile_ << "\ncannot unlock <" << mutex << ">, in latmLockedLocksAndThreadIdsMap_" << endl << endl;
+#endif
+ return;
+ }
+
+ // if the mutex is in any tx threads, we can't unblock yet
+ if (mutex_is_on_obtained_tx_list(mutex))
+ {
+#if LOGGING_BLOCKS
+ logFile_ << "\ncannot unlock <" << mutex << ">, in mutex_is_on_obtained_tx_list" << endl << endl;
+#endif
+ return;
+ }
+
+ for (ThreadMutexSetContainer::iterator iter = threadConflictingMutexes_.begin();
+ threadConflictingMutexes_.end() != iter; ++iter)
+ {
+ // if this mutex is found in the transaction's conflicting mutexes
+ // list, then allow the thread to make forward progress again
+ // by turning its "blocked" but only if it does not appear in the
+ // locked_locks_thread_id_map
+ if (iter->second->find(mutex) != iter->second->end() &&
+ 0 == thread_id_occurance_in_locked_locks_map(iter->first))
+ {
+ *threadBlockedLists_.find(iter->first)->second = false;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::unblock_threads_if_locks_are_empty()
+{
+#if 0
+ // if the size is 0, unblock everybody
+ if (0 == latmLockedLocksOfThreadMap_.size())
+ {
+ for (ThreadMutexSetContainer::iterator it = threadObtainedLocks_.begin();
+ it != threadObtainedLocks_.end(); ++it)
+ {
+ if (0 != it->second->size()) return;
+ }
+
+ for (ThreadMutexSetContainer::iterator iter = threadConflictingMutexes_.begin();
+ threadConflictingMutexes_.end() != iter; ++iter)
+ {
+ *threadBlockedLists_[iter->first] = false;
+ }
+ }
+#endif
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::doing_full_lock_protection()
+{
+ return eFullLatmProtection == eLatmType_;
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::do_full_lock_protection()
+{
+ eLatmType_ = eFullLatmProtection;
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::doing_tm_lock_protection()
+{
+ return eTmConflictingLockLatmProtection == eLatmType_;
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::do_tm_lock_protection()
+{
+ eLatmType_ = eTmConflictingLockLatmProtection;
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline bool boost::stm::transaction::doing_tx_lock_protection()
+{
+ return eTxConflictingLockLatmProtection == eLatmType_;
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::do_tx_lock_protection()
+{
+ eLatmType_ = eTxConflictingLockLatmProtection;
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline std::string const boost::stm::transaction::latm_protection_str()
+{
+ using namespace boost::stm;
+
+ switch (eLatmType_)
+ {
+ case eFullLatmProtection:
+ return "full_protect";
+ case eTmConflictingLockLatmProtection:
+ return "tm_protect";
+ case eTxConflictingLockLatmProtection:
+ return "tx_protect";
+ default:
+ throw "invalid LATM type";
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::tm_lock_conflict(Mutex *inLock)
+{
+ if (!doing_tm_lock_protection()) return;
+
+ lock(&latmMutex_);
+
+ //-------------------------------------------------------------------------
+ // insert can throw an exception
+ //-------------------------------------------------------------------------
+ try { tmConflictingLocks_.insert(inLock); }
+ catch (...)
+ {
+ unlock(&latmMutex_);
+ throw;
+ }
+ unlock(&latmMutex_);
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::clear_tm_conflicting_locks()
+{
+ lock(&latmMutex_);
+ tmConflictingLocks_.clear();
+ unlock(&latmMutex_);
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::must_be_in_tm_conflicting_lock_set(Mutex *inLock)
+{
+ if (tmConflictingLocks_.find(inLock) == tmConflictingLocks_.end())
+ {
+ throw "lock not in tx conflict lock set, use add_tm_conflicting_lock";
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::must_be_in_conflicting_lock_set(Mutex *inLock)
+{
+ if (conflictingMutexRef_.find(inLock) == conflictingMutexRef_.end())
+ {
+ throw "lock not in tx conflict lock set, use add_tx_conflicting_lock";
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::add_tx_conflicting_lock(Mutex *inLock)
+{
+ if (!doing_tx_lock_protection()) return;
+
+ {
+ var_auto_lock<PLOCK> autol(latm_lock(), general_lock(), inflight_lock(), NULL);
+
+ if (conflictingMutexRef_.find(inLock) != conflictingMutexRef_.end()) return;
+ conflictingMutexRef_.insert(inLock);
+
+ if (irrevocable()) return;
+
+ see_if_tx_must_block_due_to_tx_latm();
+ }
+
+ if (blocked())
+ {
+ lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::clear_tx_conflicting_locks()
+{
+ lock_general_access();
+ conflictingMutexRef_.clear();
+ unlock_general_access();
+}
+
+//----------------------------------------------------------------------------
+//
+// Exposed client interfaces that act as forwarding calls to the real
+// implementation based on the specific type of lock-aware transactions
+// the client chose
+//
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::pthread_lock(Mutex *mutex)
+{
+ using namespace boost::stm;
+
+ switch (eLatmType_)
+ {
+ case eFullLatmProtection:
+ if (direct_updating()) return dir_full_pthread_lock_mutex(mutex);
+ else return def_full_pthread_lock_mutex(mutex);
+ case eTmConflictingLockLatmProtection:
+ if (direct_updating()) return dir_tm_conflicting_lock_pthread_lock_mutex(mutex);
+ else return def_tm_conflicting_lock_pthread_lock_mutex(mutex);
+ case eTxConflictingLockLatmProtection:
+ if (direct_updating()) return dir_tx_conflicting_lock_pthread_lock_mutex(mutex);
+ else return def_tx_conflicting_lock_pthread_lock_mutex(mutex);
+ default:
+ throw "invalid LATM type";
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::pthread_trylock(Mutex *mutex)
+{
+ using namespace boost::stm;
+
+ switch (eLatmType_)
+ {
+ case eFullLatmProtection:
+ if (direct_updating()) return dir_full_pthread_trylock_mutex(mutex);
+ else return def_full_pthread_trylock_mutex(mutex);
+ case eTmConflictingLockLatmProtection:
+ if (direct_updating()) return dir_tm_conflicting_lock_pthread_trylock_mutex(mutex);
+ else return def_tm_conflicting_lock_pthread_trylock_mutex(mutex);
+ case eTxConflictingLockLatmProtection:
+ if (direct_updating()) return dir_tx_conflicting_lock_pthread_trylock_mutex(mutex);
+ else return def_tx_conflicting_lock_pthread_trylock_mutex(mutex);
+ default:
+ throw "invalid LATM type";
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::pthread_unlock(Mutex *mutex)
+{
+ using namespace boost::stm;
+
+ switch (eLatmType_)
+ {
+ case eFullLatmProtection:
+ if (direct_updating()) return dir_full_pthread_unlock_mutex(mutex);
+ return def_full_pthread_unlock_mutex(mutex);
+ case eTmConflictingLockLatmProtection:
+ if (direct_updating()) return dir_tm_conflicting_lock_pthread_unlock_mutex(mutex);
+ else return def_tm_conflicting_lock_pthread_unlock_mutex(mutex);
+ case eTxConflictingLockLatmProtection:
+ if (direct_updating()) return dir_tx_conflicting_lock_pthread_unlock_mutex(mutex);
+ else return def_tx_conflicting_lock_pthread_unlock_mutex(mutex);
+ default:
+ throw "invalid LATM type";
+ }
+}
+
+//-----------------------------------------------------------------------------
+//
+//
+//
+// TRANSACTION CONFLICTING LOCK LATM PROTECTION METHODS
+//
+//
+//
+//-----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+//
+// ASSUMPTION: latmMutex_ MUST BE OBTAINED BEFORE CALLING THIS METHOD
+//
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::see_if_tx_must_block_due_to_tx_latm()
+{
+ //--------------------------------------------------------------------------
+ // iterate through all currently locked locks
+ //--------------------------------------------------------------------------
+ for (MutexThreadSetMap::iterator iter = latmLockedLocksAndThreadIdsMap_.begin();
+ latmLockedLocksAndThreadIdsMap_.end() != iter; ++iter)
+ {
+ //-----------------------------------------------------------------------
+ // iterate through this transaction's conflicting mutex ref - if one of
+ // the currently locked locks is in this tx's conflicting mutex set,
+ // we need to block this tx
+ //-----------------------------------------------------------------------
+ if (conflictingMutexRef_.find(iter->first) != conflictingMutexRef_.end())
+ {
+ this->block(); break;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // iterate through all currently locked locks
+ //--------------------------------------------------------------------------
+ for (ThreadMutexSetContainer::iterator i = threadObtainedLocks_.begin();
+ threadObtainedLocks_.end() != i; ++i)
+ {
+ // if these are locks obtained by this thread (in a parent tx), don't block
+ if (i->first == THREAD_ID) continue;
+
+ for (MutexSet::iterator j = i->second->begin(); j != i->second->end(); ++j)
+ {
+ //-----------------------------------------------------------------------
+ // iterate through this transaction's conflicting mutex ref - if one of
+ // the obtained locked locks is in this tx's conflicting mutex set,
+ // we need to block this tx
+ //-----------------------------------------------------------------------
+ if (conflictingMutexRef_.find(*j) != conflictingMutexRef_.end())
+ {
+ this->block(); break;
+ }
+ }
+ }
+
+
+ for (MutexSet::iterator k = conflictingMutexRef_.begin(); k != conflictingMutexRef_.end(); ++k)
+ {
+ // if it is locked by our thread, it is ok ... otherwise it is not
+ MutexThreadMap::iterator l = latmLockedLocksOfThreadMap_.find(*k);
+
+ if (l != latmLockedLocksOfThreadMap_.end() &&
+ THREAD_ID != l->second)
+ {
+ MutexThreadSetMap::iterator locksAndThreadsIter = latmLockedLocksAndThreadIdsMap_.find(*k);
+
+ if (locksAndThreadsIter == latmLockedLocksAndThreadIdsMap_.end())
+ {
+ ThreadIdSet s;
+ s.insert(THREAD_ID);
+
+ latmLockedLocksAndThreadIdsMap_.insert
+ (std::make_pair<Mutex*, ThreadIdSet>(*k, s));
+ }
+ else
+ {
+ locksAndThreadsIter->second.insert(THREAD_ID);
+ }
+
+ this->block(); break;
+ }
+ }
+
+}
+
+//----------------------------------------------------------------------------
+//
+// ASSUMPTION: latmMutex_ MUST BE OBTAINED BEFORE CALLING THIS METHOD
+//
+//----------------------------------------------------------------------------
+inline int boost::stm::transaction::
+thread_id_occurance_in_locked_locks_map(size_t threadId)
+{
+ int count = 0;
+
+ for (MutexThreadSetMap::iterator iter = latmLockedLocksAndThreadIdsMap_.begin();
+ latmLockedLocksAndThreadIdsMap_.end() != iter; ++iter)
+ {
+ if (iter->second.find(threadId) != iter->second.end()) ++count;
+ }
+
+ return count;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+inline boost::stm::transaction* boost::stm::transaction::get_inflight_tx_of_same_thread
+(bool hasTxInFlightMutex)
+{
+ if (!hasTxInFlightMutex) lock_inflight_access();
+
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction *t = (transaction*)*i;
+
+ //--------------------------------------------------------------------
+ // if this tx's thread is the same thread iterating through the in-flight
+ // txs, then this lock is INSIDE this tx - don't abort the tx, just
+ // make it isolated and ensure it is performing direct updating
+ //--------------------------------------------------------------------
+ if (t->thread_id() == THREAD_ID)
+ {
+ if (!hasTxInFlightMutex) unlock_inflight_access();
+ return t;
+ }
+ }
+
+ if (!hasTxInFlightMutex) unlock_inflight_access();
+ return NULL;
+}
+
+#include <boost/stm/detail/latm_def_full_impl.hpp>
+#include <boost/stm/detail/latm_dir_full_impl.hpp>
+
+#endif
+
+#endif // TRANSACTION_LOCK_AWARE_GENERAL_IMPL_H
+

Added: sandbox/stm/boost/stm/detail/memory_pool.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/memory_pool.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,182 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#ifndef BOOST_STM_MEMORY_POOL_H
+#define BOOST_STM_MEMORY_POOL_H
+
+//#define MAP_MEMORY_POOL 1
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h>
+#include <map>
+#include <vector>
+
+#include <boost/stm/detail/vector_map.hpp>
+
+#ifdef WIN32
+#pragma warning( disable : 4786 )
+#endif
+
+namespace boost { namespace stm {
+ int const kDefaultAllocSize = 512;
+
+/////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class FixedReserve
+{
+public:
+
+ //////////////////////////////////////////////////////////////////////////
+ explicit FixedReserve(size_t const &amount, size_t const &size) :
+ allocSize_(amount), currentLoc_(0), currentSize_(0), chunk_(size), data_(0)
+ {
+ if (allocSize_ < 1) throw "invalid allocation size";
+ data_.reserve(allocSize_ * 2);
+ allocateBlock(allocSize_);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ ~FixedReserve() { freeAllocatedMem(); }
+
+ //////////////////////////////////////////////////////////////////////////
+ void* retrieveFixedChunk()
+ {
+ if (currentLoc_ >= currentSize_) allocateBlock(allocSize_);
+ return data_[currentLoc_++].object_;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ void returnFixedChunk(void *mem) { data_[--currentLoc_].object_ = mem; }
+
+private:
+
+ // undefined intentionally
+ FixedReserve(const FixedReserve&);
+ FixedReserve& operator=(const FixedReserve&);
+
+ //////////////////////////////////////////////////////////////////////////
+ void freeAllocatedMem()
+ {
+ // wipe out our allocated memory
+ for (register size_t i = currentLoc_; i < currentSize_; ++i)
+ {
+ free(data_[i].object_);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ void allocateBlock(const size_t amount)
+ {
+ currentSize_ += amount;
+ data_.resize(currentSize_);
+
+ for (register size_t i = currentLoc_; i < currentSize_; ++i)
+ {
+ data_[i].object_ = malloc(chunk_);
+ }
+ }
+
+ struct data
+ {
+ void* object_;
+ };
+
+ size_t allocSize_;
+ size_t currentLoc_;
+ size_t currentSize_;
+ size_t chunk_;
+ std::vector<data> data_;
+};
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename T>
+class MemoryPool
+{
+public:
+
+#ifdef MAP_MEMORY_POOL
+ typedef std::map<size_t, FixedReserve<T>* > MemoryMap;
+#else
+ typedef vector_map<size_t, FixedReserve<T>* > MemoryMap;
+#endif
+ typedef std::pair<size_t, FixedReserve<T>* > MemoryMapPair;
+
+ MemoryPool() : allocSize_(kDefaultAllocSize) {}
+
+ MemoryPool(size_t const &amount) : allocSize_(amount) {}
+
+ void alloc_size(size_t const &amount) { allocSize_ = amount; }
+
+ //////////////////////////////////////////////////////////////////////////
+ ~MemoryPool()
+ {
+ typename MemoryMap::iterator iter;
+ // wipe out all the FixedReserves we created
+ for (iter = mem.begin(); mem.end() != iter; ++iter)
+ {
+ delete iter->second;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ void* retrieveChunk(size_t const &size)
+ {
+ typename MemoryMap::iterator iter = mem.find(size);
+
+ // if no iterator was found, create one
+ if (mem.end() == iter)
+ {
+#ifdef MAP_MEMORY_POOL
+ mem.insert(MemoryMapPair(size, new FixedReserve<T>(allocSize_, size)));
+ iter = mem.find(size);
+#else
+ iter = mem.insert(MemoryMapPair(size, new FixedReserve<T>(allocSize_, size)));
+#endif
+ }
+
+ return iter->second->retrieveFixedChunk();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ void returnChunk(void *m, size_t const &size)
+ { (mem.find(size))->second->returnFixedChunk(m); }
+
+private:
+
+ MemoryMap mem;
+ size_t allocSize_;
+};
+
+} // namespace core
+}
+#endif // MEMORY_RESERVE_H

Added: sandbox/stm/boost/stm/detail/transaction_bookkeeping.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/transaction_bookkeeping.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,288 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#ifndef BOOST_STM_TRANSACTION_BOOKKEEPING_H
+#define BOOST_STM_TRANSACTION_BOOKKEEPING_H
+
+#include <iostream>
+#include <vector>
+#include <map>
+#include <pthread.h>
+#include <boost/stm/detail/datatypes.hpp>
+
+#if 0 //TBR
+#ifdef WINOS
+#pragma warning (disable:4786)
+#define SLEEP(x) Sleep(x)
+#define THREAD_ID (size_t)pthread_self().p
+#else
+#include <unistd.h>
+#define SLEEP(x) usleep(x*1000)
+#define THREAD_ID (size_t) pthread_self()
+#endif
+#endif
+
+//-----------------------------------------------------------------------------
+class ThreadIdAndCommitId
+{
+public:
+
+ ThreadIdAndCommitId(uint32 const &threadId, uint32 const &commitId) :
+ threadId_(threadId), commitId_(commitId) {}
+
+ uint32 threadId_;
+ uint32 commitId_;
+
+ bool operator==(ThreadIdAndCommitId const &rhs) const
+ { return threadId_ == rhs.threadId_ && commitId_ == rhs.commitId_; }
+
+ bool operator<(ThreadIdAndCommitId const &rhs) const
+ {
+ if (threadId_ < rhs.threadId_) return true;
+ if (threadId_ == rhs.threadId_)
+ {
+ if (commitId_ < rhs.commitId_) return true;
+ }
+ return false;
+ }
+};
+
+//-----------------------------------------------------------------------------
+class transaction_bookkeeping
+{
+public:
+
+ typedef std::map<uint32, uint32> thread_commit_map;
+ typedef std::map<ThreadIdAndCommitId, uint32> CommitHistory;
+ typedef std::map<ThreadIdAndCommitId, uint32> AbortHistory;
+
+ transaction_bookkeeping() : aborts_(0), writeAborts_(0), readAborts_(0),
+ abortPermDenied_(0), commits_(0), handOffs_(0), newMemoryCommits_(0),
+ newMemoryAborts_(0), deletedMemoryCommits_(0), deletedMemoryAborts_(0),
+ readStayedAsRead_(0), readChangedToWrite_(0), commitTimeMs_(0), lockConvoyMs_(0)
+ {
+ //abortTrackingMutex_ = PTHREAD_MUTEX_INITIALIZER;
+ }
+
+ uint32 const & lockConvoyMs() const { return lockConvoyMs_; }
+ uint32 const & commitTimeMs() const { return commitTimeMs_; }
+ uint32 const & readAborts() const { return readAborts_; }
+ uint32 const & writeAborts() const { return writeAborts_; }
+ uint32 const & abortPermDenied() const { return abortPermDenied_; }
+ uint32 const totalAborts() const { return readAborts_ + writeAborts_ + abortPermDenied_; }
+ uint32 const & commits() const { return commits_; }
+ uint32 const & handOffs() const { return handOffs_; }
+ uint32 const & newMemoryAborts() const { return newMemoryAborts_; }
+ uint32 const & newMemoryCommits() const { return newMemoryCommits_; }
+ uint32 const & deletedMemoryAborts() const { return deletedMemoryAborts_; }
+ uint32 const & deletedMemoryCommits() const { return deletedMemoryCommits_; }
+ uint32 const & readChangedToWrite() const { return readChangedToWrite_; }
+ uint32 const & readStayedAsRead() const { return readStayedAsRead_; }
+
+ void inc_read_aborts() { ++readAborts_; }
+ void inc_write_aborts() { ++writeAborts_; }
+
+ void inc_thread_commits(uint32 threadId)
+ {
+#if 0
+ std::map<uint32, uint32>::iterator i = threadedCommits_.find(threadId);
+
+ if (threadedCommits_.end() == i) threadedCommits_[threadId] = 1;
+ else i->second = i->second + 1;
+#endif
+ }
+
+ void inc_thread_aborts(uint32 threadId)
+ {
+#if 0
+ std::map<uint32, uint32>::iterator i = threadedAborts_.find(threadId);
+
+ if (threadedAborts_.end() == i)
+ {
+ threadedAborts_.insert(std::make_pair(threadId, 1));
+ }
+ else
+ {
+ i->second += 1;
+ }
+#endif
+ }
+
+ thread_commit_map const & threadedCommits() const { return threadedCommits_; }
+ thread_commit_map const & threadedAborts() const { return threadedAborts_; }
+
+ void inc_lock_convoy_ms(uint32 const &rhs) { lockConvoyMs_ += rhs; }
+ void inc_commit_time_ms(uint32 const &rhs) { commitTimeMs_ += rhs; }
+ void inc_commits() { ++commits_; inc_thread_commits(THREAD_ID); }
+ void inc_abort_perm_denied(uint32 const &threadId) { ++abortPermDenied_; inc_thread_aborts(threadId); }
+ void inc_handoffs() { ++handOffs_; }
+ void inc_new_mem_aborts_by(uint32 const &rhs) { newMemoryAborts_ += rhs; }
+ void inc_new_mem_commits_by(uint32 const &rhs) { newMemoryCommits_ += rhs; }
+ void inc_del_mem_aborts_by(uint32 const &rhs) { deletedMemoryAborts_ += rhs; }
+ void inc_del_mem_commits_by(uint32 const &rhs) { deletedMemoryCommits_ += rhs; }
+ void incrementReadChangedToWrite() { ++readChangedToWrite_; }
+ void incrementReadStayedAsRead() { ++readStayedAsRead_; }
+
+ CommitHistory const& getCommitReadSetList() const { return committedReadSetSize_; }
+ CommitHistory const& getCommitWriteSetList() const { return committedWriteSetSize_; }
+ AbortHistory const& getAbortReadSetList() const { return abortedReadSetSize_; }
+ AbortHistory const& getAbortWriteSetList() const { return abortedWriteSetSize_; }
+
+ void pushBackSizeOfReadSetWhenAborting(uint32 const &size)
+ {
+ //lock(&abortTrackingMutex_);
+
+ ThreadIdAndCommitId tcId(THREAD_ID, ++aborts_);
+
+ // if waiting for commit read from thread is already true, it means there
+ // was no commit on the last abort, so drop it from the map
+
+ if (waitingForCommitReadFromThread[THREAD_ID])
+ {
+ abortedReadSetSize_.erase(ThreadIdAndCommitId(THREAD_ID, aborts_-1));
+ abortedWriteSetSize_.erase(ThreadIdAndCommitId(THREAD_ID, aborts_-1));
+ }
+
+ abortedReadSetSize_[tcId] = size;
+ waitingForCommitReadFromThread[THREAD_ID] = true;
+ //unlock(&abortTrackingMutex_);
+ }
+
+ void pushBackSizeOfWriteSetWhenAborting(uint32 const &size)
+ {
+ //lock(&abortTrackingMutex_);
+ ThreadIdAndCommitId tcId(THREAD_ID, aborts_);
+ abortedWriteSetSize_[tcId] = size;
+ waitingForCommitWriteFromThread[THREAD_ID] = true;
+ //unlock(&abortTrackingMutex_);
+ }
+
+ void pushBackSizeOfReadSetWhenCommitting(uint32 const &size)
+ {
+ //lock(&abortTrackingMutex_);
+ ThreadIdAndCommitId tcId(THREAD_ID, aborts_);
+
+ // only insert this commit if an abort made an entry at this commit point
+ if (waitingForCommitReadFromThread[THREAD_ID])
+ {
+ committedReadSetSize_[tcId] = size;
+ waitingForCommitReadFromThread[THREAD_ID] = false;
+ }
+ //unlock(&abortTrackingMutex_);
+ }
+
+ void pushBackSizeOfWriteSetWhenCommitting(uint32 const &size)
+ {
+ //lock(&abortTrackingMutex_);
+ ThreadIdAndCommitId tcId(THREAD_ID, aborts_);
+
+ // only insert this commit if an abort made an entry at this commit point
+ if (waitingForCommitWriteFromThread[THREAD_ID])
+ {
+ committedWriteSetSize_[tcId] = size;
+ waitingForCommitWriteFromThread[THREAD_ID] = false;
+ }
+ //unlock(&abortTrackingMutex_);
+ }
+
+ bool isLoggingAbortAndCommitSize() const { return isLoggingAbortAndCommitSize_; }
+ void setIsLoggingAbortAndCommitSize(bool const &in) { isLoggingAbortAndCommitSize_ = in; }
+
+ ////////////////////////////////////////////////////////////////////////////
+ friend std::ostream& operator<<(std::ostream& out, transaction_bookkeeping const &that)
+ {
+ using namespace std;
+
+ out << "########################################" << endl;
+
+ for (thread_commit_map::const_iterator i = that.threadedCommits().begin();
+ i != that.threadedCommits().end(); ++i)
+ {
+ out << " thread [" << i->first << "]: commits: " << i->second << " aborts: ";
+
+ bool found = false;
+
+ for (thread_commit_map::const_iterator j = that.threadedAborts().begin();
+ j != that.threadedAborts().end(); ++j)
+ {
+ if (j->first == i->first)
+ {
+ out << j->second;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) out << 0;
+
+ out << endl;
+ }
+
+ return out;
+ }
+
+private:
+
+ bool isLoggingAbortAndCommitSize_;
+
+ AbortHistory abortedReadSetSize_;
+ AbortHistory abortedWriteSetSize_;
+ CommitHistory committedReadSetSize_;
+ CommitHistory committedWriteSetSize_;
+
+ std::map<uint32, bool> waitingForCommitReadFromThread;
+ std::map<uint32, bool> waitingForCommitWriteFromThread;
+
+ thread_commit_map threadedCommits_;
+ thread_commit_map threadedAborts_;
+
+ uint32 aborts_;
+ uint32 writeAborts_;
+ uint32 readAborts_;
+ uint32 abortPermDenied_;
+ uint32 commits_;
+ uint32 handOffs_;
+ uint32 newMemoryCommits_;
+ uint32 newMemoryAborts_;
+ uint32 deletedMemoryCommits_;
+ uint32 deletedMemoryAborts_;
+ uint32 readStayedAsRead_;
+ uint32 readChangedToWrite_;
+ uint32 commitTimeMs_;
+ uint32 lockConvoyMs_;
+
+ //Mutex abortTrackingMutex_;
+};
+
+
+#endif // TRANSACTION_BOOKKEEPING_H
+

Added: sandbox/stm/boost/stm/detail/transaction_conflict.hpp
==============================================================================

Added: sandbox/stm/boost/stm/detail/transaction_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/transaction_impl.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,2246 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+//
+// TransactionImpl.h
+//
+// This file contains method implementations for transaction.hpp. The main
+// purpose of this file is to reduce the complexity of the transaction class
+// by separating its implementation into a secondary .h file.
+//
+// Do NOT place these methods in a .cc/.cpp/.cxx file. These methods must be
+// inlined to keep DracoSTM performing fast. If these methods are placed in a
+// C++ source file they will incur function call overhead - something we need
+// to reduce to keep performance high.
+//
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_TRANSACTION_IMPL_H
+#define BOOST_STM_TRANSACTION_IMPL_H
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <math.h>
+
+using namespace std;
+
+//--------------------------------------------------------------------------
+//
+// PRE-CONDITION: transactionsInFlightMutex is obtained prior to call
+//
+//--------------------------------------------------------------------------
+inline bool boost::stm::transaction::isolatedTxInFlight()
+{
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ // if this is our threadId, skip it
+ if (((transaction*)*i)->threadId_ == this->threadId_) continue;
+
+ if (((transaction*)*i)->isolated()) return true;
+ }
+
+ return false;
+}
+
+//--------------------------------------------------------------------------
+//
+// PRE-CONDITION: transactionsInFlightMutex is obtained prior to call
+//
+//--------------------------------------------------------------------------
+inline bool boost::stm::transaction::irrevocableTxInFlight()
+{
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ // if this is our threadId, skip it
+ if (((transaction*)*i)->threadId_ == this->threadId_) continue;
+
+ if (((transaction*)*i)->irrevocable()) return true;
+ }
+
+ return false;
+}
+
+//--------------------------------------------------------------------------
+//
+// PRE-CONDITION: transactionMutex is obtained prior to call
+// PRE-CONDITION: transactionsInFlightMutex is obtained prior to call
+//
+//--------------------------------------------------------------------------
+inline bool boost::stm::transaction::abortAllInFlightTxs()
+{
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ // if this is our threadId, skip it
+ if (((transaction*)*i)->threadId_ == this->threadId_) continue;
+
+ ((transaction*)*i)->force_to_abort();
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------------
+//
+// PRE-CONDITION: transactionsInFlightMutex is obtained prior to call
+//
+//--------------------------------------------------------------------------
+inline bool boost::stm::transaction::canAbortAllInFlightTxs()
+{
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ // if this is our threadId, skip it
+ if (((transaction*)*i)->threadId_ == this->threadId_) continue;
+
+ if (cm_->permission_to_abort(*((transaction*)*i), *this)) return false;
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::make_irrevocable()
+{
+ if (irrevocable()) return;
+ //-----------------------------------------------------------------------
+ // in order to make a tx irrevocable, no other irrevocable txs can be
+ // running. if there are, we must stall until they commit.
+ //-----------------------------------------------------------------------
+ while (true)
+ {
+ lock_inflight_access();
+
+ if (!irrevocableTxInFlight())
+ {
+ tx_type(eIrrevocableTx);
+ unlock_inflight_access();
+ return;
+ }
+
+ unlock_inflight_access();
+ SLEEP(10);
+ cm_->perform_irrevocable_tx_wait_priority_promotion(*this);
+ }
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::make_isolated()
+{
+ if (isolated()) return;
+
+ using namespace std;
+ //-----------------------------------------------------------------------
+ // in order to make a tx irrevocable, no other irrevocable txs can be
+ // running. if there are, we must stall until they commit.
+ //-----------------------------------------------------------------------
+ while (true)
+ {
+ if (forced_to_abort())
+ {
+ lock_and_abort();
+ throw aborted_transaction_exception
+ ("aborting tx in make_isolated");
+ }
+
+ lock_general_access();
+ lock_inflight_access();
+
+ if (!irrevocableTxInFlight() && canAbortAllInFlightTxs())
+ {
+ tx_type(eIrrevocableAndIsolatedTx);
+ abortAllInFlightTxs();
+ unlock_general_access();
+ unlock_inflight_access();
+ return;
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+ //SLEEP(10);
+ cm_->perform_isolated_tx_wait_priority_promotion(*this);
+ }
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline bool boost::stm::transaction::irrevocable() const
+{
+ switch (tx_type())
+ {
+ case eNormalTx: return false;
+ case eIrrevocableTx: return true;
+ case eIrrevocableAndIsolatedTx: return true;
+ default:
+ throw "tx type not found";
+ }
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline bool boost::stm::transaction::isolated() const
+{
+ switch (tx_type())
+ {
+ case eNormalTx: return false;
+ case eIrrevocableTx: return false;
+ case eIrrevocableAndIsolatedTx: return true;
+ default:
+ throw "tx type not found";
+ }
+}
+
+//-----------------------------------------------------------------------------
+//
+// ASSUMPTIONS: this tx MUST be isolated and using DEFERRED update
+//
+// This method commits the tx's writes and clears the tx's news/deletes
+//
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::commit_deferred_update_tx()
+{
+ // ensure this method is isolated
+ if (!this->irrevocable()) throw "cannot commit deferred tx: not isolated";
+
+ //--------------------------------------------------------------------------
+ // otherwise, force the tx to commit its writes/reads
+ //--------------------------------------------------------------------------
+ while (0 != trylock(&transactionMutex_))
+ {
+ bookkeeping_.inc_lock_convoy_ms(1);
+ SLEEP(1);
+ }
+
+ lock_tx();
+
+ //--------------------------------------------------------------------------
+ // this is a very important and subtle optimization. if the transaction is
+ // only reading memory, it does not need to lock the system. it only needs
+ // to lock itself and the tx in-flight mutex and remove itself from the
+ // tx in flight list
+ //--------------------------------------------------------------------------
+ if (is_only_reading())
+ {
+ unlock_general_access();
+ unlock_tx();
+ }
+ else
+ {
+ lock_inflight_access();
+
+ //-----------------------------------------------------------------------
+ // commit writes, clear new and deletes
+ //-----------------------------------------------------------------------
+ deferredCommitWriteState();
+#ifndef DISABLE_READ_SETS
+ readList().clear();
+#endif
+ deferredCommitTransactionNewMemory();
+ deferredCommitTransactionDeletedMemory();
+
+ unlock_tx();
+ unlock_general_access();
+ unlock_inflight_access();
+ }
+
+ //--------------------------------------------------------------------------
+ // the tx remains in-flight
+ //--------------------------------------------------------------------------
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::lock_tx()
+{
+ while (0 != trylock(mutex()))
+ {
+ SLEEP(1);
+ }
+
+ hasMutex_ = 1;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::unlock_tx()
+{
+ unlock(mutex());
+ hasMutex_ = 0;
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::lock_latm_access()
+{
+ lock(&latmMutex_);
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::unlock_latm_access()
+{
+ unlock(&latmMutex_);
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::lock_inflight_access()
+{
+ lock(&transactionsInFlightMutex_);
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::unlock_inflight_access()
+{
+ unlock(&transactionsInFlightMutex_);
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::lock_general_access()
+{
+ lock(&transactionMutex_);
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::unlock_general_access()
+{
+ unlock(&transactionMutex_);
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::lockThreadMutex(size_t threadId)
+{
+ ThreadMutexContainer::iterator i = threadMutexes_.find(threadId);
+ lock(i->second);
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::unlockThreadMutex(size_t threadId)
+{
+ ThreadMutexContainer::iterator i = threadMutexes_.find(threadId);
+ unlock(i->second);
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::lock_all_mutexes_but_this(size_t threadId)
+{
+ for (ThreadMutexContainer::iterator i = threadMutexes_.begin();
+ i != threadMutexes_.end(); ++i)
+ {
+ if (i->first == threadId) continue;
+ lock(i->second);
+ }
+}
+
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::unlock_all_mutexes_but_this(size_t threadId)
+{
+ for (ThreadMutexContainer::iterator i = threadMutexes_.begin();
+ i != threadMutexes_.end(); ++i)
+ {
+ if (i->first == threadId) continue;
+ unlock(i->second);
+ }
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::lock_all_mutexes()
+{
+ for (ThreadMutexContainer::iterator i = threadMutexes_.begin();
+ i != threadMutexes_.end(); ++i)
+ {
+ lock(i->second);
+ }
+
+ hasMutex_ = 1;
+}
+
+//-----------------------------------------------------------------------------
+// side-effect: this unlocks all mutexes including its own. this is a slight
+// optimization over unlock_all_mutexes_but_this() as it doesn't have an
+// additional "if" to slow down performance. however, as it will be
+// releasing its own mutex, it must reset hasMutex_
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::unlock_all_mutexes()
+{
+ for (ThreadMutexContainer::iterator i = threadMutexes_.begin();
+ i != threadMutexes_.end(); ++i)
+ {
+ unlock(i->second);
+ }
+
+ hasMutex_ = 0;
+}
+
+//--------------------------------------------------------------------------
+//
+//
+// THREE ENTRY POINTS TO STARTING A TRANSACTION
+//
+// constructor
+// begin()
+// restart()
+//
+//
+//--------------------------------------------------------------------------
+inline boost::stm::transaction::transaction() :
+ threadId_(THREAD_ID),
+#if USE_SINGLE_THREAD_CONTEXT_MAP
+ context_(*threadMemContainer_.find(threadId_)->second),
+#endif
+#ifndef DISABLE_READ_SETS
+ readListRef_(*threadReadLists_.find(threadId_)->second),
+#endif
+
+#ifndef USE_SINGLE_THREAD_CONTEXT_MAP
+ writeListRef_(threadWriteLists_.find(threadId_)->second),
+ bloomRef_(threadBloomFilterLists_.find(threadId_)->second),
+#if PERFORMING_WRITE_BLOOM
+ wbloomRef_(threadWBloomFilterLists_.find(threadId_)->second),
+ //sm_wbv_(*threadSmallWBloomFilterLists_.find(threadId_)->second),
+#endif
+ newMemoryListRef_(threadNewMemoryLists_.find(threadId_)->second),
+ deletedMemoryListRef_(threadDeletedMemoryLists_.find(threadId_)->second),
+ txTypeRef_(threadTxTypeLists_.find(threadId_)->second),
+#ifdef USING_SHARED_FORCED_TO_ABORT
+ forcedToAbortRef_(threadForcedToAbortLists_.find(threadId_)->second),
+#else
+ forcedToAbortRef_(false),
+#endif
+#else // USE_SINGLE_THREAD_CONTEXT_MAP
+ writeListRef_(&context_.writeMem),
+ wbloomRef_(&context_.wbloom),
+ bloomRef_(&context_.bloom),
+ newMemoryListRef_(&context_.newMem),
+ deletedMemoryListRef_(&context_.delMem),
+ txTypeRef_(&context_.txType),
+ forcedToAbortRef_(&context_.abort),
+#endif
+
+ mutexRef_(threadMutexes_.find(threadId_)->second),
+
+#if PERFORMING_LATM
+ blockedRef_(*threadBlockedLists_.find(threadId_)->second),
+#endif
+#if PERFORMING_LATM
+#if USING_TRANSACTION_SPECIFIC_LATM
+ conflictingMutexRef_(*threadConflictingMutexes_.find(threadId_)->second),
+#endif
+#if PERFORMING_LATM
+ obtainedLocksRef_(*threadObtainedLocks_.find(threadId_)->second),
+ currentlyLockedLocksRef_(*threadCurrentlyLockedLocks_.find(threadId_)->second),
+#endif
+#endif
+ hasMutex_(0), priority_(0),
+ state_(e_no_state),
+ reads_(0),
+ startTime_(time(NULL))
+{
+ if (directUpdating_) doIntervalDeletions();
+#if PERFORMING_LATM
+ while (blocked()) { SLEEP(10) ; }
+#endif
+
+ put_tx_inflight();
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::begin()
+{
+ if (e_in_flight == state_) return;
+
+#if PERFORMING_LATM
+ while (blocked()) { SLEEP(10) ; }
+#endif
+ put_tx_inflight();
+}
+
+#ifdef LOGGING_BLOCKS
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline std::string boost::stm::transaction::outputBlockedThreadsAndLockedLocks()
+{
+ using namespace std;
+
+ ostringstream o;
+
+ o << "Threads and their conflicting mutexes:" << endl << endl;
+
+ for (ThreadMutexSetContainer::iterator iter = threadConflictingMutexes_.begin();
+ threadConflictingMutexes_.end() != iter; ++iter)
+ {
+ // if this mutex is found in the transaction's conflicting mutexes
+ // list, then allow the thread to make forward progress again
+ // by turning its "blocked" but only if it does not appear in the
+ // locked_locks_thread_id_map
+ o << iter->first << " blocked: " << *threadBlockedLists_[iter->first] << endl;
+ o << "\t";
+
+ for (MutexSet::iterator inner = iter->second->begin(); inner != iter->second->end(); ++inner)
+ {
+ o << *inner << " ";
+ }
+ o << endl;
+ }
+
+ o << "Currently locked locks:" << endl << endl;
+
+ for (MutexThreadSetMap::iterator i = latmLockedLocksAndThreadIdsMap_.begin();
+ i != latmLockedLocksAndThreadIdsMap_.end(); ++i)
+ {
+ o << i->first << endl << "\t";
+
+ for (ThreadIdSet::iterator j = i->second.begin(); j != i->second.end(); ++j)
+ {
+ o << *j << " ";
+ }
+ o << endl;
+ }
+
+ return o.str();
+}
+#endif
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline bool boost::stm::transaction::restart()
+{
+ if (e_in_flight == state_) lock_and_abort();
+
+#if PERFORMING_LATM
+#ifdef LOGGING_BLOCKS
+ int iterations = 0;
+#endif
+ while (blocked())
+ {
+#ifdef LOGGING_BLOCKS
+ if (++iterations > 100)
+ {
+ var_auto_lock<PLOCK> autolock(latm_lock(), general_lock(), NULL);
+ //unblock_threads_if_locks_are_empty();
+ logFile_ << outputBlockedThreadsAndLockedLocks().c_str();
+ SLEEP(10000);
+ }
+#endif
+
+ SLEEP(10);
+ }
+#endif
+ //-----------------------------------------------------------------------
+ // this is a vital check for composed transactions that abort, but the
+ // outer instance tx is never destructed, but instead restarted via
+ // restart() interface
+ //-----------------------------------------------------------------------
+#if PERFORMING_COMPOSITION
+#if USING_SHARED_FORCED_TO_ABORT
+ lock_inflight_access();
+ if (!otherInFlightTransactionsOfSameThreadNotIncludingThis(this))
+ {
+ unforce_to_abort();
+ }
+ unlock_inflight_access();
+#else
+ unforce_to_abort();
+#endif
+#endif
+
+ put_tx_inflight();
+
+#if 0
+ if (doing_dynamic_priority_assignment())
+ {
+ priority_ += 1 + (reads_ / 100);
+ }
+
+ reads_ = 0;
+#endif
+
+ return true;
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline bool boost::stm::transaction::can_go_inflight()
+{
+ // if we're doing full lock protection, allow transactions
+ // to start only if no locks are obtained or the only lock that
+ // is obtained is on THREAD_ID
+ if (transaction::doing_full_lock_protection())
+ {
+ for (MutexThreadMap::iterator j = latmLockedLocksOfThreadMap_.begin();
+ j != latmLockedLocksOfThreadMap_.end(); ++j)
+ {
+ if (THREAD_ID != j->second)
+ {
+ return false;
+ }
+ }
+ }
+
+ // if we're doing tm lock protection, allow transactions
+ // to start only if
+ else if (transaction::doing_tm_lock_protection())
+ {
+ for (MutexSet::iterator i = tmConflictingLocks_.begin(); i != tmConflictingLocks_.end(); ++i)
+ {
+ // if one of your conflicting locks is currently locked ...
+ if (latmLockedLocks_.end() != latmLockedLocks_.find(*i))
+ {
+ // if it is locked by our thread, it is ok ... otherwise it is not
+ MutexThreadMap::iterator j = latmLockedLocksOfThreadMap_.find(*i);
+
+ if (j != latmLockedLocksOfThreadMap_.end() &&
+ THREAD_ID != j->second)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::put_tx_inflight()
+{
+#if PERFORMING_LATM
+ while (true)
+ {
+ lock_inflight_access();
+
+ if (can_go_inflight() && !isolatedTxInFlight())
+ {
+ transactionsInFlight_.insert(this);
+ state_ = e_in_flight;
+ unlock_inflight_access();
+ break;
+ }
+
+ unlock_inflight_access();
+ SLEEP(10);
+ }
+#else
+ lock_inflight_access();
+ transactionsInFlight_.insert(this);
+ unlock_inflight_access();
+ state_ = e_in_flight;
+#endif
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline boost::stm::transaction::~transaction()
+{
+ // if we're not an inflight transaction - bail
+ if (state_ != e_in_flight)
+ {
+ if (hasLock()) unlock_tx();
+ return;
+ }
+
+ if (!hasLock()) lock_tx();
+ abort();
+ unlock_tx();
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::no_throw_end()
+{
+ try { end(); }
+ catch (...) {}
+}
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+inline void boost::stm::transaction::end()
+{
+ // in case this is called multiple times
+ if (!in_flight()) return;
+
+ if (directUpdating_)
+ {
+#if PERFORMING_VALIDATION
+ validating_direct_end_transaction();
+#else
+ invalidating_direct_end_transaction();
+#endif
+ }
+ else
+ {
+#if PERFORMING_VALIDATION
+ validating_deferred_end_transaction();
+#else
+ invalidating_deferred_end_transaction();
+#endif
+ }
+}
+
+//-----------------------------------------------------------------------------
+// lock_and_abort()
+//
+// used for contention managers when direct updating is happening and the tx
+// has already performed some writes. a direct_abort expects the
+// transactionMutex_ to be obtained so it can restore the global memory to its
+// original state.
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::lock_and_abort()
+{
+ if (directUpdating_)
+ {
+ bool wasWriting = isWriting() ? true : false;
+
+ if (wasWriting) lock_general_access();
+ lock_tx();
+ direct_abort();
+ unlock_tx();
+ if (wasWriting) unlock_general_access();
+ }
+ else
+ {
+ lock_tx();
+ deferred_abort();
+ unlock_tx();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// invalidating_direct_end_transaction()
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::invalidating_direct_end_transaction()
+{
+ //--------------------------------------------------------------------------
+ // this is an optimization to check forced to abort before obtaining the
+ // transaction mutex, so if we do need to abort we do it now
+ //--------------------------------------------------------------------------
+ if (forced_to_abort())
+ {
+ lock_and_abort();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+
+ lock_general_access();
+ lock_tx();
+
+ //--------------------------------------------------------------------------
+ // erase this from the inflight transactions so processing through the
+ // transactionsInFlight is faster. we have removed the check for "this"
+ // when iterating through the transactionsInFlight list. additionally,
+ // remember that transactionsInFlight has been removed for commit()
+ // so commit doesn't need to remove this from the transactionsInFlight
+ //--------------------------------------------------------------------------
+ if (forced_to_abort())
+ {
+ //-----------------------------------------------------------------------
+ // if it wasn't writing, it doesn't need the transactionMutex any more,
+ // so unlock it so we can reduce contention
+ //-----------------------------------------------------------------------
+ bool wasWriting = isWriting() ? true : false;
+ if (!wasWriting) unlock_general_access();
+ direct_abort();
+ unlock_tx();
+ //-----------------------------------------------------------------------
+ // if this tx was writing, unlock the transaction mutex now
+ //-----------------------------------------------------------------------
+ if (wasWriting) unlock_general_access();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+
+ lock_all_mutexes_but_this(threadId_);
+
+ lock_inflight_access();
+ transactionsInFlight_.erase(this);
+
+ if (other_in_flight_same_thread_transactions())
+ {
+ state_ = e_hand_off;
+ unlock_all_mutexes();
+ unlock_general_access();
+ unlock_inflight_access();
+ bookkeeping_.inc_handoffs();
+ }
+ else
+ {
+ // commit releases the inflight mutex as soon as its done with it
+ invalidating_direct_commit();
+
+ if (e_committed == state_)
+ {
+ unlock_all_mutexes();
+ unlock_general_access();
+ unlock_inflight_access();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// invalidating_deferred_end_transaction()
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::invalidating_deferred_end_transaction()
+{
+ //--------------------------------------------------------------------------
+ // this is an optimization to check forced to abort before obtaining the
+ // transaction mutex, so if we do need to abort we do it now
+ //--------------------------------------------------------------------------
+#ifndef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ if (forced_to_abort())
+ {
+ deferred_abort(true);
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+#endif
+
+ //--------------------------------------------------------------------------
+ // this is a very important and subtle optimization. if the transaction is
+ // only reading memory, it does not need to lock the system. it only needs
+ // to lock tx in-flight mutex and remove itself from the tx in flight list
+ //--------------------------------------------------------------------------
+ if (is_only_reading())
+ {
+ lock_inflight_access();
+ transactionsInFlight_.erase(this);
+ unlock_inflight_access();
+
+#if PERFORMING_COMPOSITION
+ if (other_in_flight_same_thread_transactions())
+ {
+ state_ = e_hand_off;
+ bookkeeping_.inc_handoffs();
+ }
+ else
+#endif
+ {
+ tx_type(eNormalTx);
+#if PERFORMING_LATM
+ conflictingMutexRef_.clear();
+ clear_latm_obtained_locks();
+#endif
+ state_ = e_committed;
+ }
+ ++globalClock_;
+
+ return;
+ }
+
+ while (0 != trylock(&transactionMutex_)) { }
+
+ //--------------------------------------------------------------------------
+ // as much as I'd like to transactionsInFlight_.erase() here, we have
+ // to do it inside of abort() because the contention managers must abort
+ // the txs and therefore must do a transactionsInFlight_.erase(this)
+ // anyway. so we actually lose performance by doing it here and then
+ // doing it again inside abort()
+ //--------------------------------------------------------------------------
+ if (forced_to_abort())
+ {
+ unlock_general_access();
+ deferred_abort(true);
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+ else
+ {
+ //-----------------------------------------------------------------------
+ // erase this from the inflight transactions so processing through the
+ // transactionsInFlight is faster. we have removed the check for "this"
+ // when iterating through the transactionsInFlight list. additionally,
+ // remember that transactionsInFlight has been removed for commit()
+ // so commit doesn't need to remove this from the transactionsInFlight
+ //-----------------------------------------------------------------------
+
+ //-----------------------------------------------------------------------
+ // before we get the transactions in flight mutex - get all the locks for
+ // al threads, because aborted threads will try to obtain the
+ // transactionsInFlightMutex
+ //-----------------------------------------------------------------------
+ lock_all_mutexes();
+ lock_inflight_access();
+
+#if PERFORMING_COMPOSITION
+ if (other_in_flight_same_thread_transactions())
+ {
+ transactionsInFlight_.erase(this);
+ state_ = e_hand_off;
+ unlock_all_mutexes();
+ unlock_general_access();
+ unlock_inflight_access();
+ bookkeeping_.inc_handoffs();
+ }
+ else
+#endif
+ {
+ // commit releases the inflight mutex as soon as its done with it
+ invalidating_deferred_commit();
+ }
+
+ ++globalClock_;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// validating_direct_end_transaction()
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::validating_direct_end_transaction()
+{
+ lock_general_access();
+ lock_tx();
+
+ //--------------------------------------------------------------------------
+ // can only be called after above transactionMutex_ is called
+ //--------------------------------------------------------------------------
+ if (cm_->abort_before_commit(*this))
+ {
+ abort();
+ //bookkeeping_.inc_abort_perm_denied(threadId_);
+ unlock_tx();
+ unlock_general_access();
+ throw aborted_transaction_exception
+ ("aborting commit due to CM priority");
+ }
+
+ //--------------------------------------------------------------------------
+ // erase this from the inflight transactions so processing through the
+ // transactionsInFlight is faster. we have removed the check for "this"
+ // when iterating through the transactionsInFlight list. additionally,
+ // remember that transactionsInFlight has been removed for commit()
+ // so commit doesn't need to remove this from the transactionsInFlight
+ //--------------------------------------------------------------------------
+ if (forced_to_abort())
+ {
+ //-----------------------------------------------------------------------
+ // if it wasn't writing, it doesn't need the transactionMutex any more,
+ // so unlock it so we can reduce contention
+ //-----------------------------------------------------------------------
+ bool wasWriting = isWriting() ? true : false;
+ if (!wasWriting) unlock_general_access();
+ direct_abort();
+ unlock_tx();
+ //-----------------------------------------------------------------------
+ // if this tx was writing, unlock the transaction mutex now
+ //-----------------------------------------------------------------------
+ if (wasWriting) unlock_general_access();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+
+ lock_all_mutexes_but_this(threadId_);
+
+ lock_inflight_access();
+ transactionsInFlight_.erase(this);
+
+ if (other_in_flight_same_thread_transactions())
+ {
+ state_ = e_hand_off;
+ unlock_all_mutexes();
+ unlock_general_access();
+ unlock_inflight_access();
+ bookkeeping_.inc_handoffs();
+ }
+ else
+ {
+ // commit releases the inflight mutex as soon as its done with it
+ validating_direct_commit();
+
+ if (e_committed == state_)
+ {
+ unlock_all_mutexes();
+ unlock_general_access();
+ unlock_inflight_access();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// validating_deferred_end_transaction()
+//-----------------------------------------------------------------------------
+inline void boost::stm::transaction::validating_deferred_end_transaction()
+{
+ lock_general_access();
+ lock_inflight_access();
+ lock_tx();
+
+ //--------------------------------------------------------------------------
+ // can only be called after above transactionMutex_ is called
+ //--------------------------------------------------------------------------
+ if (cm_->abort_before_commit(*this))
+ {
+ //bookkeeping_.inc_abort_perm_denied(threadId_);
+ unlock_inflight_access();
+ unlock_general_access();
+ deferred_abort();
+ unlock_tx();
+ throw aborted_transaction_exception
+ ("aborting commit due to CM priority");
+ }
+
+ // unlock this - we only needed it to check abort_before_commit()
+ unlock_inflight_access();
+
+ uint32 ms = clock();
+
+ //--------------------------------------------------------------------------
+ // as much as I'd like to transactionsInFlight_.erase() here, we have
+ // to do it inside of abort() because the contention managers must abort
+ // the txs and therefore must do a transactionsInFlight_.erase(this)
+ // anyway. so we actually lose performance by doing it here and then
+ // doing it again inside abort()
+ //--------------------------------------------------------------------------
+ if (forced_to_abort())
+ {
+ unlock_general_access();
+ deferred_abort();
+ unlock_tx();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+ else
+ {
+ //--------------------------------------------------------------------------
+ // this is a very important and subtle optimization. if the transaction is
+ // only reading memory, it does not need to lock the system. it only needs
+ // to lock itself and the tx in-flight mutex and remove itself from the
+ // tx in flight list
+ //--------------------------------------------------------------------------
+ if (is_only_reading())
+ {
+ lock_inflight_access();
+ transactionsInFlight_.erase(this);
+
+ if (other_in_flight_same_thread_transactions())
+ {
+ state_ = e_hand_off;
+ bookkeeping_.inc_handoffs();
+ }
+ else
+ {
+ tx_type(eNormalTx);
+#if PERFORMING_LATM
+ conflictingMutexRef_.clear();
+ clear_latm_obtained_locks();
+#endif
+ state_ = e_committed;
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+
+ bookkeeping_.inc_commits();
+#ifndef DISABLE_READ_SETS
+ bookkeeping_.pushBackSizeOfReadSetWhenCommitting(readList().size());
+#endif
+ bookkeeping_.inc_commit_time_ms(clock() - ms);
+ unlock_tx();
+ }
+
+ //-----------------------------------------------------------------------
+ // erase this from the inflight transactions so processing through the
+ // transactionsInFlight is faster. we have removed the check for "this"
+ // when iterating through the transactionsInFlight list. additionally,
+ // remember that transactionsInFlight has been removed for commit()
+ // so commit doesn't need to remove this from the transactionsInFlight
+ //-----------------------------------------------------------------------
+
+ //-----------------------------------------------------------------------
+ // before we get the transactions in flight mutex - get all the locks for
+ // al threads, because aborted threads will try to obtain the
+ // transactionsInFlightMutex
+ //-----------------------------------------------------------------------
+ lock_all_mutexes_but_this(threadId_);
+
+ lock_inflight_access();
+ transactionsInFlight_.erase(this);
+
+ if (other_in_flight_same_thread_transactions())
+ {
+ state_ = e_hand_off;
+ unlock_all_mutexes();
+ unlock_general_access();
+ unlock_inflight_access();
+ bookkeeping_.inc_handoffs();
+ }
+ else
+ {
+ // commit releases the inflight mutex as soon as its done with it
+ validating_deferred_commit();
+
+ // if the commit actually worked, then we can release these locks
+ // an exception happened which caused the tx to abort and thus
+ // unlocked these already
+ if (e_committed == state_)
+ {
+ unlock_tx();
+ unlock_general_access();
+ unlock_inflight_access();
+ }
+ }
+ }
+
+ bookkeeping_.inc_commit_time_ms(clock() - ms);
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::forceOtherInFlightTransactionsWritingThisWriteMemoryToAbort()
+{
+#ifndef ALWAYS_ALLOW_ABORT
+ std::list<transaction*> aborted;
+#endif
+ InflightTxes::iterator next;
+
+ // iterate through all our written memory
+ for (WriteContainer::iterator i = writeList().begin(); writeList().end() != i; ++i)
+ {
+ // iterate through all the in flight transactions
+ for (InflightTxes::iterator j = transactionsInFlight_.begin();
+ j != transactionsInFlight_.end();)
+ {
+ transaction *t = (transaction*)*j;
+
+ // if we're already aborting for this transaction, skip it
+ if (t->forced_to_abort()) {++j; continue;}
+
+ ///////////////////////////////////////////////////////////////////
+ // as only one thread can commit at a time, and we know that
+ // composed txs, handoff, rather than commit, we should never be
+ // in this loop when another inflight tx has our threadid.
+ ///////////////////////////////////////////////////////////////////
+ assert(t->threadId_ != this->threadId_);
+
+ ///////////////////////////////////////////////////////////////////
+ // if t's modifiedList is modifying memory we are also modifying, make t bail
+ ///////////////////////////////////////////////////////////////////
+#ifdef USE_BLOOM_FILTER
+ if (t->bloom().exists((size_t)i->first))
+#else
+ if (t->writeList().end() != t->writeList().find(i->first))
+#endif
+ {
+#if ALWAYS_ALLOW_ABORT
+ t->force_to_abort();
+
+ next = j;
+ ++next;
+ transactionsInFlight_.erase(j);
+ j = next;
+
+#else
+ if (this->irrevocable())
+ {
+ aborted.push_front(t);
+ }
+ else if (!t->irrevocable() && cm_->permission_to_abort(*this, *t))
+ {
+ aborted.push_front(t);
+ }
+ else
+ {
+ force_to_abort();
+ //bookkeeping_.inc_abort_perm_denied(threadId_);
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+#endif
+ }
+
+ ++j;
+ }
+ }
+
+#ifndef ALWAYS_ALLOW_ABORT
+ // ok, forced to aborts are allowed, do them
+ for (std::list<transaction*>::iterator k = aborted.begin(); k != aborted.end();)
+ {
+ (*k)->force_to_abort();
+ transactionsInFlight_.erase(*k);
+ }
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Two ways for transactions to end:
+//
+// abort() - failed transaction
+// commit() - successful transaction
+//
+///////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::direct_abort
+ (bool const &alreadyRemovedFromInFlight) throw()
+{
+
+#if LOGGING_COMMITS_AND_ABORTS
+ bookkeeping_.pushBackSizeOfReadSetWhenAborting(readList().size());
+ bookkeeping_.pushBackSizeOfWriteSetWhenAborting(writeList().size());
+#endif
+
+ try
+ {
+ state_ = e_aborted;
+
+ directAbortWriteList();
+#ifndef DISABLE_READ_SETS
+ directAbortReadList();
+#endif
+ directAbortTransactionDeletedMemory();
+ directAbortTransactionNewMemory();
+
+ bloom().clear();
+#if PERFORMING_WRITE_BLOOM
+ wbloom().clear();
+#endif
+ if (!alreadyRemovedFromInFlight)
+ {
+ lock_inflight_access();
+ // if I'm the last transaction of this thread, reset abort to false
+ transactionsInFlight_.erase(this);
+ }
+
+#if USING_SHARED_FORCED_TO_ABORT
+ if (!other_in_flight_same_thread_transactions())
+ {
+ unforce_to_abort();
+ }
+#else
+ unforce_to_abort();
+#endif
+ if (!alreadyRemovedFromInFlight)
+ {
+ unlock_inflight_access();
+ }
+ }
+ catch (...)
+ {
+ std::cout << "Exception caught in abort - bad" << std::endl;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::deferred_abort
+ (bool const &alreadyRemovedFromInFlight) throw()
+{
+#if LOGGING_COMMITS_AND_ABORTS
+ bookkeeping_.pushBackSizeOfReadSetWhenAborting(readList().size());
+ bookkeeping_.pushBackSizeOfWriteSetWhenAborting(writeList().size());
+#endif
+
+ state_ = e_aborted;
+
+ deferredAbortWriteList();
+#ifndef DISABLE_READ_SETS
+ deferredAbortReadList();
+#endif
+
+ deferredAbortTransactionDeletedMemory();
+ deferredAbortTransactionNewMemory();
+
+ bloom().clear();
+#if PERFORMING_WRITE_BLOOM
+ wbloom().clear();
+#endif
+
+ if (alreadyRemovedFromInFlight)
+ {
+ lock_inflight_access();
+ // if I'm the last transaction of this thread, reset abort to false
+ transactionsInFlight_.erase(this);
+
+#if USING_SHARED_FORCED_TO_ABORT
+ if (!other_in_flight_same_thread_transactions())
+ {
+ unforce_to_abort();
+ }
+#else
+ unforce_to_abort();
+#endif
+
+ unlock_inflight_access();
+ }
+ else unforce_to_abort();
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::invalidating_direct_commit()
+{
+ //--------------------------------------------------------------------------
+ // transactionMutex must be obtained before calling commit
+ //--------------------------------------------------------------------------
+ try
+ {
+#if LOGGING_COMMITS_AND_ABORTS
+ bookkeeping_.pushBackSizeOfReadSetWhenCommitting(readList().size());
+ bookkeeping_.pushBackSizeOfWriteSetWhenCommitting(writeList().size());
+#endif
+
+ bookkeeping_.inc_commits();
+
+ if (0 != transactionsInFlight_.size())
+ {
+ forceOtherInFlightTransactionsReadingThisWriteMemoryToAbort();
+ }
+
+ directCommitWriteState();
+#ifndef DISABLE_READ_SETS
+ directCommitReadState();
+#endif
+ bookkeeping_.inc_del_mem_commits_by(deletedMemoryList().size());
+ directCommitTransactionDeletedMemory();
+ bookkeeping_.inc_new_mem_commits_by(newMemoryList().size());
+ directCommitTransactionNewMemory();
+
+ tx_type(eNormalTx);
+#if PERFORMING_LATM
+ conflictingMutexRef_.clear();
+ clear_latm_obtained_locks();
+#endif
+ state_ = e_committed;
+ }
+ //-----------------------------------------------------------------------
+ // aborted exceptions can be thrown from the forceOtherInFlight ...
+ // if one is thrown it means this transaction was preempted by cm
+ //-----------------------------------------------------------------------
+ catch (aborted_transaction_exception&)
+ {
+ unlock_all_mutexes_but_this(threadId_);
+ unlock_general_access();
+ unlock_inflight_access();
+
+ direct_abort();
+ unlock_tx();
+
+ throw;
+ }
+ //-----------------------------------------------------------------------
+ // still - what do we do in the event the exception was the commitState()?
+ //-----------------------------------------------------------------------
+ catch (...)
+ {
+ unlock_all_mutexes_but_this(threadId_);
+ unlock_general_access();
+ unlock_inflight_access();
+
+ direct_abort();
+ unlock_tx();
+
+ throw;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::invalidating_deferred_commit()
+{
+ //--------------------------------------------------------------------------
+ // transactionMutex must be obtained before calling commit
+ //--------------------------------------------------------------------------
+
+ try
+ {
+#if LOGGING_COMMITS_AND_ABORTS
+ bookkeeping_.pushBackSizeOfReadSetWhenCommitting(readList().size());
+ bookkeeping_.pushBackSizeOfWriteSetWhenCommitting(writeList().size());
+#endif
+
+ //-----------------------------------------------------------------------
+ // optimization:
+ //
+ // whenever multiple transactions are running, if one goes to commit, it
+ // never commits, but instead hands-off and exits. thus, from this we
+ // know that when a tx is committing it means only one tx for that thread
+ // is running.
+ //
+ // therefore, we can remove our tx from the inflight list at commit time
+ // and know that if the in flight tx list is > 1, other threads are
+ // currently processing and we must force their memory to abort.
+ //
+ // this opti gains significant performance improvement since many times
+ // only a single tx is processing - so save many cycles from having to
+ // walk its read and write list
+ //-----------------------------------------------------------------------
+
+ //-----------------------------------------------------------------------
+ // remember commit can only be called from end_transaction() and
+ // end_transaction() has already removed "this" from the
+ // transactionsInFlight_ set
+ //-----------------------------------------------------------------------
+ // commit() already has the transactionsInFlightMutex
+
+ if (transactionsInFlight_.size() > 1)
+ {
+ static int stalling_ = 0;
+
+ bool wait = stalling_ * stalls_ < globalClock_;
+ transaction *stallingOn = NULL;
+ //int iter = 1;
+
+#if USE_BLOOM_FILTER
+ while (!forceOtherInFlightTransactionsAccessingThisWriteMemoryToAbort(wait, stallingOn))
+ {
+ ++stalling_;
+ size_t local_clock = globalClock_;
+
+ unlock_inflight_access();
+ unlock_general_access();
+ unlock_all_mutexes();
+
+ for (;;)
+ {
+ while (local_clock == globalClock_)// && sleepTime < maxSleep)
+ {
+ SLEEP(1);
+ }
+
+ if (forced_to_abort())
+ {
+ --stalling_;
+ deferred_abort();
+ throw aborted_transaction_exception_no_unlocks();
+ }
+
+ lock_general_access();
+ lock_inflight_access();
+
+ // if our stalling on tx is gone, continue
+ if (transactionsInFlight_.end() == transactionsInFlight_.find(stallingOn))
+ {
+ --stalling_;
+ wait = stalling_ * stalls_ < globalClock_;
+ //std::cout << "stalling : stalls : commits: " << stalling_ << " : " << stalls_ << " : " << globalClock_ << std::endl;
+ //set_priority(priority() + reads());
+ break;
+ }
+
+ unlock_general_access();
+ unlock_inflight_access();
+ }
+
+ lock_all_mutexes();
+
+ if (forced_to_abort())
+ {
+ deferred_abort();
+ unlock_all_mutexes(); // i added this after the fact, is this right?
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+ }
+#else
+ forceOtherInFlightTransactionsWritingThisWriteMemoryToAbort();
+ forceOtherInFlightTransactionsReadingThisWriteMemoryToAbort();
+#endif
+ }
+
+ transactionsInFlight_.erase(this);
+ unlock_inflight_access();
+ unlock_general_access();
+
+ deferredCommitWriteState();
+
+ if (0 != newMemoryList().size())
+ {
+ bookkeeping_.inc_new_mem_commits_by(newMemoryList().size());
+ deferredCommitTransactionNewMemory();
+ }
+
+ //-----------------------------------------------------------------------
+ // if the commit actually worked, then we can release these locks
+ //-----------------------------------------------------------------------
+
+ //-----------------------------------------------------------------------
+ // once our write state is committed and our new memory has been cleared,
+ // we can allow the other threads to make forward progress ... so unlock
+ // them all now
+ //-----------------------------------------------------------------------
+ unlock_all_mutexes();
+
+ if (0 != deletedMemoryList().size())
+ {
+ bookkeeping_.inc_del_mem_commits_by(deletedMemoryList().size());
+ deferredCommitTransactionDeletedMemory();
+ }
+
+ // finally set the state to committed
+ bookkeeping_.inc_commits();
+ tx_type(eNormalTx);
+#if PERFORMING_LATM
+ conflictingMutexRef_.clear();
+ clear_latm_obtained_locks();
+#endif
+ state_ = e_committed;
+ }
+ //-----------------------------------------------------------------------
+ // aborted exceptions can be thrown from the forceOtherInFlight ...
+ // if one is thrown it means this transaction was preempted by cm
+ //-----------------------------------------------------------------------
+ catch (aborted_transaction_exception_no_unlocks&)
+ {
+ throw aborted_transaction_exception("whatever");
+ }
+ catch (aborted_transaction_exception&)
+ {
+ unlock_all_mutexes_but_this(threadId_);
+ unlock_general_access();
+ unlock_inflight_access();
+ deferred_abort();
+ unlock_tx();
+
+ throw;
+ }
+ //-----------------------------------------------------------------------
+ // copy constructor failures can cause ..., catch, unlock and re-throw
+ //-----------------------------------------------------------------------
+ catch (...)
+ {
+ unlock_all_mutexes_but_this(threadId_);
+ unlock_general_access();
+ unlock_inflight_access();
+ deferred_abort();
+ unlock_tx();
+
+ throw;
+ }
+}
+
+
+#if PERFORMING_VALIDATION
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::validating_direct_commit()
+{
+ throw "not implemented yet";
+
+
+
+
+
+
+ //--------------------------------------------------------------------------
+ // transactionMutex must be obtained before calling commit
+ //--------------------------------------------------------------------------
+ try
+ {
+#if LOGGING_COMMITS_AND_ABORTS
+ bookkeeping_.pushBackSizeOfReadSetWhenCommitting(readList().size());
+ bookkeeping_.pushBackSizeOfWriteSetWhenCommitting(writeList().size());
+#endif
+
+ bookkeeping_.inc_commits();
+
+ if (0 != transactionsInFlight_.size())
+ {
+ forceOtherInFlightTransactionsReadingThisWriteMemoryToAbort();
+ }
+
+ directCommitWriteState();
+ directCommitReadState();
+ bookkeeping_.inc_del_mem_commits_by(deletedMemoryList().size());
+ directCommitTransactionDeletedMemory();
+ bookkeeping_.inc_new_mem_commits_by(newMemoryList().size());
+ directCommitTransactionNewMemory();
+
+ txTypeRef_ = eNormalTx;
+#if PERFORMING_LATM
+ conflictingMutexRef_.clear();
+ clear_latm_obtained_locks();
+#endif
+ state_ = e_committed;
+ }
+ //-----------------------------------------------------------------------
+ // aborted exceptions can be thrown from the forceOtherInFlight ...
+ // if one is thrown it means this transaction was preempted by cm
+ //-----------------------------------------------------------------------
+ catch (aborted_transaction_exception&)
+ {
+ unlock_all_mutexes_but_this(threadId_);
+ unlock_general_access();
+ unlock_inflight_access();
+
+ direct_abort();
+ unlock_tx();
+
+ throw;
+ }
+ //-----------------------------------------------------------------------
+ // still - what do we do in the event the exception was the commitState()?
+ //-----------------------------------------------------------------------
+ catch (...)
+ {
+ unlock_all_mutexes_but_this(threadId_);
+ unlock_general_access();
+ unlock_inflight_access();
+
+ direct_abort();
+ unlock_tx();
+
+ throw;
+ }
+}
+#endif
+
+#if PERFORMING_VALIDATION
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::validating_deferred_commit()
+{
+ //--------------------------------------------------------------------------
+ // transactionMutex must be obtained before calling commit
+ //--------------------------------------------------------------------------
+
+ try
+ {
+#if LOGGING_COMMITS_AND_ABORTS
+ bookkeeping_.pushBackSizeOfReadSetWhenCommitting(readList().size());
+ bookkeeping_.pushBackSizeOfWriteSetWhenCommitting(writeList().size());
+#endif
+
+ //-----------------------------------------------------------------------
+ // optimization:
+ //
+ // whenever multiple transactions are running, if one goes to commit, it
+ // never commits, but instead hands-off and exits. thus, from this we
+ // know that when a tx is committing it means only one tx for that thread
+ // is running.
+ //
+ // therefore, we can remove our tx from the inflight list at commit time
+ // and know that if the in flight tx list is > 1, other threads are
+ // currently processing and we must force their memory to abort.
+ //
+ // this opti gains significant performance improvement since many times
+ // only a single tx is processing - so save many cycles from having to
+ // walk its read and write list
+ //-----------------------------------------------------------------------
+
+ //-----------------------------------------------------------------------
+ // remember commit can only be called from end_transaction() and
+ // end_transaction() has already removed "this" from the
+ // transactionsInFlight_ set
+ //-----------------------------------------------------------------------
+ // commit() already has the transactionsInFlightMutex
+
+ verifyReadMemoryIsValidWithGlobalMemory();
+ verifyWrittenMemoryIsValidWithGlobalMemory();
+
+ if (this->isWriting())
+ {
+ deferredCommitWriteState();
+ }
+
+ if (0 != newMemoryList().size())
+ {
+ bookkeeping_.inc_new_mem_commits_by(newMemoryList().size());
+ deferredCommitTransactionNewMemory();
+ }
+
+ //-----------------------------------------------------------------------
+ // once our write state is committed and our new memory has been cleared,
+ // we can allow the other threads to make forward progress ... so unlock
+ // them all now
+ //-----------------------------------------------------------------------
+ unlock_all_mutexes_but_this(threadId_);
+
+ if (0 != deletedMemoryList().size())
+ {
+ bookkeeping_.inc_del_mem_commits_by(deletedMemoryList().size());
+ deferredCommitTransactionDeletedMemory();
+ }
+
+ // finally set the state to committed
+ bookkeeping_.inc_commits();
+ txTypeRef_ = eNormalTx;
+#if PERFORMING_LATM
+ conflictingMutexRef_.clear();
+ clear_latm_obtained_locks();
+#endif
+ state_ = e_committed;
+ }
+
+ //-----------------------------------------------------------------------
+ // aborted exceptions can be thrown from the forceOtherInFlight ...
+ // if one is thrown it means this transaction was preempted by cm
+ //-----------------------------------------------------------------------
+ catch (aborted_transaction_exception&)
+ {
+ unlock_all_mutexes_but_this(threadId_);
+ unlock_general_access();
+ unlock_inflight_access();
+ deferred_abort();
+ unlock_tx();
+
+ throw;
+ }
+ //-----------------------------------------------------------------------
+ // copy constructor failures can cause ..., catch, unlock and re-throw
+ //-----------------------------------------------------------------------
+ catch (...)
+ {
+ unlock_all_mutexes_but_this(threadId_);
+ unlock_general_access();
+ unlock_inflight_access();
+ deferred_abort();
+ unlock_tx();
+
+ throw;
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::unlockAllLockedThreads(LockedTransactionContainer &l)
+{
+ for (LockedTransactionContainer::iterator i = l.begin(); i != l.end(); ++i) (*i)->unlock_tx();
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::directAbortWriteList()
+{
+ //--------------------------------------------------------------------------
+ // copy the newObject into the oldObject, updating the real data back to
+ // what it was before we changed it
+ //--------------------------------------------------------------------------
+ for (WriteContainer::iterator i = writeList().begin(); writeList().end() != i; ++i)
+ {
+ //-----------------------------------------------------------------------
+ // i->second == NULL will happen when a transaction has added a piece of
+ // memory to its writeList_ that it is deleting (not writing to).
+ // Thus, when seeing NULL as the second value, it signifies that this
+ // memory is being destroyed, not updated. Do not perform copy_state()
+ // on it.
+ //
+ // However, deleted memory MUST reset its kInvalidThread
+ // transaction_thread (which is performed in void directAbortTransactionDeletedMemory() throw();
+
+ //-----------------------------------------------------------------------
+ if (NULL == i->second) continue;
+
+ if (using_move_semantics()) i->first->move_state(i->second);
+ else i->first->copy_state(i->second);
+ i->first->transaction_thread(boost::stm::kInvalidThread);
+
+ delete i->second;
+ }
+
+ writeList().clear();
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::directAbortTransactionDeletedMemory() throw()
+{
+ for (MemoryContainerList::iterator j = deletedMemoryList().begin();
+ j != deletedMemoryList().end(); ++j)
+ {
+ (*j)->transaction_thread(boost::stm::kInvalidThread);
+ }
+
+ deletedMemoryList().clear();
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::deferredAbortWriteList() throw()
+{
+ for (WriteContainer::iterator i = writeList().begin(); writeList().end() != i; ++i)
+ {
+ delete i->second; // delete all the temporary memory
+ }
+
+ writeList().clear();
+}
+
+//----------------------------------------------------------------------------
+inline size_t boost::stm::transaction::earliest_start_time_of_inflight_txes()
+{
+ var_auto_lock<PLOCK> a(inflight_lock(), NULL);
+
+ size_t secs = 0xffffffff;
+
+ for (InflightTxes::iterator j = transactionsInFlight_.begin();
+ j != transactionsInFlight_.end(); ++j)
+ {
+ transaction *t = (transaction*)*j;
+ //-----------------------------------------------------------------------
+ // since this is called while direct_writes are occurring, the transaction
+ // calling it will be inflight, so we have to check for it and skip it
+ //-----------------------------------------------------------------------
+ if (t->startTime_ < secs) secs = t->startTime_;
+ }
+
+ return secs;
+}
+
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::doIntervalDeletions()
+{
+ using namespace boost::stm;
+
+ size_t earliestInFlightTx = earliest_start_time_of_inflight_txes();
+
+ var_auto_lock<PLOCK> a(&deletionBufferMutex_, NULL);
+
+ for (DeletionBuffer::iterator i = deletionBuffer_.begin(); i != deletionBuffer_.end();)
+ {
+ if (earliestInFlightTx > i->first)
+ {
+ for (MemoryContainerList::iterator j = i->second.begin(); j != i->second.end(); ++j)
+ {
+ delete *j;
+ }
+ deletionBuffer_.erase(i);
+ i = deletionBuffer_.begin();
+ }
+ // getting to the else means there is an inflight
+ // tx that is older than the first entry to delete,
+ // so exit, since no other deletions will succeed
+ else break;
+ }
+}
+
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::directCommitTransactionDeletedMemory() throw()
+{
+ using namespace boost::stm;
+
+ if (deletedMemoryList().size() > 0)
+ {
+ var_auto_lock<PLOCK> a(&deletionBufferMutex_, NULL);
+ deletionBuffer_.insert( std::pair<size_t, MemoryContainerList>
+ (time(NULL), deletedMemoryList()) );
+ deletedMemoryList().clear();
+ }
+}
+
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::deferredCommitTransactionDeletedMemory() throw()
+{
+ for (MemoryContainerList::iterator i = deletedMemoryList().begin();
+ i != deletedMemoryList().end(); ++i)
+ {
+ delete *i;
+ }
+
+ deletedMemoryList().clear();
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::deferredAbortTransactionNewMemory() throw()
+{
+ for (MemoryContainerList::iterator i = newMemoryList().begin(); i != newMemoryList().end(); ++i)
+ {
+ delete *i;
+ }
+
+ newMemoryList().clear();
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::deferredCommitTransactionNewMemory()
+{
+ for (MemoryContainerList::iterator i = newMemoryList().begin(); i != newMemoryList().end(); ++i)
+ {
+ (*i)->transaction_thread(boost::stm::kInvalidThread);
+ (*i)->new_memory(0);
+ }
+
+ newMemoryList().clear();
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::directCommitWriteState()
+{
+ // direct commit for writes just deletes the backup and changes global memory
+ // so its no longer flagged as being transactional
+ for (WriteContainer::iterator i = writeList().begin(); writeList().end() != i; ++i)
+ {
+ //-----------------------------------------------------------------------
+ // i->second == NULL will happen when a transaction has added a piece of
+ // memory to its writeList_ that it is deleting (not writing to).
+ // Thus, when seeing NULL as the second value, it signifies that this
+ // memory is being destroyed, not updated. Do not perform copyState()
+ // on it.
+ //-----------------------------------------------------------------------
+ i->first->transaction_thread(boost::stm::kInvalidThread);
+ i->first->new_memory(0);
+
+ //-----------------------------------------------------------------------
+ // it is true that i->second can be null, but C++ allows delete on null
+ // faster to just always delete
+ //-----------------------------------------------------------------------
+ delete i->second;
+ }
+
+ writeList().clear();
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::deferredCommitWriteState()
+{
+ // copy the newObject into the oldObject, updating the real data
+ for (WriteContainer::iterator i = writeList().begin(); writeList().end() != i; ++i)
+ {
+ //-----------------------------------------------------------------------
+ // i->second == NULL will happen when a transaction has added a piece of
+ // memory to its writeList_ that it is deleting (not writing to).
+ // Thus, when seeing NULL as the second value, it signifies that this
+ // memory is being destroyed, not updated. Do not perform copyState()
+ // on it.
+ //-----------------------------------------------------------------------
+ if (NULL == i->second)
+ {
+ continue;
+ }
+
+ if (using_move_semantics()) i->first->move_state(i->second);
+ else i->first->copy_state(i->second);
+
+ i->first->transaction_thread(boost::stm::kInvalidThread);
+ i->first->new_memory(0);
+
+#if PERFORMING_VALIDATION
+ i->first->version_++;
+#endif
+
+ delete i->second;
+ }
+
+ writeList().clear();
+}
+
+#if PERFORMING_VALIDATION
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::verifyReadMemoryIsValidWithGlobalMemory()
+{
+ // copy the newObject into the oldObject, updating the real data
+ for (ReadContainer::iterator i = readList().begin(); readList().end() != i; ++i)
+ {
+ if (i->first->version_ != i->second)
+ {
+ bookkeeping_.inc_read_aborts();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to invalid read");
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+inline void boost::stm::transaction::verifyWrittenMemoryIsValidWithGlobalMemory()
+{
+ // copy the newObject into the oldObject, updating the real data
+ for (WriteContainer::iterator i = writeList().begin(); writeList().end() != i; ++i)
+ {
+ if (NULL == i->second) continue;
+ if (i->first->version_ != i->second->version_)
+ {
+ bookkeeping_.inc_write_aborts();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to invalid write");
+ }
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+inline bool boost::stm::transaction::otherInFlightTransactionsWritingThisMemory(base_transaction_object *obj)
+{
+ // iterate through all the in flight transactions
+ for (InflightTxes::iterator j = transactionsInFlight_.begin();
+ j != transactionsInFlight_.end(); ++j)
+ {
+ transaction *t = (transaction*)*j;
+ //-----------------------------------------------------------------------
+ // since this is called while direct_writes are occurring, the transaction
+ // calling it will be inflight, so we have to check for it and skip it
+ //-----------------------------------------------------------------------
+ if (t->threadId_ == this->threadId_) continue;
+
+ // if we're already aborting for this transaction, skip it
+ if (!t->isWriting()) continue;
+ if (t->forced_to_abort()) continue;
+
+ // if t's writing to this memory return true
+ if (t->writeList().end() != t->writeList().find(obj)) return true;
+ }
+
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline bool boost::stm::transaction::forceOtherInFlightTransactionsAccessingThisWriteMemoryToAbort
+ (bool allow_stall, transaction* &stallingOn)
+{
+ static std::list<transaction*> aborted;
+ //static bool initialized = false;
+
+ if (writes() > 3) allow_stall = false;
+
+ // warm up the cache with this transaction's bloom filter
+#if PERFORMING_WRITE_BLOOM
+ bloom_filter &wbloom = this->wbloom();
+ bool singleWriteComp = writeList().size() < 20;
+#else
+ bool const singleWriteComp = true;
+#endif
+
+ // iterate through all the in flight transactions
+ for (InflightTxes::iterator j = transactionsInFlight_.begin();
+ j != transactionsInFlight_.end(); ++j)
+ {
+ transaction *t = (transaction*)*j;
+ // if we're already aborting for this transaction, skip it
+ if (t->forced_to_abort()) continue;
+
+ //////////////////////////////////////////////////////////////////////
+ // as only one thread can commit at a time, and we know that
+ // composed txs, handoff, rather than commit, we should never be
+ // in this loop when another inflight tx has our threadid.
+ //////////////////////////////////////////////////////////////////////
+ if (t->threadId_ == this->threadId_) continue;
+
+ if (singleWriteComp)
+ {
+ // iterate through all our written memory
+ for (WriteContainer::iterator i = writeList().begin(); writeList().end() != i; ++i)
+ {
+ //////////////////////////////////////////////////////////////////////
+ // if t's readList is reading memory we are modifying, make t bail
+ //////////////////////////////////////////////////////////////////////
+ if (t->bloom().exists((size_t)i->first))
+ {
+ if (allow_stall && t->is_only_reading())// && t->reads() > work)
+ {
+ ++stalls_;
+ stallingOn = t;
+ return false;
+ }
+ // if the conflict is not a write-write conflict, stall
+#if 0
+ if (allow_stall && !t->wbloom().exists((size_t)i->first))
+ {
+ ++stalls_;
+ stallingOn = t;
+ return false;
+ }
+#endif
+#if PERFORMING_LATM
+ if (this->irrevocable())
+ {
+ aborted.push_front(t);
+ }
+ else if (!t->irrevocable() && cm_->permission_to_abort(*this, *t))
+ {
+ aborted.push_front(t);
+ }
+ else
+ {
+ force_to_abort();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+#else
+ if (cm_->permission_to_abort(*this, *t)) aborted.push_front(t);
+ else
+ {
+ force_to_abort();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+#endif
+ }
+ }
+ }
+#if PERFORMING_WRITE_BLOOM
+ else if (wbloom.intersection(t->bloom()))
+ {
+ if (allow_stall && t->is_only_reading())// && t->reads() > work)
+ {
+ ++stalls_;
+ stallingOn = t;
+ return false;
+ }
+#if PERFORMING_LATM
+ if (this->irrevocable())
+ {
+ aborted.push_front(t);
+ }
+ else if (!t->irrevocable() && cm_->permission_to_abort(*this, *t))
+ {
+ aborted.push_front(t);
+ }
+ else
+ {
+ force_to_abort();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+#else
+ if (cm_->permission_to_abort(*this, *t)) aborted.push_front(t);
+ else
+ {
+ force_to_abort();
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+#endif
+ }
+#endif
+ }
+
+ if (aborted.size() > 0)
+ {
+ // ok, forced to aborts are allowed, do them
+ for (std::list<transaction*>::iterator k = aborted.begin(); k != aborted.end(); ++k)
+ {
+ (*k)->force_to_abort();
+ }
+
+ aborted.clear();
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////
+inline void boost::stm::transaction::forceOtherInFlightTransactionsReadingThisWriteMemoryToAbort()
+{
+ std::list<transaction*> aborted;
+
+ // iterate through all the in flight transactions
+ for (InflightTxes::iterator j = transactionsInFlight_.begin();
+ j != transactionsInFlight_.end(); ++j)
+ {
+ transaction *t = (transaction*)*j;
+ // if we're already aborting for this transaction, skip it
+#ifndef DISABLE_READ_SETS
+ if (!t->isReading()) continue;
+#endif
+ if (t->forced_to_abort()) continue;
+
+ //////////////////////////////////////////////////////////////////////
+ // as only one thread can commit at a time, and we know that
+ // composed txs, handoff, rather than commit, we should never be
+ // in this loop when another inflight tx has our threadid.
+ //////////////////////////////////////////////////////////////////////
+ assert(t->threadId_ != this->threadId_);
+
+ // iterate through all our written memory
+ for (WriteContainer::iterator i = writeList().begin(); writeList().end() != i; ++i)
+ {
+
+ //////////////////////////////////////////////////////////////////////
+ // if t's readList is reading memory we are modifying, make t bail
+ //////////////////////////////////////////////////////////////////////
+#ifdef USE_BLOOM_FILTER
+ if (t->bloom().exists((size_t)i->first))
+#else
+ if (t->readList().end() != t->readList().find(i->first))
+#endif
+ {
+ if (this->irrevocable())
+ {
+ aborted.push_front(t);
+ }
+ else if (!t->irrevocable() && cm_->permission_to_abort(*this, *t))
+ {
+ aborted.push_front(t);
+ }
+ else
+ {
+ force_to_abort();
+ //bookkeeping_.inc_abort_perm_denied(threadId_);
+ throw aborted_transaction_exception
+ ("aborting committing transaction due to contention manager priority inversion");
+ }
+ }
+ }
+ }
+
+ // ok, forced to aborts are allowed, do them
+ for (std::list<transaction*>::iterator k = aborted.begin(); k != aborted.end(); ++k)
+ {
+ (*k)->force_to_abort();
+ //bookkeeping_.inc_abort_perm_denied((*k)->threadId_);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// IMPORTANT ASSUMPTION:
+//
+// "this" must not be on the list. Thus, otherInFlightTransactionsOfSameThread
+// must be checked BEFORE "this" is inserted into the transactionsInFlight_ if
+// checked at ctor or begin_transaction().
+//
+// Or it must be checked AFTER "this" is removed from the transactionsInFlight_
+//
+//-----------------------------------------------------------------------------
+inline bool boost::stm::transaction::other_in_flight_same_thread_transactions() const throw()
+{
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ if (((transaction*)*i) == this) continue;
+ // if this is not our threadId or this thread is not composable, skip it
+ if (((transaction*)*i)->threadId_ != this->threadId_) continue;
+ return true;
+ }
+
+ return false;
+}
+
+inline bool boost::stm::transaction::
+otherInFlightTransactionsOfSameThreadNotIncludingThis(transaction const * const rhs)
+{
+ //////////////////////////////////////////////////////////////////////
+ for (InflightTxes::iterator i = transactionsInFlight_.begin(); i != transactionsInFlight_.end(); ++i)
+ {
+ if (*i == rhs) continue;
+ // if this is not our threadId or this thread is not composable, skip it
+ if (((transaction*)*i)->threadId_ != this->threadId_) continue;
+ return true;
+ }
+
+ return false;
+}
+
+
+#endif // TRANSACTION_IMPL_H
+

Added: sandbox/stm/boost/stm/detail/vector_map.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/vector_map.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,102 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_VECTOR_MAP_H
+#define BOOST_STM_VECTOR_MAP_H
+
+#include <vector>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace boost { namespace stm {
+
+ size_t const def_map_reserve = 128;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename T, typename U>
+class vector_map
+{
+public:
+
+ vector_map(size_t const &res = def_map_reserve) { pairs_.reserve(res); }
+
+ typedef T first_t;
+ typedef U second_t;
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ typedef std::vector<std::pair<T, U> > cont;
+ typedef std::pair<T, U> cont_pair;
+ typedef typename std::vector<std::pair<T, U> >::iterator iterator;
+
+ typename vector_map<T,U>::iterator begin() { return pairs_.begin(); }
+ typename vector_map<T,U>::iterator end() { return pairs_.end(); }
+
+ size_t size() { return pairs_.size(); }
+
+ T& first(size_t const val) { return pairs_[val].first; }
+ U& second(size_t const val) { return pairs_[val].second; }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ typename vector_map<T,U>::iterator find(first_t const &t)
+ {
+ for (typename vector_map<T,U>::iterator i = pairs_.begin(); i != pairs_.end(); ++i)
+ {
+ if (t == i->first) return i;
+ }
+
+ return pairs_.end();
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ typename vector_map<T,U>::iterator insert(cont_pair const &wp)
+ {
+ T const &f = wp.first;
+
+ for (typename vector_map<T,U>::iterator i = pairs_.begin(); i != pairs_.end(); ++i)
+ {
+ if (f == i->first)
+ {
+ i->second = wp.second;
+ return i;
+ }
+ }
+
+ pairs_.push_back(wp);
+ return (typename vector_map<T,U>::iterator)&pairs_[pairs_.size()-1];
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ void erase(typename vector_map<T,U>::iterator &iter)
+ {
+ pairs_.erase(iter);
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ void clear() { pairs_.clear(); }
+
+private:
+ cont pairs_;
+};
+
+} // core namespace
+}
+#endif
+

Added: sandbox/stm/boost/stm/detail/vector_set.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/detail/vector_set.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,110 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#ifndef BOOST_STM_VECTOR_SET_H
+#define BOOST_STM_VECTOR_SET_H
+
+#include <vector>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace boost { namespace stm {
+size_t const def_set_reserve = 128;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename T>
+class vector_set
+{
+public:
+
+ vector_set(size_t const res = def_set_reserve) { elements_.reserve(res); }
+
+ typedef T first_t;
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ typedef std::vector<T> cont;
+ typedef typename std::vector<T>::iterator iterator;
+ typedef typename std::vector<T>::const_iterator const_iterator;
+
+ typename vector_set<T>::iterator begin() { return elements_.begin(); }
+ typename vector_set<T>::const_iterator begin() const { return elements_.begin(); }
+
+ typename vector_set<T>::iterator end() { return elements_.end(); }
+ typename vector_set<T>::const_iterator end() const { return elements_.end(); }
+
+ size_t size() { return elements_.size(); }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ typename vector_set<T>::iterator find(T const &t)
+ {
+ for (typename vector_set<T>::iterator i = elements_.begin(); i != elements_.end(); ++i)
+ {
+ if (t == i) return i;
+ }
+
+ return elements_.end();
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ typename vector_set<T>::iterator insert(first_t const &rhs)
+ {
+ for (typename vector_set<T>::iterator i = elements_.begin(); i != elements_.end(); ++i)
+ {
+ if (rhs == *i)
+ {
+ return i;
+ }
+ }
+
+ elements_.push_back(rhs);
+ return (typename vector_set<T>::iterator)&elements_[elements_.size()-1];
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ void erase(vector_set<T>::first_t const &rhs)
+ {
+ for (typename vector_set<T>::iterator i = elements_.begin(); i != elements_.end(); ++i)
+ {
+ if (rhs == *i)
+ {
+ elements_.erase(i); return;
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ void push_back(vector_set<T>::first_t const &rhs)
+ {
+ elements_.push_back(rhs);
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ void clear() { elements_.clear(); }
+
+private:
+ cont elements_;
+};
+
+} // core namespace
+}
+#endif
+

Added: sandbox/stm/boost/stm/transaction.hpp
==============================================================================
--- (empty file)
+++ sandbox/stm/boost/stm/transaction.hpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,1382 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+
+
+#ifndef BOOST_STM_TRANSACTION__HPP
+#define BOOST_STM_TRANSACTION__HPP
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include <boost/stm/detail/config.hpp>
+#include <boost/stm/detail/datatypes.hpp>
+#include <boost/stm/detail/transaction_bookkeeping.hpp>
+#include <boost/stm/base_transaction.hpp>
+#include <boost/stm/detail/bloom_filter.hpp>
+#include <boost/stm/detail/vector_map.hpp>
+#include <boost/stm/detail/vector_set.hpp>
+#include <assert.h>
+#include <string>
+#include <iostream>
+#include <list>
+#include <set>
+#include <map>
+#include <vector>
+#include <pthread.h>
+
+#if BUILD_MOVE_SEMANTICS
+#include <type_traits>
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace boost { namespace stm {
+
+ enum LatmType
+ {
+ kMinLatmType = 0,
+ eFullLatmProtection = kMinLatmType,
+ eTmConflictingLockLatmProtection,
+ eTxConflictingLockLatmProtection,
+ kMaxLatmType
+ };
+
+ enum TxType
+ {
+ kMinIrrevocableType = 0,
+ eNormalTx = kMinIrrevocableType,
+ eIrrevocableTx,
+ eIrrevocableAndIsolatedTx,
+ kMaxIrrevocableType
+ };
+
+ typedef std::pair<base_transaction_object*, base_transaction_object*> tx_pair;
+
+///////////////////////////////////////////////////////////////////////////////
+// transaction Class
+///////////////////////////////////////////////////////////////////////////////
+class transaction
+{
+public:
+ //--------------------------------------------------------------------------
+ // transaction typedefs
+ //--------------------------------------------------------------------------
+
+#if PERFORMING_VALIDATION
+ typedef std::map<base_transaction_object*, size_t> ReadContainer;
+#else
+ typedef std::set<base_transaction_object*> ReadContainer;
+#endif
+ typedef std::map<size_t, ReadContainer*> ThreadReadContainer;
+
+#ifdef MAP_WRITE_CONTAINER
+ typedef std::map<base_transaction_object*, base_transaction_object*> WriteContainer;
+#else
+ typedef boost::stm::vector_map<base_transaction_object*, base_transaction_object*> WriteContainer;
+#endif
+
+#ifndef MAP_NEW_CONTAINER
+ typedef boost::stm::vector_set<base_transaction_object*> MemoryContainerList;
+#else
+ typedef std::list<base_transaction_object*> MemoryContainerList;
+#endif
+
+ typedef std::map<size_t, WriteContainer*> ThreadWriteContainer;
+ typedef std::map<size_t, TxType*> ThreadTxTypeContainer;
+
+ typedef std::set<transaction*> TContainer;
+ typedef std::set<transaction*> InflightTxes;
+
+ 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<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 boost::stm::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, boost::stm::bloom_filter*> ThreadBloomFilterList;
+ typedef std::map<size_t, boost::stm::bit_vector*> ThreadBitVectorList;
+
+ typedef std::pair<size_t, int*> thread_bool_pair;
+#ifndef MAP_THREAD_BOOL_CONTAINER
+ typedef boost::stm::vector_map<size_t, int*> ThreadBoolContainer;
+#else
+ typedef std::map<size_t, int*> ThreadBoolContainer;
+#endif
+
+ typedef std::map<Mutex*, ThreadIdSet > MutexThreadSetMap;
+ typedef std::map<Mutex*, size_t> MutexThreadMap;
+
+ typedef std::set<transaction*> LockedTransactionContainer;
+
+ typedef InflightTxes in_flight_transaction_container;
+ typedef in_flight_transaction_container in_flight_trans_cont;
+
+ struct tx_context
+ {
+ MemoryContainerList newMem;
+ MemoryContainerList delMem;
+ WriteContainer writeMem;
+ bloom_filter wbloom;
+ bloom_filter bloom;
+ TxType txType;
+
+ int abort;
+ };
+
+ typedef std::map<size_t, tx_context*> ThreadMemContainer;
+
+ //--------------------------------------------------------------------------
+ // transaction static methods
+ //--------------------------------------------------------------------------
+ static void initialize();
+ static void initialize_thread();
+ static void terminate_thread();
+ static void contention_manager(base_contention_manager *rhs) { delete cm_; cm_ = rhs; }
+ static base_contention_manager* get_contention_manager() { return cm_; }
+
+ static void enableLoggingOfAbortAndCommitSetSize() { bookkeeping_.setIsLoggingAbortAndCommitSize(true); }
+ static void disableLoggingOfAbortAndCommitSetSize() { bookkeeping_.setIsLoggingAbortAndCommitSize(false); }
+
+ static const transaction_bookkeeping & bookkeeping() { return bookkeeping_; }
+
+ static bool early_conflict_detection() { return !directLateWriteReadConflict_ && direct_updating(); }
+ static bool late_conflict_detection() { return directLateWriteReadConflict_ || !direct_updating(); }
+
+ static bool enable_dynamic_priority_assignment()
+ {
+ return dynamicPriorityAssignment_ = true;
+ }
+
+ static bool disable_dynamic_priority_assignment()
+ {
+ return dynamicPriorityAssignment_ = false;
+ }
+
+ static bool using_move_semantics() { return usingMoveSemantics_; }
+ static bool using_copy_semantics() { return !using_move_semantics(); }
+
+ static void enable_move_semantics()
+ {
+ if (!kDracoMoveSemanticsCompiled)
+ throw "move semantics off - rebuild with #define BUILD_MOVE_SEMANTICS 1";
+ usingMoveSemantics_ = true;
+ }
+
+ static void disable_move_semantics()
+ {
+ usingMoveSemantics_ = false;
+ }
+
+ static bool doing_dynamic_priority_assignment()
+ {
+ return dynamicPriorityAssignment_;
+ }
+
+ static bool do_early_conflict_detection()
+ {
+ if (transactionsInFlight_.size() > 0) return false;
+ if (deferred_updating()) return false;
+ else return !(directLateWriteReadConflict_ = false);
+ }
+
+ static bool do_late_conflict_detection()
+ {
+ if (transactionsInFlight_.size() > 0) return false;
+ else return directLateWriteReadConflict_ = true;
+ }
+
+ static std::string consistency_checking_string()
+ {
+ if (validating()) return "val";
+ else return "inval";
+ }
+
+ static bool validating()
+ {
+#ifdef PERFORMING_VALIDATION
+ return true;
+#endif
+ return false;
+ }
+
+ static bool invalidating() { return !validating(); }
+
+ static bool direct_updating() { return directUpdating_; }
+ static bool deferred_updating() { return !directUpdating_; }
+
+ //--------------------------------------------------------------------------
+ // make all transactions direct as long as no transactions are in flight
+ //--------------------------------------------------------------------------
+ static bool do_direct_updating()
+ {
+ if (transactionsInFlight_.size() > 0) return false;
+ else return directUpdating_ = true;
+ }
+
+ //--------------------------------------------------------------------------
+ // make all transactions deferred as long as no transactions are in flight
+ //--------------------------------------------------------------------------
+ static bool do_deferred_updating()
+ {
+ if (transactionsInFlight_.size() > 0) return false;
+ else directUpdating_ = false;
+ return true;
+ }
+
+ static std::string update_policy_string()
+ {
+ return directUpdating_ ? "dir" : "def";
+ }
+
+ //--------------------------------------------------------------------------
+ // Lock Aware Transactional Memory support methods
+ //--------------------------------------------------------------------------
+ static LatmType const latm_protection() { return eLatmType_; }
+ static std::string const latm_protection_str();
+ static void do_full_lock_protection();
+ static void do_tm_lock_protection();
+ static void do_tx_lock_protection();
+
+ static bool doing_full_lock_protection();
+ static bool doing_tm_lock_protection();
+ static bool doing_tx_lock_protection();
+
+
+#ifdef WIN32
+ template <typename T>
+ static int lock_(T *lock) { throw "unsupported lock type"; }
+
+ template <typename T>
+ static int trylock_(T *lock) { throw "unsupported lock type"; }
+
+ template <typename T>
+ static int unlock_(T *lock) { throw "unsupported lock type"; }
+
+ template <>
+ static int lock_(Mutex &lock) { return pthread_lock(&lock); }
+
+ template <>
+ static int lock_(Mutex *lock) { return pthread_lock(lock); }
+
+ template <>
+ static int trylock_(Mutex &lock) { return pthread_trylock(&lock); }
+
+ template <>
+ static int trylock_(Mutex *lock) { return pthread_trylock(lock); }
+
+ template <>
+ static int unlock_(Mutex &lock) { return pthread_unlock(&lock); }
+
+ template <>
+ static int unlock_(Mutex *lock) { return pthread_unlock(lock); }
+#else
+ static int lock_(PLOCK &lock) { return pthread_lock(&lock); }
+ static int lock_(PLOCK *lock) { return pthread_lock(lock); }
+
+ static int trylock_(PLOCK &lock) { return pthread_trylock(&lock); }
+ static int trylock_(PLOCK *lock) { return pthread_trylock(lock); }
+
+ static int unlock_(PLOCK &lock) { return pthread_unlock(&lock); }
+ static int unlock_(PLOCK *lock) { return pthread_unlock(lock); }
+#endif
+
+ static int pthread_lock(Mutex *lock);
+ static int pthread_trylock(Mutex *lock);
+ static int pthread_unlock(Mutex *lock);
+
+
+
+ //--------------------------------------------------------------------------
+#if PERFORMING_LATM
+ //--------------------------------------------------------------------------
+ static void tm_lock_conflict(Mutex &lock)
+ {
+ tm_lock_conflict(&lock);
+ }
+ static void tm_lock_conflict(Mutex *lock);
+
+ static void clear_tm_conflicting_locks();
+ static MutexSet get_tm_conflicting_locks() { return tmConflictingLocks_; }
+
+ 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
+ void see_if_tx_must_block_due_to_tx_latm();
+
+ void lock_conflict(Mutex &lock)
+ { add_tx_conflicting_lock(&lock); }
+
+ void lock_conflict(Mutex *lock)
+ { add_tx_conflicting_lock(lock); }
+
+ void add_tx_conflicting_lock(Mutex &lock)
+ {
+ add_tx_conflicting_lock(&lock);
+ }
+ void add_tx_conflicting_lock(Mutex *lock);
+
+ void clear_tx_conflicting_locks();
+ MutexSet get_tx_conflicting_locks() { return conflictingMutexRef_; }
+#endif
+
+ void add_to_obtained_locks(Mutex* );
+ static void unblock_conflicting_threads(Mutex *mutex);
+ static bool mutex_is_on_obtained_tx_list(Mutex *mutex);
+ static void unblock_threads_if_locks_are_empty();
+ void clear_latm_obtained_locks();
+
+ void add_to_currently_locked_locks(Mutex* m);
+ void remove_from_currently_locked_locks(Mutex *m);
+ bool is_currently_locked_lock(Mutex *m);
+ bool is_on_obtained_locks_list(Mutex *m);
+#endif
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ transaction();
+ ~transaction();
+
+ int const forced_to_abort() const { return *forcedToAbortRef_; }
+
+ bool check_throw_before_restart() const
+ {
+ // if this transaction is in-flight or it committed, just ignore it
+ if (in_flight() || committed()) return true;
+
+ //-----------------------------------------------------------------------
+ // if there is another in-flight transaction from this thread, and we
+ // are using closed nesting with flattened transactions, we should throw
+ // an exception here because restarting the transactions will cause it to
+ // infinitely fail
+ //-----------------------------------------------------------------------
+ lock_inflight_access();
+ if (other_in_flight_same_thread_transactions())
+ {
+ unlock_inflight_access();
+ throw aborted_transaction_exception("closed nesting throw");
+ }
+ unlock_inflight_access();
+
+ return true;
+ }
+
+ bool committed() const { return state() == e_committed || state() == e_hand_off; }
+ bool aborted() const { return state() == e_aborted; }
+ bool in_flight() const { return state() == e_in_flight; }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T& find_original(T& in)
+ {
+ //-----------------------------------------------------------------------
+ // if transactionThread_ is not invalid it means this is the original, so
+ // we can return it. Otherwise, we need to search for the original in
+ // our write set
+ //-----------------------------------------------------------------------
+ if (1 == in.new_memory()) return in;
+ if (in.transaction_thread() == boost::stm::kInvalidThread) return in;
+
+ base_transaction_object *inPtr = (base_transaction_object*)&in;
+
+ for (WriteContainer::iterator i = writeList().begin(); i != writeList().end(); ++i)
+ {
+ if (i->second == (inPtr))
+ {
+ return *static_cast<T*>(i->first);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ // if it's not in our original / new list, then we need to except
+ //-----------------------------------------------------------------------
+ throw aborted_transaction_exception("original not found");
+ }
+
+ //--------------------------------------------------------------------------
+ // The below methods change their behavior based on whether the transaction
+ // is direct or deferred:
+ //
+ // read - deferred_read or direct_read
+ // write - deferred_write or direct_write
+ // delete_memory - deferred_delete_memory or direct_delete_memory
+ // commit - deferred_commit or direct_commit
+ // abort - deferred_abort or direct_abort
+ //
+ // In addition, a number of commit or abort methods must be made deferred or
+ // direct as their version / memory management is entirely different if the
+ // transaction is direct or deferred.
+ //
+ //--------------------------------------------------------------------------
+#ifndef DISABLE_READ_SETS
+ size_t const read_set_size() const { return readListRef_.size(); }
+#endif
+
+ size_t const writes() const { return writeListRef_->size(); }
+ size_t const reads() const { return reads_; }
+
+ template <typename T> T const * read_ptr(T const * in) { return &read(*in); }
+ template <typename T> T const & r(T const & in) { return read(in); }
+
+ //--------------------------------------------------------------------------
+ // attempts to find the written value of T based on
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T* get_written(T const & in)
+ {
+ WriteContainer::iterator i = writeList().find
+ ((base_transaction_object*)(&in));
+ if (i == writeList().end()) return NULL;
+ else return static_cast<T*>(i->second);
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
+ 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>
+ T const & read(T const & in)
+ {
+ if (directUpdating_)
+ {
+#if PERFORMING_VALIDATION
+ throw "direct updating not implemented for validation yet";
+#else
+ return direct_read(in);
+#endif
+ }
+ else
+ {
+ return deferred_read(in);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T> T* write_ptr(T* in) { return &write(*in); }
+ template <typename T> T& w(T& in) { return write(in); }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T& write(T& in)
+ {
+ if (directUpdating_)
+ {
+#if PERFORMING_VALIDATION
+ throw "direct updating not implemented for validation yet";
+#else
+ return direct_write(in);
+#endif
+ }
+ else
+ {
+ return deferred_write(in);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
+ void delete_memory(T &in)
+ {
+ if (directUpdating_)
+ {
+#if PERFORMING_VALIDATION
+ throw "direct updating not implemented for validation yet";
+#else
+ direct_delete_memory(in);
+#endif
+ }
+ else
+ {
+ deferred_delete_memory(in);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // allocation of new memory behaves the same for both deferred and direct
+ // transaction implementations
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T* new_memory(T const &rhs)
+ {
+ if (forced_to_abort())
+ {
+ if (!directUpdating_)
+ {
+ deferred_abort(true);
+ throw aborted_tx("");
+ }
+
+#ifndef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cm_->abort_on_new(*this);
+#endif
+ }
+ T *newNode = new T();
+ newNode->transaction_thread(threadId_);
+ newNode->new_memory(1);
+ newMemoryList().push_front(newNode);
+
+ return newNode;
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T* new_memory_copy(T const &rhs)
+ {
+ if (forced_to_abort())
+ {
+ if (!directUpdating_)
+ {
+ deferred_abort(true);
+ throw aborted_tx("");
+ }
+#ifndef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cm_->abort_on_new(*this);
+#endif
+ }
+ T *newNode = new T(rhs);
+ newNode->transaction_thread(threadId_);
+ newNode->new_memory(1);
+ newMemoryList().push_back(newNode);
+
+ return newNode;
+ }
+
+ void begin();
+ bool restart();
+
+ bool restart_if_not_inflight()
+ {
+ if (in_flight()) return true;
+ else return restart();
+ }
+
+ void end();
+ void no_throw_end();
+
+ void force_to_abort()
+ {
+ *forcedToAbortRef_ = true;
+
+#ifdef PERFORMING_COMPOSITION
+#ifndef USING_SHARED_FORCED_TO_ABORT
+ // now set all txes of this threadid that are in-flight to force to abort
+ for (InflightTxes::iterator j = transactionsInFlight_.begin();
+ j != transactionsInFlight_.end(); ++j)
+ {
+ transaction *t = (transaction*)*j;
+
+ // if this is a parent or child tx, it must abort too
+ if (t->threadId_ == this->threadId_) t->forcedToAbortRef_ = true;
+ }
+#endif
+#endif
+ }
+
+ void unforce_to_abort() { *forcedToAbortRef_ = false; }
+
+ //--------------------------------------------------------------------------
+ void lock_and_abort();
+
+ size_t writeListSize() const { return writeListRef_->size(); }
+
+ size_t const &priority() const { return priority_; }
+ void set_priority(uint32 const &rhs) const { priority_ = rhs; }
+ void raise_priority()
+ {
+ if (priority_ < size_t(-1))
+ {
+ ++priority_;
+ }
+ }
+
+ static InflightTxes const & in_flight_transactions() { return transactionsInFlight_; }
+
+ void make_irrevocable();
+ void make_isolated();
+ bool irrevocable() const;
+ bool isolated() const;
+
+ size_t const & thread_id() const { return threadId_; }
+
+private:
+
+#ifdef LOGGING_BLOCKS
+ static std::string outputBlockedThreadsAndLockedLocks();
+#endif
+ //--------------------------------------------------------------------------
+ int const& hasLock() const { return hasMutex_; }
+ void lock_tx();
+ void unlock_tx();
+
+ static void lock_latm_access();
+ static void unlock_latm_access();
+
+ static void lock_inflight_access();
+ static void unlock_inflight_access();
+
+ static void lock_general_access();
+ static void unlock_general_access();
+
+ static PLOCK* latm_lock() { return &latmMutex_; }
+ static PLOCK* general_lock() { return &transactionMutex_; }
+ static PLOCK* inflight_lock() { return &transactionsInFlightMutex_; }
+
+#if PERFORMING_LATM
+ void block() { blockedRef_ = true; }
+ void unblock() { blockedRef_ = false; }
+#endif
+
+ bool irrevocableTxInFlight();
+ bool isolatedTxInFlight();
+ void commit_deferred_update_tx();
+
+ bool canAbortAllInFlightTxs();
+ bool abortAllInFlightTxs();
+ void put_tx_inflight();
+ bool can_go_inflight();
+ static transaction* get_inflight_tx_of_same_thread(bool);
+
+#if !PERFORMING_VALIDATION
+ //--------------------------------------------------------------------------
+ // DIRECT UPDATING SECTION
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T const & direct_read(T const & in)
+ {
+ if (in.transaction_thread() == threadId_) return in;
+
+ if (forced_to_abort())
+ {
+#ifndef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ // let the contention manager decide to throw or not
+ cm_->abort_on_write(*this, (base_transaction_object&)(in));
+#endif
+ }
+
+ //--------------------------------------------------------------------
+ // otherwise, see if its in our read list
+ //--------------------------------------------------------------------
+#ifndef DISABLE_READ_SETS
+ ReadContainer::iterator i = readList().find((base_transaction_object*)&in);
+ if (i != readList().end()) return in;
+#endif
+#if USE_BLOOM_FILTER
+ if (bloom().exists((size_t)&in)) return in;
+#endif
+
+ //--------------------------------------------------------------------
+ // if we want direct write-read conflict to be done late (commit time)
+ // perform the following section of code
+ //--------------------------------------------------------------------
+ if (directLateWriteReadConflict_)
+ {
+ //--------------------------------------------------------------------
+ // if transaction_thread() is not invalid (and not us), we get original
+ // object from the thread that is changing it
+ //--------------------------------------------------------------------
+ lock(&transactionMutex_);
+ lock_tx();
+
+ if (in.transaction_thread() != boost::stm::kInvalidThread)
+ {
+ lockThreadMutex(in.transaction_thread());
+
+ ThreadWriteContainer::iterator writeIter =
+ threadWriteLists_.find(in.transaction_thread());
+
+ WriteContainer::iterator readMem = writeIter->second->find((base_transaction_object*)&in);
+
+ if (readMem == writeIter->second->end())
+ {
+ std::cout << "owner did not contain item in write list" << std::endl;
+ }
+
+#ifndef DISABLE_READ_SETS
+ readList().insert((base_transaction_object*)readMem->second);
+#endif
+#if USE_BLOOM_FILTER
+ bloom().insert((size_t)readMem->second);
+#endif
+ unlock(&transactionMutex_);
+ unlock_tx();
+ unlockThreadMutex(in.transaction_thread());
+
+ ++reads_;
+ return *static_cast<T*>(readMem->second);
+ }
+
+ // already have locked us above - in both if / else
+#ifndef DISABLE_READ_SETS
+ readList().insert((base_transaction_object*)&in);
+#endif
+#if USE_BLOOM_FILTER
+ bloom().insert((size_t)&in);
+#endif
+ unlock(&transactionMutex_);
+ unlock_tx();
+ ++reads_;
+ return in;
+ }
+ else
+ {
+ //--------------------------------------------------------------------
+ // if we want direct write-read conflict to be done early, bail
+ // if someone owns this
+ //--------------------------------------------------------------------
+ if (in.transaction_thread() != boost::stm::kInvalidThread)
+ {
+ // let the contention manager decide to throw or not
+ cm_->abort_on_write(*this, (base_transaction_object&)(in));
+ }
+
+ lock_tx();
+ // already have locked us above - in both if / else
+#ifndef DISABLE_READ_SETS
+ readList().insert((base_transaction_object*)&in);
+#endif
+#if USE_BLOOM_FILTER
+ bloom().insert((size_t)&in);
+#endif
+ unlock_tx();
+ ++reads_;
+ }
+ return in;
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T& direct_write(T& in)
+ {
+ // if this is our memory (new or mod global) just return
+ if (in.transaction_thread() == threadId_) return in;
+
+ if (forced_to_abort())
+ {
+#ifndef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cm_->abort_on_write(*this, static_cast<base_transaction_object&>(in));
+#endif
+ }
+ //-----------------------------------------------------------------------
+ // first we globally lock all threads before we poke at this global
+ // memory - since we need to ensure other threads don't try to
+ // manipulate this at the same time we are going to
+ //-----------------------------------------------------------------------
+ lock(&transactionMutex_);
+
+ // we currently don't allow write stealing in direct update. if another
+ // tx beat us to the memory, we abort
+ if (in.transaction_thread() != boost::stm::kInvalidThread)
+ {
+ unlock(&transactionMutex_);
+ throw aborted_tx("direct writer already exists.");
+ }
+
+ in.transaction_thread(threadId_);
+ writeList().insert(tx_pair((base_transaction_object*)&in, new T(in)));
+#if USE_BLOOM_FILTER
+ bloom().insert((size_t)&in);
+#endif
+ unlock(&transactionMutex_);
+ return in;
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
+ void direct_delete_memory(T &in)
+ {
+ if (in.transaction_thread() == threadId_)
+ {
+ //deletedMemoryList().push_back(&(T)in);
+ deletedMemoryList().push_back((base_transaction_object*)&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
+ //-----------------------------------------------------------------------
+ lock(&transactionMutex_);
+
+ if (in.transaction_thread() != boost::stm::kInvalidThread)
+ {
+ unlock(&transactionMutex_);
+ cm_->abort_on_write(*this, (base_transaction_object&)(in));
+ }
+ else
+ {
+ in.transaction_thread(threadId_);
+ unlock(&transactionMutex_);
+ // 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] = NULL;
+
+ deletedMemoryList().push_back((base_transaction_object*)&in);
+ }
+ }
+#endif
+
+
+ //--------------------------------------------------------------------------
+ // DEFERRED UPDATING SECTION
+ //--------------------------------------------------------------------------
+ template <typename T>
+ T const & deferred_read(T const & in)
+ {
+ if (forced_to_abort())
+ {
+ deferred_abort(true);
+ throw aborted_tx("");
+ }
+
+ //----------------------------------------------------------------
+ // always check if the writeList size is 0 first, since if it is
+ // it can save construction of an iterator and search setup.
+ //----------------------------------------------------------------
+#if PERFORMING_WRITE_BLOOM
+ if (0 == writeList().size() ||
+ (writeList().size() > 16 &&
+ !wbloom().exists((size_t)&in))) return insert_and_return_read_memory(in);
+#else
+ if (0 == writeList().size()) return insert_and_return_read_memory(in);
+#endif
+
+ WriteContainer::iterator i = writeList().find
+ ((base_transaction_object*)(&in));
+ //----------------------------------------------------------------
+ // always check to see if read memory is in write list since it is
+ // possible to have already written to memory being read now
+ //----------------------------------------------------------------
+ if (i == writeList().end()) return insert_and_return_read_memory(in);
+ else return *static_cast<T*>(i->second);
+ }
+
+ //-------------------------------------------------------------------
+ template <typename T>
+ T& insert_and_return_read_memory(T& 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
+ //----------------------------------------------------------------
+ if (i != readList().end()) return in;
+#else
+ if (bloom().exists((size_t)&in)) return in;
+#endif
+ lock_tx();
+#ifndef DISABLE_READ_SETS
+#if PERFORMING_VALIDATION
+ readList()[(base_transaction_object*)&in] = in.version_;
+#else
+ readList().insert((base_transaction_object*)&in);
+#endif
+#endif
+#if USE_BLOOM_FILTER
+ bloom().insert((size_t)&in);
+#endif
+ unlock_tx();
+ ++reads_;
+ return in;
+ }
+
+ template <typename T>
+ T& deferred_write(T& in)
+ {
+ if (forced_to_abort())
+ {
+ deferred_abort(true);
+ throw aborted_tx("");
+ }
+ //----------------------------------------------------------------
+ // if transactionThread_ is not invalid, then already writing to
+ // non-global memory - so succeed.
+ //----------------------------------------------------------------
+ if (in.transaction_thread() != boost::stm::kInvalidThread) return in;
+
+ WriteContainer::iterator i = writeList().find
+ (static_cast<base_transaction_object*>(&in));
+ //----------------------------------------------------------------
+ // if !in write set, add. lock first, for version consistency
+ //----------------------------------------------------------------
+ if (i == writeList().end())
+ {
+ // get the lock before we make a copy of this object
+ lock_tx();
+#if USE_BLOOM_FILTER
+ bloom().insert((size_t)&in);
+ unlock_tx();
+#endif
+#if PERFORMING_WRITE_BLOOM
+ wbloom().set_bv1(bloom().h1());
+ wbloom().set_bv2(bloom().h2());
+ //sm_wbv().set_bit((size_t)&in % sm_wbv().size());
+#endif
+ base_transaction_object* returnValue = new T(in);
+ returnValue->transaction_thread(threadId_);
+ writeList().insert(tx_pair((base_transaction_object*)&in, returnValue));
+#ifndef USE_BLOOM_FILTER
+ unlock_tx();
+#endif
+ return *static_cast<T*>(returnValue);
+ }
+ else return *static_cast<T*>(i->second);
+ }
+
+ //--------------------------------------------------------------------------
+ template <typename T>
+ void deferred_delete_memory(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() != boost::stm::kInvalidThread)
+ {
+ lock_tx();
+ bloom().insert((size_t)&in);
+ unlock_tx();
+ writeList().insert(tx_pair((base_transaction_object*)&in, NULL));
+ }
+ //-----------------------------------------------------------------------
+ // 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
+ {
+ lock_tx();
+ bloom().insert((size_t)&in);
+ unlock_tx();
+ // 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 == &(T)in)
+ {
+ writeList().insert(tx_pair(j->first, NULL));
+ deletedMemoryList().push_back(j->first);
+ }
+ }
+ }
+
+ deletedMemoryList().push_back((base_transaction_object *)&in);
+ }
+
+ //--------------------------------------------------------------------------
+ void verifyReadMemoryIsValidWithGlobalMemory();
+ void verifyWrittenMemoryIsValidWithGlobalMemory();
+
+ //--------------------------------------------------------------------------
+ void abort() throw() { directUpdating_ ? direct_abort() : deferred_abort(); }
+ void deferred_abort(bool const &alreadyRemovedFromInflightList = false) throw();
+ void direct_abort(bool const &alreadyRemovedFromInflightList = false) throw();
+
+ //--------------------------------------------------------------------------
+ void validating_deferred_commit();
+ void invalidating_deferred_commit();
+ void validating_direct_commit();
+ void invalidating_direct_commit();
+
+ //--------------------------------------------------------------------------
+ void lockThreadMutex(size_t threadId);
+ void unlockThreadMutex(size_t threadId);
+ static void lock_all_mutexes_but_this(size_t threadId);
+ static void unlock_all_mutexes_but_this(size_t threadId);
+
+ //--------------------------------------------------------------------------
+ // side-effect: this unlocks all mutexes including its own. this is a slight
+ // optimization over unlock_all_mutexes_but_this() as it doesn't have an
+ // additional "if" to slow down performance. however, as it will be
+ // releasing its own mutex, it must reset hasMutex_
+ //--------------------------------------------------------------------------
+ void lock_all_mutexes();
+ void unlock_all_mutexes();
+
+ transaction_state const & state() const { return state_; }
+
+#if PERFORMING_LATM
+ int const blocked() const { return blockedRef_; }
+#endif
+ WriteContainer& writeList() { return *writeListRef_; }
+#ifndef DISABLE_READ_SETS
+ ReadContainer& readList() { return readListRef_; }
+#endif
+
+ bloom_filter& bloom() { return *bloomRef_; }
+#if PERFORMING_WRITE_BLOOM
+ bloom_filter& wbloom() { return *wbloomRef_; }
+ //bit_vector& sm_wbv() { return sm_wbv_; }
+#endif
+
+#ifndef DISABLE_READ_SETS
+ bool isReading() const { return 0 != readListRef_.size(); }
+#endif
+ bool isWriting() const { return 0 != writeListRef_->size(); }
+ bool is_only_reading() const { return !isWriting(); }
+
+ MemoryContainerList& newMemoryList() { return *newMemoryListRef_; }
+ MemoryContainerList& deletedMemoryList() { return *deletedMemoryListRef_; }
+
+ TxType const tx_type() const { return *txTypeRef_; }
+ void tx_type(TxType const &rhs) { *txTypeRef_ = rhs; }
+
+ Mutex * mutex() { return mutexRef_; }
+
+ // undefined and hidden - never allow these - bad things would happen
+ transaction& operator=(transaction const &);
+ transaction(transaction const &);
+
+ bool otherInFlightTransactionsWritingThisMemory(base_transaction_object *obj);
+ bool other_in_flight_same_thread_transactions() const throw();
+ bool otherInFlightTransactionsOfSameThreadNotIncludingThis(transaction const * const);
+
+ void removeAllSharedValuesOfThread(base_transaction_object *key);
+ void copyOtherInFlightComposableTransactionalMemoryOfSameThread();
+ bool setAllInFlightComposableTransactionsOfThisThreadToAbort();
+
+ //--------------------------------------------------------------------------
+ void forceOtherInFlightTransactionsWritingThisWriteMemoryToAbort();
+ void forceOtherInFlightTransactionsReadingThisWriteMemoryToAbort();
+ bool forceOtherInFlightTransactionsAccessingThisWriteMemoryToAbort(bool, transaction* &);
+
+ void unlockAllLockedThreads(LockedTransactionContainer &);
+
+ //--------------------------------------------------------------------------
+ // direct and deferred transaction method for version / memory management
+ //--------------------------------------------------------------------------
+ void directCommitTransactionDeletedMemory() throw();
+ size_t earliest_start_time_of_inflight_txes();
+ void doIntervalDeletions();
+
+ void deferredCommitTransactionDeletedMemory() throw();
+ void directCommitTransactionNewMemory() { deferredCommitTransactionNewMemory(); }
+ void deferredCommitTransactionNewMemory();
+
+ void directAbortTransactionDeletedMemory() throw();
+ void deferredAbortTransactionDeletedMemory() throw() { deletedMemoryList().clear(); }
+ void directAbortTransactionNewMemory() throw() { deferredAbortTransactionNewMemory(); }
+ void deferredAbortTransactionNewMemory() throw();
+
+ void directCommitWriteState();
+ void deferredCommitWriteState();
+
+#ifndef DISABLE_READ_SETS
+ void directCommitReadState() { readList().clear(); }
+ void deferredCommitReadState() { readList().clear(); }
+#endif
+
+ void directAbortWriteList();
+ void deferredAbortWriteList() throw();
+
+#ifndef DISABLE_READ_SETS
+ void directAbortReadList() { readList().clear(); }
+ void deferredAbortReadList() throw() { readList().clear(); }
+#endif
+
+ void validating_direct_end_transaction();
+ void invalidating_direct_end_transaction();
+
+ void validating_deferred_end_transaction();
+ void invalidating_deferred_end_transaction();
+
+ //--------------------------------------------------------------------------
+ //
+ // Lock Aware Transactional Memory (LATM) support methods
+ //
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // deferred updating methods
+ //--------------------------------------------------------------------------
+ static bool def_do_core_tm_conflicting_lock_pthread_lock_mutex
+ (Mutex *mutex, int lockWaitTime, int lockAborted);
+ static bool def_do_core_tx_conflicting_lock_pthread_lock_mutex
+ (Mutex *mutex, int lockWaitTime, int lockAborted, bool txIsIrrevocable);
+ static bool def_do_core_full_pthread_lock_mutex
+ (Mutex *mutex, int lockWaitTime, int lockAborted);
+
+ //--------------------------------------------------------------------------
+ // direct updating methods
+ //--------------------------------------------------------------------------
+ static bool dir_do_core_tm_conflicting_lock_pthread_lock_mutex
+ (Mutex *mutex, int lockWaitTime, int lockAborted);
+ static bool dir_do_core_tx_conflicting_lock_pthread_lock_mutex
+ (Mutex *mutex, int lockWaitTime, int lockAborted, bool txIsIrrevocable);
+ static bool dir_do_core_full_pthread_lock_mutex
+ (Mutex *mutex, int lockWaitTime, int lockAborted);
+
+ static int thread_id_occurance_in_locked_locks_map(size_t threadId);
+
+ static void wait_until_all_locks_are_released(bool);
+
+ //--------------------------------------------------------------------------
+ // deferred updating locking methods
+ //--------------------------------------------------------------------------
+ static int def_full_pthread_lock_mutex(Mutex *mutex);
+ static int def_full_pthread_trylock_mutex(Mutex *mutex);
+ static int def_full_pthread_unlock_mutex(Mutex *mutex);
+
+ static int def_tm_conflicting_lock_pthread_lock_mutex(Mutex *mutex);
+ static int def_tm_conflicting_lock_pthread_trylock_mutex(Mutex *mutex);
+ static int def_tm_conflicting_lock_pthread_unlock_mutex(Mutex *mutex);
+
+ static int def_tx_conflicting_lock_pthread_lock_mutex(Mutex *mutex);
+ static int def_tx_conflicting_lock_pthread_trylock_mutex(Mutex *mutex);
+ static int def_tx_conflicting_lock_pthread_unlock_mutex(Mutex *mutex);
+
+ //--------------------------------------------------------------------------
+ // direct updating locking methods
+ //--------------------------------------------------------------------------
+ static int dir_full_pthread_lock_mutex(Mutex *mutex);
+ static int dir_full_pthread_trylock_mutex(Mutex *mutex);
+ static int dir_full_pthread_unlock_mutex(Mutex *mutex);
+
+ static int dir_tm_conflicting_lock_pthread_lock_mutex(Mutex *mutex);
+ static int dir_tm_conflicting_lock_pthread_trylock_mutex(Mutex *mutex);
+ static int dir_tm_conflicting_lock_pthread_unlock_mutex(Mutex *mutex);
+
+ static int dir_tx_conflicting_lock_pthread_lock_mutex(Mutex *mutex);
+ static int dir_tx_conflicting_lock_pthread_trylock_mutex(Mutex *mutex);
+ static int dir_tx_conflicting_lock_pthread_unlock_mutex(Mutex *mutex);
+
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ static DeletionBuffer deletionBuffer_;
+ static std::ofstream logFile_;
+
+ static MutexSet tmConflictingLocks_;
+ static MutexSet latmLockedLocks_;
+ static MutexThreadSetMap latmLockedLocksAndThreadIdsMap_;
+ static MutexThreadMap latmLockedLocksOfThreadMap_;
+ static LatmType eLatmType_;
+ static InflightTxes transactionsInFlight_;
+
+ static Mutex deletionBufferMutex_;
+ static Mutex transactionMutex_;
+ static Mutex transactionsInFlightMutex_;
+ static Mutex latmMutex_;
+ static pthread_mutexattr_t transactionMutexAttribute_;
+
+ static bool initialized_;
+ static bool directLateWriteReadConflict_;
+ static bool dynamicPriorityAssignment_;
+ static bool usingMoveSemantics_;
+ static transaction_bookkeeping bookkeeping_;
+ static base_contention_manager *cm_;
+
+#if PERFORMING_LATM
+ static ThreadMutexSetContainer threadConflictingMutexes_;
+ static ThreadMutexSetContainer threadObtainedLocks_;
+ static ThreadMutexSetContainer threadCurrentlyLockedLocks_;
+#endif
+
+ static ThreadMutexContainer threadMutexes_;
+ static ThreadBoolContainer threadBlockedLists_;
+
+#ifndef USE_SINGLE_THREAD_CONTEXT_MAP
+ static ThreadWriteContainer threadWriteLists_;
+ static ThreadReadContainer threadReadLists_;
+ static ThreadBloomFilterList threadBloomFilterLists_;
+ static ThreadBloomFilterList threadWBloomFilterLists_;
+ static ThreadMemoryContainerList threadNewMemoryLists_;
+ static ThreadMemoryContainerList threadDeletedMemoryLists_;
+ static ThreadTxTypeContainer threadTxTypeLists_;
+ static ThreadBoolContainer threadForcedToAbortLists_;
+#else
+ static ThreadMemContainer threadMemContainer_;
+#endif
+
+ //--------------------------------------------------------------------------
+ static bool directUpdating_;
+ static size_t globalClock_;
+ static size_t stalls_;
+
+ //--------------------------------------------------------------------------
+ // must be mutable because in cases where reads collide with other txs
+ // modifying the same memory location in-flight, we add that memory
+ // location ourselves to the modifiedList for us since performing a read
+ // when another in-flight transaction is modifying the same location can
+ // cause us to end up reading stale data if the other tx commits with
+ // its newly modified data that we were reading.
+ //
+ // thus, we promote our read to a write and therefore need this map to
+ // be mutable - see the read() interface for more documentation
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // ******** WARNING ******** MOVING threadId_ WILL BREAK TRANSACTION.
+ // threadId_ MUST ALWAYS THE FIRST MEMBER OF THIS CLASS. THE MEMBER
+ // INITIALIZATION IS ORDER DEPENDENT UPON threadId_!!
+ // ******** WARNING ******** MOVING threadId_ WILL BREAK TRANSACTION
+ //--------------------------------------------------------------------------
+ size_t threadId_;
+
+
+#ifdef USE_SINGLE_THREAD_CONTEXT_MAP
+ tx_context &context_;
+#endif
+ //--------------------------------------------------------------------------
+ // ******** WARNING ******** MOVING threadId_ WILL BREAK TRANSACTION.
+ // threadId_ MUST ALWAYS THE FIRST MEMBER OF THIS CLASS. THE MEMBER
+ // INITIALIZATION IS ORDER DEPENDENT UPON threadId_!!
+ // ******** WARNING ******** MOVING threadId_ WILL BREAK TRANSACTION
+ //--------------------------------------------------------------------------
+ mutable WriteContainer *writeListRef_;
+#ifndef DISABLE_READ_SETS
+ mutable ReadContainer &readListRef_;
+#endif
+ mutable bloom_filter *bloomRef_;
+#if PERFORMING_WRITE_BLOOM
+ mutable bloom_filter *wbloomRef_;
+ //mutable bit_vector &sm_wbv_;
+#endif
+
+ MemoryContainerList *newMemoryListRef_;
+ MemoryContainerList *deletedMemoryListRef_;
+ TxType *txTypeRef_;
+
+#if USING_SHARED_FORCED_TO_ABORT
+ int *forcedToAbortRef_;
+#else
+ int forcedToAbortRef_;
+#endif
+
+ Mutex *mutexRef_;
+
+#if PERFORMING_LATM
+ int &blockedRef_;
+#endif
+
+#if PERFORMING_LATM
+#if USING_TRANSACTION_SPECIFIC_LATM
+ MutexSet &conflictingMutexRef_;
+#endif
+ MutexSet &obtainedLocksRef_;
+ MutexSet &currentlyLockedLocksRef_;
+#endif
+ int hasMutex_;
+ mutable size_t priority_;
+ transaction_state state_;
+ size_t reads_;
+
+ mutable size_t startTime_;
+};
+
+#if 0
+
+template <>
+inline int transaction::lock<Mutex> (Mutex &lock) { return transaction::pthread_lock(&lock); }
+
+template <>
+inline int transaction::lock<Mutex*> (Mutex *lock) { return transaction::pthread_lock(lock); }
+
+template <>
+inline int transaction::trylock<Mutex> (Mutex &lock) { return transaction::pthread_trylock(&lock); }
+
+template <>
+inline int transaction::trylock<Mutex*> (Mutex *lock) { return transaction::pthread_trylock(lock); }
+
+template <>
+inline int transaction::unlock<Mutex> (Mutex &lock) { return transaction::pthread_unlock(&lock); }
+
+template <>
+inline int transaction::unlock<Mutex*> (Mutex *lock) { return transaction::pthread_unlock(lock); }
+
+#endif
+
+//---------------------------------------------------------------------------
+// do not remove if (). It is necessary a necessary fix for compilers
+// that do not destroy index variables of for loops. In addition, the
+// rand()+1 check is necessarily complex so smart compilers can't
+// optimize the if away
+//---------------------------------------------------------------------------
+#define use_atomic(T) if (0 != rand()+1) for (transaction T; !T.committed() && T.restart(); T.end())
+#define try_atomic(T) if (0 != rand()+1) for (transaction T; !T.committed() && T.restart(); T.no_throw_end()) try
+#define atomic(T) if (0 != rand()+1) for (transaction T; !T.committed() && T.check_throw_before_restart() && T.restart_if_not_inflight(); T.no_throw_end()) try
+
+
+
+#define catch_before_retry(E) catch (aborted_tx &E)
+#define before_retry catch (aborted_tx &)
+#define end_atom catch (aborted_tx &) {}
+
+} // core namespace
+}
+#include <boost/stm/detail/transaction_impl.hpp>
+#include <boost/stm/detail/latm_general_impl.hpp>
+#include <boost/stm/detail/auto_lock.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+#endif // TRANSACTION_H
+
+

Added: sandbox/stm/doc/html/boostbook.css
==============================================================================
--- (empty file)
+++ sandbox/stm/doc/html/boostbook.css 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,538 @@
+/*=============================================================================
+ Copyright (c) 2004 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+
+/*=============================================================================
+ Body defaults
+=============================================================================*/
+
+ body
+ {
+ margin: 1em;
+ font-family: sans-serif;
+ }
+
+/*=============================================================================
+ Paragraphs
+=============================================================================*/
+
+ p
+ {
+ text-align: left;
+ font-size: 10pt;
+ line-height: 1.15;
+ }
+
+/*=============================================================================
+ Program listings
+=============================================================================*/
+
+ /* Code on paragraphs */
+ p tt.computeroutput
+ {
+ font-size: 10pt;
+ }
+
+ pre.synopsis
+ {
+ font-size: 10pt;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ .programlisting,
+ .screen
+ {
+ font-size: 10pt;
+ display: block;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+/*=============================================================================
+ Headings
+=============================================================================*/
+
+ h1, h2, h3, h4, h5, h6
+ {
+ text-align: left;
+ margin: 1em 0em 0.5em 0em;
+ font-weight: bold;
+ }
+
+ h1 { font: 140% }
+ h2 { font: bold 140% }
+ h3 { font: bold 130% }
+ h4 { font: bold 120% }
+ h5 { font: italic 110% }
+ h6 { font: italic 100% }
+
+ /* Top page titles */
+ title,
+ h1.title,
+ h2.title
+ h3.title,
+ h4.title,
+ h5.title,
+ h6.title,
+ .refentrytitle
+ {
+ font-weight: bold;
+ margin-bottom: 1pc;
+ }
+
+ h1.title { font-size: 140% }
+ h2.title { font-size: 140% }
+ h3.title { font-size: 130% }
+ h4.title { font-size: 120% }
+ h5.title { font-size: 110% }
+ h6.title { font-size: 100% }
+
+ .section h1
+ {
+ margin: 0em 0em 0.5em 0em;
+ font-size: 140%;
+ }
+
+ .section h2 { font-size: 140% }
+ .section h3 { font-size: 130% }
+ .section h4 { font-size: 120% }
+ .section h5 { font-size: 110% }
+ .section h6 { font-size: 100% }
+
+ /* Code on titles */
+ h1 tt.computeroutput { font-size: 140% }
+ h2 tt.computeroutput { font-size: 140% }
+ h3 tt.computeroutput { font-size: 130% }
+ h4 tt.computeroutput { font-size: 120% }
+ h5 tt.computeroutput { font-size: 110% }
+ h6 tt.computeroutput { font-size: 100% }
+
+/*=============================================================================
+ Author
+=============================================================================*/
+
+ h3.author
+ {
+ font-size: 100%
+ }
+
+/*=============================================================================
+ Lists
+=============================================================================*/
+
+ li
+ {
+ font-size: 10pt;
+ line-height: 1.3;
+ }
+
+ /* Unordered lists */
+ ul
+ {
+ text-align: left;
+ }
+
+ /* Ordered lists */
+ ol
+ {
+ text-align: left;
+ }
+
+/*=============================================================================
+ Links
+=============================================================================*/
+
+ a
+ {
+ text-decoration: none; /* no underline */
+ }
+
+ a:hover
+ {
+ text-decoration: underline;
+ }
+
+/*=============================================================================
+ Spirit style navigation
+=============================================================================*/
+
+ .spirit-nav
+ {
+ text-align: right;
+ }
+
+ .spirit-nav a
+ {
+ color: white;
+ padding-left: 0.5em;
+ }
+
+ .spirit-nav img
+ {
+ border-width: 0px;
+ }
+
+/*=============================================================================
+ Table of contents
+=============================================================================*/
+
+ .toc
+ {
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.1pc 1pc 0.1pc 1pc;
+ font-size: 10pt;
+ line-height: 1.15;
+ }
+
+ .toc-main
+ {
+ width: 600;
+ text-align: center;
+ margin: 1pc 1pc 1pc 10%;
+ padding: 2pc 1pc 3pc 1pc;
+ line-height: 0.1;
+ }
+
+ .boost-toc
+ {
+ float: right;
+ padding: 0.5pc;
+ }
+
+/*=============================================================================
+ Tables
+=============================================================================*/
+
+ .table-title,
+ div.table p.title
+ {
+ margin-left: 4%;
+ padding-right: 0.5em;
+ padding-left: 0.5em;
+ }
+
+ .informaltable table,
+ .table table
+ {
+ width: 92%;
+ margin-left: 4%;
+ margin-right: 4%;
+ }
+
+ div.informaltable table,
+ div.table table
+ {
+ padding: 4px;
+ }
+
+ /* Table Cells */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ padding: 0.5em;
+ text-align: left;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ padding: 0.5em 0.5em 0.5em 0.5em;
+ border: 1pt solid white;
+ font-size: 120%;
+ }
+
+/*=============================================================================
+ Blurbs
+=============================================================================*/
+
+ div.note,
+ div.tip,
+ div.important,
+ div.caution,
+ div.warning,
+ p.blurb
+ {
+ font-size: 10pt;
+ line-height: 1.2;
+ display: block;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ p.blurb img
+ {
+ padding: 1pt;
+ }
+
+/*=============================================================================
+ Variable Lists
+=============================================================================*/
+
+ span.term
+ {
+ font-weight: bold;
+ font-size: 10pt;
+ }
+
+ div.variablelist table tbody tr td
+ {
+ text-align: left;
+ vertical-align: top;
+ padding: 0em 2em 0em 0em;
+ font-size: 10pt;
+ }
+
+ div.variablelist table tbody tr td p
+ {
+ margin: 0em 0em 0.5em 0em;
+ }
+
+ /* Make the terms in definition lists bold */
+ div.variablelist dl dt
+ {
+ font-weight: bold;
+ font-size: 10pt;
+ }
+
+ div.variablelist dl dd
+ {
+ margin: 1em 0em 1em 2em;
+ font-size: 10pt;
+ }
+
+/*=============================================================================
+ Misc
+=============================================================================*/
+
+ /* Title of books and articles in bibliographies */
+ span.title
+ {
+ font-style: italic;
+ }
+
+ span.underline
+ {
+ text-decoration: underline;
+ }
+
+ span.strikethrough
+ {
+ text-decoration: line-through;
+ }
+
+ /* Copyright, Legal Notice */
+ div div.legalnotice p
+ {
+ font-size: 8pt;
+ text-align: left
+ }
+
+/*=============================================================================
+ Colors
+=============================================================================*/
+
+ @media screen
+ {
+ /* Links */
+ a
+ {
+ color: #0C7445;
+ }
+
+ a:visited
+ {
+ color: #663974;
+ }
+
+ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
+ h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
+ h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
+ {
+ text-decoration: none; /* no underline */
+ color: #000000;
+ }
+
+ /* Syntax Highlighting */
+ .keyword { color: #0000AA; }
+ .identifier { color: #000000; }
+ .special { color: #707070; }
+ .preprocessor { color: #402080; }
+ .char { color: teal; }
+ .comment { color: #800000; }
+ .string { color: teal; }
+ .number { color: teal; }
+ .white_bkd { background-color: #E8FBE9; }
+ .dk_grey_bkd { background-color: #A0DAAC; }
+
+ /* Copyright, Legal Notice */
+ .copyright
+ {
+ color: #666666;
+ font-size: small;
+ }
+
+ div div.legalnotice p
+ {
+ color: #666666;
+ }
+
+ /* Program listing */
+ pre.synopsis
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ .programlisting,
+ .screen
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ /* Blurbs */
+ div.note,
+ div.tip,
+ div.important,
+ div.caution,
+ div.warning,
+ p.blurb
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ /* Table of contents */
+ .toc-main
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+
+ /* Tables */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ border: 1px solid #DCDCDC;
+ background-color: #FAFFFB;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ background-color: #E3F9E4;
+ border: 1px solid #DCDCDC;
+ }
+
+ /* Misc */
+ span.highlight
+ {
+ color: #00A000;
+ }
+ }
+
+ @media print
+ {
+ /* Links */
+ a
+ {
+ color: black;
+ }
+
+ a:visited
+ {
+ color: black;
+ }
+
+ .spirit-nav
+ {
+ display: none;
+ }
+
+ /* Program listing */
+ pre.synopsis
+ {
+ border: 1px solid gray;
+ background-color: #FAFFFB;
+ }
+
+ .programlisting,
+ .screen
+ {
+ border: 1px solid gray;
+ background-color: #FAFFFB;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ /* Table of contents */
+ .toc-main
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ .informaltable table,
+ .table table
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ border-collapse: collapse;
+ background-color: #FAFFFB;
+ }
+
+ /* Tables */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ border: 1px solid #DCDCDC;
+ background-color: #FAFFFB;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ border: 1px solid #DCDCDC;
+ background-color: #FAFFFB;
+ }
+
+ /* Misc */
+ span.highlight
+ {
+ font-weight: bold;
+ }
+ }

Added: sandbox/stm/doc/html/images/Thumbs.db
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/alert.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/blank.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/1.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/10.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/11.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/12.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/13.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/14.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/15.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/2.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/3.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/4.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/5.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/6.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/7.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/8.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/9.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/callouts/Thumbs.db
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/caution.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/draft.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/home.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/important.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/next.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/next_disabled.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/note.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/prev.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/prev_disabled.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/smiley.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/tip.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/toc-blank.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/toc-minus.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/toc-plus.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/up.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/up_disabled.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/images/warning.png
==============================================================================
Binary file. No diff available.

Added: sandbox/stm/doc/html/reference.css
==============================================================================
--- (empty file)
+++ sandbox/stm/doc/html/reference.css 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,13 @@
+/*=============================================================================
+ Copyright (c) 2004 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+PRE.synopsis {
+ background-color: #e0ffff;
+ border: thin solid blue;
+ padding: 1em
+}

Added: sandbox/stm/libs/stm/build/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/build/Jamfile.v2 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,218 @@
+# (C) Copyright William E. Kempf 2001.
+# (C) Copyright 2007 Anthony Williams.
+# (C) Copyright 2008-2009 Vicente Botet Escriba.
+# (C) Copyright 2008-2009 Justin E. Gottchlich.
+# 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)
+
+#########################################################################
+# The boost threading library can be built on top of different API's
+# Currently this is the win32 API and the pthreads API.
+# Pthread is native on unix variants.
+# To get pthread on windows you need the pthread win32 library
+# http://sourceware.org/pthreads-win32 which is available under LGPL.
+#
+# You need to provide the include path and lib path in the variables
+# PTW32_INCLUDE and PTW32_LIB respectively. You can specify these
+# paths in site-config.jam, user-config.jam or in the environment.
+# A new feature is provided to request a specific API:
+# <threadapi>win32 and <threadapi)pthread.
+#
+# The naming of the resulting libraries is mostly the same for the
+# variant native to the build platform, i.e.
+# boost_thread and the boost specific tagging.
+# For the library variant that is not native on the build platform
+# an additional tag is applied:
+# boost_thread_pthread for the pthread variant on windows, and
+# boost_thread_win32 for the win32 variant (likely when built on cygwin).
+#
+# To request the pthread variant on windows, from boost root you would
+# say e.g:
+# bjam msvc-8.0 --with-thread install threadapi=pthread
+#########################################################################
+
+import os ;
+import feature ;
+import indirect ;
+import path ;
+
+project boost/STM
+ : source-location ../src
+ : requirements
+ <threading>multi
+# <target-os>cygwin
+# <interthreadapi>pthread
+ <variant>debug
+# <define>BOOST_THREAD_HAS_THREAD_ATTR
+
+ <include>../../..
+ <include>../../../../../boost_1_38_0
+ <link>static:<define>BOOST_INTERTHREADS_BUILD_LIB=1
+ <link>shared:<define>BOOST_INTERTHREADS_BUILD_DLL=1
+# <link>shared:<library>/boost/thread//boost_thread/<link>shared
+ -<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
+ <tag>@$(__name__).tag
+# <library>$(BOOST_ROOT)/libs/thread/build//boost_thread/<link>shared
+ : default-build <threading>multi
+ ;
+
+local rule default_interthreadapi ( )
+{
+ local api = pthread ;
+ if [ os.name ] = "NT" { api = win32 ; }
+ return $(api) ;
+}
+
+feature.feature interthreadapi : pthread win32 : propagated ;
+feature.set-default interthreadapi : [ default_interthreadapi ] ;
+
+rule tag ( name : type ? : property-set )
+{
+ local result = $(name) ;
+
+ if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
+ {
+ local api = [ $(property-set).get <interthreadapi> ] ;
+
+ # non native api gets additional tag
+ if $(api) != [ default_interthreadapi ] {
+ result = $(result)_$(api) ;
+ }
+ }
+
+ # forward to the boost tagging rule
+ return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
+ $(result) : $(type) : $(property-set) ] ;
+}
+
+rule win32_pthread_paths ( properties * )
+{
+ local result ;
+ local PTW32_INCLUDE ;
+ local PTW32_LIB ;
+ PTW32_INCLUDE = [ modules.peek : PTW32_INCLUDE ] ;
+ PTW32_LIB = [ modules.peek : PTW32_LIB ] ;
+ PTW32_INCLUDE ?= [ modules.peek user-config : PTW32_INCLUDE ] ;
+ PTW32_LIB ?= [ modules.peek user-config : PTW32_LIB ] ;
+ PTW32_INCLUDE ?= [ modules.peek site-config : PTW32_INCLUDE ] ;
+ PTW32_LIB ?= [ modules.peek site-config : PTW32_LIB ] ;
+
+ if ! ( $(PTW32_INCLUDE) && $(PTW32_LIB) )
+ {
+ if ! $(.notified)
+ {
+ echo "************************************************************" ;
+ echo "Trying to build Boost.InterThread with pthread support." ;
+ echo "If you need pthread you should specify the paths." ;
+ echo "You can specify them in site-config.jam, user-config.jam" ;
+ echo "or in the environment." ;
+ echo "For example:" ;
+ echo "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
+ echo "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib" ;
+ echo "************************************************************" ;
+ .notified = true ;
+ }
+ }
+ else
+ {
+ local include_path = [ path.make $(PTW32_INCLUDE) ] ;
+ local lib_path = [ path.make $(PTW32_LIB) ] ;
+ local libname = pthread ;
+ if <toolset>msvc in $(properties)
+ {
+ libname = $(libname)VC2.lib ;
+ }
+ if <toolset>gcc in $(properties)
+ {
+ libname = lib$(libname)GC2.a ;
+ }
+ lib_path = [ path.glob $(lib_path) : $(libname) ] ;
+ if ! $(lib_path)
+ {
+ if ! $(.notified)
+ {
+ echo "************************************************************" ;
+ echo "Trying to build Boost.InterThread with pthread support." ;
+ echo "But the library" $(libname) "could not be found in path" ;
+ echo $(PTW32_LIB) ;
+ echo "************************************************************" ;
+ .notified = true ;
+ }
+ }
+ else
+ {
+ result += <include>$(include_path) ;
+ result += <library>$(lib_path) ;
+ }
+ }
+ return $(result) ;
+}
+
+rule usage-requirements ( properties * )
+{
+ local result ;
+ if <interthreadapi>pthread in $(properties)
+ {
+ result += <define>BOOST_THREAD_POSIX ;
+ if <target-os>windows in $(properties)
+ {
+ result += [ win32_pthread_paths $(properties) ] ;
+ # TODO: What is for static linking? Is the <library> also needed
+ # in that case?
+ }
+ }
+ return $(result) ;
+}
+
+rule requirements ( properties * )
+{
+ local result ;
+
+ if <interthreadapi>pthread in $(properties)
+ {
+ result += <define>BOOST_THREAD_POSIX ;
+ if <target-os>windows in $(properties)
+ {
+ local paths = [ win32_pthread_paths $(properties) ] ;
+ if $(paths)
+ {
+ result += $(paths) ;
+ }
+ else
+ {
+ result = <build>no ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+alias interthreads_sources
+ : ## win32 sources ##
+ : ## requirements ##
+ <interthreadapi>win32
+ ;
+
+alias interthreads_sources
+ : ## pthread sources ##
+ : ## requirements ##
+ <interthreadapi>pthread
+ ;
+
+explicit interthreads_sources ;
+
+
+
+static-lib boost_STM
+ : bloom_filter.cpp contention_manager.cpp transaction.cpp interthreads_sources
+# ../../../../libs/thread/build//boost_thread
+ : <conditional>@requirements
+ :
+ : <link>shared:<define>BOOST_INTERTHREADS_USE_DLL=1
+ <link>static:<define>BOOST_INTERTHREADS_USE_LIB=1
+# <link>static:<library>/boost/thread//boost_thread/<link>static
+ <conditional>@usage-requirements
+
+ ;
+

Added: sandbox/stm/libs/stm/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/Jamfile.v2 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,73 @@
+# Boost.LUID library documentation Jamfile ---------------------------------
+#
+# Copyright Justin E. Gottchlich 2009.
+# Copyright Vicente J. Botet Escriba 2009.
+# Use, modification and
+# distribution is subject to 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 for updates, documentation, and revision history.
+
+#import doxygen ;
+import quickbook ;
+
+#doxygen autodoc
+# :
+# [ glob ../../../boost/stm/*.hpp ]
+# :
+# <doxygen:param>EXTRACT_ALL=NO
+# <doxygen:param>HIDE_UNDOC_MEMBERS=YES
+# <doxygen:param>EXTRACT_PRIVATE=NO
+# <doxygen:param>EXPAND_ONLY_PREDEF=YES
+# <doxygen:param>PREDEFINED=BOOST_INTERPROCESS_DOXYGEN_INVOKED
+# <xsl:param>"boost.doxygen.reftitle=Boost.Interprocess Reference"
+# ;
+
+xml stm : stm.qbk ;
+
+boostbook standalone
+ :
+ stm
+ :
+ # HTML options first:
+ # Use graphics not text for navigation:
+ <xsl:param>navig.graphics=1
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=2
+ # Don't put the first section on the same page as the TOC:
+ <xsl:param>chunk.first.sections=1
+ # How far down sections get TOC's
+ <xsl:param>toc.section.depth=4
+ # Max depth in each TOC:
+ <xsl:param>toc.max.depth=2
+ # How far down we go with TOC's
+ <xsl:param>generate.section.toc.level=10
+ # Path for links to Boost:
+ <xsl:param>boost.root=../../../..
+ # Path for libraries index:
+ <xsl:param>boost.libraries=../../../../libs/libraries.htm
+ # Use the main Boost stylesheet:
+ <xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
+
+ # PDF Options:
+ # TOC Generation: this is needed for FOP-0.9 and later:
+ #<xsl:param>fop1.extensions=1
+ # Or enable this if you're using XEP:
+ <xsl:param>xep.extensions=1
+ # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
+ <xsl:param>fop.extensions=0
+ # No indent on body text:
+ <xsl:param>body.start.indent=0pt
+ # Margin size:
+ <xsl:param>page.margin.inner=0.5in
+ # Margin size:
+ <xsl:param>page.margin.outer=0.5in
+ # Yes, we want graphics for admonishments:
+ <xsl:param>admon.graphics=1
+ # Set this one for PDF generation *only*:
+ # default pnd graphics are awful in PDF form,
+ # better use SVG's instead:
+ <format>pdf:<xsl:param>admon.graphics.extension=".svg"
+ <format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
+ ;

Added: sandbox/stm/libs/stm/doc/acknowledgements.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/acknowledgements.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,13 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+[section:acknowledgements Appendix D: Acknowledgements]
+
+TBC
+
+[endsect]

Added: sandbox/stm/libs/stm/doc/appendices.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/appendices.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,76 @@
+[/
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+[/=================]
+[section Appendices]
+[/=================]
+
+[include history.qbk]
+
+[include rationale.qbk]
+
+[include implementation.qbk]
+
+[include acknowledgements.qbk]
+
+[include tests.qbk]
+
+[include tickets.qbk]
+
+
+[/=====================================]
+[section:todo Appendix E: Future plans]
+[/=====================================]
+
+[heading Tasks to do before review]
+
+[section Boostifying STM]
+
+[heading Porting to Boost]
+* [*DONE] set boost directory architecture
+* [*DONE] name files in lowercase
+* [*DONE] Replace bit_vector by std::bitset or boost::dynamic_bitset (BOOST_STM_BLOOM_FILTER_USE_DYNAMIC_BITSET)
+* [*DONE] Add a config file with all the configuration macros
+* [*DONE] Add a stm file at the boost level including all the STM interfaces
+* [*DONE] Replace Sleep by boost::this_thread::sleep
+* [*DONE] Replace pthread_mutex by boost::mutex
+* Replace THREAD_ID by boost::thread_id
+* Replace auto_lock by boost::interthreads::unique_locker and redefine use_lock macros
+* Redifine var_auto_lock
+* Add an scoped guard for transaction::lock/unlock
+* use lock_guard when lock/unlock
+
+[heading Restructure the data]
+* Separate the data that is global, thread local or specific to a transaction.
+* Separate the interface from the implementation
+* Define access to these data using functions
+
+[heading Tests]
+* Add unit tests
+
+[heading Documentation]
+* [*DONE] Create the empty files and set the doc generation environement
+* Write the Motivation section
+* Write the Getting started section
+* Write the Tutorial section
+* Write the Example section
+* Write the Reference section
+
+[heading Other tasks]
+* Implement a generic blom_filter
+* Replace the user class transactional_object by an internal transactional_object_cache
+
+[endsect]
+
+[heading For later releases]
+
+[endsect]
+
+[endsect]
+

Added: sandbox/stm/libs/stm/doc/boostbook.css
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/boostbook.css 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,538 @@
+/*=============================================================================
+ Copyright (c) 2004 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+
+/*=============================================================================
+ Body defaults
+=============================================================================*/
+
+ body
+ {
+ margin: 1em;
+ font-family: sans-serif;
+ }
+
+/*=============================================================================
+ Paragraphs
+=============================================================================*/
+
+ p
+ {
+ text-align: left;
+ font-size: 10pt;
+ line-height: 1.15;
+ }
+
+/*=============================================================================
+ Program listings
+=============================================================================*/
+
+ /* Code on paragraphs */
+ p tt.computeroutput
+ {
+ font-size: 10pt;
+ }
+
+ pre.synopsis
+ {
+ font-size: 10pt;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ .programlisting,
+ .screen
+ {
+ font-size: 10pt;
+ display: block;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+/*=============================================================================
+ Headings
+=============================================================================*/
+
+ h1, h2, h3, h4, h5, h6
+ {
+ text-align: left;
+ margin: 1em 0em 0.5em 0em;
+ font-weight: bold;
+ }
+
+ h1 { font: 140% }
+ h2 { font: bold 140% }
+ h3 { font: bold 130% }
+ h4 { font: bold 120% }
+ h5 { font: italic 110% }
+ h6 { font: italic 100% }
+
+ /* Top page titles */
+ title,
+ h1.title,
+ h2.title
+ h3.title,
+ h4.title,
+ h5.title,
+ h6.title,
+ .refentrytitle
+ {
+ font-weight: bold;
+ margin-bottom: 1pc;
+ }
+
+ h1.title { font-size: 140% }
+ h2.title { font-size: 140% }
+ h3.title { font-size: 130% }
+ h4.title { font-size: 120% }
+ h5.title { font-size: 110% }
+ h6.title { font-size: 100% }
+
+ .section h1
+ {
+ margin: 0em 0em 0.5em 0em;
+ font-size: 140%;
+ }
+
+ .section h2 { font-size: 140% }
+ .section h3 { font-size: 130% }
+ .section h4 { font-size: 120% }
+ .section h5 { font-size: 110% }
+ .section h6 { font-size: 100% }
+
+ /* Code on titles */
+ h1 tt.computeroutput { font-size: 140% }
+ h2 tt.computeroutput { font-size: 140% }
+ h3 tt.computeroutput { font-size: 130% }
+ h4 tt.computeroutput { font-size: 120% }
+ h5 tt.computeroutput { font-size: 110% }
+ h6 tt.computeroutput { font-size: 100% }
+
+/*=============================================================================
+ Author
+=============================================================================*/
+
+ h3.author
+ {
+ font-size: 100%
+ }
+
+/*=============================================================================
+ Lists
+=============================================================================*/
+
+ li
+ {
+ font-size: 10pt;
+ line-height: 1.3;
+ }
+
+ /* Unordered lists */
+ ul
+ {
+ text-align: left;
+ }
+
+ /* Ordered lists */
+ ol
+ {
+ text-align: left;
+ }
+
+/*=============================================================================
+ Links
+=============================================================================*/
+
+ a
+ {
+ text-decoration: none; /* no underline */
+ }
+
+ a:hover
+ {
+ text-decoration: underline;
+ }
+
+/*=============================================================================
+ Spirit style navigation
+=============================================================================*/
+
+ .spirit-nav
+ {
+ text-align: right;
+ }
+
+ .spirit-nav a
+ {
+ color: white;
+ padding-left: 0.5em;
+ }
+
+ .spirit-nav img
+ {
+ border-width: 0px;
+ }
+
+/*=============================================================================
+ Table of contents
+=============================================================================*/
+
+ .toc
+ {
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.1pc 1pc 0.1pc 1pc;
+ font-size: 10pt;
+ line-height: 1.15;
+ }
+
+ .toc-main
+ {
+ width: 600;
+ text-align: center;
+ margin: 1pc 1pc 1pc 10%;
+ padding: 2pc 1pc 3pc 1pc;
+ line-height: 0.1;
+ }
+
+ .boost-toc
+ {
+ float: right;
+ padding: 0.5pc;
+ }
+
+/*=============================================================================
+ Tables
+=============================================================================*/
+
+ .table-title,
+ div.table p.title
+ {
+ margin-left: 4%;
+ padding-right: 0.5em;
+ padding-left: 0.5em;
+ }
+
+ .informaltable table,
+ .table table
+ {
+ width: 92%;
+ margin-left: 4%;
+ margin-right: 4%;
+ }
+
+ div.informaltable table,
+ div.table table
+ {
+ padding: 4px;
+ }
+
+ /* Table Cells */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ padding: 0.5em;
+ text-align: left;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ padding: 0.5em 0.5em 0.5em 0.5em;
+ border: 1pt solid white;
+ font-size: 120%;
+ }
+
+/*=============================================================================
+ Blurbs
+=============================================================================*/
+
+ div.note,
+ div.tip,
+ div.important,
+ div.caution,
+ div.warning,
+ p.blurb
+ {
+ font-size: 10pt;
+ line-height: 1.2;
+ display: block;
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+ }
+
+ p.blurb img
+ {
+ padding: 1pt;
+ }
+
+/*=============================================================================
+ Variable Lists
+=============================================================================*/
+
+ span.term
+ {
+ font-weight: bold;
+ font-size: 10pt;
+ }
+
+ div.variablelist table tbody tr td
+ {
+ text-align: left;
+ vertical-align: top;
+ padding: 0em 2em 0em 0em;
+ font-size: 10pt;
+ }
+
+ div.variablelist table tbody tr td p
+ {
+ margin: 0em 0em 0.5em 0em;
+ }
+
+ /* Make the terms in definition lists bold */
+ div.variablelist dl dt
+ {
+ font-weight: bold;
+ font-size: 10pt;
+ }
+
+ div.variablelist dl dd
+ {
+ margin: 1em 0em 1em 2em;
+ font-size: 10pt;
+ }
+
+/*=============================================================================
+ Misc
+=============================================================================*/
+
+ /* Title of books and articles in bibliographies */
+ span.title
+ {
+ font-style: italic;
+ }
+
+ span.underline
+ {
+ text-decoration: underline;
+ }
+
+ span.strikethrough
+ {
+ text-decoration: line-through;
+ }
+
+ /* Copyright, Legal Notice */
+ div div.legalnotice p
+ {
+ font-size: 8pt;
+ text-align: left
+ }
+
+/*=============================================================================
+ Colors
+=============================================================================*/
+
+ @media screen
+ {
+ /* Links */
+ a
+ {
+ color: #0C7445;
+ }
+
+ a:visited
+ {
+ color: #663974;
+ }
+
+ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
+ h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
+ h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
+ {
+ text-decoration: none; /* no underline */
+ color: #000000;
+ }
+
+ /* Syntax Highlighting */
+ .keyword { color: #0000AA; }
+ .identifier { color: #000000; }
+ .special { color: #707070; }
+ .preprocessor { color: #402080; }
+ .char { color: teal; }
+ .comment { color: #800000; }
+ .string { color: teal; }
+ .number { color: teal; }
+ .white_bkd { background-color: #E8FBE9; }
+ .dk_grey_bkd { background-color: #A0DAAC; }
+
+ /* Copyright, Legal Notice */
+ .copyright
+ {
+ color: #666666;
+ font-size: small;
+ }
+
+ div div.legalnotice p
+ {
+ color: #666666;
+ }
+
+ /* Program listing */
+ pre.synopsis
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ .programlisting,
+ .screen
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ /* Blurbs */
+ div.note,
+ div.tip,
+ div.important,
+ div.caution,
+ div.warning,
+ p.blurb
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ /* Table of contents */
+ .toc-main
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+
+ /* Tables */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ border: 1px solid #DCDCDC;
+ background-color: #FAFFFB;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ background-color: #E3F9E4;
+ border: 1px solid #DCDCDC;
+ }
+
+ /* Misc */
+ span.highlight
+ {
+ color: #00A000;
+ }
+ }
+
+ @media print
+ {
+ /* Links */
+ a
+ {
+ color: black;
+ }
+
+ a:visited
+ {
+ color: black;
+ }
+
+ .spirit-nav
+ {
+ display: none;
+ }
+
+ /* Program listing */
+ pre.synopsis
+ {
+ border: 1px solid gray;
+ background-color: #FAFFFB;
+ }
+
+ .programlisting,
+ .screen
+ {
+ border: 1px solid gray;
+ background-color: #FAFFFB;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ /* Table of contents */
+ .toc-main
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ background-color: #FAFFFB;
+ }
+
+ .informaltable table,
+ .table table
+ {
+ border: 1px solid #DCDCDC;
+ border-bottom: 3px solid #9D9D9D;
+ border-right: 3px solid #9D9D9D;
+ border-collapse: collapse;
+ background-color: #FAFFFB;
+ }
+
+ /* Tables */
+ div.informaltable table tr td,
+ div.table table tr td
+ {
+ border: 1px solid #DCDCDC;
+ background-color: #FAFFFB;
+ }
+
+ div.informaltable table tr th,
+ div.table table tr th
+ {
+ border: 1px solid #DCDCDC;
+ background-color: #FAFFFB;
+ }
+
+ /* Misc */
+ span.highlight
+ {
+ font-weight: bold;
+ }
+ }

Added: sandbox/stm/libs/stm/doc/case_studies.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/case_studies.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,16 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+[/============================]
+[section Examples]
+[/============================]
+
+This section includes complete examples using the library.
+
+
+[endsect]
\ No newline at end of file

Added: sandbox/stm/libs/stm/doc/getting_started.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/getting_started.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,26 @@
+[/
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+
+[/======================================]
+[section:getting_started Getting Started]
+[/======================================]
+
+[include installation.qbk]
+
+[/=============================]
+[section Hello World! ]
+[/=============================]
+
+
+[endsect]
+
+[endsect]
+
+

Added: sandbox/stm/libs/stm/doc/history.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/history.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,27 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+[section:changes Appendix A: History]
+
+[heading [*Version 0.1, XX YY, 2009] ['Announcement of STM]]
+
+[*Features:]
+
+*
+
+[*Toolsets:]
+
+* Tested with static library.
+* Tested on cygwin gcc 3.4.6.
+
+[heading [*Tickets:]]
+
+[*v0.1#1: .]
+
+
+[endsect]

Added: sandbox/stm/libs/stm/doc/implementation.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/implementation.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,15 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+[section:implementation Appendix C: Implementation Notes]
+
+
+TBC
+
+
+[endsect]

Added: sandbox/stm/libs/stm/doc/index.html
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/index.html 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,9 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=html/index.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+../../doc/html/stm.html
+</body>
+</html>

Added: sandbox/stm/libs/stm/doc/installation.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/installation.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,82 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+
+[/======================================]
+[section:install Installing STM]
+[/======================================]
+
+[/=================================]
+[heading Getting Boost.STM]
+[/=================================]
+
+You can get the last stable release of Boost.STM by downloading [^stm.zip] from the
+[@http://www.boost-consulting.com/vault/index.php?directory=Concurrent%20Programming Boost Vault]
+
+You can also access the latest (unstable?) state from the [@https://svn.boost.org/svn/boost/sandbox/stm Boost Sandbox].
+
+[/=================================]
+[heading Building Boost.STM]
+[/=================================]
+
+Boost.STM is not a header only library. You need to compile it before use.
+
+ cd libs/stm/build
+ bjam
+
+[/=========================]
+[heading Requirements]
+[/=========================]
+
+[*Boost.STM] depends on Boost. You must use either Boost version 1.38.x
+or the version in SVN trunk (even if Boost version 1.35.x should works also).
+In particular, [*Boost.STM] depends on:
+
+
+[variablelist
+[
+ [[@http://www.boost.org/libs/dynamic_bitset [*Boost.DynamicBitset]]]
+ [dynamic_bitsets]
+]
+[
+ [[@http://www.boost.org/libs/synchro [*Boost.Synchro]]]
+ [synchronization primitives]
+]
+[
+ [[@http://www.boost.org/libs/thread [*Boost.Thread]]]
+ [threads and synchronization primitives]
+]
+]
+
+
+[/========================]
+[heading Exceptions safety]
+[/========================]
+
+All functions in the library are exception-neutral and provide strong guarantee of exception safety as long as
+the underlying parameters provide it.
+
+[/====================]
+[heading Thread safety]
+[/====================]
+
+All functions in the library are thread-unsafe except when noted explicitly.
+
+
+[/=======================]
+[heading Tested compilers]
+[/=======================]
+
+Currently, [*Boost.STM] has been tested in the following compilers/platforms:
+
+* GCC 3.4.4 Cygwin
+
+[note Please send any questions, comments and bug reports to boost <at> lists <dot> boost <dot> org.]
+
+[endsect]
+

Added: sandbox/stm/libs/stm/doc/introduction.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/introduction.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,14 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+[section:intro Introduction]
+
+
+
+
+[endsect]
\ No newline at end of file

Added: sandbox/stm/libs/stm/doc/introduction_traits_and_concepts.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/introduction_traits_and_concepts.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,106 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+
+[section:uniform Using Thread, Interprocess and Null synchronization mechanisms uniformly]
+
+One of the problems when doing multi threaded application with Boost.Thread and Boost.Interprocess is that the synchronization mechanism of these two libraries even if they are very close since the release 1.35, there are some minor differences that make quite difficult to design a class that can work independently with synchronization mechanisms of both libraries.
+
+This library proposes some classes that allows to write code that can be used indistinguishably with thread or interprocess synchronization mechanisms. This section is inspired on the work from [*C++ Threading - A Generic-Programming Approach] - Kevlin Henney.
+
+
+[*Lock substitutability]
+
+The Boost (C++0x) mutexes have associated a category which form a sub-typing hierarchy:
+
+ ExclusiveLockable <- SharedLockable <- UpgradeLockable
+
+[category_tag_hierarchy]
+
+Locking behavior can be further categorized as:
+
+* Re-entrancy: recursive or not
+
+ non_recursive <- recursive
+
+* Scope: whether the lock is usable with a mono-threaded, multi-threaded or multi-process context
+
+ mono_threaded <- multi_threaded <- multi_process
+
+* Lifetime: The lifetime of a lock could be associated to the process, the kernel or the file-system
+
+ process_lifetime <- kernel_lifetime <- filesystem_lifetime
+
+* Timed interface: has or not a timed interfaces
+
+ hasnt_timed_interface <- has_timed_interface
+
+Substitutability applies both to the degree of syntactic support and to the locking semantics
+
+* A recursive mutex and binary semaphore are substitutable in code written against a exclusive mutex
+* A null mutex is substitutable for all others in a single-threaded environment
+
+
+We can see these axes of variation expressed against some
+Boost synchronization mechanisms (from now bip stands for boost::interprocess):
+
+* boost::mutex: ExclusiveLock, non-recursive, has-not-timed-interface, multi-threaded
+* boost::shared_mutex: UpgradableLock, non-recursive, has-timed-interface, multi-threaded
+* bip::synchro::null_mutex: UpgradableLock, recursive, has-timed-interface, mono-threaded
+* bip::synchro::interprocess_recursive_mutex ExclusiveLock, recursive, has-timed-interface, multi_process.
+
+[*Lock traits]
+
+The Boost.Synchro library contains a set of very specific traits classes, some of them encapsulate a single trait for
+a Lockable type; for example, is a lock recursive (is_recursive), is useful in a multi threaded context
+(is_multi_threaded).
+
+The Boost.Synchro lock-traits classes share a unified design that mimic the one of Boost.TypeTraits: each class
+inherits from a the type true_type if the type has the specified property and inherits from false_type otherwise.
+
+Boost.Synchro also contains a set of classes that perform a specific transformation on a type;
+for example, they can remove a top-level const or volatile qualifier from a type.
+Each class that performs a transformation defines a single typedef-member type that is the result of the transformation.
+
+[*Finding the best lock]
+
+Inverse traits can match a lockable type based on specific traits, for a given family of lock types.
+
+It is also possible to specify characteristics to perform a reverse lookup to find a primitive lock type, either by
+exact match or by substitutable match.
+
+[*Synchronization family]
+
+A class that will do internal locking can be parameterized by the type of synchronization family needed to achieve
+the desired level of concurrency control. This depends of the usage scope of this class, and this can be
+mono_threaded, multi_threaded, multi_process.
+
+For example the thread_synchronization_family can be used to instantiate a message_queue class in a multi_threaded
+environment, all public methods will be thread-safe, with the corresponding overhead that implies. In contrast, if a
+null_synchronization_policy class is used to instantiate message_queue, all public methods will not be thread-safe,
+and there will be no additional overhead.
+
+[*Syntactic lock traits]
+
+The Boost.Synchro library also contains classes that try to remove the syntactic differences between the synchronization
+mechanisms of the Boost.Thread and Boost::Interprocess libraries. The differences identified up to now are:
+
+* The scoped locks live in a different namespace and some have different names with the same semantic. IMO these
+should be shared.
+* The exception thrown lives in a different name space and different names with the same semantic.
+* This exception should be common.
+* The move semantics (&&) are expressed with a class named differently. This class could be a good candidate of Boost
+library by itself.
+* The scoped locks can be initialized with static const variables in order to overload the constructor for lock
+adoption, lock deferral or try to lock. Even if the name of these variables is the same, these variables live in
+different namespace. It would be nice if these both libraries use the same type and the same variables
+
+I hope that these two Boost libraries will merge their synchronization mechanisms in a near future. Waiting for this merge this could serve as a temporary solution.
+
+[endsect]
+

Added: sandbox/stm/libs/stm/doc/overview.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/overview.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,54 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+[/========================]
+[section:overview Overview]
+[/========================]
+
+[/==================]
+[heading Description]
+[/==================]
+
+Transactional memory (TM) is a new parallel programming mechanism that reduces the complexity of parallel programming. TM reduces parallel programming complexity by abstracting away the necessary synchronization mechanisms from the parallel code, allowing the programmer to write parallel applications without worry of deadlocks, livelocks or race conditions.
+
+Transactional memory is an active research interest for many academic and industry institutions with many open questions about its behavior.
+
+Boost.STM is a C++ lock-based software transactional memory (STM) library. Our approach to STM is to use only native language semantics while implementing the least intrusive, most type-safe object oriented solution possible.
+
+
+[*Boost.STM] provides:
+
+
+
+[/====================================]
+[heading How to Use This Documentation]
+[/====================================]
+
+This documentation makes use of the following naming and formatting conventions.
+
+* Code is in `fixed width font` and is syntax-highlighted.
+* Replaceable text that you will need to supply is in [~italics].
+* If a name refers to a free function, it is specified like this:
+ `free_function()`; that is, it is in code font and its name is followed by `()` to indicate that it is a free function.
+* If a name refers to a class template, it is specified like this: `class_template<>`; that is, it is in code font and its name is followed by `<>` to indicate that it is a class template.
+* If a name refers to a function-like macro, it is specified like this: `MACRO()`;
+ that is, it is uppercase in code font and its name is followed by `()` to indicate that it is a function-like macro. Object-like macros appear without the trailing `()`.
+* Names that refer to /concepts/ in the generic programming sense are specified in CamelCase.
+
+[note In addition, notes such as this one specify non-essential information that provides additional background or rationale.]
+
+Finally, you can mentally add the following to any code fragments in this document:
+
+ // Include all of InterThreads
+ #include <boost/stm.hpp>
+
+ // Create a namespace aliases
+ namespace bstm = boost::stm;
+
+[include introduction.qbk]
+[endsect]

Added: sandbox/stm/libs/stm/doc/rationale.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/rationale.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,13 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+[section:rationale Appendix B: Rationale]
+
+TBC
+
+[endsect]

Added: sandbox/stm/libs/stm/doc/reference.css
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/reference.css 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,13 @@
+/*=============================================================================
+ Copyright (c) 2004 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+PRE.synopsis {
+ background-color: #e0ffff;
+ border: thin solid blue;
+ padding: 1em
+}

Added: sandbox/stm/libs/stm/doc/reference.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/reference.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,15 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+[section Reference]
+
+
+
+[endsect]
+
+

Added: sandbox/stm/libs/stm/doc/references.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/references.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,18 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+[section:ext_references References]
+[variablelist
+[
+ [ [*Toward Simplified Parallel Support in C++]]
+ [Justin E. Gottschlich & Paul J. Rogers, 2009 - Not yet published]
+]
+
+]
+
+[endsect]

Added: sandbox/stm/libs/stm/doc/stm.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/stm.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,54 @@
+[/
+ / Copyright (c) 2009 Justin E. Gottchlich
+ / Copyright (c) 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+[library Boost.STM
+ [quickbook 1.3]
+ [authors [Gottchlich, Justin E.]]
+ [authors [Botet Escriba, Vicente J.]]
+ [copyright 2009 Justin E. Gottchlich]
+ [copyright 2009 Vicente J. Botet Escriba]
+
+ [id boost.synchro]
+ [dirname synchro]
+ [purpose Concurrent synchronization utilities]
+ [license
+ 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])
+ ]
+]
+
+[/
+[section Preface]
+
+[:[".]]
+[:[*['-- ]]]
+
+[endsect]
+/]
+
+[warning STM is not a part of the Boost libraries.]
+
+[/import code.cpp]
+
+
+
+
+[include overview.qbk]
+
+[include users_guide.qbk]
+
+[include reference.qbk]
+
+[/xinclude autodoc.xml]
+
+[include case_studies.qbk]
+
+[include appendices.qbk]
+
+

Added: sandbox/stm/libs/stm/doc/tests.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/tests.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,20 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+[section Appendix E: Tests]
+
+
+[section XXX]
+[table
+ [[Name] [kind] [Description] [Result] [Ticket]]
+ [[XXX] [compile] [XXX] [Pass] [#]]
+]
+[endsect]
+
+
+[endsect]

Added: sandbox/stm/libs/stm/doc/tickets.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/tickets.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,27 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+[section Appendix F: Tickets]
+
+
+[table
+[[Kind] [Identifier] [Description] [Resolution] [State] [Tests] [Version]]
+[
+ [feature]
+ [v0.0#1]
+ [boostify]
+ [XXX]
+ [Open]
+ [See array_locker_tests]
+ [v1.0]
+]
+]
+
+
+
+[endsect]

Added: sandbox/stm/libs/stm/doc/tutorial.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/tutorial.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,16 @@
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ /
+ / 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)
+ /]
+
+
+
+[section:tutorial Tutorial]
+
+[/include tutorial/xxx.qbk]
+
+
+[endsect]

Added: sandbox/stm/libs/stm/doc/users_guide.qbk
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/doc/users_guide.qbk 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,37 @@
+[/
+[/
+ (C) Copyright 2009 Justin E. Gottchlich.
+ (C) Copyright 2009 Vicente J. Botet Escriba
+ 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).
+]
+
+[/==============================]
+[section:users_guide Users'Guide]
+[/==============================]
+
+[include getting_started.qbk]
+[include tutorial.qbk]
+[include references.qbk]
+
+
+[/=======================]
+[section:glosary Glossary]
+[/=======================]
+
+
+[variablelist
+
+[[lockable] [.]]
+[[reentrancy] [.]]
+[[lock] [.]]
+[[locker] [.]]
+[[lifetime] [.]]
+[[scope] [.]]
+[[scope] [.]]
+]
+
+[endsect]
+
+[endsect]
\ No newline at end of file

Added: sandbox/stm/libs/stm/src/bloom_filter.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/src/bloom_filter.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,14 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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/detail/bloom_filter.hpp>

Added: sandbox/stm/libs/stm/src/contention_manager.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/src/contention_manager.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,140 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <boost/stm/contention_manager.hpp>
+#include <boost/stm/transaction.hpp>
+#include <pthread.h>
+
+using namespace boost::stm;
+
+////////////////////////////////////////////////////////////////////////////
+void DefaultContentionManager::abort_on_write
+(transaction &t, base_transaction_object const &in)
+{
+ t.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+}
+
+/////////////////////////////////////////////////////////////////////////
+void DefaultContentionManager::abort_on_delete(boost::stm::transaction const &t,
+ boost::stm::base_transaction_object const &in)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////
+void DefaultContentionManager::abort_on_read
+(transaction const &constT, base_transaction_object const &in)
+{
+ transaction &t = const_cast<transaction&>(constT);
+
+ t.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+}
+
+/////////////////////////////////////////////////////////////////////////
+void DefaultContentionManager::abort_on_new(boost::stm::transaction const &constT)
+{
+ transaction &t = const_cast<transaction&>(constT);
+
+ t.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+}
+
+////////////////////////////////////////////////////////////////////////////
+bool DefaultContentionManager::allow_lock_to_abort_tx
+(int const & lockWaitTime, int const &lockAborted, bool txTryingToAbortIsIrrevocable,
+ boost::stm::transaction const &rhs)
+{
+ if (txTryingToAbortIsIrrevocable) return true;
+#ifndef DISABLE_READ_SETS
+ if ((size_t)lockWaitTime > rhs.read_set_size() + rhs.writes()) return true;
+#else
+ if ((size_t)lockWaitTime > 100 + 100 * rhs.writes()) return true;
+#endif
+
+ else return false;
+}
+
+////////////////////////////////////////////////////////////////////////////
+void DefaultContentionManager::
+perform_isolated_tx_wait_priority_promotion(boost::stm::transaction &lhs)
+{
+ lhs.raise_priority();
+}
+
+////////////////////////////////////////////////////////////////////////////
+void DefaultContentionManager::
+perform_irrevocable_tx_wait_priority_promotion(boost::stm::transaction &lhs)
+{
+ lhs.raise_priority();
+}
+
+////////////////////////////////////////////////////////////////////////////
+void ExceptAndBackOffOnAbortNoticeCM::abort_on_write
+(transaction &t, base_transaction_object const &in)
+{
+ //SLEEP(initialSleepTime_);
+ t.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+}
+
+/////////////////////////////////////////////////////////////////////////
+void ExceptAndBackOffOnAbortNoticeCM::abort_on_read
+(transaction const &constT, base_transaction_object const &in)
+{
+ transaction &t = const_cast<transaction&>(constT);
+
+ //SLEEP(initialSleepTime_);
+ t.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+}
+
+/////////////////////////////////////////////////////////////////////////
+void ExceptAndBackOffOnAbortNoticeCM::abort_on_delete
+(transaction const &constT, base_transaction_object const &in)
+{
+ transaction &t = const_cast<transaction&>(constT);
+
+ //SLEEP(initialSleepTime_);
+ t.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+}
+
+/////////////////////////////////////////////////////////////////////////
+void ExceptAndBackOffOnAbortNoticeCM::abort_on_new(boost::stm::transaction const &constT)
+{
+ transaction &t = const_cast<transaction&>(constT);
+
+ //SLEEP(initialSleepTime_);
+ t.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+}

Added: sandbox/stm/libs/stm/src/transaction.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/src/transaction.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,367 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <boost/stm/transaction.hpp>
+#include <boost/stm/contention_manager.hpp>
+#include <iostream>
+
+using namespace std;
+using namespace boost::stm;
+
+///////////////////////////////////////////////////////////////////////////////
+// Static initialization
+///////////////////////////////////////////////////////////////////////////////
+transaction::InflightTxes transaction::transactionsInFlight_;
+transaction::MutexSet transaction::latmLockedLocks_;
+transaction::MutexThreadSetMap transaction::latmLockedLocksAndThreadIdsMap_;
+transaction::MutexThreadMap transaction::latmLockedLocksOfThreadMap_;
+transaction::MutexSet transaction::tmConflictingLocks_;
+transaction::DeletionBuffer transaction::deletionBuffer_;
+
+size_t transaction::globalClock_ = 0;
+size_t transaction::stalls_ = 0;
+
+bool transaction::dynamicPriorityAssignment_ = false;
+bool transaction::directUpdating_ = false;
+bool transaction::directLateWriteReadConflict_ = false;
+bool transaction::usingMoveSemantics_ = false;
+
+pthread_mutexattr_t transaction::transactionMutexAttribute_;
+
+Mutex transaction::transactionsInFlightMutex_;
+Mutex transaction::transactionMutex_;
+Mutex transaction::deletionBufferMutex_;
+Mutex transaction::latmMutex_;
+
+boost::stm::LatmType transaction::eLatmType_ = eFullLatmProtection;
+std::ofstream transaction::logFile_;
+
+#if USE_STM_MEMORY_MANAGER
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+Mutex base_transaction_object::transactionObjectMutex_ = PTHREAD_MUTEX_INITIALIZER;
+#else
+boost::mutex base_transaction_object::transactionObjectMutex_;
+#endif
+boost::stm::MemoryPool<base_transaction_object> base_transaction_object::memory_(16384);
+#endif
+
+bool transaction::initialized_ = false;
+///////////////////////////////////////////////////////////////////////////////
+// first param = initialSleepTime (millis)
+// second param = sleepIncrease factor (initialSleepTime * factor)
+// third param = # of increases before resetting
+///////////////////////////////////////////////////////////////////////////////
+base_contention_manager *transaction::cm_ =
+ new ExceptAndBackOffOnAbortNoticeCM(0, 0, 0);
+// new DefaultContentionManager();
+// new NoExceptionOnAbortNoticeOnReadWritesCM();
+// new DefaultContentionManager();
+// new ExceptAndBackOffOnAbortNoticeCM(5, 2, 10);
+transaction_bookkeeping transaction::bookkeeping_;
+
+transaction::ThreadMutexContainer transaction::threadMutexes_;
+#if PERFORMING_LATM
+#if USING_TRANSACTION_SPECIFIC_LATM
+transaction::ThreadMutexSetContainer transaction::threadConflictingMutexes_;
+#endif
+transaction::ThreadMutexSetContainer transaction::threadObtainedLocks_;
+transaction::ThreadMutexSetContainer transaction::threadCurrentlyLockedLocks_;
+#endif
+
+#ifndef USE_SINGLE_THREAD_CONTEXT_MAP
+transaction::ThreadWriteContainer transaction::threadWriteLists_;
+transaction::ThreadReadContainer transaction::threadReadLists_;
+//transaction::ThreadEagerReadContainer transaction::threadEagerReadLists_;
+transaction::ThreadMemoryContainerList transaction::threadNewMemoryLists_;
+transaction::ThreadMemoryContainerList transaction::threadDeletedMemoryLists_;
+transaction::ThreadTxTypeContainer transaction::threadTxTypeLists_;
+transaction::ThreadBloomFilterList transaction::threadBloomFilterLists_;
+transaction::ThreadBloomFilterList transaction::threadWBloomFilterLists_;
+transaction::ThreadBoolContainer transaction::threadForcedToAbortLists_;
+#else
+transaction::ThreadMemContainer transaction::threadMemContainer_;
+#endif
+
+transaction::ThreadBoolContainer transaction::threadBlockedLists_;
+
+///////////////////////////////////////////////////////////////////////////////
+// static initialization method - must be called before the transaction
+// class is used because it initializes our transactionMutex_ which is used
+// to guarantee a consistent state of the static
+// transactionsInFlight_<transaction* > is correct.
+///////////////////////////////////////////////////////////////////////////////
+void transaction::initialize()
+{
+ base_transaction_object::alloc_size(16384);
+
+ if (initialized_) return;
+ initialized_ = true;
+
+ logFile_.open("DracoSTM_log.txt");
+
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ //pthread_mutexattr_settype(&transactionMutexAttribute_, PTHREAD_MUTEX_NORMAL);
+
+ pthread_mutex_init(&transactionMutex_, NULL);
+ pthread_mutex_init(&transactionsInFlightMutex_, NULL);
+ pthread_mutex_init(&deletionBufferMutex_, NULL);
+ pthread_mutex_init(&latmMutex_, NULL);
+
+ //pthread_mutex_init(&transactionMutex_, &transactionMutexAttribute_);
+ //pthread_mutex_init(&transactionsInFlightMutex_, &transactionMutexAttribute_);
+ //pthread_mutex_init(&latmMutex_, &transactionMutexAttribute_);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void transaction::initialize_thread()
+{
+ lock_general_access();
+
+ size_t threadId = THREAD_ID;
+
+#ifndef USE_SINGLE_THREAD_CONTEXT_MAP
+ ThreadWriteContainer::iterator writeIter = threadWriteLists_.find(threadId);
+ ThreadReadContainer::iterator readIter = threadReadLists_.find(threadId);
+ ThreadBloomFilterList::iterator bloomIter = threadBloomFilterLists_.find(threadId);
+ ThreadBloomFilterList::iterator wbloomIter = threadWBloomFilterLists_.find(threadId);
+
+ ThreadMemoryContainerList::iterator newMemIter = threadNewMemoryLists_.find(threadId);
+ ThreadMemoryContainerList::iterator deletedMemIter = threadDeletedMemoryLists_.find(threadId);
+ ThreadTxTypeContainer::iterator txTypeIter = threadTxTypeLists_.find(threadId);
+ ThreadBoolContainer::iterator abortIter = threadForcedToAbortLists_.find(threadId);
+#else
+ ThreadMemContainer::iterator memIter = threadMemContainer_.find(threadId);
+#endif
+
+ ThreadBoolContainer::iterator blockedIter = threadBlockedLists_.find(threadId);
+ ThreadMutexContainer::iterator mutexIter = threadMutexes_.find(threadId);
+
+#if PERFORMING_LATM
+#if USING_TRANSACTION_SPECIFIC_LATM
+ ThreadMutexSetContainer::iterator conflictingMutexIter = threadConflictingMutexes_.find(threadId);
+ if (threadConflictingMutexes_.end() == conflictingMutexIter)
+ {
+ threadConflictingMutexes_[threadId] = new MutexSet;
+ }
+#endif
+
+ ThreadMutexSetContainer::iterator obtainedLocksIter = threadObtainedLocks_.find(threadId);
+ if (threadObtainedLocks_.end() == obtainedLocksIter)
+ {
+ threadObtainedLocks_[threadId] = new MutexSet;
+ }
+
+ ThreadMutexSetContainer::iterator currentlyLockedLocksIter = threadCurrentlyLockedLocks_.find(threadId);
+ if (threadCurrentlyLockedLocks_.end() == currentlyLockedLocksIter)
+ {
+ threadCurrentlyLockedLocks_[threadId] = new MutexSet;
+ }
+#endif
+
+
+#ifndef USE_SINGLE_THREAD_CONTEXT_MAP
+ if (threadWriteLists_.end() == writeIter)
+ {
+ threadWriteLists_[threadId] = new WriteContainer();
+ }
+
+ if (threadReadLists_.end() == readIter)
+ {
+ threadReadLists_[threadId] = new ReadContainer();
+ }
+
+ if (threadBloomFilterLists_.end() == bloomIter)
+ {
+ bloom_filter *bf = new boost::stm::bloom_filter();
+ threadBloomFilterLists_[threadId] = bf;
+ }
+
+ if (threadWBloomFilterLists_.end() == wbloomIter)
+ {
+ bloom_filter *bf = new boost::stm::bloom_filter();
+ threadWBloomFilterLists_[threadId] = bf;
+ }
+
+
+ if (threadNewMemoryLists_.end() == newMemIter)
+ {
+ threadNewMemoryLists_[threadId] = new MemoryContainerList();
+ }
+
+ if (threadDeletedMemoryLists_.end() == deletedMemIter)
+ {
+ threadDeletedMemoryLists_[threadId] = new MemoryContainerList();
+ }
+
+ if (threadTxTypeLists_.end() == txTypeIter)
+ {
+ threadTxTypeLists_[threadId] = new TxType(eNormalTx);
+ }
+
+ if (threadForcedToAbortLists_.end() == abortIter)
+ {
+ threadForcedToAbortLists_.insert(thread_bool_pair(threadId, new int(0)));
+ }
+#else
+ if (threadMemContainer_.end() == memIter)
+ {
+ threadMemContainer_.insert(std::pair<size_t, tx_context*>(threadId, new tx_context));
+ memIter = threadMemContainer_.find(threadId);
+ memIter->second->txType = eNormalTx;
+ }
+#endif
+
+
+
+ if (threadBlockedLists_.end() == blockedIter)
+ {
+ threadBlockedLists_.insert(thread_bool_pair(threadId, new int(0)));
+ }
+
+ if (threadMutexes_.end() == mutexIter)
+ {
+ Mutex *mutex = new Mutex;
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+#if WIN32
+ *mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+ pthread_mutex_init(mutex, NULL);
+#endif
+ threadMutexes_.insert(thread_mutex_pair(threadId, mutex));
+ mutexIter = threadMutexes_.find(threadId);
+ }
+
+ unlock_general_access();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void transaction::terminate_thread()
+{
+ lock_general_access();
+ lock_inflight_access();
+
+ size_t threadId = THREAD_ID;
+
+#ifndef USE_SINGLE_THREAD_CONTEXT_MAP
+ ThreadWriteContainer::iterator writeIter = threadWriteLists_.find(threadId);
+ ThreadReadContainer::iterator readIter = threadReadLists_.find(threadId);
+ ThreadMemoryContainerList::iterator newMemIter = threadNewMemoryLists_.find(threadId);
+ ThreadMemoryContainerList::iterator deletedMemIter = threadDeletedMemoryLists_.find(threadId);
+ ThreadBloomFilterList::iterator bloomIter = threadBloomFilterLists_.find(threadId);
+ ThreadBloomFilterList::iterator wbloomIter = threadWBloomFilterLists_.find(threadId);
+ ThreadTxTypeContainer::iterator txTypeIter = threadTxTypeLists_.find(threadId);
+ ThreadBoolContainer::iterator abortIter = threadForcedToAbortLists_.find(threadId);
+
+ delete writeIter->second;
+ delete readIter->second;
+ delete bloomIter->second;
+ delete wbloomIter->second;
+
+ delete newMemIter->second;
+ delete deletedMemIter->second;
+ delete txTypeIter->second;
+ delete abortIter->second;
+
+ threadWriteLists_.erase(writeIter);
+ threadReadLists_.erase(readIter);
+ threadBloomFilterLists_.erase(bloomIter);
+ threadWBloomFilterLists_.erase(wbloomIter);
+
+ threadNewMemoryLists_.erase(newMemIter);
+ threadDeletedMemoryLists_.erase(deletedMemIter);
+ threadTxTypeLists_.erase(txTypeIter);
+ threadForcedToAbortLists_.erase(abortIter);
+#else
+ ThreadMemContainer::iterator memIter = threadMemContainer_.find(threadId);
+ delete memIter->second;
+ threadMemContainer_.erase(memIter);
+#endif
+
+ ThreadBoolContainer::iterator blockedIter = threadBlockedLists_.find(threadId);
+ delete blockedIter->second;
+ threadBlockedLists_.erase(blockedIter);
+
+ ThreadMutexContainer::iterator mutexIter = threadMutexes_.find(threadId);
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ pthread_mutex_destroy(mutexIter->second);
+#endif
+ delete mutexIter->second;
+ threadMutexes_.erase(mutexIter);
+
+#ifndef MAP_THREAD_MUTEX_CONTAINER
+ {
+ // realign all in-flight transactions so they are accessing the correct mutex
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction* t = *i;
+
+ t->mutexRef_ = threadMutexes_.find(t->threadId_)->second;
+ }
+ }
+#endif
+
+#ifndef MAP_THREAD_BOOL_CONTAINER
+ {
+ // realign all in-flight transactions so they are accessing the correct mutex
+ for (InflightTxes::iterator i = transactionsInFlight_.begin();
+ i != transactionsInFlight_.end(); ++i)
+ {
+ transaction* t = *i;
+
+ t->forcedToAbortRef_ = threadForcedToAbortLists_.find(t->threadId_)->second;
+ t->blockedRef_ = threadBlockedLists_.find(t->threadId_)->second;
+ }
+ }
+#endif
+
+#if PERFORMING_LATM
+#if USING_TRANSACTION_SPECIFIC_LATM
+ ThreadMutexSetContainer::iterator conflictingMutexIter = threadConflictingMutexes_.find(threadId);
+ delete conflictingMutexIter->second;
+ threadConflictingMutexes_.erase(conflictingMutexIter);
+#endif
+
+ ThreadMutexSetContainer::iterator obtainedLocksIter = threadObtainedLocks_.find(threadId);
+ delete obtainedLocksIter->second;
+ threadObtainedLocks_.erase(obtainedLocksIter);
+
+ ThreadMutexSetContainer::iterator currentlyLockedLocksIter = threadCurrentlyLockedLocks_.find(threadId);
+ delete currentlyLockedLocksIter->second;
+ threadCurrentlyLockedLocks_.erase(currentlyLockedLocksIter);
+#endif
+
+ unlock_inflight_access();
+ unlock_general_access();
+}
+

Added: sandbox/stm/libs/stm/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/Jamfile.v2 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,56 @@
+# (C) Copyright William E. Kempf 2001.
+# (C) Copyright 2007 Anthony Williams.
+# (C) Copyright 2008-2009 Vicente Botet Escriba.
+# 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)
+#
+# Boost.InterThreads test Jamfile
+#
+# Additional configuration variables used:
+# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
+# library should be used instead of "native" threads. This feature is
+# mostly used for testing and it's generally recommended you use the
+# native threading libraries instead. PTW32 should be set to be a list
+# of two strings, the first specifying the installation path of the
+# pthreads-win32 library and the second specifying which library
+# variant to link against (see the pthreads-win32 documentation).
+# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
+
+# bring in rules for testing
+import testing ;
+
+project
+ : requirements
+# <library>/boost/test//boost_unit_test_framework/<link>static
+# <library>/boost/thread//boost_thread/<link>static
+# <library>../../../../../boost_1_38_0/libs/test/build//boost_unit_test_framework/<link>static
+ <library>../build//boost_STM/<link>static
+# <library>../../../../../boost_1_38_0/libs/thread/build//boost_thread/<link>static
+
+ <include>.
+ <include>../../..
+ <include>../../../../../boost_1_38_0
+ <threading>multi
+# <target-os>cygwin
+# <interthreadapi>pthread
+ <variant>debug
+# <define>BOOST_THREAD_HAS_THREAD_ATTR
+
+ ;
+
+rule interthreads-run ( sources * )
+{
+ return
+ [ run $(sources) : : : <link>static ]
+# [ run $(sources) ../../../../libs/thread/build//boost_thread : : : : $(sources[1]:B)_lib ]
+ ;
+}
+
+
+
+{
+ test-suite "tests"
+ :
+ [ interthreads-run stm.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 ]
+ ;
+}

Added: sandbox/stm/libs/stm/test/globalIntArr.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/globalIntArr.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,265 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//---------------------------------------------------------------------------
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#include "transferFun.h"
+#include "main.h"
+#include "testRBTree.h"
+#include <math.h>
+#include <fstream>
+#include <sstream>
+
+//---------------------------------------------------------------------------
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+namespace nGlobalIntArr
+{
+ int const kMaxGlobalIntSize = 100000;
+}
+
+using namespace nGlobalIntArr;
+int globalCountExe = 0;
+boost::stm::native_trans<int> global_int;
+boost::stm::native_trans<int> arr[kMaxGlobalIntSize];
+
+int executionsPending = 0;
+
+int outArr[kMaxGlobalIntSize];
+
+//-------------------------------------------
+// thread 2 executes this iteratively
+//-------------------------------------------
+void sum_arr(int out[])
+{
+ transaction t;
+
+ for (;; t.raise_priority())
+ {
+ try
+ {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ out[i] = t.read(arr[i]).value();
+ }
+
+ t.end();
+ return;
+ }
+ catch (aborted_transaction_exception&)
+ { t.restart(); }
+ }
+}
+
+
+//-------------------------------------------
+// thread 3 executes this iteratively
+//-------------------------------------------
+int set_int(int v)
+{
+ transaction t;
+ t.set_priority(10 + (rand() % 90));
+
+ for (;; t.raise_priority())
+ {
+ try
+ {
+ int ret = t.read(global_int).value();
+ t.write(global_int).value() = v;
+ SLEEP(rand() % t.priority());
+ if (0 == rand() % 1000)
+ {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ outArr[i] = t.read(arr[i]).value();
+ }
+ // verify out and orig are the same
+ }
+
+ t.end();
+ return ret;
+ }
+ catch (...) { t.restart(); }
+ }
+}
+
+//-------------------------------------------
+// thread 1 executes this iteratively
+//-------------------------------------------
+void set_arr(int val, int loc)
+{
+ for (transaction t ;; t.raise_priority())
+ {
+ try
+ {
+ t.write(arr[loc]).value() = val;
+ t.end();
+ break;
+ }
+ catch (aborted_transaction_exception&)
+ { t.restart(); }
+ }
+}
+//---------------------------------------------------------------------------
+void* SetGlobalInt(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ for (;globalCountExe < kMaxArrIter;)
+ {
+ set_arr(100, rand() % kMaxArrSize);
+ }
+
+ pthread_exit(threadId);
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+void* SumGlobalArray(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ SLEEP(10);
+
+ int out[kMaxGlobalIntSize];
+ int currentIter = 0;
+ int percentDone = 0;
+
+ for (globalCountExe = 0; globalCountExe < kMaxArrIter; ++globalCountExe)
+ {
+ ++currentIter;
+
+ // output every 10% completed
+ if (currentIter >= (kMaxArrIter / 10))
+ {
+ percentDone += 10;
+ if (percentDone == 10) cout << "Percent done: " << percentDone << "% ";
+ else cout << percentDone << "% ";
+
+ if (percentDone >= 100) cout << endl;
+
+ currentIter = 0;
+ }
+
+ sum_arr(out);
+ ++executionsPending;
+ }
+
+ SLEEP(10);
+
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+void* SetGlobalIntThread3(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ for (;globalCountExe < kMaxArrIter;)
+ {
+ set_int(rand() % kMaxArrSize);
+ --executionsPending;
+ }
+
+ pthread_exit(threadId);
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+void TestGlobalIntArrayWithMultipleThreads()
+{
+ static std::vector<int> runVector;
+ int i;
+
+ for (i = 0; i < kMaxArrSize; ++i) arr[i].value() = 100;
+
+ transaction::initialize();
+ transaction::initialize_thread();
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ int const kLocalThreads = 3;
+
+ pthread_t* threads = new pthread_t[kLocalThreads];
+ int* threadId = new int[kLocalThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ endTimer = 0;
+
+ pthread_create(&threads[0], NULL, SetGlobalInt, (void *)&threadId[0]);
+ pthread_create(&threads[1], NULL, SetGlobalIntThread3, (void *)&threadId[1]);
+
+ int mainThreadId = kLocalThreads-1;
+
+ startTimer = time(NULL);
+ SumGlobalArray((void*)&mainThreadId);
+ endTimer = time(NULL);
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << transaction::consistency_checking_string() << " ";
+ cout << "(array size, copy iters, time, commits, priority aborts, total aborts)\t";
+ cout << kMaxArrSize << "\t" << kMaxArrIter << "\t";
+ cout << averageRunTime << "\t" << transaction::bookkeeping().commits() << "\t";
+ cout << transaction::bookkeeping().abortPermDenied() << "\t";
+ cout << transaction::bookkeeping().totalAborts() << endl;
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "rbTreeFun_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ //delete threads;
+ //delete threadId;
+}
+

Added: sandbox/stm/libs/stm/test/globalIntArr.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/globalIntArr.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,22 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef GLOBAL_INT_ARR_H
+#define GLOBAL_INT_ARR_H
+
+#include <ostream>
+
+void TestGlobalIntArrayWithMultipleThreads();
+
+#endif //TRANSFER_FUN_H
+

Added: sandbox/stm/libs/stm/test/irrevocableInt.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/irrevocableInt.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,166 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <iostream>
+#include "irrevocableInt.h"
+#include <boost/stm/transaction.hpp>
+#include "main.h"
+
+static boost::stm::native_trans<int> gInt;
+static boost::stm::native_trans<int> gInt2;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestIrrevocableCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = start * 100000;
+ int endingValue = startingValue + kMaxInserts;
+
+ for (int i = startingValue; i < endingValue; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ t.make_irrevocable();
+ //if (t.irrevocable()) cout << "irr tx" << endl;
+
+ try
+ {
+ t.w(gInt).value()++;
+ t.end();
+ cout << gInt.value() << endl;
+ break;
+ }
+ catch (aborted_tx&)
+ {
+ cout << "Irrevocable transaction aborted" << endl;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = start * 100000;
+ int endingValue = startingValue + kMaxInserts;
+
+ for (int i = startingValue; i < endingValue; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ t.w(gInt2).value()++;
+
+ if (1)//0 == rand() % 2)
+ {
+ t.w(gInt).value()++;
+ }
+ t.end();
+ break;
+ }
+ catch (aborted_tx&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestIrrevocableInt()
+{
+ transaction::initialize();
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = 0;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, TestCount, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestIrrevocableCount((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+}
+

Added: sandbox/stm/libs/stm/test/irrevocableInt.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/irrevocableInt.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,37 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#ifndef IRREVOCABLE_INT_H
+#define IRREVOCABLE_INT_H
+
+void TestIrrevocableInt();
+
+#endif

Added: sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,170 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <iostream>
+#include "isolatedComposedIntLockInTx.h"
+#include <boost/stm/transaction.hpp>
+#include "main.h"
+
+static boost::stm::native_trans<int> gInt;
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+static Mutex lock1 = PTHREAD_MUTEX_INITIALIZER;
+#else
+static Mutex lock1;
+#endif
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+
+static boost::stm::native_trans<int> globalInt;
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestIsolatedComposedLockInTxCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = 0;
+ int endingValue = (startingValue + kMaxInserts);
+
+ for (int i = startingValue; i < endingValue/2; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ transaction::lock_(lock1);
+ ++gInt.value();
+ cout << "\t" << gInt.value() << endl;
+ transaction::unlock_(lock1);
+
+ SLEEP(1000);
+ // do nothing on purpose, allowing other threads time to see
+ // intermediate state IF they can get lock1 (they shouldn't)
+
+ transaction::lock_(lock1);
+ --gInt.value();
+ cout << "\t" << gInt.value() << endl;
+ transaction::unlock_(lock1);
+
+ t.end();
+ SLEEP(1000);
+
+ break;
+ }
+ catch (aborted_tx&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestComposedCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = start * 100000;
+ int endingValue = startingValue + kMaxInserts;
+
+ for (int i = startingValue; i < 100*endingValue; ++i)
+ {
+ transaction::lock_(lock1);
+ cout << gInt.value() << endl;
+ transaction::unlock_(lock1);
+ SLEEP(10); // do nothing on purpose
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestIsolatedComposedIntLockInTx()
+{
+ transaction::initialize();
+ transaction::tm_lock_conflict(&lock1);
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = 0;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, TestIsolatedComposedLockInTxCount, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestComposedCount((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ cout << "gInt : " << gInt.value() << endl;
+}
+

Added: sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,37 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#ifndef ISOLATED_COMPOSED_INT_LOCK_IN_TX_H
+#define ISOLATED_COMPOSED_INT_LOCK_IN_TX_H
+
+void TestIsolatedComposedIntLockInTx();
+
+#endif

Added: sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx2.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx2.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,218 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <iostream>
+#include "isolatedComposedIntLockInTx.h"
+#include <boost/stm/transaction.hpp>
+#include "main.h"
+
+static boost::stm::native_trans<int> gInt;
+static boost::stm::native_trans<int> gInt2;
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+static Mutex lock1 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex lock2 = PTHREAD_MUTEX_INITIALIZER;
+#else
+static Mutex lock1;
+static Mutex lock2;
+#endif
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+
+///////////////////////////////////////////////////////////////////////////////
+static void* Test1(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = 0;
+ int endingValue = (startingValue + kMaxInserts);
+
+ for (int i = startingValue; i < endingValue/2; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ t.add_tx_conflicting_lock(&lock1);
+ try
+ {
+ transaction::lock_(lock1);
+ ++gInt.value();
+ cout << "\t" << gInt.value() << endl;
+ transaction::unlock_(lock1);
+
+ SLEEP(50);
+ // do nothing on purpose, allowing other threads time to see
+ // intermediate state IF they can get lock1 (they shouldn't)
+
+ transaction::lock_(lock1);
+ --gInt.value();
+ cout << "\t" << gInt.value() << endl;
+ transaction::unlock_(lock1);
+
+ t.end();
+ SLEEP(50);
+
+ break;
+ }
+ catch (aborted_tx&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* Test2(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = start * 100000;
+ int endingValue = startingValue + kMaxInserts;
+
+ for (int i = startingValue; i < 100*endingValue; ++i)
+ {
+ try
+ {
+ transaction t;
+ t.add_tx_conflicting_lock(&lock1);
+ int val = t.r(gInt).value();
+ //transaction::lock(lock2);
+ cout << val << endl;
+ //transaction::unlock(lock2);
+ t.end();
+ SLEEP(10); // do nothing on purpose
+ } catch (aborted_tx&) {}
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* Test3(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = 0;
+ int endingValue = (startingValue + kMaxInserts);
+
+ for (int i = startingValue; i < endingValue/2; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ ++gInt2.value();
+ t.end();
+ cout << "\t\t" << gInt2.value() << endl;
+ SLEEP(rand() % 50);
+ break;
+ }
+ catch (aborted_tx&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestIsolatedComposedIntLockInTx2()
+{
+ transaction::initialize();
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = 0;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, Test1, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ Test3((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ cout << "gInt : " << gInt.value() << endl;
+}
+

Added: sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx2.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/isolatedComposedIntLockInTx2.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,37 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#ifndef ISOLATED_COMPOSED_INT_LOCK_IN_TX2_H
+#define ISOLATED_COMPOSED_INT_LOCK_IN_TX2_H
+
+void TestIsolatedComposedIntLockInTx2();
+
+#endif

Added: sandbox/stm/libs/stm/test/isolatedInt.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/isolatedInt.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,170 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <iostream>
+#include "isolatedInt.h"
+#include <boost/stm/transaction.hpp>
+#include "main.h"
+
+static boost::stm::native_trans<int> gInt;
+static boost::stm::native_trans<int> gInt2;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestIsolatedCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = start * 100000;
+ int endingValue = startingValue + kMaxInserts;
+ volatile int oldVal;
+
+ for (int i = startingValue; i < endingValue; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ t.make_isolated();
+ //SLEEP(1);
+ oldVal = gInt2.value();
+
+ ++gInt2.value();
+
+ if (oldVal + 1 != gInt2.value())
+ {
+ cout << "invariant changed" << endl;
+ }
+ t.end();
+ //cout << gInt2.value() << endl;
+ break;
+ }
+ catch (aborted_tx&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = start * 100000;
+ int endingValue = startingValue + kMaxInserts;
+
+ for (int i = startingValue; i < endingValue; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ t.w(gInt2).value()++;
+
+ if (1)//0 == rand() % 2)
+ {
+ t.w(gInt).value()++;
+ }
+ t.end();
+ break;
+ }
+ catch (aborted_tx&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestIsolatedInt()
+{
+ transaction::initialize();
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = 0;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, TestCount, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestIsolatedCount((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+}
+

Added: sandbox/stm/libs/stm/test/isolatedInt.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/isolatedInt.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,37 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#ifndef ISOLATED_INT_H
+#define ISOLATED_INT_H
+
+void TestIsolatedInt();
+
+#endif

Added: sandbox/stm/libs/stm/test/isolatedIntLockInTx.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/isolatedIntLockInTx.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,203 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <iostream>
+#include "isolatedInt.h"
+#include <boost/stm/transaction.hpp>
+#include "main.h"
+
+static boost::stm::native_trans<int> gInt;
+static boost::stm::native_trans<int> gInt2;
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+static Mutex lock1 = PTHREAD_MUTEX_INITIALIZER;
+#else
+static Mutex lock1;
+#endif
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+
+static boost::stm::native_trans<int> globalInt;
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestIsolatedLockInTxCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = 0;
+ int endingValue = (startingValue + kMaxInserts);
+ int oldVal, newVal;
+
+ for (int i = startingValue; i < endingValue/2; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ oldVal = gInt.value();
+
+ //-------------------------------------------------------
+ // increase gInt's value inside tx
+ //-------------------------------------------------------
+ ++t.w(gInt).value();
+
+ //-------------------------------------------------------
+ // lock mutex inside of tx and then DIRECTLY access
+ // global memory (gInt), its state must be updated to
+ // reflect all changes made previously inside the tx
+ //-------------------------------------------------------
+ transaction::lock_(lock1);
+ cout << gInt.value() << endl;
+
+ ++gInt.value();
+
+ if (oldVal + 2 != gInt.value()) cout << "invariant violated" << endl;
+
+ transaction::unlock_(lock1);
+
+ //-------------------------------------------------------
+ // now again access gInt via tx. tx should access the
+ // changes previously made by the lock
+ //-------------------------------------------------------
+ --t.w(gInt).value();
+
+ newVal = t.r(gInt).value();
+
+ if (oldVal + 1 != newVal) cout << "invariant violated" << endl;
+
+ t.end();
+
+ break;
+ }
+ catch (aborted_tx&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = start * 100000;
+ int endingValue = startingValue + kMaxInserts;
+
+ for (int i = startingValue; i < endingValue; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ t.w(gInt).value()++;
+
+ if (1)//0 == rand() % 2)
+ {
+ t.w(gInt2).value()++;
+ }
+ t.end();
+ break;
+ }
+ catch (aborted_tx&)
+ {
+ cout << "aborted" << endl;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestIsolatedIntLockInTx()
+{
+ transaction::initialize();
+ transaction::do_full_lock_protection();
+ //transaction::do_direct_updating();
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = 0;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, TestIsolatedLockInTxCount, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestIsolatedLockInTxCount((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ cout << "gInt : " << gInt.value() << endl;
+}
+

Added: sandbox/stm/libs/stm/test/isolatedIntLockInTx.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/isolatedIntLockInTx.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,37 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#ifndef ISOLATED_INT_LOCK_IN_TX_H
+#define ISOLATED_INT_LOCK_IN_TX_H
+
+void TestIsolatedIntLockInTx();
+
+#endif

Added: sandbox/stm/libs/stm/test/litExample.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/litExample.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,383 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <iostream>
+#include "litExample.h"
+#include <boost/stm/transaction.hpp>
+#include "main.h"
+
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+static Mutex L2 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L3 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L4 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L8 = PTHREAD_MUTEX_INITIALIZER;
+#else
+static Mutex L2;
+static Mutex L3;
+static Mutex L4;
+static Mutex L8;
+#endif
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+
+static native_trans<int> *arr1, *arr2, *arr3, *arr4, *arr5, *arr6, *arr7, *arr8;
+
+static bool work1 = false, work2 = false, work3 = false;
+
+static int txFactor = 1;
+static int lockFactor = 1;
+
+////////////////////////////////////////////////////////////////////////////
+static int iterations = 0;
+
+
+static void inc2()
+{
+ transaction::lock_(L2);
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++arr2[i].value();
+ }
+ transaction::unlock_(L2);
+}
+
+static void inc3()
+{
+ transaction::lock_(L3);
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++arr3[i].value();
+ }
+ transaction::unlock_(L3);
+}
+
+static void inc4()
+{
+ transaction::lock_(L4);
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++arr4[i].value();
+ }
+ transaction::unlock_(L4);
+}
+
+
+static void do_work1()
+{
+ if (work1) return;
+ work1 = true;
+
+ if (kBalancedWork == gWorkLoadType || kTxIntenseWork == gWorkLoadType)
+ {
+ for (int iters = 0; iters < txFactor*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++t.w(arr6[i]).value();
+ }
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+ }
+}
+
+static void do_work2()
+{
+ if (work2) return;
+ work2 = true;
+
+ if (kBalancedWork == gWorkLoadType || kTxIntenseWork == gWorkLoadType)
+ {
+ for (int iters = 0; iters < txFactor*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++t.w(arr7[i]).value();
+ }
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+ }
+}
+
+static void do_work3()
+{
+ if (work3) return;
+ work3 = true;
+
+ transaction::lock_(L8);
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++arr8[i].value();
+ }
+ transaction::unlock_(L8);
+}
+
+static void* tx1(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < txFactor*10*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++t.w(arr1[i]).value();
+ }
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+
+ if (!work1) { do_work1(); }
+ if (!work2) { do_work2(); }
+
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* tx2(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < txFactor*10*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+ t.add_tx_conflicting_lock(L2);
+ inc2();
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+
+ if (!work1) { do_work1(); }
+ if (!work2) { do_work2(); }
+
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* tx3(void *threadId)
+{
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < txFactor*10*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+
+ t.add_tx_conflicting_lock(L3);
+ inc3();
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+
+ if (!work1) { do_work1(); }
+ if (!work2) { do_work2(); }
+
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* lock1(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < lockFactor*1000*iterations; ++iters)
+ {
+ inc2();
+ }
+
+ endTimer = time(NULL);
+ finishThread();
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* lock2(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < lockFactor*1000*iterations; ++iters)
+ {
+ inc3();
+ }
+
+ endTimer = time(NULL);
+ finishThread();
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* lock3(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < lockFactor*2000*iterations; ++iters)
+ {
+ inc4();
+ }
+
+ endTimer = time(NULL);
+ finishThread();
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestLitExample()
+{
+ iterations = kMaxArrIter;
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ arr1 = new native_trans<int>[kMaxArrSize];
+ arr2 = new native_trans<int>[kMaxArrSize];
+ arr3 = new native_trans<int>[kMaxArrSize];
+ arr4 = new native_trans<int>[kMaxArrSize];
+ arr5 = new native_trans<int>[kMaxArrSize];
+ arr6 = new native_trans<int>[kMaxArrSize];
+ arr7 = new native_trans<int>[kMaxArrSize];
+ arr8 = new native_trans<int>[kMaxArrSize];
+
+ transaction::initialize();
+ transaction::tm_lock_conflict(L2);
+ transaction::tm_lock_conflict(L3);
+
+ if (kTxIntenseWork == gWorkLoadType) txFactor = 5;
+ if (kLockIntenseWork == gWorkLoadType) lockFactor = 10;
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = 0;
+ endTimer = 0;
+
+ threadId[0] = 0;
+ pthread_create(&threads[0], NULL, tx1, (void *)&threadId[0]);
+
+ threadId[1] = 1;
+ pthread_create(&threads[1], NULL, tx2, (void *)&threadId[1]);
+
+ threadId[2] = 2;
+ pthread_create(&threads[2], NULL, tx3, (void *)&threadId[2]);
+
+ threadId[3] = 3;
+ pthread_create(&threads[3], NULL, lock1, (void *)&threadId[3]);
+
+ threadId[4] = 4;
+ pthread_create(&threads[4], NULL, lock2, (void *)&threadId[4]);
+
+ int mainThreadId = kMaxThreads-1;
+ lock3((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ if (transaction::doing_full_lock_protection()) cout << "full_";
+ else if (transaction::doing_tm_lock_protection()) cout << "tm_";
+ else if (transaction::doing_tx_lock_protection()) cout << "tx_";
+
+ cout << "run_time\t" << endTimer - startTimer << endl;
+}
+
+
+

Added: sandbox/stm/libs/stm/test/litExample.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/litExample.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,23 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef LIT_EXAMPLE_H
+#define LIT_EXAMPLE_H
+
+void TestLitExample();
+
+#endif // LOT_EXAMPLE_H
+
+
+

Added: sandbox/stm/libs/stm/test/lotExample.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/lotExample.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,388 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <iostream>
+#include "lotExample.h"
+#include <boost/stm/transaction.hpp>
+#include "main.h"
+
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+
+static Mutex L1 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L2 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L3 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L8 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L9 = PTHREAD_MUTEX_INITIALIZER;
+
+#else
+static Mutex L1;
+static Mutex L2;
+static Mutex L3;
+static Mutex L8;
+static Mutex L9;
+
+#endif
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+
+static native_trans<int> *arr1, *arr2, *arr3, *arr4, *arr5, *arr6, *arr7, *arr8, *arr9;
+
+static bool work1 = false, work2 = false, work3 = false, work4 = false;
+static int txFactor = 1;
+static int lockFactor = 1;
+
+////////////////////////////////////////////////////////////////////////////
+static int iterations = 0;
+
+static void do_work1()
+{
+ if (work1) return;
+ work1 = true;
+
+ if (kBalancedWork == gWorkLoadType || kTxIntenseWork == gWorkLoadType)
+ {
+ for (int iters = 0; iters < txFactor*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++t.w(arr6[i]).value();
+ }
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+ }
+}
+
+static void do_work2()
+{
+ if (work2) return;
+ work2 = true;
+
+ if (kBalancedWork == gWorkLoadType || kTxIntenseWork == gWorkLoadType)
+ {
+ for (int iters = 0; iters < txFactor*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++t.w(arr7[i]).value();
+ }
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+ }
+}
+
+static void do_work3()
+{
+ if (work3) return;
+ work3 = true;
+
+ for (int iters = 0; iters < iterations; ++iters)
+ {
+ transaction::lock_(L8);
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++arr8[i].value();
+ }
+ transaction::unlock_(L8);
+ }
+}
+
+static void do_work4()
+{
+ if (work4) return;
+ work4 = true;
+
+ for (int iters = 0; iters < iterations; ++iters)
+ {
+ transaction::lock_(L9);
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++arr9[i].value();
+ }
+ transaction::unlock_(L9);
+ }
+}
+
+static void* tx1(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < txFactor*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++t.w(arr4[i]).value();
+ }
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+
+ if (!work1) { do_work1(); }
+ if (!work2) { do_work2(); }
+
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* tx2(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < txFactor*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++t.w(arr5[i]).value();
+ }
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+
+ if (!work1) { do_work1(); }
+ if (!work2) { do_work2(); }
+
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* tx3(void *threadId)
+{
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < txFactor*iterations; ++iters)
+ {
+ for (transaction t;;t.restart())
+ try {
+
+ t.add_tx_conflicting_lock(L1);
+ t.add_tx_conflicting_lock(L2);
+
+ for (int i = 0; i < kMaxArrSize; ++i)
+ {
+ ++t.w(arr1[i]).value();
+ ++t.w(arr2[i]).value();
+ }
+ t.end(); break;
+ } catch (aborted_tx&) {}
+ }
+
+ if (!work1) { do_work1(); }
+ if (!work2) { do_work2(); }
+
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* lock1(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < lockFactor*3000*iterations; ++iters)
+ {
+ transaction::lock_(L1); int sum = 0;
+ for (int i = 0; i < kMaxArrSize; ++i) sum += arr1[i].value();
+ transaction::unlock_(L1);
+ }
+
+ endTimer = time(NULL);
+ finishThread();
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* lock2(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < lockFactor*3000*iterations; ++iters)
+ {
+ transaction::lock_(L2); int sum = 0;
+ for (int i = 0; i < kMaxArrSize; ++i) sum += arr2[i].value();
+ transaction::unlock_(L2);
+ }
+
+ endTimer = time(NULL);
+ finishThread();
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+static void* lock3(void *threadId)
+{
+ transaction::initialize_thread();
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ startTimer = time(NULL);
+
+ for (int iters = 0; iters < 10000*iterations; ++iters)
+ {
+ transaction::lock_(L3); int sum = 0;
+ for (int i = 0; i < kMaxArrSize; ++i) sum += arr3[i].value();
+ transaction::unlock_(L3);
+ }
+
+ endTimer = time(NULL);
+ finishThread();
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ pthread_exit(threadId);
+ }
+
+ return threadId;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestLotExample()
+{
+ iterations = kMaxArrIter;
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ arr1 = new native_trans<int>[kMaxArrSize];
+ arr2 = new native_trans<int>[kMaxArrSize];
+ arr3 = new native_trans<int>[kMaxArrSize];
+ arr4 = new native_trans<int>[kMaxArrSize];
+ arr5 = new native_trans<int>[kMaxArrSize];
+ arr6 = new native_trans<int>[kMaxArrSize];
+ arr7 = new native_trans<int>[kMaxArrSize];
+ arr8 = new native_trans<int>[kMaxArrSize];
+
+ transaction::initialize();
+ transaction::tm_lock_conflict(L1);
+ transaction::tm_lock_conflict(L2);
+
+ if (kTxIntenseWork == gWorkLoadType) txFactor = 5;
+ if (kLockIntenseWork == gWorkLoadType) lockFactor = 10;
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = 0;
+ endTimer = 0;
+
+ threadId[0] = 0;
+ pthread_create(&threads[0], NULL, tx1, (void *)&threadId[0]);
+
+ threadId[1] = 1;
+ pthread_create(&threads[1], NULL, tx2, (void *)&threadId[1]);
+
+ threadId[2] = 2;
+ pthread_create(&threads[2], NULL, tx3, (void *)&threadId[2]);
+
+ threadId[3] = 3;
+ pthread_create(&threads[3], NULL, lock1, (void *)&threadId[3]);
+
+ threadId[4] = 4;
+ pthread_create(&threads[4], NULL, lock2, (void *)&threadId[4]);
+
+ int mainThreadId = kMaxThreads-1;
+ lock3((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ if (transaction::doing_full_lock_protection()) cout << "full_";
+ else if (transaction::doing_tm_lock_protection()) cout << "tm_";
+ else if (transaction::doing_tx_lock_protection()) cout << "tx_";
+
+ cout << "run_time\t" << endTimer - startTimer << endl;
+}
+
+
+

Added: sandbox/stm/libs/stm/test/lotExample.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/lotExample.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,23 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef LOT_EXAMPLE_H
+#define LOT_EXAMPLE_H
+
+void TestLotExample();
+
+#endif // LOT_EXAMPLE_H
+
+
+

Added: sandbox/stm/libs/stm/test/main.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/main.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,67 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <boost/stm/transaction.hpp>
+
+namespace nMain
+{
+ int const kStartingTime = -1;
+}
+
+enum eWorkType
+{
+ kBalancedWork,
+ kTxIntenseWork,
+ kLockIntenseWork,
+};
+
+extern eWorkType gWorkLoadType;
+
+extern int kMaxInserts;
+extern bool kInsertSameValues;
+extern bool kDoRemoval;
+extern bool kDoLookup;
+extern bool kDoMove;
+extern bool kMoveSemantics;
+extern std::string bench;
+
+extern int kMaxThreads;
+extern int kMainThreadId;
+extern int kMaxArrSize;
+extern int kMaxArrIter;
+
+////////////////////////////////////////////////////////////////////////////
+//
+// global variables all of which are used in the main transaction iteration
+//
+////////////////////////////////////////////////////////////////////////////
+class String;
+class Integer;
+
+extern Mutex outputMutex;
+extern String globalString;
+
+extern boost::stm::native_trans<int> threadsFinished;
+extern boost::stm::native_trans<int> threadsStarted;
+extern time_t startTimer;
+extern time_t endTimer;
+
+void idleUntilAllThreadsHaveReached(int const &threadId);
+void finishThread(int const &threadId);
+void finishThread();
+void logCommitsAndAborts(std::string const &typeOfRun);
+
+#endif // MAIN_H

Added: sandbox/stm/libs/stm/test/nestedTxs.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/nestedTxs.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,268 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <sstream>
+#include "nestedTxs.h"
+
+
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+static Mutex L = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L2 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L3 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L4 = PTHREAD_MUTEX_INITIALIZER;
+#else
+static Mutex L;
+static Mutex L2;
+static Mutex L3;
+static Mutex L4;
+#endif
+
+using namespace boost::stm;
+
+static native_trans<int> x = 0;
+static native_trans<int> y = 0;
+
+static void tx_bar();
+static void lk_bar();
+
+static void* tx_foo(void*)
+{
+ transaction::initialize_thread();
+ size_t tries = 0;
+
+ try_atomic(t)
+ {
+ t.lock_conflict(L);
+
+ ++t.write(x);
+ tx_bar();
+ }
+ before_retry { ++tries; }
+
+ cout << "tx done" << endl;
+ return 0;
+}
+
+static void tx_bar()
+{
+ use_atomic(t)
+ {
+ t.write(y) = t.read(x) + y;
+ }
+}
+
+
+
+static void* lk_foo(void*)
+{
+ use_lock(&L)
+ {
+ ++x;
+ lk_bar();
+ }
+
+ return 0;
+}
+
+static void lk_bar()
+{
+ use_lock(L)
+ {
+ y = x + y;
+ cout << "locking done" << endl;
+ }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void* stall(void *)
+{
+ transaction::initialize_thread();
+
+ transaction::lock_(&L2);
+
+ SLEEP(10000);
+
+ transaction::unlock_(&L2);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void nested2()
+{
+ bool fail = true;
+
+ atomic(t)
+ {
+ if (fail)
+ {
+ t.force_to_abort();
+ fail = false;
+ }
+ ++t.w(x);
+ }
+ before_retry
+ {
+ cout << "caught at nested2\n";
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void nested1()
+{
+ atomic(t)
+ {
+ ++t.w(x);
+ nested2();
+ }
+ before_retry
+ {
+ cout << "caught at nested1\n";
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void nested0()
+{
+ atomic(t)
+ {
+ ++t.w(x);
+ nested1();
+ }
+ before_retry
+ {
+ cout << "caught at nested0" << endl;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void TestTransactionInsideLock()
+{
+ using namespace boost::stm;
+
+ cout << "X: " << x.value() << endl;
+
+ SLEEP(1000);
+
+ transaction::lock_(&L);
+ transaction::lock_(&L3);
+
+ try_atomic(t)
+ {
+ t.lock_conflict(&L);
+ t.lock_conflict(&L2);
+ t.lock_conflict(&L3);
+
+ ++t.write(x);
+
+ } before_retry {}
+
+ transaction::unlock_(&L);
+ transaction::unlock_(&L3);
+
+ cout << "X: " << x.value() << endl;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void TestEarlyRelease()
+{
+ using namespace boost::stm;
+
+ cout << "X: " << x.value() << endl;
+
+ SLEEP(1000);
+
+ transaction::lock_(&L);
+ transaction::lock_(&L3);
+
+ try_atomic(t)
+ {
+ t.lock_conflict(&L);
+ t.lock_conflict(&L2);
+ t.lock_conflict(&L3);
+
+ transaction::unlock_(&L);
+
+ ++t.write(x);
+
+ } before_retry {}
+
+ transaction::unlock_(&L);
+ transaction::unlock_(&L3);
+
+ cout << "X: " << x.value() << endl;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+void NestedTxTest()
+{
+ static std::vector<int> runVector;
+ int iterations = 0;
+
+ transaction::initialize();
+ transaction::initialize_thread();
+
+ //transaction::do_tm_lock_protection();
+ transaction::do_tx_lock_protection();
+
+ //transaction::tm_lock_conflict(&L);
+ //transaction::tm_lock_conflict(&L2);
+ //transaction::tm_lock_conflict(&L3);
+
+ nested2();
+ nested1();
+ nested0();
+
+ exit(0);
+
+ pthread_t *second_thread = new pthread_t;
+
+ pthread_create(second_thread, NULL, stall, (void*)NULL);
+
+ TestTransactionInsideLock();
+ TestEarlyRelease();
+
+ exit(0);
+}

Added: sandbox/stm/libs/stm/test/nestedTxs.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/nestedTxs.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,25 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef NESTED_TXS_H
+#define NESTED_TXS_H
+
+#include "main.h"
+#include <boost/stm/transaction.hpp>
+#include <pthread.h>
+#include <fstream>
+
+void NestedTxTest();
+
+#endif // TEST_LINKED_LIST_H

Added: sandbox/stm/libs/stm/test/smart.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/smart.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,260 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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/transaction.hpp>
+#include "main.h"
+
+using namespace boost::stm;
+
+int kMaxOuterLoops = 10000;
+int kMaxInnerLoops = 50000;
+
+native_trans<int> txInt = 0, txInt2, txInt3 = 0;
+
+
+template <typename T>
+class tx_wptr
+{
+public:
+
+ tx_wptr(boost::stm::transaction &t, T & tx_obj) :
+ t_(t), tx_obj_(t_.write(tx_obj))
+ {}
+
+ T& operator*()
+ {
+ if (t_.forced_to_abort())
+ {
+ t_.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+ }
+
+ return tx_obj_;
+ }
+
+ T* operator->()
+ {
+ if (t_.forced_to_abort())
+ {
+ t_.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+ }
+
+ return &tx_obj_;
+ }
+
+#if 0
+ T& w()
+ {
+ if (t_.forced_to_abort())
+ {
+ t_.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+ }
+ if (written_) return *tx_ptr_;
+
+ // recheck initialization ...
+ initialize();
+
+ if (written_) return *tx_ptr_;
+
+ // if it's only been read, a write will construct a new obj
+ tx_ptr_ = &t_.write(*tx_ptr_);
+ written_ = true;
+ return *tx_ptr_;
+ }
+
+ T const & r() const
+ {
+ if (t_.forced_to_abort())
+ {
+ t_.lock_and_abort();
+ throw aborted_transaction_exception("aborting transaction");
+ }
+ if (written_) return *tx_ptr_;
+
+ // recheck initialization ...
+ initialize();
+
+ if (written_) return *tx_ptr_;
+
+ if (read_) return *tx_ptr_;
+
+ t_.read(*tx_ptr_);
+ read_ = true;
+ return *tx_ptr_;
+ }
+
+private:
+
+ void initialize() const
+ {
+ // check transaction to see if tx_obj is
+ // already in a transaction for this thread
+ T* temp = t_.get_written(*tx_ptr_);
+
+ // if we found something, store this as the tx_ptr_
+ if (0 != temp)
+ {
+ tx_ptr_ = temp;
+ written_ = true;
+ }
+ else
+ {
+ read_ = t_.has_been_read(*tx_ptr_);
+ }
+ }
+#endif
+
+ mutable boost::stm::transaction &t_;
+ mutable T &tx_obj_;
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+static void test_nested()
+{
+ atomic(t)
+ {
+ tx_wptr<native_trans<int> > tx(t, txInt);
+ ++*tx;
+ } end_atom
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+static void test_parent()
+{
+ atomic(t)
+ {
+ tx_wptr<native_trans<int> > tx(t, txInt);
+ if (0 == *tx) test_nested();
+ cout << *tx << endl;
+ } end_atom
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+static void test()
+{
+ int x = 0, y = 0, z = 0;
+
+ for (int i = 0; i < kMaxOuterLoops; ++i)
+ {
+ atomic(t)
+ {
+ for (int j = 0; j < kMaxInnerLoops; ++j)
+ {
+ tx_wptr<native_trans<int> > tx(t, txInt);
+
+ x = *tx;
+ y = *tx;
+
+ ++*tx;
+
+ z = *tx;
+ }
+
+ } end_atom
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+static void test_no_private()
+{
+ int x = 0, y = 0, z = 0;
+
+ for (int i = 0; i < kMaxOuterLoops; ++i)
+ {
+ atomic(t)
+ {
+ for (int j = 0; j < kMaxInnerLoops; ++j)
+ {
+ x = t.r(txInt);
+ y = t.r(txInt);
+
+ ++t.w(txInt);
+
+ z = t.r(txInt);
+ }
+
+ } end_atom
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+static void test2()
+{
+ atomic(t)
+ {
+ native_trans<int> const loc = t.r(txInt);
+
+ ++t.w(txInt);
+
+ } end_atom
+
+ int y = 0;
+}
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+void test_smart()
+{
+ boost::stm::transaction::initialize();
+ boost::stm::transaction::initialize_thread();
+
+ boost::stm::transaction::do_direct_updating();
+
+ test_parent();
+
+ int const kMaxTestLoops = 4;
+
+ test();
+
+ for (int i = 0; i < kMaxTestLoops; ++i)
+ {
+ txInt = 0;
+
+ cout << "outer loop #: " << kMaxOuterLoops << endl;
+ cout << "inner loop #: " << kMaxInnerLoops << endl << endl;
+
+ startTimer = time(NULL);
+ test_no_private();
+ endTimer = time(NULL);
+
+ cout << "no_privatization time: " << endTimer - startTimer << endl;
+ cout << " txInt: " << txInt << endl << endl;
+
+
+ startTimer = time(NULL);
+ test();
+ endTimer = time(NULL);
+
+ cout << " privatization time: " << endTimer - startTimer << endl;
+ cout << " txInt: " << txInt << endl << endl;
+
+ cout << "---------------------------------" << endl;
+
+ kMaxOuterLoops /= 10;
+ kMaxInnerLoops *= 10;
+ }
+
+}
+
+
+

Added: sandbox/stm/libs/stm/test/smart.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/smart.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#ifndef SMART_H
+#define SMART_H
+
+void test_smart();
+
+#endif // SMART_H
+
+
+
+
+

Added: sandbox/stm/libs/stm/test/stm.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/stm.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,273 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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/transaction.hpp>
+#include "main.h"
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <pthread.h>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include "testLinkedList.h"
+#include "testHashMap.h"
+#include "testRBTree.h"
+#include "usingLockTx.h"
+#include "nestedTxs.h"
+#include "testLL_latm.h"
+#include "testHT_latm.h"
+#if 0
+#include "testLinkedListWithLocks.h"
+#include "testHashMapAndLinkedListsWithLocks.h"
+#include "testHashMapWithLocks.h"
+#include "irrevocableInt.h"
+#include "isolatedInt.h"
+#include "isolatedIntLockInTx.h"
+#include "isolatedComposedIntLockInTx.h"
+#include "isolatedComposedIntLockInTx2.h"
+#include "txLinearLock.h"
+#include "lotExample.h"
+#include "litExample.h"
+#endif
+
+using namespace boost::stm; using namespace nMain; using namespace std;
+
+boost::stm::native_trans<int> threadsFinished;
+boost::stm::native_trans<int> threadsStarted;
+time_t startTimer = kStartingTime;
+time_t endTimer = 0;
+eWorkType gWorkLoadType;
+
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+static Mutex finishLock = PTHREAD_MUTEX_INITIALIZER;
+#else
+static Mutex finishLock;
+#endif
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int kMaxArrSize = 10;
+int kMaxArrIter = 10;
+int kMaxIterations = 1;
+int kMaxInserts = 100;
+bool kInsertSameValues = false;
+bool kDoRemoval = false;
+bool kDoLookup = false;
+bool kDoMove = false;
+bool kMoveSemantics = false;
+std::string bench = "rbtree";
+std::string updateMethod = "deferred";
+std::string insertAmount = "5000";
+
+int kMaxThreads = 2;
+int kMainThreadId = kMaxThreads-1;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void usage()
+{
+ cout << "DracoSTM usage:" << endl << endl;
+ cout << " -bench <name> - 'rbtree', 'linkedlist', 'hashmap' (or 'hashtable')" << endl;
+ cout << " 'irrevocable_int'" << endl;
+ cout << " 'isolated_int'" << endl;
+ cout << " 'isolated_int_lock'" << endl;
+ cout << " 'isolated_composed_int_lock'" << endl;
+ cout << " 'isolated_composed_int_lock2'" << endl;
+ cout << " 'linkedlist_w_locks' (uses transactions and locks)" << endl;
+ cout << " 'hashmap_w_locks' (uses transactions and locks)" << endl;
+ cout << " 'list_hash_w_locks' (uses transactions and locks)" << endl;
+ cout << " 'tx_linear_lock' (uses transactions and multiple linearly ordered locks)" << endl;
+ cout << " 'lot_example' (for paper)" << endl;
+ cout << " -def - do deferred updating transactions" << endl;
+ cout << " -dir - do direct updating transactions" << endl;
+ cout << " -latm <name> - 'full', 'tm', 'tx'" << endl;
+ cout << " -h - shows this help (usage) output" << endl;
+ cout << " -inserts <#> - sets the # of inserts per container per thread" << endl;
+ cout << " -threads <#> - sets the # of threads" << endl;
+ cout << " -lookup - performs individual lookup after inserts" << endl;
+ cout << " -remove - performs individual remove after inserts/lookup" << endl;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void setupEnvironment(int argc, char **argv)
+{
+ for (int i = 1; i < argc; ++i)
+ {
+ std::string first = argv[i];
+
+ if (first == "-def") transaction::do_deferred_updating();
+ else if (first == "-dir") transaction::do_direct_updating();
+ else if (first == "-lookup") kDoLookup = true;
+ else if (first == "-remove") kDoRemoval = true;
+ else if (first == "-inserts")
+ {
+ kMaxInserts = atoi(argv[++i]);
+ }
+ else if (first == "-threads")
+ {
+ kMaxThreads = atoi(argv[++i]);
+ kMainThreadId = kMaxThreads-1;
+ }
+ else if (first == "-moveSemantics")
+ {
+ kMoveSemantics = true;
+ }
+ else if (first == "-maxArrSize")
+ {
+ kMaxArrSize = atoi(argv[++i]);
+ }
+ else if (first == "-maxArrIter")
+ {
+ kMaxArrIter = atoi(argv[++i]);
+ }
+ else if (first == "-bench") bench = argv[++i];
+ else if (first == "-latm")
+ {
+#if PERFORMING_LATM
+
+ std::string latmType = argv[++i];
+ if (latmType == "full") transaction::do_full_lock_protection();
+ else if (latmType == "tm") transaction::do_tm_lock_protection();
+ else if (latmType == "tx") transaction::do_tx_lock_protection();
+ else
+ {
+ cout << "invalid LATM protection type, exiting" << endl;
+ cout << first << latmType << endl;
+ exit(0);
+ }
+#endif
+ }
+ else
+ {
+ usage();
+ exit(0);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// main
+//-----------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+ transaction::enable_dynamic_priority_assignment();
+
+ setupEnvironment(argc, argv);
+
+ for (int i = 0; i < kMaxIterations; ++i)
+ {
+ if ("rbtree" == bench) TestRedBlackTreeWithMultipleThreads();
+ else if ("linkedlist" == bench) TestLinkedListWithMultipleThreads();
+ else if ("hashmap" == bench || "hashtable" == bench) TestHashMapWithMultipleThreads();
+ else if ("using_linkedlist" == bench) TestLinkedListWithUsingLocks();
+ else if ("nested_tx" == bench) NestedTxTest();
+ else if ("ht" == bench) TestHashTableSetsWithLocks();
+ else if ("ll" == bench) TestLinkedListSetsWithLocks();
+#if 0
+ else if ("linkedlist_w_locks" == bench) TestLinkedListWithLocks();
+ else if ("hashmap_w_locks" == bench) TestHashMapWithLocks();
+ else if ("list_hash_w_locks" == bench) TestHashMapAndLinkedListWithLocks();
+ else if ("irrevocable_int" == bench) TestIrrevocableInt();
+ else if ("isolated_int" == bench) TestIsolatedInt();
+ else if ("isolated_int_lock" == bench) TestIsolatedIntLockInTx();
+ else if ("isolated_composed_int_lock" == bench) TestIsolatedComposedIntLockInTx();
+ else if ("isolated_composed_int_lock2" == bench) TestIsolatedComposedIntLockInTx2();
+ else if ("tx_linear_lock" == bench) TestTxLinearLock();
+ else if ("lot_example" == bench) TestLotExample();
+ else if ("lit_example" == bench) TestLitExample();
+#endif
+ else { usage(); return 0; }
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+void idleUntilAllThreadsHaveReached(int const &threadId)
+{
+ lock(&finishLock);
+ threadsStarted.value()++;
+ unlock(&finishLock);
+
+ while (threadsStarted.value() != kMaxThreads) SLEEP(5);
+}
+
+//-----------------------------------------------------------------------------
+void finishThread()
+{
+ lock(&finishLock);
+ threadsFinished.value()++;
+ unlock(&finishLock);
+}
+
+//-----------------------------------------------------------------------------
+void finishThread(int const &threadId)
+{
+ lock(&finishLock);
+ threadsFinished.value()++;
+ unlock(&finishLock);
+}
+
+//-----------------------------------------------------------------------------
+void logCommitsAndAborts(std::string const &typeOfRun)
+{
+ ofstream aborts("abortSetSize.txt", std::ios::app);
+
+ transaction_bookkeeping::AbortHistory::const_iterator j =
+ transaction::bookkeeping().getAbortWriteSetList().begin();
+ transaction_bookkeeping::AbortHistory::const_iterator k =
+ transaction::bookkeeping().getAbortReadSetList().begin();
+
+ transaction_bookkeeping::CommitHistory::const_iterator l =
+ transaction::bookkeeping().getCommitWriteSetList().begin();
+ transaction_bookkeeping::CommitHistory::const_iterator m =
+ transaction::bookkeeping().getCommitReadSetList().begin();
+
+ std::vector<double> percentList;
+
+ for (;k != transaction::bookkeeping().getAbortReadSetList().end(); ++k, ++j, ++l, ++m)
+ {
+ if (j->second + k->second > m->second + l->second) continue;
+
+#if 0
+ char *space = k->first.commitId_ > 10 ? " " : k->first.commitId_ > 100 ? " " : " ";
+
+ aborts << k->first.threadId_ << "\t\t" << space
+ << k->first.commitId_ << "\t\t" << k->second << "\t\t" << j->second
+ << "\t\t\t\t" << m->second << "\t\t" << l->second << "\t\t";
+#endif
+ double percent = double(j->second + k->second) / double(m->second + l->second);
+#if 0
+ aborts << percent << endl;
+#endif
+ percentList.push_back(percent);
+ }
+
+ double percentTotal = 0.0;
+
+ for (int i = 0; i < (int)percentList.size(); ++i) percentTotal += percentList[i];
+
+ percentTotal = percentTotal / double(percentList.size());
+
+ uint32 abortCount = transaction::bookkeeping().getAbortReadSetList().size()
+ + transaction::bookkeeping().getAbortWriteSetList().size();
+
+ aborts << typeOfRun.c_str() << " total_aborts: " << transaction::bookkeeping().totalAborts()
+ << "\t\taborted_r+w_count: " << abortCount
+ << "\t\tabort_ops/commit_ops: " << percentTotal << endl;
+
+ aborts.close();
+}
+

Added: sandbox/stm/libs/stm/test/testHT_latm.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testHT_latm.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,370 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <sstream>
+#include "testHT_latm.h"
+
+typedef int list_node_type;
+
+static int const kMaxThreadsWhenTestingSets = 128;
+// Subtract one max linked list per complete set of four threads
+static int const kMaxLinkedLists = kMaxThreadsWhenTestingSets - ((kMaxThreadsWhenTestingSets + 1) / 4);
+static LATM::LATM_HashMap< list_node_type > *llist[kMaxLinkedLists] = { NULL };
+static bool usingSingleList = false;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+////////////////////////////////////////////////////////////////////////////
+static int convertThreadIdToLinkedListIndex(int id)
+{
+ //------------------------------------------------------------------------------
+ // In set testing, threads are created in groups of four, assigned sequentially
+ // to sets of three linked lists with the last pair of threads sharing a list:
+ // trans -> list A
+ // lock -> list B
+ // trans + lock -> list C
+ //
+ // Thus, for every set of four incremental thread ids, the linked list index
+ // increments only with the first three incremental thread ids.
+ //------------------------------------------------------------------------------
+ return id - ((id + 1) / 4);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInsertsWithLocks(void *threadId)
+{
+ LATM::list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ int llindex = convertThreadIdToLinkedListIndex(start);
+ if (usingSingleList) llindex = 0;
+
+ //cout << "L" << llindex << endl;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist[llindex]->lock_insert(node);
+ }
+
+
+ if (kDoMove)
+ {
+ LATM::list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist[llindex]->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!llist[llindex]->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist[llindex]->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInserts(void *threadId)
+{
+ LATM::list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ int llindex = convertThreadIdToLinkedListIndex(start);
+ if (usingSingleList) llindex = 0;
+
+ //cout << "T" << llindex << endl;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist[llindex]->insert(node);
+ }
+
+ if (kDoMove)
+ {
+ LATM::list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist[llindex]->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!llist[llindex]->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist[llindex]->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+void TestHashTableSetsWithLocks()
+{
+ static std::vector<int> runVector;
+ int iterations = 0;
+
+ usingSingleList = false;
+
+ if (kMaxThreads > kMaxThreadsWhenTestingSets)
+ {
+ kMaxThreads = kMaxThreadsWhenTestingSets;
+ std::cout << "Limiting max threads to " << kMaxThreadsWhenTestingSets << "." << endl;
+ }
+ else if (kMaxThreads % 4 != 0)
+ {
+ // threads are always in multiples of four: transaction, lock, and transaction + lock
+ kMaxThreads += (4 - (kMaxThreads % 4));
+ std::cout << "Rounding max threads to the next multiple of 4 (" << kMaxThreads << ")." << endl;
+ }
+
+ kMainThreadId = kMaxThreads-1;
+ int lists = (kMaxThreads / 4) * 3;
+
+ for (int k = 0; k < kMaxThreads; ++k)
+ {
+ llist[k] = new LATM::LATM_HashMap<list_node_type>;
+
+ transaction::initialize();
+ transaction::initialize_thread();
+
+ int index = convertThreadIdToLinkedListIndex(k);
+
+ //----------------------------------------------------------------
+ // every 4th thread works on the same linked list that
+ // the 3rd thread is working on, so only add that conflict
+ //----------------------------------------------------------------
+ if (transaction::doing_tm_lock_protection() && 0 == (k+1) % 2)
+ {
+ //transaction::add_tm_conflicting_lock(llist[index]->get_list_lock());
+ //cout << "TM-lock conflict added: " << index << endl;
+ }
+ }
+
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ if (0 == j % 2) pthread_create(&threads[j], NULL, TestLinkedListInserts, (void *)&threadId[j]);
+ else pthread_create(&threads[j], NULL, TestLinkedListInsertsWithLocks, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestLinkedListInsertsWithLocks((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ int totalInserts = 0;
+ for (int m = 0; m < kMaxThreads; ++m)
+ {
+ totalInserts += llist[m]->walk_size();
+ }
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (int i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << "LL: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << averageRunTime << " " << "AVE: " << totalAverageRunTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / (totalAverageRunTime * runVector.size()) << endl;
+ cout << transaction::bookkeeping() << endl;
+
+#if 0
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * kMaxThreads))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN LINKED LIST - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+ }
+
+ ofstream outTest("testOutput.txt");
+ for (int p = 0; p < kMaxThreads; ++p)
+ {
+ llist[p]->outputList(outTest);
+ }
+ outTest.close();
+#endif
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "linkedList_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ for (int q = 0; q < kMaxThreads; ++q)
+ {
+ delete llist[q];
+ }
+ delete threads;
+ delete threadId;
+}

Added: sandbox/stm/libs/stm/test/testHT_latm.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testHT_latm.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,120 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef LATM_HASH_MAP_WITH_LOCKS_H
+#define LATM_HASH_MAP_WITH_LOCKS_H
+
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/stm/transaction.hpp>
+#include "testLL_latm.h"
+
+void TestHashMapWithLocks();
+
+namespace LATM
+{
+ namespace nHashMap
+ {
+ int const kBuckets = 256;
+ }
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class LATM_HashMap
+{
+public:
+
+ bool lock_lookup(T &val)
+ {
+ return buckets_[val % nHashMap::kBuckets].lock_lookup(val);
+ }
+
+ bool lock_insert(list_node<T> &element)
+ {
+ return buckets_[element.value() % nHashMap::kBuckets].lock_insert(element);
+ }
+
+ bool lookup(T &val)
+ {
+ return buckets_[val % nHashMap::kBuckets].lookup(val);
+ }
+
+ bool insert(list_node<T> &element)
+ {
+ return buckets_[element.value() % nHashMap::kBuckets].insert(element);
+ }
+
+ bool move(list_node<T> const &node1, list_node<T> const &node2)
+ {
+ using namespace boost::stm;
+ bool succeeded1 = true, succeeded2 = true;
+ transaction_state state = e_no_state;
+
+ do
+ {
+ try
+ {
+ transaction t;
+ succeeded1 = buckets_[node1.value() % nHashMap::kBuckets].remove(node1);
+ succeeded2 = buckets_[node2.value() % nHashMap::kBuckets].insert(node2);
+ t.end();
+ }
+ catch (aborted_transaction_exception&) {}
+
+ if (!succeeded1 || !succeeded2)
+ {
+ return false; // auto abort of t
+ }
+
+ } while (e_committed != state);
+
+ return true;
+ }
+
+
+ bool remove(list_node<T> &v)
+ {
+ return buckets_[v.value() % nHashMap::kBuckets].remove(v);
+ }
+
+ size_t walk_size()
+ {
+ size_t count = 0;
+ for (int i = 0; i < nHashMap::kBuckets; ++i)
+ {
+ count += buckets_[i].walk_size();
+ }
+
+ return count;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ void outputList(std::ofstream &o)
+ {
+ for (int i = 0; i < nHashMap::kBuckets; ++i)
+ {
+ buckets_[i].outputList(o);
+ }
+ }
+
+ Mutex* get_hash_lock(int val) { return buckets_[val].get_list_lock(); }
+
+private:
+ LATM::LinkedList<T> buckets_[nHashMap::kBuckets];
+};
+
+} // namespace LATM
+
+void TestHashTableSetsWithLocks();
+
+#endif // HASH_MAP_H

Added: sandbox/stm/libs/stm/test/testHashMap.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testHashMap.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,193 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include "testHashMap.h"
+#include <fstream>
+#include <sstream>
+
+HashMap<int> *hashMap = NULL;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm; using namespace nHashMap;
+using namespace nMain;
+
+///////////////////////////////////////////////////////////////////////////////
+void* TestHashMapInserts(void *threadId)
+{
+ list_node<int> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ //cout << "i: " << startingValue << endl;
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ hashMap->insert(node);
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ if (!hashMap->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ hashMap->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestHashMapWithMultipleThreads()
+{
+ static std::vector<int> runVector;
+
+ hashMap = new HashMap<int>;
+ transaction::initialize();
+ transaction::initialize_thread();
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, TestHashMapInserts, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestHashMapInserts((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ int totalInserts = hashMap->walk_size();
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (int i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << "HT: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << averageRunTime << " " << "AVE: " << totalAverageRunTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / (totalAverageRunTime * runVector.size()) << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * kMaxThreads))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN HASH MAP - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+
+ ofstream out("testOutput.txt");
+ hashMap->outputList(out);
+ out.close();
+ }
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "hashTable_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ delete hashMap;
+ delete threads;
+ delete threadId;
+}

Added: sandbox/stm/libs/stm/test/testHashMap.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testHashMap.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef HASH_MAP_H
+#define HASH_MAP_H
+
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/stm/transaction.hpp>
+#include "testLinkedList.h"
+
+void TestHashMapWithMultipleThreads();
+
+namespace nHashMap
+{
+ int const kBuckets = 256;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class HashMap
+{
+public:
+
+ bool lookup(T &val)
+ {
+ return buckets_[val % nHashMap::kBuckets].lookup(val);
+ }
+
+ bool insert(list_node<T> &element)
+ {
+ return buckets_[element.value() % nHashMap::kBuckets].insert(element);
+ }
+
+ bool remove(list_node<T> &v)
+ {
+ return buckets_[v.value() % nHashMap::kBuckets].remove(v);
+ }
+
+ size_t walk_size()
+ {
+ size_t count = 0;
+ for (int i = 0; i < nHashMap::kBuckets; ++i)
+ {
+ count += buckets_[i].walk_size();
+ }
+
+ return count;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ void outputList(std::ofstream &o)
+ {
+ for (int i = 0; i < nHashMap::kBuckets; ++i)
+ {
+ buckets_[i].outputList(o);
+ }
+ }
+
+private:
+ LinkedList<T> buckets_[nHashMap::kBuckets];
+};
+
+#endif // HASH_MAP_H

Added: sandbox/stm/libs/stm/test/testHashMapAndLinkedListsWithLocks.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testHashMapAndLinkedListsWithLocks.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,478 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include "testHashMapAndLinkedListsWithLocks.h"
+#include <fstream>
+#include <sstream>
+
+static LATM::HashMap<int> *globalHashMap = NULL;
+static LATM::LinkedList<int> *globalLinkedList = NULL;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm; using namespace LATM::nHashMap;
+using namespace nMain;
+
+
+#if 0
+native_trans<int> arr1[99], arr2[99];
+
+void tx1() { /* no conflict */ }
+void tx2() { /* no conflict */ }
+
+void tx3() {
+ for (transaction t;;t.restart())
+ try {
+ for (int i = 0; i < 99; ++i)
+ {
+ ++t.w(arr1[i]).value();
+ ++t.w(arr2[i]).value();
+ }
+ t.end(); break;
+ } catch (abort_tx&) {}
+}
+
+int lock1() {
+ lock(L1); int sum = 0;
+ for (int i = 0; i < 99; ++i) sum += arr1[i];
+ unlock(L1); return sum;
+}
+
+int lock2() {
+ lock(L2); int sum = 0;
+ for (int i = 0; i < 99; ++i) sum += arr2[i];
+ unlock(L2); return sum;
+}
+
+int lock3() { /* no conflict */ }
+
+#endif
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInsertsWithLocks(void *threadId)
+{
+ LATM::list_node<int> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalLinkedList->lock_insert(node);
+ }
+
+ if (kDoMove)
+ {
+ LATM::list_node<int> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ globalLinkedList->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ if (!globalLinkedList->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalLinkedList->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInserts(void *threadId)
+{
+ LATM::list_node<int> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalLinkedList->insert(node);
+ }
+
+ if (kDoMove)
+ {
+ LATM::list_node<int> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ globalLinkedList->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!globalLinkedList->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalLinkedList->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestHashMapInserts(void *threadId)
+{
+ LATM::list_node<int> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ //cout << "i: " << startingValue << endl;
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalHashMap->insert(node);
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ if (!globalHashMap->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalHashMap->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestHashMapInsertsWithLocks(void *threadId)
+{
+ LATM::list_node<int> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ //cout << "i: " << startingValue << endl;
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalHashMap->lock_insert(node);
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ if (!globalHashMap->lock_lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalHashMap->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void DoHashMapAndLinkedListOutput(int threadsDoingHashMap, int threadsDoingLinkedList)
+{
+ int totalInserts = globalHashMap->walk_size();
+ int runTime = endTimer - startTimer;
+
+ if (runTime < 1) runTime = 1;
+
+ cout << "LATM: " << transaction::latm_protection_str() << endl << endl;
+ cout << "HT: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << runTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / runTime << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * threadsDoingHashMap))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN HASH MAP - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+
+ ofstream out("testOutput.txt");
+ globalHashMap->outputList(out);
+ out.close();
+ }
+
+ totalInserts = globalLinkedList->walk_size();
+
+ cout << "LL: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << runTime << " ";
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / runTime << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * threadsDoingLinkedList))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN LINKED LIST - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+
+ ofstream out("testOutput.txt");
+ globalLinkedList->outputList(out);
+ out.close();
+ }
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void DoHashMapAndLinkedListInitialization()
+{
+ globalHashMap = new LATM::HashMap<int>;
+ globalLinkedList = new LATM::LinkedList<int>;
+ transaction::initialize();
+
+ if (transaction::doing_tm_lock_protection())
+ {
+ for (int k = 1; k < kBuckets; ++k)
+ {
+ transaction::tm_lock_conflict(globalHashMap->get_hash_lock(k));
+ }
+ }
+
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestHashMapAndLinkedListWithLocks()
+{
+ DoHashMapAndLinkedListInitialization();
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ int hashingThreads = 0, listThreads = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ if (0 == j % 2) pthread_create(&threads[j], NULL, TestHashMapInserts, (void *)&threadId[j]);
+ else pthread_create(&threads[j], NULL, TestHashMapInsertsWithLocks, (void *)&threadId[j]);
+ //pthread_create(&threads[j], NULL, TestLinkedListInserts, (void *)&threadId[j]);
+ ++hashingThreads;
+ }
+
+ int mainThreadId = kMaxThreads-1;
+ TestLinkedListInsertsWithLocks((void*)&mainThreadId);
+ ++listThreads;
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ DoHashMapAndLinkedListOutput(hashingThreads, listThreads);
+
+ delete globalHashMap;
+ delete threads;
+ delete threadId;
+}
+

Added: sandbox/stm/libs/stm/test/testHashMapAndLinkedListsWithLocks.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testHashMapAndLinkedListsWithLocks.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,24 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef HASH_MAP_AND_LINKED_LISTS_WITH_LOCKS_H
+#define HASH_MAP_AND_LINKED_LISTS_WITH_LOCKS_H
+
+///////////////////////////////////////////////////////////////////////////////
+#include "testHashMapWithLocks.h"
+#include "testLinkedListWithLocks.h"
+
+void TestHashMapAndLinkedListWithLocks();
+
+#endif // HASH_MAP_H

Added: sandbox/stm/libs/stm/test/testHashMapWithLocks.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testHashMapWithLocks.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,256 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include "testHashMapWithLocks.h"
+#include <fstream>
+#include <sstream>
+
+static LATM::HashMap<int> *globalHashMap = NULL;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm; using namespace LATM::nHashMap;
+using namespace nMain;
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestHashMapInserts(void *threadId)
+{
+ LATM::list_node<int> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ //cout << "i: " << startingValue << endl;
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalHashMap->insert(node);
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ if (!globalHashMap->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalHashMap->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestHashMapInsertsWithLocks(void *threadId)
+{
+ LATM::list_node<int> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+ //cout << "i: " << startingValue << endl;
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalHashMap->lock_insert(node);
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ if (!globalHashMap->lock_lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ globalHashMap->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void DoHashMapOutput()
+{
+ int totalInserts = globalHashMap->walk_size();
+ int runTime = endTimer - startTimer;
+
+ if (runTime < 1) runTime = 1;
+
+ cout << "HT: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << runTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / runTime << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * kMaxThreads))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN HASH MAP - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+
+ ofstream out("testOutput.txt");
+ globalHashMap->outputList(out);
+ out.close();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void DoHashMapInitialization()
+{
+ globalHashMap = new LATM::HashMap<int>;
+ transaction::initialize();
+
+ transaction::do_full_lock_protection();
+
+#if 0
+ transaction::do_tm_conflicting_lock_protection();
+
+ for (int k = 1; k < kBuckets; ++k)
+ {
+ transaction::add_tm_conflicting_lock(globalHashMap->get_hash_lock(k));
+ }
+#endif
+
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestHashMapWithLocks()
+{
+ DoHashMapInitialization();
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ if (0 == j % 2) pthread_create(&threads[j], NULL, TestHashMapInserts, (void *)&threadId[j]);
+ else pthread_create(&threads[j], NULL, TestHashMapInsertsWithLocks, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+ TestHashMapInsertsWithLocks((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ DoHashMapOutput();
+
+ delete globalHashMap;
+ delete threads;
+ delete threadId;
+}
+

Added: sandbox/stm/libs/stm/test/testHashMapWithLocks.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testHashMapWithLocks.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,90 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef HASH_MAP_WITH_LOCKS_H
+#define HASH_MAP_WITH_LOCKS_H
+
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/stm/transaction.hpp>
+#include "testLinkedListWithLocks.h"
+
+void TestHashMapWithLocks();
+
+namespace LATM
+{
+ namespace nHashMap
+ {
+ int const kBuckets = 256;
+ }
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class HashMap
+{
+public:
+
+ bool lock_lookup(T &val)
+ {
+ return buckets_[val % nHashMap::kBuckets].lock_lookup(val);
+ }
+
+ bool lock_insert(list_node<T> &element)
+ {
+ return buckets_[element.value() % nHashMap::kBuckets].lock_insert(element);
+ }
+
+ bool lookup(T &val)
+ {
+ return buckets_[val % nHashMap::kBuckets].lookup(val);
+ }
+
+ bool insert(list_node<T> &element)
+ {
+ return buckets_[element.value() % nHashMap::kBuckets].insert(element);
+ }
+
+ bool remove(list_node<T> &v)
+ {
+ return buckets_[v.value() % nHashMap::kBuckets].remove(v);
+ }
+
+ size_t walk_size()
+ {
+ size_t count = 0;
+ for (int i = 0; i < nHashMap::kBuckets; ++i)
+ {
+ count += buckets_[i].walk_size();
+ }
+
+ return count;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ void outputList(std::ofstream &o)
+ {
+ for (int i = 0; i < nHashMap::kBuckets; ++i)
+ {
+ buckets_[i].outputList(o);
+ }
+ }
+
+ Mutex* get_hash_lock(int val) { return buckets_[val].get_list_lock(); }
+
+private:
+ LATM::LinkedList<T> buckets_[nHashMap::kBuckets];
+};
+
+} // namespace LATM
+
+#endif // HASH_MAP_H

Added: sandbox/stm/libs/stm/test/testInt.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testInt.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,99 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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 "testInt.h"
+#include <boost/stm/transaction.hpp>
+
+Integer *globalInt = NULL;
+
+////////////////////////////////////////////////////////////////////////////
+namespace nIntTest
+{
+ int const kMaxInserts = 75000;
+ int const kMaxThreads = 10;
+}
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm; using namespace nIntTest;
+
+#if USING_INTEGER_IMPL
+//MemoryPool<IntegerImpl> IntegerImpl::memory_(200000);
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+void innerFun()
+{
+ transaction t;
+ ++t.write(*globalInt).value();
+ t.end();
+}
+
+////////////////////////////////////////////////////////////////////////////
+bool intThreadsHaveCommitted()
+{
+ if (globalInt->value() >= kMaxThreads * kMaxInserts) return true;
+ else return false;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+void* TestCount(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId - 1;
+
+ int startingValue = start * 100000;
+ int endingValue = startingValue + kMaxInserts;
+
+ for (int i = startingValue; i < endingValue; ++i)
+ {
+ while (true)
+ {
+ try { innerFun(); break; }
+ catch (...) {}
+ }
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestInt()
+{
+ transaction::initialize();
+ globalInt = new Integer;
+
+ pthread_t threads[kMaxThreads];
+ int rc;
+
+ for (int i = 0; i < kMaxThreads; ++i)
+ {
+ cout << "Creating thread: " << i << endl;
+ rc = pthread_create(&threads[i], NULL, TestCount, (void *)&i);
+
+ if (rc)
+ {
+ cerr << "ERROR; return code from pthread_create() is: " << rc << endl;
+ exit(-1);
+ }
+ }
+
+ while (!intThreadsHaveCommitted()) { SLEEP(70); }
+
+ cout << "RUN_TIME: " << clock() << "\t";
+ cout << "THREADS: " << kMaxThreads << "\t";
+ cout << endl << transaction::bookkeeping();
+
+ cout << endl << globalInt->value() << endl;
+}
+

Added: sandbox/stm/libs/stm/test/testInt.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testInt.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,47 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TEST_INT_H
+#define TEST_INT_H
+
+#include <boost/stm/transaction.hpp>
+
+////////////////////////////////////////////////////////////////////////////
+// Int Transaction class
+////////////////////////////////////////////////////////////////////////////
+class Integer : public boost::stm::transaction_object<Integer>
+{
+public:
+
+ Integer() : value_(0) {}
+
+#if BUILD_MOVE_SEMANTICS
+ //--------------------------------------------------
+ // move semantics
+ //--------------------------------------------------
+ Integer(Integer &&rhs) { value_ = rhs.value_;}
+ Integer& operator=(Integer &&rhs)
+ { value_ = rhs.value_; return *this; }
+#endif
+
+ int &value() { return value_; }
+ int const &value() const { return value_; }
+
+private:
+
+ int value_;
+};
+
+void TestInt();
+
+#endif

Added: sandbox/stm/libs/stm/test/testLL_latm.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testLL_latm.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,370 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <sstream>
+#include "testLL_latm.h"
+
+typedef int list_node_type;
+
+int const kMaxThreadsWhenTestingSets = 128;
+// Subtract one max linked list per complete set of four threads
+int const kMaxLinkedLists = kMaxThreadsWhenTestingSets - ((kMaxThreadsWhenTestingSets + 1) / 4);
+static LATM::LinkedList< list_node_type > *llist[kMaxLinkedLists] = { NULL };
+bool usingSingleList = false;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+////////////////////////////////////////////////////////////////////////////
+int convertThreadIdToLinkedListIndex(int id)
+{
+ //------------------------------------------------------------------------------
+ // In set testing, threads are created in groups of four, assigned sequentially
+ // to sets of three linked lists with the last pair of threads sharing a list:
+ // trans -> list A
+ // lock -> list B
+ // trans + lock -> list C
+ //
+ // Thus, for every set of four incremental thread ids, the linked list index
+ // increments only with the first three incremental thread ids.
+ //------------------------------------------------------------------------------
+ return id - ((id + 1) / 4);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInsertsWithLocks(void *threadId)
+{
+ LATM::list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ int llindex = convertThreadIdToLinkedListIndex(start);
+ if (usingSingleList) llindex = 0;
+
+ //cout << "L" << llindex << endl;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist[llindex]->lock_insert(node);
+ }
+
+
+ if (kDoMove)
+ {
+ LATM::list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist[llindex]->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!llist[llindex]->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist[llindex]->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInserts(void *threadId)
+{
+ LATM::list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ int llindex = convertThreadIdToLinkedListIndex(start);
+ if (usingSingleList) llindex = 0;
+
+ //cout << "T" << llindex << endl;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist[llindex]->insert(node);
+ }
+
+ if (kDoMove)
+ {
+ LATM::list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist[llindex]->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!llist[llindex]->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist[llindex]->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+void TestLinkedListSetsWithLocks()
+{
+ static std::vector<int> runVector;
+ int iterations = 0;
+
+ usingSingleList = false;
+
+ if (kMaxThreads > kMaxThreadsWhenTestingSets)
+ {
+ kMaxThreads = kMaxThreadsWhenTestingSets;
+ std::cout << "Limiting max threads to " << kMaxThreadsWhenTestingSets << "." << endl;
+ }
+ else if (kMaxThreads % 4 != 0)
+ {
+ // threads are always in multiples of four: transaction, lock, and transaction + lock
+ kMaxThreads += (4 - (kMaxThreads % 4));
+ std::cout << "Rounding max threads to the next multiple of 4 (" << kMaxThreads << ")." << endl;
+ }
+
+ kMainThreadId = kMaxThreads-1;
+ int lists = (kMaxThreads / 4) * 3;
+
+ for (int k = 0; k < kMaxThreads; ++k)
+ {
+ llist[k] = new LATM::LinkedList<list_node_type>;
+
+ transaction::initialize();
+ transaction::initialize_thread();
+
+ int index = convertThreadIdToLinkedListIndex(k);
+
+ //----------------------------------------------------------------
+ // every 4th thread works on the same linked list that
+ // the 3rd thread is working on, so only add that conflict
+ //----------------------------------------------------------------
+ if (transaction::doing_tm_lock_protection() && 0 == (k+1) % 2)
+ {
+ //transaction::add_tm_conflicting_lock(llist[index]->get_list_lock());
+ //cout << "TM-lock conflict added: " << index << endl;
+ }
+ }
+
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ if (0 == j % 2) pthread_create(&threads[j], NULL, TestLinkedListInserts, (void *)&threadId[j]);
+ else pthread_create(&threads[j], NULL, TestLinkedListInsertsWithLocks, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestLinkedListInsertsWithLocks((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ int totalInserts = 0;
+ for (int m = 0; m < kMaxThreads; ++m)
+ {
+ totalInserts += llist[m]->walk_size();
+ }
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (int i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << "LL: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << averageRunTime << " " << "AVE: " << totalAverageRunTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / (totalAverageRunTime * runVector.size()) << endl;
+ cout << transaction::bookkeeping() << endl;
+
+#if 0
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * kMaxThreads))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN LINKED LIST - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+ }
+
+ ofstream outTest("testOutput.txt");
+ for (int p = 0; p < kMaxThreads; ++p)
+ {
+ llist[p]->outputList(outTest);
+ }
+ outTest.close();
+#endif
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "linkedList_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ for (int q = 0; q < kMaxThreads; ++q)
+ {
+ delete llist[q];
+ }
+ delete threads;
+ delete threadId;
+}

Added: sandbox/stm/libs/stm/test/testLL_latm.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testLL_latm.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,551 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef TEST_LINKED_LIST_WITH_LOCKS_H
+#define TEST_LINKED_LIST_WITH_LOCKS_H
+
+#include "main.h"
+#include <boost/stm/transaction.hpp>
+#include <pthread.h>
+#include <fstream>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace LATM
+{
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename T>
+class list_node : public boost::stm::transaction_object< list_node<T> >
+{
+public:
+
+ list_node() : value_(0), next_(0) {}
+ explicit list_node(int const &rhs) : value_(rhs), next_(NULL) {}
+
+ // zero initialization for native types
+ void clear() { value_ = T(); next_ = NULL; }
+
+ T &value() { return value_; }
+ T const &value() const { return value_; }
+
+ list_node *next() { return next_; }
+ list_node const *next() const { return next_; }
+
+ void next(list_node const *rhs) { next_ = (list_node*)rhs; }
+
+ void next(list_node const *rhs, boost::stm::transaction &t)
+ {
+ if (NULL == rhs) next_ = NULL;
+ else next_ = &t.find_original(*(list_node*)rhs);
+ }
+
+ void next_for_new_mem(list_node *rhs, boost::stm::transaction &t)
+ {
+ if (NULL == rhs) next_ = NULL;
+ else next_ = &t.find_original(*rhs);
+ }
+
+#if BUILD_MOVE_SEMANTICS
+ list_node& operator=(list_node const & rhs)
+ {
+ value_ = rhs.value_;
+ next_ = rhs.next_;
+ return *this;
+ }
+
+ list_node(list_node &&rhs) : next_(rhs.next_), value_(boost::stm::draco_move(rhs.value_))
+ { rhs.next_ = 0; }
+
+ list_node& operator=(list_node&& rhs)
+ {
+ value_ = boost::stm::draco_move(rhs.value_);
+ std::swap(next_, rhs.next_);
+ return *this;
+ }
+#endif
+
+
+private:
+
+ list_node *next_;
+ T value_;
+};
+
+////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class LinkedList
+{
+public:
+
+ LinkedList()
+ {
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ pthread_mutex_init (&list_lock_, NULL);
+#endif
+ head_.value() = T();
+ }
+
+ ~LinkedList() { quick_clear(); }
+
+ Mutex* get_list_lock() { return &list_lock_; }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool move(list_node<T> const &node1, list_node<T> 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)
+ {
+ using namespace boost::stm;
+
+ transaction t;
+
+ if (transaction::doing_tx_lock_protection())
+ {
+ t.lock_conflict(&list_lock_);
+ }
+ else if (transaction::doing_tm_lock_protection())
+ {
+ transaction::tm_lock_conflict(&list_lock_);
+ }
+
+ for (; ;t.restart())
+ {
+ try {
+ if (!lock_lookup(node.value()))
+ {
+ lock_insert(node);
+ t.end();
+ return true;
+ }
+ else
+ {
+ t.end();
+ return true;
+ }
+ }
+ catch (aborted_transaction_exception&) {}
+ catch (char const *err) { std::cout << "error: " << err << std::endl; }
+ }
+
+#if 0
+ for (; ;t.restart())
+ {
+ try { return internal_insert(node, t); }
+ catch (aborted_transaction_exception&) {}
+ }
+#endif
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lookup(T const &val)
+ {
+ using namespace boost::stm;
+
+ transaction t;
+
+ if (eTxConflictingLockLatmProtection == transaction::latm_protection())
+ {
+ t.add_tx_conflicting_lock(&list_lock_);
+ }
+
+ for (; ; t.restart())
+ {
+ try { return internal_lookup(val, t); }
+ catch (aborted_transaction_exception&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lock_insert(list_node<T> const &rhs)
+ {
+ using namespace boost::stm;
+ transaction::lock_(&list_lock_);
+
+ list_node<T> *headP = &head_;
+
+ if (NULL != headP->next())
+ {
+ list_node<T> *prev = headP;
+ list_node<T> *cur = headP->next();
+ T val = rhs.value();
+
+ while (true)
+ {
+ if (cur->value() == val)
+ {
+ transaction::unlock_(&list_lock_);
+ return false;
+ }
+ else if (cur->value() > val || !cur->next()) break;
+
+ prev = cur;
+
+ list_node<T> *curNext = cur->next();
+
+ if (NULL == curNext) break;
+
+ cur = curNext;
+ }
+
+ list_node<T> *newNode = new list_node<T>(rhs);
+
+ //--------------------------------------------------------------------
+ // if cur->next() is null it means our newNode value is greater than
+ // cur, so insert ourselves after cur.
+ //--------------------------------------------------------------------
+ if (NULL == cur->next()) cur->next(newNode);
+ //--------------------------------------------------------------------
+ // otherwise, we are smaller than cur, so insert between prev and cur
+ //--------------------------------------------------------------------
+ else
+ {
+ newNode->next(cur);
+ prev->next(newNode);
+ }
+ }
+ else
+ {
+ list_node<T> *newNode = new list_node<T>(rhs);
+ head_.next(newNode);
+ }
+
+ transaction::unlock_(&list_lock_);
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lock_lookup(T const &val)
+ {
+ using namespace boost::stm;
+ transaction::lock_(&list_lock_);
+
+ LATM::list_node<T> *cur = &head_;
+
+ for (; ; cur = cur->next() )
+ {
+ if (cur->value() == val)
+ {
+ transaction::unlock_(&list_lock_);
+ return true;
+ }
+
+ if (NULL == cur->next()) break;
+ }
+
+ transaction::unlock_(&list_lock_);
+ return false;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool remove(list_node<T> const &node)
+ {
+ using namespace boost::stm;
+ bool succeeded = true;
+
+ for (transaction t; ; t.restart())
+ {
+ try { return internal_remove(node, t); }
+ catch (aborted_transaction_exception&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void outputList(std::ofstream &o)
+ {
+ int i = 0;
+ for (list_node<T> *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> *cur = head_.next(); cur != NULL; cur = cur->next())
+ {
+ ++i;
+ }
+
+ return i;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void quick_clear()
+ {
+ for (list_node<T> *cur = head_.next(); cur != NULL;)
+ {
+ list_node<T> *prev = cur;
+ cur = cur->next();
+ delete prev;
+ }
+
+ head_.clear();
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void clear()
+ {
+ using namespace boost::stm;
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ for (list_node<T> *cur = t.read(head_).next(); cur != NULL;)
+ {
+ list_node<T> *prev = &t.read(*cur);
+ cur = t.read(*cur).next();
+ t.delete_memory(*prev);
+ }
+
+ t.write(head_).clear();
+ t.end();
+ }
+ catch (aborted_transaction_exception&) {}
+ }
+ }
+
+private:
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, bail
+ //--------------------------------------------------------------------------
+ bool internal_insert(list_node<T> const &rhs, boost::stm::transaction &t)
+ {
+ list_node<T> *headP = &t.read(head_);
+
+ if (NULL != headP->next())
+ {
+ list_node<T> *prev = headP;
+ list_node<T> *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> *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(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(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);
+ }
+
+ t.end();
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, bail
+ //--------------------------------------------------------------------------
+ bool internal_lookup(T const &val, boost::stm::transaction &t)
+ {
+ list_node<T> *cur = &t.read(head_);
+
+ for (; true ; cur = t.read(*cur).next() )
+ {
+ list_node<T> *trueCur = &t.read(*cur);
+
+ if (trueCur->value() == val)
+ {
+ t.end();
+ return true;
+ }
+
+ if (NULL == trueCur->next()) break;
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool internal_remove(list_node<T> const &rhs, 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 (NULL == cur) break;
+
+ if (cur->value() == rhs.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);
+ }
+
+ t.end();
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ 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;
+ }
+ }
+
+ return false;
+ }
+
+public:
+
+ list_node<T> head_;
+ Mutex list_lock_;
+};
+
+} // LockAwareTransactions
+
+void TestLinkedListWithLocks();
+void TestLinkedListSetsWithLocks();
+
+#endif // TEST_LINKED_LIST_H

Added: sandbox/stm/libs/stm/test/testLinkedList.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testLinkedList.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,209 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <sstream>
+#include "testLinkedList.h"
+
+typedef int list_node_type;
+
+LinkedList< list_node_type > *llist = NULL;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInserts(void *threadId)
+{
+ list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->insert(node);
+ }
+
+ if (kDoMove)
+ {
+ list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ if (!llist->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestLinkedListWithMultipleThreads()
+{
+ static std::vector<int> runVector;
+
+ llist = new LinkedList<list_node_type>;
+ transaction::initialize();
+ transaction::initialize_thread();
+ //transaction::do_direct_updating();
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, TestLinkedListInserts, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestLinkedListInserts((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ int totalInserts = llist->walk_size();
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (int i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << "LL: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << averageRunTime << " " << "AVE: " << totalAverageRunTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / (totalAverageRunTime * runVector.size()) << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * kMaxThreads))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN LINKED LIST - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+
+ ofstream out("testOutput.txt");
+ llist->outputList(out);
+ out.close();
+ }
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "linkedList_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ delete llist;
+ delete threads;
+ delete threadId;
+}

Added: sandbox/stm/libs/stm/test/testLinkedList.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testLinkedList.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,391 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef TEST_LINKED_LIST_H
+#define TEST_LINKED_LIST_H
+
+#include "main.h"
+#include <boost/stm/transaction.hpp>
+
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class list_node : public boost::stm::transaction_object< list_node<T> >
+{
+public:
+
+ list_node() : value_(0), next_(0) {}
+ explicit list_node(int const &rhs) : value_(rhs), next_(NULL) {}
+
+ // zero initialization for native types
+ void clear() { value_ = T(); next_ = NULL; }
+
+ T &value() { return value_; }
+ T const &value() const { return value_; }
+
+ list_node const *next() const { return next_; }
+
+ void next(list_node const *rhs, boost::stm::transaction &t)
+ {
+ if (NULL == rhs) next_ = NULL;
+ else next_ = &t.find_original(*(list_node<T>*)rhs);
+ }
+
+ void next_for_new_mem(list_node const *rhs, boost::stm::transaction &t)
+ {
+ if (NULL == rhs) next_ = NULL;
+ else next_ = &t.find_original(*(list_node<T>*)rhs);
+ }
+
+#if BUILD_MOVE_SEMANTICS
+ list_node& operator=(list_node const & rhs)
+ {
+ value_ = rhs.value_;
+ next_ = rhs.next_;
+ return *this;
+ }
+
+ list_node(list_node &&rhs) : next_(rhs.next_), value_(boost::stm::draco_move(rhs.value_))
+ { rhs.next_ = 0; }
+
+ list_node& operator=(list_node&& rhs)
+ {
+ value_ = boost::stm::draco_move(rhs.value_);
+ std::swap(next_, rhs.next_);
+ return *this;
+ }
+#endif
+
+
+private:
+
+ list_node *next_;
+ T value_;
+};
+
+////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class LinkedList
+{
+public:
+
+ LinkedList() { head_.value() = T(); }
+
+ ~LinkedList() { quick_clear(); }
+
+ bool move(list_node<T> const &node1, list_node<T> 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)
+ {
+ using namespace boost::stm;
+
+ for (transaction t; ;t.restart())
+ {
+ try { return internal_insert(node, t); }
+ catch (aborted_transaction_exception&) {}
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ bool lookup(T const &val)
+ {
+ using namespace boost::stm;
+
+ for (transaction t; ; t.restart())
+ {
+ try { return internal_lookup(val, t); }
+ catch (aborted_transaction_exception&) {}
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ bool remove(list_node<T> const &node)
+ {
+ using namespace boost::stm;
+
+ for (transaction t; ; t.restart())
+ {
+ try { return internal_remove(node, t); }
+ catch (aborted_transaction_exception&) {}
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ 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()
+ {
+ boost::stm::transaction t;
+
+ for (list_node<T> const *cur = t.read(head_).next(); cur != NULL;)
+ {
+ list_node<T> const *prev = &t.read(*cur);
+ cur = t.read(*cur).next();
+ t.delete_memory(*prev);
+ }
+
+ t.write(head_).clear();
+
+ return t.end();
+ }
+
+private:
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, bail
+ //--------------------------------------------------------------------------
+ bool internal_insert(list_node<T> const &rhs, 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 (val > cur->value()) 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);
+ }
+
+ t.end();
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, bail
+ //--------------------------------------------------------------------------
+ bool internal_lookup(T const &val, boost::stm::transaction &t)
+ {
+ list_node<T> const *cur = &t.read(head_);
+
+ for (; true ; cur = t.read(*cur).next() )
+ {
+ list_node<T> const *trueCur = &t.read(*cur);
+
+ if (trueCur->value() == val)
+ {
+ t.end();
+ return true;
+ }
+
+ if (NULL == trueCur->next()) break;
+ }
+
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ bool internal_remove(list_node<T> const &rhs, 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 (NULL == cur) break;
+
+ if (cur->value() == rhs.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);
+ }
+
+ t.end();
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ 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;
+ }
+ }
+
+ return false;
+ }
+
+ list_node<T> head_;
+};
+
+void TestLinkedListWithMultipleThreads();
+void* TestThreadLinkedList(void *threadId);
+
+#endif // TEST_LINKED_LIST_H

Added: sandbox/stm/libs/stm/test/testLinkedListWithLocks.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testLinkedListWithLocks.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,299 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <sstream>
+#include "testLinkedListWithLocks.h"
+
+typedef int list_node_type;
+
+static LATM::LinkedList< list_node_type > *llist = NULL;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInsertsWithLocks(void *threadId)
+{
+ LATM::list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->lock_insert(node);
+ }
+
+ if (kDoMove)
+ {
+ LATM::list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!llist->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInserts(void *threadId)
+{
+ LATM::list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->insert(node);
+ }
+
+ if (kDoMove)
+ {
+ LATM::list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!llist->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestLinkedListWithLocks()
+{
+ static std::vector<int> runVector;
+ int iterations = 0;
+
+ llist = new LATM::LinkedList<list_node_type>;
+ transaction::initialize();
+ transaction::initialize_thread();
+
+ transaction::tm_lock_conflict(llist->get_list_lock());
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ if (0 == j % 2) pthread_create(&threads[j], NULL, TestLinkedListInserts, (void *)&threadId[j]);
+ else pthread_create(&threads[j], NULL, TestLinkedListInsertsWithLocks, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestLinkedListInsertsWithLocks((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ int totalInserts = llist->walk_size();
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (int i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << "LL: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << averageRunTime << " " << "AVE: " << totalAverageRunTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / (totalAverageRunTime * runVector.size()) << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * kMaxThreads))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN LINKED LIST - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+
+ ofstream out("testOutput.txt");
+ llist->outputList(out);
+ out.close();
+ }
+
+ ofstream outTest("testOutput.txt");
+ llist->outputList(outTest);
+ outTest.close();
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "linkedList_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ delete llist;
+ delete threads;
+ delete threadId;
+}

Added: sandbox/stm/libs/stm/test/testLinkedListWithLocks.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testLinkedListWithLocks.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,526 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef TEST_LINKED_LIST_WITH_LOCKS_H
+#define TEST_LINKED_LIST_WITH_LOCKS_H
+
+#include "main.h"
+#include <boost/stm/transaction.hpp>
+#include <pthread.h>
+
+#include <fstream>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace LATM
+{
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename T>
+class list_node : public boost::stm::transaction_object< list_node<T> >
+{
+public:
+
+ list_node() : value_(0), next_(0) {}
+ explicit list_node(int const &rhs) : value_(rhs), next_(NULL) {}
+
+ // zero initialization for native types
+ void clear() { value_ = T(); next_ = NULL; }
+
+ T &value() { return value_; }
+ T const &value() const { return value_; }
+
+ list_node *next() { return next_; }
+ list_node const *next() const { return next_; }
+
+ void next(list_node const *rhs) { next_ = (list_node*)rhs; }
+
+ void next(list_node const *rhs, boost::stm::transaction &t)
+ {
+ if (NULL == rhs) next_ = NULL;
+ else next_ = (list_node*)&t.find_original(*rhs);
+ }
+
+ void next_for_new_mem(list_node *rhs, boost::stm::transaction &t)
+ {
+ if (NULL == rhs) next_ = NULL;
+ else next_ = &t.find_original(*rhs);
+ }
+
+#if BUILD_MOVE_SEMANTICS
+ list_node& operator=(list_node const & rhs)
+ {
+ value_ = rhs.value_;
+ next_ = rhs.next_;
+ return *this;
+ }
+
+ list_node(list_node &&rhs) : next_(rhs.next_), value_(boost::stm::draco_move(rhs.value_))
+ { rhs.next_ = 0; }
+
+ list_node& operator=(list_node&& rhs)
+ {
+ value_ = boost::stm::draco_move(rhs.value_);
+ std::swap(next_, rhs.next_);
+ return *this;
+ }
+#endif
+
+
+private:
+
+ list_node *next_;
+ T value_;
+};
+
+////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class LinkedList
+{
+public:
+
+ LinkedList()
+ {
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ pthread_mutex_init (&list_lock_, NULL);
+#endif
+ head_.value() = T();
+ }
+
+ ~LinkedList() { quick_clear(); }
+
+ Mutex* get_list_lock() { return &list_lock_; }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool move(list_node<T> const &node1, list_node<T> 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 (boost::stm::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)
+ {
+ using namespace boost::stm;
+
+ transaction t;
+
+ if (eTxConflictingLockLatmProtection == transaction::latm_protection())
+ {
+ t.add_tx_conflicting_lock(&list_lock_);
+ }
+
+ for (; ;t.restart())
+ {
+ try { return internal_insert(node, t); }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lookup(T const &val)
+ {
+ using namespace boost::stm;
+
+ transaction t;
+
+ if (eTxConflictingLockLatmProtection == transaction::latm_protection())
+ {
+ t.add_tx_conflicting_lock(&list_lock_);
+ }
+
+ for (; ; t.restart())
+ {
+ try { return internal_lookup(val, t); }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lock_insert(list_node<T> const &rhs)
+ {
+ using namespace boost::stm;
+ transaction::lock_(&list_lock_);
+
+ list_node<T> *headP = &head_;
+
+ if (NULL != headP->next())
+ {
+ list_node<T> *prev = headP;
+ list_node<T> *cur = headP->next();
+ T val = rhs.value();
+
+ while (true)
+ {
+ if (cur->value() == val)
+ {
+ transaction::unlock_(&list_lock_);
+ return false;
+ }
+ else if (cur->value() > val || !cur->next()) break;
+
+ prev = cur;
+
+ list_node<T> *curNext = cur->next();
+
+ if (NULL == curNext) break;
+
+ cur = curNext;
+ }
+
+ list_node<T> *newNode = new list_node<T>(rhs);
+
+ //--------------------------------------------------------------------
+ // if cur->next() is null it means our newNode value is greater than
+ // cur, so insert ourselves after cur.
+ //--------------------------------------------------------------------
+ if (NULL == cur->next()) cur->next(newNode);
+ //--------------------------------------------------------------------
+ // otherwise, we are smaller than cur, so insert between prev and cur
+ //--------------------------------------------------------------------
+ else
+ {
+ newNode->next(cur);
+ prev->next(newNode);
+ }
+ }
+ else
+ {
+ list_node<T> *newNode = new list_node<T>(rhs);
+ head_.next(newNode);
+ }
+
+ transaction::unlock_(&list_lock_);
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lock_lookup(T const &val)
+ {
+ using namespace boost::stm;
+ transaction::lock_(&list_lock_);
+
+ LATM::list_node<T> *cur = &head_;
+
+ for (; ; cur = cur->next() )
+ {
+ if (cur->value() == val)
+ {
+ transaction::unlock_(&list_lock_);
+ return true;
+ }
+
+ if (NULL == cur->next()) break;
+ }
+
+ transaction::unlock_(&list_lock_);
+ return false;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool remove(list_node<T> const &node)
+ {
+ using namespace boost::stm;
+ bool succeeded = true;
+
+ for (transaction t; ; t.restart())
+ {
+ try { return internal_remove(node, t); }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void outputList(std::ofstream &o)
+ {
+ int i = 0;
+ for (list_node<T> *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> *cur = head_.next(); cur != NULL; cur = cur->next())
+ {
+ ++i;
+ }
+
+ return i;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void quick_clear()
+ {
+ for (list_node<T> *cur = head_.next(); cur != NULL;)
+ {
+ list_node<T> *prev = cur;
+ cur = cur->next();
+ delete prev;
+ }
+
+ head_.clear();
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void clear()
+ {
+ using namespace boost::stm;
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ for (list_node<T> *cur = t.read(head_).next(); cur != NULL;)
+ {
+ list_node<T> *prev = &t.read(*cur);
+ cur = t.read(*cur).next();
+ t.delete_memory(*prev);
+ }
+
+ t.write(head_).clear();
+ t.end();
+ }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+ }
+
+private:
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, bail
+ //--------------------------------------------------------------------------
+ bool internal_insert(list_node<T> const &rhs, 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((list_node<T>*)cur, t);
+ t.write_ptr((list_node<T>*)prev)->next_for_new_mem((list_node<T>*)newNode, t);
+ }
+ }
+ else
+ {
+ list_node<T> *newNode = t.new_memory_copy(rhs);
+ t.write(head_).next_for_new_mem(newNode, t);
+ }
+
+ t.end();
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, bail
+ //--------------------------------------------------------------------------
+ bool internal_lookup(T const &val, boost::stm::transaction &t)
+ {
+ list_node<T> const *cur = &t.read(head_);
+
+ for (; true ; cur = t.read(*cur).next() )
+ {
+ list_node<T> const *trueCur = &t.read(*cur);
+
+ if (trueCur->value() == val)
+ {
+ t.end();
+ return true;
+ }
+
+ if (NULL == trueCur->next()) break;
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool internal_remove(list_node<T> const &rhs, 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 (NULL == cur) break;
+
+ if (cur->value() == rhs.value())
+ {
+ list_node<T> const *curNext = t.read(*cur).next();
+ t.delete_memory(*cur);
+ t.write(*(list_node<T>*)prev).next((list_node<T>*)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((list_node<T>*)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);
+ }
+
+ t.end();
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ 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;
+ }
+ }
+
+ return false;
+ }
+
+ list_node<T> head_;
+ Mutex list_lock_;
+};
+
+} // LockAwareTransactions
+
+void TestLinkedListWithLocks();
+
+#endif // TEST_LINKED_LIST_H
+

Added: sandbox/stm/libs/stm/test/testPerson.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testPerson.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,171 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//---------------------------------------------------------------------------
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#include "transferFun.h"
+#include "main.h"
+#include "testRBTree.h"
+#include <math.h>
+#include <fstream>
+#include <sstream>
+#include <stdlib.h>
+#include "testPerson.h"
+
+//---------------------------------------------------------------------------
+using namespace std; using namespace boost::stm;
+
+//---------------------------------------------------------------------------
+
+named_array<int> intArr;
+named_array<string> strArr;
+
+//---------------------------------------------------------------------------
+
+void norm_fun()
+{
+ int const max = 100; int i;
+
+ intArr.set_name("int array");
+ strArr.set_name("str array");
+
+ intArr.resize(max);
+ strArr.resize(max);
+
+ for (i = 0; i < max; ++i)
+ {
+ intArr.array()[i] = i;
+
+ ostringstream o;
+ o << i;
+
+ strArr.array()[i] = o.str();
+ }
+
+ for (i = 0; i < max; ++i)
+ {
+ cout << intArr.array()[i] << endl;
+ cout << strArr.array()[i] << endl;
+ }
+}
+
+//---------------------------------------------------------------------------
+void trans_fun2()
+{
+ transaction::initialize_thread();
+
+ if (kMoveSemantics) transaction::enable_move_semantics();
+
+ int const max = kMaxArrSize; int i;
+
+ for (transaction t;;)
+ {
+ try
+ {
+ t.w(intArr).set_name("int array");
+ t.w(intArr).resize(max);
+ t.end();
+ break;
+
+ } catch (aborted_transaction_exception&) {}
+ }
+
+ for (i = 0; i < max; ++i)
+ {
+ for (transaction t;;)
+ {
+ try
+ {
+ t.w(intArr).array()[i] = i;
+ t.end();
+ break;
+ } catch (aborted_transaction_exception&) {}
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+void trans_fun()
+{
+ transaction::initialize_thread();
+
+ if (kMoveSemantics) transaction::enable_move_semantics();
+
+ int const max = kMaxArrSize; int i;
+
+ for (transaction t;;)
+ {
+ try
+ {
+ t.w(intArr).set_name("int array");
+ t.w(strArr).set_name("str array");
+
+ t.w(intArr).resize(max);
+ t.w(strArr).resize(max);
+
+ for (i = 0; i < max; ++i)
+ {
+ t.w(intArr).array()[i] = i;
+ ostringstream o;
+ o << i;
+
+ t.w(strArr).array()[i] = o.str();
+ }
+
+ t.end();
+ break;
+ } catch (aborted_transaction_exception&) {}
+ }
+}
+
+//---------------------------------------------------------------------------
+void TestPerson()
+{
+ //------------------------------------------------------------------------
+ // this will prevent any thread 2 from causing the idle until all threads
+ // have reached from breaking
+ //------------------------------------------------------------------------
+ kMaxThreads = 2;
+
+ transaction::initialize();
+ transaction::initialize_thread();
+
+ //trans_fun();
+ trans_fun2();
+
+ cout << "(move semantics, array size, commits, total aborts)\t";
+ cout << transaction::using_move_semantics() << "\t";
+ cout << kMaxArrSize << "\t";
+ cout << transaction::bookkeeping().commits() << "\t";
+ cout << transaction::bookkeeping().totalAborts() << endl;
+
+ exit(0);
+}
+

Added: sandbox/stm/libs/stm/test/testPerson.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testPerson.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,149 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TEST_PERSON_H
+#define TEST_PERSON_H
+
+#include <iostream>
+#include "main.h"
+#include <boost/stm/transaction.hpp>
+
+void TestPerson();
+
+template <typename T>
+class named_array :
+public boost::stm::transaction_object < named_array<T> >
+{
+public:
+
+ friend std::ostream& operator<<(std::ostream &str, named_array<T> const &t)
+ {
+ str << 0 == t.name_ ? "" : t.name();
+ return str;
+ }
+
+ named_array() : name_(0), array_(0), size_(0)
+ {
+ set_name("temp");
+ resize(kMaxArrSize);
+ }
+
+ ~named_array() { delete [] name_; delete [] array_; size_ = 0; }
+
+ char const * const name() const { return name_; }
+ T* array() { return array_; }
+
+ named_array& operator=(T &rhs)
+ {
+ array_[0] = rhs;
+ return *this;
+ }
+
+ bool operator==(T &rhs) { return array_[0] == rhs; }
+
+ bool operator==(named_array const &rhs)
+ {
+ return this->array_[0] == rhs.array_[0];
+ }
+
+ bool operator>(named_array const &rhs) { return this->array_[0] > rhs.array_[0]; }
+
+ //--------------------------------------------------
+ // copy semantics
+ //--------------------------------------------------
+ named_array(named_array const &rhs) : name_(0), array_(0), size_(0)
+ {
+ using namespace std;
+ //cout << "c()";
+ this->operator=(rhs);
+ }
+
+ named_array& operator=(named_array const &rhs)
+ {
+ using namespace std;
+ //cout << "c=";
+ if (0 != rhs.size())
+ {
+ T* tempArray = new T[rhs.size()];
+ delete [] array_;
+
+ array_ = tempArray;
+ size_ = rhs.size();
+
+ for (size_t i = 0; i < size_; ++i) array_[i] = rhs.array_[i];
+ }
+
+ if (0 != rhs.name())
+ {
+ set_name(rhs.name());
+ }
+
+ return *this;
+ }
+
+#if BUILD_MOVE_SEMANTICS
+
+ //--------------------------------------------------
+ // move semantics
+ //--------------------------------------------------
+ named_array(named_array &&rhs)
+ {
+ using namespace std;
+ //cout << "m()";
+ this->array_ = rhs.array_;
+ this->size_ = rhs.size_;
+ this->name_ = rhs.name_;
+ rhs.array_ = 0;
+ rhs.name_ = 0;
+ rhs.size_ = 0;
+ }
+
+ named_array& operator=(named_array &&rhs)
+ {
+ using namespace std;
+ //cout << "m=";
+ std::swap(array_, rhs.array_);
+ std::swap(name_, rhs.name_);
+
+ int tempSize = rhs.size_;
+ rhs.size_ = this->size_;
+ this->size_ = tempSize;
+
+ return *this;
+ }
+#endif
+
+ void set_name(char const * const newName)
+ {
+ delete [] name_;
+ name_ = new char[strlen(newName)+1];
+ strcpy(name_, newName);
+ }
+
+ size_t size() const { return size_; }
+ void resize(size_t newSize)
+ {
+ delete [] array_;
+ array_ = new T[newSize];
+ size_ = newSize;
+ }
+
+private:
+ char* name_;
+ T* array_;
+ size_t size_;
+};
+
+
+#endif //TRANSFER_FUN_H
+

Added: sandbox/stm/libs/stm/test/testRBTree.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testRBTree.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,195 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include "main.h"
+#include "testRBTree.h"
+#include <fstream>
+#include <sstream>
+
+RedBlackTree<int> *rbTree = NULL;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+///////////////////////////////////////////////////////////////////////////////
+void* TestRedBlackTreeInserts(void *threadId)
+{
+ RedBlackNode<int> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ rbTree->insert(node);
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+ int *found = NULL;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ if (!rbTree->lookup(i, found))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ rbTree->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestRedBlackTreeWithMultipleThreads()
+{
+ static std::vector<int> runVector;
+
+ rbTree = new RedBlackTree<int>;
+ transaction::initialize();
+ transaction::initialize_thread();
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ pthread_t* threads = new pthread_t[kMaxThreads];
+ int* threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, TestRedBlackTreeInserts, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestRedBlackTreeInserts((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ int totalInserts = rbTree->walk_size();
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (int i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << "RB: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << averageRunTime << " " << "AVE: " << totalAverageRunTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / (totalAverageRunTime * runVector.size()) << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * kMaxThreads))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN RBTREE - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+
+ ofstream out("testOutput.txt");
+ rbTree->print(out);
+ }
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "rbTree_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ rbTree->cheap_clear();
+ delete rbTree;
+ delete threads;
+ delete threadId;
+}
+

Added: sandbox/stm/libs/stm/test/testRBTree.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/testRBTree.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,786 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#ifndef RED_BLACK_TREE_H
+#define RED_BLACK_TREE_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <boost/stm/transaction.hpp>
+
+void TestRedBlackTree();
+void TestRedBlackTreeWithMultipleThreads();
+
+///////////////////////////////////////////////////////////////////////////////
+namespace nRedBlackTree
+{
+ std::string const kRootStr = "root ";
+ std::string const kLeftStr = "left ";
+ std::string const kRightStr = "right";
+
+ enum NodeColor
+ {
+ eRed,
+ eBlack,
+ eMaxColors
+ };
+
+ std::string const colorStrings[eMaxColors] =
+ { " red ",
+ "black"
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class RedBlackNode : public boost::stm::transaction_object < RedBlackNode<T> >
+{
+public:
+
+ typedef T type;
+
+ ////////////////////////////////////////////////////////////////////////////
+ RedBlackNode(T const &in) : value_(in), color_(nRedBlackTree::eRed),
+ parent_(&sentinel), left_(&sentinel), right_(&sentinel) {}
+
+ ////////////////////////////////////////////////////////////////////////////
+ RedBlackNode() : value_(T()), color_(nRedBlackTree::eRed), parent_(&sentinel),
+ left_(&sentinel), right_(&sentinel) {}
+
+ T const & const_value(boost::stm::transaction &t) const
+ { return t.read(*const_cast<RedBlackNode<T>*>(this)).value_; }
+
+ T & value(boost::stm::transaction &t)
+ { return t.write(*const_cast<RedBlackNode<T>*>(this)).value_; }
+ T & value() { return value_; }
+ T const & value() const { return value_; }
+
+ nRedBlackTree::NodeColor & color(boost::stm::transaction &t)
+ { return t.write(*const_cast<RedBlackNode<T>*>(this)).color_; }
+ nRedBlackTree::NodeColor const & read_color(boost::stm::transaction &t)
+ { return t.read(*const_cast<RedBlackNode<T>*>(this)).color_; }
+
+ nRedBlackTree::NodeColor & color() { return color_; }
+ nRedBlackTree::NodeColor const & color() const { return color_; }
+
+ RedBlackNode<T>* read_right(boost::stm::transaction &t)
+ { return t.read(*const_cast<RedBlackNode<T>*>(this)).right_; }
+ RedBlackNode<T> const * read_right(boost::stm::transaction &t) const
+ { return t.read(*const_cast<RedBlackNode<T>*>(this)).right_; }
+
+ RedBlackNode<T>*& right(boost::stm::transaction &t)
+ { return t.write(*const_cast<RedBlackNode<T>*>(this)).right_; }
+ RedBlackNode<T>*& right(boost::stm::transaction &t) const
+ { return t.write(*const_cast<RedBlackNode<T>*>(this)).right_; }
+
+ RedBlackNode<T> *& right() { return right_; }
+ RedBlackNode<T> const * right() const { return right_; }
+
+ RedBlackNode<T>* read_left(boost::stm::transaction &t)
+ { return t.read(*const_cast<RedBlackNode<T>*>(this)).left_; }
+ RedBlackNode<T> const * read_left(boost::stm::transaction &t) const
+ { return t.read(*const_cast<RedBlackNode<T>*>(this)).left_; }
+
+ RedBlackNode<T>*& left(boost::stm::transaction &t)
+ { return t.write(*const_cast<RedBlackNode<T>*>(this)).left_; }
+ RedBlackNode<T>*& left(boost::stm::transaction &t) const
+ { return t.write(*const_cast<RedBlackNode<T>*>(this)).left_; }
+
+ RedBlackNode<T> *& left() { return left_; }
+ RedBlackNode<T> const * left() const { return left_; }
+
+ RedBlackNode<T>* read_parent(boost::stm::transaction &t)
+ { return t.read(*const_cast<RedBlackNode<T>*>(this)).parent_; }
+
+ RedBlackNode<T>*& parent(boost::stm::transaction &t)
+ { return t.write(*const_cast<RedBlackNode<T>*>(this)).parent_; }
+ RedBlackNode<T>*& parent(boost::stm::transaction &t) const
+ { return t.write(*const_cast<RedBlackNode<T>*>(this)).parent_; }
+
+ RedBlackNode<T> *& parent() { return parent_; }
+ RedBlackNode<T> const * parent() const { return parent_; }
+
+ ////////////////////////////////////////////////////////////////////////////
+ static void initializeSentinel()
+ {
+ sentinel.left_ = NULL;
+ sentinel.right_ = NULL;
+ sentinel.color_ = nRedBlackTree::eBlack;
+ }
+
+ static RedBlackNode<T> sentinel;
+
+private:
+
+ nRedBlackTree::NodeColor color_;
+
+ T value_;
+
+ mutable RedBlackNode<T> *left_;
+ mutable RedBlackNode<T> *right_;
+ mutable RedBlackNode<T> *parent_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+RedBlackNode<T> RedBlackNode<T>::sentinel;
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class RedBlackTree
+{
+public:
+
+ RedBlackTree() : root(new RedBlackNode<T>(T()))
+ { root->color() = nRedBlackTree::eBlack; RedBlackNode<T>::initializeSentinel(); }
+
+ //--------------------------------------------------------------------------
+ bool insert(RedBlackNode<T> const &node)
+ {
+ using namespace boost::stm;
+
+ for (transaction t; ; t.restart())
+ {
+ try { return internal_insert(node, t); }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ bool lookup(T const &v, T* found)
+ {
+ using namespace boost::stm;
+
+ for (transaction t; ; t.restart())
+ {
+ try { return internal_lookup(v, found, t); }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+ }
+
+ bool remove(RedBlackNode<T> const &node);
+
+ boost::stm::transaction_state clear();
+ void cheap_clear();
+
+ void print(std::ofstream &o);
+
+ int walk_size();
+ int internal_walk_size(int &i, RedBlackNode<T> *cur);
+
+private:
+
+ bool internal_remove(RedBlackNode<T> const &inNode, boost::stm::transaction &inT);
+ bool internal_insert(RedBlackNode<T> const &node, boost::stm::transaction &inT);
+ bool internal_lookup(T const &v, T* found, boost::stm::transaction &inT);
+
+ void internal_cheap_clear(RedBlackNode<T> *cur);
+ void internal_clear(RedBlackNode<T> &cur, boost::stm::transaction &t);
+ void internal_remove_help(RedBlackNode<T> *x, boost::stm::transaction &t);
+ RedBlackNode<T>* get_successor(RedBlackNode<T> *x, boost::stm::transaction &t) const;
+
+ void internal_print(int const &i, std::string const &outputStr,
+ RedBlackNode<T> *cur, std::ofstream &o);
+ RedBlackNode<T>* binary_insert(RedBlackNode<T> const &newEntry, boost::stm::transaction &t);
+ void left_rotate(RedBlackNode<T> *node, boost::stm::transaction &t);
+ void right_rotate(RedBlackNode<T> *node, boost::stm::transaction &t);
+
+ RedBlackNode<T> *root;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+inline void RedBlackTree<T>::right_rotate(RedBlackNode<T> *y, boost::stm::transaction &t)
+{
+ RedBlackNode<T> &writeY = t.write(*y);
+
+ RedBlackNode<T> *x = writeY.left();
+ RedBlackNode<T> *xRight = x->read_right(t);
+
+ writeY.left() = xRight;
+
+ if (&RedBlackNode<T>::sentinel != xRight) xRight->parent(t) = y;
+
+ RedBlackNode<T> *yParent = writeY.parent();
+ x->parent(t) = yParent;
+
+ if (y == yParent->read_left(t)) yParent->left(t) = x;
+ else yParent->right(t) = x;
+
+ x->right(t) = y;
+ writeY.parent() = x;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+inline void RedBlackTree<T>::left_rotate(RedBlackNode<T> *x, boost::stm::transaction &t)
+{
+ RedBlackNode<T> &writeX = t.write(*x);
+
+ RedBlackNode<T> *y = writeX.right();
+ RedBlackNode<T> *yLeft = y->read_left(t);
+
+ writeX.right() = yLeft;
+
+ if (&RedBlackNode<T>::sentinel != yLeft) yLeft->parent(t) = x;
+
+ RedBlackNode<T> *xParent = writeX.parent();
+ y->parent(t) = xParent;
+
+ if (x == xParent->read_left(t)) xParent->left(t) = y;
+ else xParent->right(t) = y;
+
+ y->left(t) = x;
+ writeX.parent() = y;
+}
+
+//--------------------------------------------------------------------------
+template <typename T>
+inline bool RedBlackTree<T>::internal_lookup(T const &v, T* found, boost::stm::transaction &t)
+{
+ //--------------------------------------------------------------------------
+ // the actual root node is this->root->left()
+ //--------------------------------------------------------------------------
+ RedBlackNode<T> *y = root;
+ RedBlackNode<T> *x = root->read_left(t);
+
+ while (x != &RedBlackNode<T>::sentinel)
+ {
+ if (NULL == x) throw boost::stm::aborted_transaction_exception("aborting transaction");
+ if (x->value() == v)
+ {
+ found = &x->value();
+ t.end();
+ return true;
+ }
+
+ y = x;
+ x = x->value() > v ? x->read_left(t) : x->read_right(t);
+ }
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+inline RedBlackNode<T>* RedBlackTree<T>::binary_insert(RedBlackNode<T> const &newEntry,
+ boost::stm::transaction &t)
+{
+ //--------------------------------------------------------------------------
+ // the actual root node is this->root->left()
+ //--------------------------------------------------------------------------
+ RedBlackNode<T> *y = root;
+ RedBlackNode<T> *x = root->read_left(t);
+
+ T const &val = newEntry.value();
+
+ while (x != &RedBlackNode<T>::sentinel)
+ {
+ if (NULL == x) throw boost::stm::aborted_transaction_exception("aborting transaction");
+ if (x->value() == val)
+ {
+ t.lock_and_abort();
+ return NULL;
+ }
+
+ y = x;
+ x = x->value() > val ? x->read_left(t) : x->read_right(t);
+ }
+
+ // create new memory if this element will be inserted
+ RedBlackNode<T> *z = t.new_memory_copy(newEntry);
+
+ z->parent() = y;
+
+ // in the event y is the dummy root, z should be to its left()
+ if (y == root || y->value() > val) y->left(t) = z;
+ else y->right(t) = z;
+
+ return z;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+bool RedBlackTree<T>::internal_insert(RedBlackNode<T> const & newEntry, boost::stm::transaction &t)
+{
+ using namespace nRedBlackTree;
+
+ //--------------------------------------------------------------------------
+ // try to do a binary insert of this element. if the element already exists,
+ // return null and end the transactions since we don't allow duplicates
+ //--------------------------------------------------------------------------
+ RedBlackNode<T> *x = binary_insert(newEntry, t);
+
+ if (NULL == x) return false;
+
+ RedBlackNode<T> *xParent = x->parent();
+ //RedBlackNode<T> *xParentParent = NULL;
+
+ while (eRed == xParent->read_color(t) && xParent != &RedBlackNode<T>::sentinel)
+ {
+ RedBlackNode<T> *xParentParent = xParent->read_parent(t);
+
+ //-----------------------------------------------------------------------
+ // if my parent() is on the left() side of the tree
+ //-----------------------------------------------------------------------
+ RedBlackNode<T> *xParentParentLeft = xParentParent->read_left(t);
+ if (xParent == xParentParentLeft)
+ {
+ // then my uncle is to the right() side
+ RedBlackNode<T> *y = xParentParent->read_right(t);
+
+ //--------------------------------------------------------------------
+ // if my uncle's color is red and my parent()'s color is red,
+ // change my parent()'s and my uncle's color to black and
+ // make my grandparent() red, then move me to my grandparent()
+ //--------------------------------------------------------------------
+ if (eRed == y->color())
+ {
+ xParent->color(t) = eBlack;
+ y->color(t) = eBlack;
+ xParentParent->color(t)= eRed;
+ x = xParentParent;
+ }
+ //--------------------------------------------------------------------
+ // otherwise, set me to my parent() and left()-rotate. then set my
+ // parent()'s color to black, my grandparent()'s color to red and
+ // right() rotate my grandparent()
+ //--------------------------------------------------------------------
+ else
+ {
+ if (x == xParent->read_right(t))
+ {
+ // set x up one level
+ x = xParent;
+ left_rotate(x, t);
+ }
+
+ RedBlackNode<T> &writeObj = t.write(*x->read_parent(t));
+
+ writeObj.color() = eBlack;
+ writeObj.parent()->color(t) = eRed;
+ right_rotate(writeObj.parent(), t);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ // the same as the above if, except right() and left() are exchanged
+ //-----------------------------------------------------------------------
+ else
+ {
+ RedBlackNode<T> *y = xParentParentLeft; // saves a tx read by setting to xParParLeft
+
+ if (eRed == y->color())
+ {
+ xParent->color(t) = eBlack;
+ y->color(t) = eBlack;
+ xParentParent->color(t) = eRed;
+ x = xParentParent;
+ }
+ else
+ {
+ if (x == xParent->read_left(t))
+ {
+ // set x up one level
+ x = xParent;
+ right_rotate(x, t);
+ }
+
+ RedBlackNode<T> &writeObj = t.write(*x->read_parent(t));
+
+ writeObj.color() = eBlack;
+ writeObj.parent()->color(t) = eRed;
+ left_rotate(writeObj.parent(), t);
+ }
+ }
+
+ xParent = x->read_parent(t);
+ }
+
+ // always set the root to black - root->left() *IS* the root. root is
+ // just a dummy node (-1 value).
+ root->read_left(t)->color(t) = eBlack;
+
+ t.end();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+void RedBlackTree<T>::internal_remove_help(RedBlackNode<T> *x, boost::stm::transaction &t)
+{
+ using namespace nRedBlackTree;
+
+ RedBlackNode<T> *y = NULL;
+ RedBlackNode<T> *xParent = NULL;
+
+ while ( eBlack == x->read_color(t) && root->read_left(t) != x)
+ {
+ xParent = x->read_parent(t);
+
+ RedBlackNode<T> *xParentLeft = xParent->read_left(t);
+ if (x == xParentLeft)
+ {
+ y = xParent->read_right(t);
+
+ if (eRed == y->read_color(t))
+ {
+ y->color(t) = eBlack;
+ xParent->color(t) = eRed;
+ left_rotate(xParent, t);
+ //-----------------------------------------------------------------
+ // I think we have to read_parent instead of xParent since
+ // right_rotate could have changed xParent
+ //-----------------------------------------------------------------
+ y = x->read_parent(t)->read_right(t);
+ }
+
+ if (eBlack == y->read_right(t)->read_color(t) &&
+ eBlack == y->read_left(t)->read_color(t))
+ {
+ y->color(t) = eRed;
+ x = xParent;
+ }
+ else
+ {
+ if (eBlack == y->read_right(t)->read_color(t))
+ {
+ y->read_left(t)->color(t) = eBlack;
+ y->color(t) = eRed;
+ right_rotate(y, t);
+ y = xParent->read_right(t);
+ }
+
+ y->color(t) = x->parent(t)->read_color(t);
+ xParent->color(t) = eBlack;
+ y->read_right(t)->color(t) = eBlack;
+ left_rotate(xParent, t);
+ break;
+ }
+ }
+ else
+ {
+ y = xParentLeft;
+
+ if (eRed == y->read_color(t))
+ {
+ y->color(t)= eBlack;
+ xParent->color(t) = eRed;
+ right_rotate(xParent, t);
+ //-----------------------------------------------------------------
+ // I think we have to read_parent instead of xParent since
+ // right_rotate could have changed xParent
+ //-----------------------------------------------------------------
+ y = x->read_parent(t)->read_left(t);
+ }
+
+ if (eBlack == y->read_left(t)->read_color(t) &&
+ eBlack == y->read_right(t)->read_color(t))
+ {
+ y->color(t) = eRed;
+ x = xParent;
+ }
+ else
+ {
+ if (eBlack == y->read_left(t)->read_color(t))
+ {
+ y->read_right(t)->color(t) = eBlack;
+ y->color(t) = eRed;
+ left_rotate(y, t);
+ y = xParent->read_left(t);
+ }
+
+ y->color(t) = xParent->read_color(t);
+ xParent->color(t) = eBlack;
+ y->read_left(t)->color(t) = eBlack;
+ right_rotate(xParent, t);
+ break;
+ }
+ }
+ }
+
+ x->color(t) = eBlack;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+RedBlackNode<T>* RedBlackTree<T>::get_successor(RedBlackNode<T> *x, boost::stm::transaction &t) const
+{
+ RedBlackNode<T> *y = x->read_right(t);
+
+ if (&RedBlackNode<T>::sentinel != y)
+ {
+ RedBlackNode<T> *prevY = y;
+
+ while ((y = y->read_left(t)) != &RedBlackNode<T>::sentinel)
+ {
+ prevY = y;
+ }
+
+ return prevY;
+ }
+ else
+ {
+ y = x->read_parent(t);
+
+ while (x == y->read_right(t))
+ {
+ x = y;
+ y = y->read_parent(t);
+ }
+
+ if (y == root) return &RedBlackNode<T>::sentinel;
+ else return y;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+void RedBlackTree<T>::cheap_clear()
+{
+ using namespace nRedBlackTree;
+
+ internal_cheap_clear(root->left());
+
+ root->left() = &RedBlackNode<T>::sentinel;
+ root->right() = &RedBlackNode<T>::sentinel;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+void RedBlackTree<T>::internal_cheap_clear(RedBlackNode<T> *cur)
+{
+ if (&RedBlackNode<T>::sentinel == cur) return;
+
+ internal_cheap_clear(cur->left());
+ internal_cheap_clear(cur->right());
+
+ delete cur;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+boost::stm::transaction_state RedBlackTree<T>::clear()
+{
+ using namespace nRedBlackTree; using namespace boost::stm;
+ transaction t(begin_transaction);
+
+ RedBlackNode<T> &curLeft = t.write(*root->left());
+ internal_clear(curLeft, t);
+
+ root->left() = &RedBlackNode<T>::sentinel;
+ root->right() = &RedBlackNode<T>::sentinel;
+
+ return t.end();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+void RedBlackTree<T>::internal_clear(RedBlackNode<T> &cur, boost::stm::transaction &t)
+{
+ if (&RedBlackNode<T>::sentinel == &cur) return;
+
+ if (&RedBlackNode<T>::sentinel != cur.left())
+ {
+ RedBlackNode<T> &curLeft = t.write(*cur.left());
+ internal_clear(curLeft, t);
+ }
+ if (&RedBlackNode<T>::sentinel != cur.right())
+ {
+ RedBlackNode<T> &curRight = t.write(*cur.right());
+ internal_clear(curRight, t);
+ }
+
+ t.delete_memory(cur);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+bool RedBlackTree<T>::remove(RedBlackNode<T> const &inNode)
+{
+ using namespace nRedBlackTree; using namespace boost::stm;
+
+ for (transaction t; ; t.restart())
+ {
+ try { return internal_remove(inNode, t); }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+bool RedBlackTree<T>::internal_remove(RedBlackNode<T> const &inNode, boost::stm::transaction &t)
+{
+ using namespace nRedBlackTree;
+ t.begin();
+
+ RedBlackNode<T> *z = root->left(t);
+
+ // find node inNode in our tree then delete it
+ for (; &RedBlackNode<T>::sentinel != z; )
+ {
+ if (NULL == z) throw boost::stm::aborted_transaction_exception("altered tree");
+ if (z->value() == inNode.value()) break;
+ z = z->value() > inNode.value() ? z->read_left(t) : z->read_right(t);
+ }
+
+ //--------------------------------------------------------------------------
+ // if the node wasn't found, exit
+ //--------------------------------------------------------------------------
+ if (z->value() != inNode.value()) return false;
+
+ RedBlackNode<T> *y = (z->read_left(t) == &RedBlackNode<T>::sentinel
+ || z->read_right(t) == &RedBlackNode<T>::sentinel) ? z : get_successor(z, t);
+
+ RedBlackNode<T> *yLeft = y->read_left(t);
+
+ RedBlackNode<T> *x = (yLeft == &RedBlackNode<T>::sentinel)
+ ? y->read_right(t) : yLeft;
+
+ RedBlackNode<T> *yParent = y->read_parent(t);
+
+ if (root == (x->parent(t) = yParent)) root->left(t) = x;
+ else if (y == yParent->read_left(t)) yParent->left(t) = x;
+ else yParent->right(t) = x;
+
+ RedBlackNode<T> &writeY = t.write(*y);
+
+ if (y != z)
+ {
+ RedBlackNode<T> const *readZ = &t.read(*z);
+ RedBlackNode<T> const *zLeft = readZ->left();
+ RedBlackNode<T> const *zRight = readZ->right();
+ RedBlackNode<T> const *zParent = readZ->parent();
+
+ writeY.left() = (RedBlackNode<T>*)zLeft;
+ writeY.right() = (RedBlackNode<T>*)zRight;
+ writeY.parent() = (RedBlackNode<T>*)zParent;
+
+ zLeft->parent(t) = y;
+ zRight->parent(t) = y;
+
+ if (z == zParent->read_left(t)) zParent->left(t) = y;
+ else zParent->right(t) = y;
+
+ if (eBlack == writeY.color())
+ {
+ writeY.color() = readZ->color();
+ internal_remove_help(x, t);
+ }
+ else
+ {
+ writeY.color() = readZ->color();
+ }
+
+ t.delete_memory(*z);
+ }
+ else
+ {
+ if (eBlack == writeY.color()) internal_remove_help(x, t);
+ t.delete_memory(*y);
+ }
+
+ t.end();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+int RedBlackTree<T>::walk_size()
+{
+ using namespace std;
+ using namespace nRedBlackTree;
+ int i = 0;
+ return internal_walk_size(i, root->left());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+int RedBlackTree<T>::internal_walk_size(int &i, RedBlackNode<T> *cur)
+{
+ using namespace std;
+ using namespace nRedBlackTree;
+
+ if (&RedBlackNode<T>::sentinel == cur) return i;
+
+ // increment i for this node
+ ++i;
+
+ i = internal_walk_size(i, cur->left());
+ i = internal_walk_size(i, cur->right());
+
+ return i;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+void RedBlackTree<T>::print(std::ofstream &o)
+{
+ using namespace std;
+ using namespace nRedBlackTree;
+
+ int i = 0;
+
+ o << "[ size: " << walk_size() << " ]" << endl;
+ internal_print(i, kRootStr, root->left(), o);
+ o << endl;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+void RedBlackTree<T>::internal_print(int const &i, std::string const &outputStr,
+ RedBlackNode<T> *cur, std::ofstream &o)
+{
+ using namespace std;
+ using namespace nRedBlackTree;
+
+ if (&RedBlackNode<T>::sentinel == cur) return;
+ else
+ {
+ o << "[ " << outputStr << " - " << colorStrings[cur->color()] << i
+ << " ]: " << cur->value() << endl;
+ }
+
+ internal_print(i + 1, kLeftStr, cur->left(), o);
+ internal_print(i + 1, kRightStr, cur->right(), o);
+}
+
+#endif // RED_BLACK_TREE_H

Added: sandbox/stm/libs/stm/test/transferFun.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/transferFun.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,226 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//---------------------------------------------------------------------------
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+#include "transferFun.h"
+#include <math.h>
+#include "main.h"
+#include "testRBTree.h"
+#include <fstream>
+#include <sstream>
+
+boost::stm::native_trans<int> global_int2;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+namespace nMath
+{
+ double const constantE = 2.718281828;
+}
+
+using namespace nMath;
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+void* TestTreeTransferFunctionInserts(void *threadId)
+{
+ transaction::initialize_thread();
+
+ int id = *(int*)threadId;
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+#if 1
+
+ for (;;)
+ {
+ try
+ {
+ transaction t;
+ t.write(global_int2).value() = t.read(global_int2).value() + 1;
+ t.end();
+ break;
+ }
+ catch (aborted_transaction_exception&) {}
+ }
+#endif
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestTransferFunctionMultipleThreads()
+{
+ static std::vector<int> runVector;
+ int iterations = 0;
+
+ global_int2.value() = 0;
+
+ transaction::initialize();
+ transaction::initialize_thread();
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ pthread_t* threads = new pthread_t[kMaxThreads];
+ int* threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, TestTreeTransferFunctionInserts, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ TestTreeTransferFunctionInserts((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (int i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << "TF: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "TIME: " << averageRunTime << " " << "AVE: " << totalAverageRunTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / (totalAverageRunTime * runVector.size()) << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ cout << "global int value: " << global_int2.value() << endl;
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "rbTreeFun_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ delete threads;
+ delete threadId;
+}
+
+//---------------------------------------------------------------------------
+void TransferFunction::performFunction()
+{
+ //------------------------------------------------------------------------
+ // based on the transfer function of this object, perform the correct
+ // operation and store its output in the output field
+ //------------------------------------------------------------------------
+ switch (fun())
+ {
+ case eHardLimit:
+ output_ = input_ >= 0 ? 1 : 0;
+ break;
+
+ case eHardLimitSymmetric:
+ output_ = input_ >= 0 ? 1 : -1;
+ break;
+
+ case eLinear:
+ output_ = input_;
+ break;
+
+ case ePositiveLinear:
+ output_ = input_ < 0 ? 0 : input_;
+ break;
+
+ case eSaturatingLinear:
+ if (input_ <= 0) output_ = 0;
+ else if (input_ >= 1) output_ = 1;
+ else output_ = input_;
+ break;
+
+ case eSaturatingLinearSymmetric:
+ if (input_ <= -1) output_ = -1;
+ else if (input_ >= 1) output_ = 1;
+ else output_ = input_;
+ break;
+
+ case eSigmoid:
+ output_ = 1 / (1 + pow(constantE, -input_));
+ break;
+
+ case eTanSigmoid:
+ output_ = (pow(constantE, input_) - pow(constantE, -input_))
+ / (pow(constantE, input_) + pow(constantE, -input_));
+ break;
+
+ default:
+ break;
+ }
+
+}

Added: sandbox/stm/libs/stm/test/transferFun.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/transferFun.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,92 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TRANSFER_FUN_H
+#define TRANSFER_FUN_H
+
+#include <ostream>
+
+void TestTransferFunctionMultipleThreads();
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+enum eTransferFunction
+{
+ eNoTransferFunction = 0,
+ eHardLimit,
+ eHardLimitSymmetric,
+ eLinear,
+ ePositiveLinear,
+ eSaturatingLinear,
+ eSaturatingLinearSymmetric,
+ eSigmoid,
+ eTanSigmoid,
+ eMaxTransferFunction = eTanSigmoid
+};
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+class TransferFunction
+{
+public:
+
+ TransferFunction(eTransferFunction const &fun, double inputVal) :
+ fun_(fun), input_(inputVal), output_(0) {}
+
+ TransferFunction() : fun_(eNoTransferFunction), input_(0), output_(0) {}
+
+ double const &input() const { return input_; }
+ double const &output() const { return output_; }
+ eTransferFunction const &fun() const { return fun_; }
+
+ void input(double const &rhs) { input_ = rhs; }
+ void output(double const &rhs) { output_ = rhs; }
+ void fun(eTransferFunction const &rhs) { fun_ = rhs; }
+
+ void performFunction();
+
+ bool operator==(TransferFunction const & rhs) const
+ { return fun_ == rhs.fun_ && input_ == rhs.input_; }
+
+ bool operator!=(TransferFunction const & rhs) const
+ { return !this->operator==(rhs); }
+
+ bool operator<(TransferFunction const & rhs) const
+ {
+ if (fun_ < rhs.fun_) return true;
+ else if (input_ < rhs.input_) return true;
+ else return false;
+ }
+
+ bool operator>(TransferFunction const & rhs) const
+ {
+ if (fun_ > rhs.fun_) return true;
+ else if (input_ > rhs.input_) return true;
+ else return false;
+ }
+
+ friend std::ostream& operator<<(std::ostream &out, TransferFunction &rhs)
+ {
+ out << rhs.fun_ << ":" << rhs.input_;
+ return out;
+ }
+
+private:
+
+ eTransferFunction fun_;
+ double input_;
+ double output_;
+};
+
+#endif //TRANSFER_FUN_H
+

Added: sandbox/stm/libs/stm/test/txLinearLock.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/txLinearLock.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,178 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <iostream>
+#include "txLinearLock.h"
+#include <boost/stm/transaction.hpp>
+#include "main.h"
+
+static boost::stm::native_trans<int> gInt1;
+static boost::stm::native_trans<int> gInt2;
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+static Mutex lock1 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex lock2 = PTHREAD_MUTEX_INITIALIZER;
+#else
+static Mutex lock1;
+static Mutex lock2;
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+
+///////////////////////////////////////////////////////////////////////////////
+static void* Test1(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = 0;
+ int endingValue = (startingValue + kMaxInserts);
+
+ for (int i = startingValue; i < endingValue/2; ++i)
+ {
+ for (transaction t; ; t.restart())
+ {
+ t.add_tx_conflicting_lock(&lock1);
+ t.add_tx_conflicting_lock(&lock2);
+
+ try
+ {
+ transaction::lock_(lock2);
+ --gInt2.value();
+ cout << "\tgInt2: " << gInt2.value() << endl;
+ transaction::unlock_(lock2);
+
+ SLEEP(1000);
+
+ transaction::lock_(lock1);
+ ++gInt1.value();
+ cout << "\tgInt1: " << gInt1.value() << endl;
+ transaction::unlock_(lock1);
+
+ t.end();
+ SLEEP(50);
+
+ break;
+ }
+ catch (aborted_tx&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* Test3(void *threadId)
+{
+ transaction::initialize_thread();
+ int start = *(int*)threadId;
+
+ int startingValue = 0;
+ int endingValue = (startingValue + kMaxInserts);
+
+ for (int i = startingValue; i < endingValue/2; ++i)
+ {
+ SLEEP(1000);
+
+ transaction::lock_(lock1);
+ transaction::lock_(lock2);
+
+ --gInt1.value();
+ ++gInt2.value();
+ cout << "\t\tgInt1: " << gInt1.value() << endl;
+ cout << "\t\tgInt2: " << gInt2.value() << endl;
+
+ transaction::unlock_(lock2);
+ transaction::unlock_(lock1);
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void TestTxLinearLock()
+{
+ transaction::initialize();
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = 0;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ pthread_create(&threads[j], NULL, Test1, (void *)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ Test3((void*)&mainThreadId);
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+}
+

Added: sandbox/stm/libs/stm/test/txLinearLock.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/txLinearLock.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,21 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef TX_LINEAR_LOCK_H
+#define TX_LINEAR_LOCK_H
+
+void TestTxLinearLock();
+
+#endif // TX_LINEAR_LOCK_H
+

Added: sandbox/stm/libs/stm/test/usingLockTx.cpp
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/usingLockTx.cpp 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,529 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/* The DRACO Research Group (rogue.colorado.edu/draco) */
+/*****************************************************************************\
+ *
+ * Copyright Notices/Identification of Licensor(s) of
+ * Original Software in the File
+ *
+ * Copyright 2000-2006 The Board of Trustees of the University of Colorado
+ * Contact: Technology Transfer Office,
+ * University of Colorado at Boulder;
+ * https://www.cu.edu/techtransfer/
+ *
+ * All rights reserved by the foregoing, respectively.
+ *
+ * This is licensed software. The software license agreement with
+ * the University of Colorado specifies the terms and conditions
+ * for use and redistribution.
+ *
+\*****************************************************************************/
+
+#include <sstream>
+#include "usingLockTx.h"
+
+typedef int list_node_type;
+
+static newSyntaxNS::LinkedList< list_node_type > *llist = NULL;
+
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+static Mutex L = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L2 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L3 = PTHREAD_MUTEX_INITIALIZER;
+static Mutex L4 = PTHREAD_MUTEX_INITIALIZER;
+#else
+static Mutex L;
+static Mutex L2;
+static Mutex L3;
+static Mutex L4;
+#endif
+
+using namespace boost::stm;
+
+static native_trans<int> x = 0;
+static native_trans<int> y = 0;
+
+static void tx_bar();
+static void lk_bar();
+
+static void* tx_foo(void*)
+{
+ transaction::initialize_thread();
+ size_t tries = 0;
+
+ try_atomic(t)
+ {
+ t.lock_conflict(L);
+
+ ++t.write(x);
+ tx_bar();
+ }
+ before_retry { ++tries; }
+
+ cout << "tx done" << endl;
+ return 0;
+}
+
+static void tx_bar()
+{
+ use_atomic(t)
+ {
+ t.write(y) = t.read(x) + y;
+ }
+}
+
+
+
+static void* lk_foo(void*)
+{
+ use_lock(&L)
+ {
+ ++x;
+ lk_bar();
+ }
+
+ return 0;
+}
+
+static void lk_bar()
+{
+ use_lock(L)
+ {
+ y = x + y;
+ cout << "locking done" << endl;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+using namespace std; using namespace boost::stm;
+using namespace nMain;
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInsertsWithLocks(void *threadId)
+{
+ newSyntaxNS::list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ //llist->insert(node);
+ llist->lock_insert(node);
+ }
+
+ if (kDoMove)
+ {
+ newSyntaxNS::list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!llist->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void* TestLinkedListInserts(void *threadId)
+{
+ newSyntaxNS::list_node<list_node_type> node;
+ transaction::initialize_thread();
+
+ int start = *(int*)threadId;
+ int startingValue = start * kMaxInserts;
+ int threadInserts = 0;
+
+ if (kInsertSameValues) startingValue = 0;
+
+ int endingValue = startingValue + kMaxInserts;
+
+ idleUntilAllThreadsHaveReached(*(int*)threadId);
+
+ if (kStartingTime == startTimer) startTimer = time(NULL);
+
+ //--------------------------------------------------------------------------
+ // do the transactional inserts. this is the main transactional loop.
+ //--------------------------------------------------------------------------
+ int i;
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->insert(node);
+ }
+
+ if (kDoMove)
+ {
+ newSyntaxNS::list_node<list_node_type> node1, node2;
+
+ for (int j = startingValue; j < endingValue; ++j)
+ {
+ node1.value() = j;
+ //node2.value() = -j;
+ llist->move(node1, node2);
+ }
+
+ }
+
+ if (kDoLookup)
+ {
+ bool allFound = true;
+
+ for (i = startingValue; i < endingValue; ++i)
+ {
+#if 0
+ if (!llist->lookup(i))
+ {
+ allFound = false;
+ std::cout << "Element not found: " << i << endl;
+ }
+#endif
+ }
+ }
+
+ if (kDoRemoval)
+ {
+ for (i = startingValue; i < endingValue; ++i)
+ {
+ node.value() = i;
+ llist->remove(node);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // last thread out sets the endTimer
+ //--------------------------------------------------------------------------
+ endTimer = time(NULL);
+ finishThread(start);
+
+ if (*(int*)threadId != kMainThreadId)
+ {
+ transaction::terminate_thread();
+ pthread_exit(threadId);
+ }
+
+ return 0;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void* stall(void *)
+{
+ transaction::initialize_thread();
+
+ transaction::lock_(&L2);
+
+ SLEEP(10000);
+
+ transaction::unlock_(&L2);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void TestNested2()
+{
+ atomic(t)
+ {
+ //t.force_to_abort();
+ --t.w(x);
+ }
+ before_retry
+ {
+ cout << "TestNested2 caught exception" << endl;
+ }
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void TestNested()
+{
+ atomic(t)
+ {
+ ++t.w(x);
+ TestNested2();
+ }
+ before_retry
+ {
+ cout << "TestNested caught exception" << endl;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+static void TestTransactionInsideLock()
+{
+ using namespace boost::stm;
+
+ cout << "X: " << x.value() << endl;
+
+ SLEEP(1000);
+
+ transaction::lock_(&L);
+ transaction::lock_(&L3);
+
+ try_atomic(t)
+ {
+ t.lock_conflict(&L);
+ t.lock_conflict(&L2);
+ t.lock_conflict(&L3);
+
+ ++t.write(x);
+
+ } before_retry {}
+
+ transaction::unlock_(&L);
+ transaction::unlock_(&L3);
+
+ cout << "X: " << x.value() << endl;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+static void TestEarlyRelease()
+{
+ using namespace boost::stm;
+
+ cout << "X: " << x.value() << endl;
+
+ SLEEP(1000);
+
+ transaction::lock_(&L);
+ transaction::lock_(&L3);
+
+ try_atomic(t)
+ {
+ t.lock_conflict(&L);
+ t.lock_conflict(&L2);
+ t.lock_conflict(&L3);
+
+ transaction::unlock_(&L);
+
+ ++t.write(x);
+
+ } before_retry {}
+
+ transaction::unlock_(&L);
+ transaction::unlock_(&L3);
+
+ cout << "X: " << x.value() << endl;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+void TestLinkedListWithUsingLocks()
+{
+ static std::vector<int> runVector;
+ int iterations = 0;
+
+ llist = new newSyntaxNS::LinkedList<list_node_type>;
+
+ transaction::initialize();
+ transaction::initialize_thread();
+
+ //transaction::do_tm_lock_protection();
+ transaction::do_tx_lock_protection();
+
+ //transaction::tm_lock_conflict(&L);
+ //transaction::tm_lock_conflict(&L2);
+ //transaction::tm_lock_conflict(&L3);
+
+ //TestNested();
+
+ //exit(0);
+
+ pthread_t *second_thread = new pthread_t;
+
+ pthread_create(second_thread, NULL, stall, (void*)NULL);
+
+ TestTransactionInsideLock();
+ TestEarlyRelease();
+
+ exit(0);
+
+
+
+
+
+
+
+
+
+ transaction::tm_lock_conflict(llist->get_list_lock());
+
+#if LOGGING_COMMITS_AND_ABORTS
+ transaction::enableLoggingOfAbortAndCommitSetSize();
+#endif
+
+ pthread_t *threads = new pthread_t[kMaxThreads];
+ int *threadId = new int[kMaxThreads];
+
+ //--------------------------------------------------------------------------
+ // Reset barrier variables before creating any threads. Otherwise, it is
+ // possible for the first thread
+ //--------------------------------------------------------------------------
+ threadsFinished.value() = 0;
+ threadsStarted.value() = 0;
+ startTimer = kStartingTime;
+ endTimer = 0;
+
+ for (int j = 0; j < kMaxThreads - 1; ++j)
+ {
+ threadId[j] = j;
+ //if (0 == j % 2) pthread_create(&threads[j], NULL, TestLinkedListInserts, (void *)&threadId[j]);
+ //else pthread_create(&threads[j], NULL, TestLinkedListInsertsWithLocks, (void *)&threadId[j]);
+
+ pthread_create(&threads[j], NULL, tx_foo, (void*)&threadId[j]);
+ }
+
+ int mainThreadId = kMaxThreads-1;
+
+ //TestLinkedListInsertsWithLocks((void*)&mainThreadId);
+ lk_foo((void*)mainThreadId);
+
+ return;
+
+ while (true)
+ {
+ if (threadsFinished.value() == kMaxThreads) break;
+ SLEEP(10);
+ }
+
+ int totalInserts = llist->walk_size();
+
+ int averageRunTime = endTimer - startTimer;
+ if (averageRunTime < 1) averageRunTime = 1;
+ runVector.push_back(averageRunTime);
+
+ int totalAverageRunTime = 0;
+ for (int i = 0; i < (int)runVector.size(); ++i) totalAverageRunTime += runVector[i];
+
+ totalAverageRunTime /= (int)runVector.size();
+
+
+#ifdef DELAY_INVALIDATION_DOOMED_TXS_UNTIL_COMMIT
+ cout << "DEL_INVAL_";
+#endif
+ cout << "LL: DSTM_" << transaction::update_policy_string() << " ";
+ cout << "THRD: " << kMaxThreads << " ";
+ cout << "SIZE: " << totalInserts << " ";
+ cout << "TIME: " << averageRunTime << " " << "AVE: " << totalAverageRunTime;
+ cout << " TX_SEC: " << transaction::bookkeeping().commits() / (totalAverageRunTime * runVector.size()) << endl;
+ cout << transaction::bookkeeping() << endl;
+
+ if ((kInsertSameValues && totalInserts != kMaxInserts) ||
+ (!kInsertSameValues && totalInserts != kMaxInserts * kMaxThreads))
+ {
+ std::cout << std::endl << std::endl << "###########################################################";
+ std::cout << std::endl << "LOST ITEMS IN LINKED LIST - HALTING: " << totalInserts << std::endl;
+ std::cout << "###########################################################" << std::endl << std::endl;
+
+ ofstream out("testOutput.txt");
+ llist->outputList(out);
+ out.close();
+ }
+
+ ofstream outTest("testOutput.txt");
+ llist->outputList(outTest);
+ outTest.close();
+
+#if LOGGING_COMMITS_AND_ABORTS
+ std::ostringstream out;
+ out << kMaxThreads << "_" << kMaxInserts;
+ std::string typeOfRun = "linkedList_" + out.str();
+ logCommitsAndAborts(typeOfRun);
+#endif
+
+ delete llist;
+ delete threads;
+ delete threadId;
+}

Added: sandbox/stm/libs/stm/test/usingLockTx.h
==============================================================================
--- (empty file)
+++ sandbox/stm/libs/stm/test/usingLockTx.h 2009-04-27 15:36:28 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,524 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+#ifndef USING_LOCK_TX_H
+#define USING_LOCK_TX_H
+
+#include "main.h"
+#include "testHT_latm.h"
+#include <boost/stm/transaction.hpp>
+#include <pthread.h>
+
+#include <fstream>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace newSyntaxNS
+{
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename T>
+class list_node : public boost::stm::transaction_object< list_node<T> >
+{
+public:
+
+ list_node() : value_(0), next_(0) {}
+ explicit list_node(int const &rhs) : value_(rhs), next_(NULL) {}
+
+ // zero initialization for native types
+ void clear() { value_ = T(); next_ = NULL; }
+
+ T &value() { return value_; }
+ T const &value() const { return value_; }
+
+ list_node const *next() const { return next_; }
+ list_node *next() { return next_; }
+
+ void next(list_node const *rhs) { next_ = (list_node<T>*)rhs; }
+
+ void next(list_node const *rhs, boost::stm::transaction &t)
+ {
+ if (NULL == rhs) next_ = NULL;
+ else next_ = &t.find_original(*(list_node<T>*)rhs);
+ }
+
+ void next_for_new_mem(list_node *rhs, boost::stm::transaction &t)
+ {
+ if (NULL == rhs) next_ = NULL;
+ else next_ = &t.find_original(*rhs);
+ }
+
+#if BUILD_MOVE_SEMANTICS
+ list_node& operator=(list_node const & rhs)
+ {
+ value_ = rhs.value_;
+ next_ = rhs.next_;
+ return *this;
+ }
+
+ list_node(list_node &&rhs) : next_(rhs.next_), value_(boost::stm::draco_move(rhs.value_))
+ { rhs.next_ = 0; }
+
+ list_node& operator=(list_node&& rhs)
+ {
+ value_ = boost::stm::draco_move(rhs.value_);
+ std::swap(next_, rhs.next_);
+ return *this;
+ }
+#endif
+
+
+private:
+
+ T value_;
+ list_node *next_;
+};
+
+////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class LinkedList
+{
+public:
+
+ LinkedList()
+ {
+#ifndef BOOST_STM_USE_BOOST_MUTEX
+ pthread_mutex_init (&list_lock_, NULL);
+#endif
+ head_.value() = T();
+ }
+
+ ~LinkedList() { quick_clear(); }
+
+ Mutex* get_list_lock() { return &list_lock_; }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool move(list_node<T> const &node1, list_node<T> 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 (boost::stm::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)
+ {
+ using namespace boost::stm;
+
+ try_atomic(t)
+ {
+ if (eTxConflictingLockLatmProtection == transaction::latm_protection())
+ {
+ t.add_tx_conflicting_lock(&list_lock_);
+ }
+
+ return internal_insert(node, t);
+ }
+ before_retry
+ {
+ std::cout << "transaction failed, retrying" << std::endl;
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lookup(T const &val)
+ {
+ using namespace boost::stm;
+
+ try_atomic(t)
+ {
+ if (eTxConflictingLockLatmProtection == transaction::latm_protection())
+ {
+ t.add_tx_conflicting_lock(&list_lock_);
+ }
+
+ return internal_lookup(val, t);
+ }
+ catch_before_retry(except) {}
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lock_insert(list_node<T> const &rhs)
+ {
+ using namespace boost::stm;
+ use_lock(list_lock_)
+ {
+ list_node<T> *headP = &head_;
+
+ if (NULL != headP->next())
+ {
+ list_node<T> *prev = headP;
+ list_node<T> *cur = 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> *curNext = cur->next();
+
+ if (NULL == curNext) break;
+
+ cur = curNext;
+ }
+
+ list_node<T> *newNode = new list_node<T>(rhs);
+
+ //--------------------------------------------------------------------
+ // if cur->next() is null it means our newNode value is greater than
+ // cur, so insert ourselves after cur.
+ //--------------------------------------------------------------------
+ if (NULL == cur->next()) cur->next(newNode);
+ //--------------------------------------------------------------------
+ // otherwise, we are smaller than cur, so insert between prev and cur
+ //--------------------------------------------------------------------
+ else
+ {
+ newNode->next(cur);
+ prev->next(newNode);
+ }
+ }
+ else
+ {
+ list_node<T> *newNode = new list_node<T>(rhs);
+ head_.next(newNode);
+ }
+ }
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool lock_lookup(T const &val)
+ {
+ using namespace boost::stm;
+ transaction::lock_(&list_lock_);
+
+ LATM::list_node<T> *cur = &head_;
+
+ for (; ; cur = cur->next() )
+ {
+ if (cur->value() == val)
+ {
+ transaction::unlock_(&list_lock_);
+ return true;
+ }
+
+ if (NULL == cur->next()) break;
+ }
+
+ transaction::unlock_(&list_lock_);
+ return false;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool remove(list_node<T> const &node)
+ {
+ using namespace boost::stm;
+ bool succeeded = true;
+
+ for (transaction t; ; t.restart())
+ {
+ try { return internal_remove(node, t); }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void outputList(std::ofstream &o)
+ {
+ int i = 0;
+ for (list_node<T> *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> *cur = head_.next(); cur != NULL; cur = cur->next())
+ {
+ ++i;
+ }
+
+ return i;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void quick_clear()
+ {
+ for (list_node<T> *cur = head_.next(); cur != NULL;)
+ {
+ list_node<T> *prev = cur;
+ cur = cur->next();
+ delete prev;
+ }
+
+ head_.clear();
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ void clear()
+ {
+ using namespace boost::stm;
+ for (transaction t; ; t.restart())
+ {
+ try
+ {
+ for (list_node<T> *cur = t.read(head_).next(); cur != NULL;)
+ {
+ list_node<T> *prev = &t.read(*cur);
+ cur = t.read(*cur).next();
+ t.delete_memory(*prev);
+ }
+
+ t.write(head_).clear();
+ t.end();
+ }
+ catch (boost::stm::aborted_transaction_exception&) {}
+ }
+ }
+
+private:
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, bail
+ //--------------------------------------------------------------------------
+ bool internal_insert(list_node<T> const &rhs, 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);
+ }
+
+ t.end();
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ // find the location to insert the node. if the value already exists, bail
+ //--------------------------------------------------------------------------
+ bool internal_lookup(T const &val, boost::stm::transaction &t)
+ {
+ list_node<T> *cur = &t.read(head_);
+
+ for (; true ; cur = t.read(*cur).next() )
+ {
+ list_node<T> *trueCur = &t.read(*cur);
+
+ if (trueCur->value() == val)
+ {
+ t.end();
+ return true;
+ }
+
+ if (NULL == trueCur->next()) break;
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ bool internal_remove(list_node<T> const &rhs, 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 (NULL == cur) break;
+
+ if (cur->value() == rhs.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);
+ }
+
+ t.end();
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ 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;
+ }
+ }
+
+ return false;
+ }
+
+ list_node<T> head_;
+ Mutex list_lock_;
+};
+
+} // LockAwareTransactions
+
+void TestLinkedListWithUsingLocks();
+
+#endif // TEST_LINKED_LIST_H


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