libfoedus-core
FOEDUS Core Library
foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock > Class Template Reference

The Extended MCS-RW lock. More...

Detailed Description

template<typename ADAPTOR>
class foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >

The Extended MCS-RW lock.

Same as above, we partially specialize the whole class, not functions.

Definition at line 676 of file xct_mcs_impl.cpp.

Public Member Functions

McsBlockIndex acquire_unconditional_rw_reader (McsRwLock *lock)
 
McsBlockIndex acquire_unconditional_rw_writer (McsRwLock *lock)
 
McsBlockIndex acquire_try_rw_writer (McsRwLock *lock)
 Instant-try versions, won't leave node in the queue if failed. More...
 
McsBlockIndex acquire_try_rw_reader (McsRwLock *lock)
 
void release_rw_reader (McsRwLock *lock, McsBlockIndex block_index)
 
void release_rw_writer (McsRwLock *lock, McsBlockIndex block_index)
 
AcquireAsyncRet acquire_async_rw_reader (McsRwLock *lock)
 Async acquire methods, passing timeout 0 will avoid cancelling upon timeout in the internal rountines; caller should explicitly cancel when needed. More...
 
AcquireAsyncRet acquire_async_rw_writer (McsRwLock *lock)
 
bool retry_async_rw_reader (McsRwLock *lock, McsBlockIndex block_index)
 
bool retry_async_rw_writer (McsRwLock *lock, McsBlockIndex block_index)
 
void cancel_async_rw_reader (McsRwLock *lock, McsBlockIndex block_index)
 
void cancel_async_rw_writer (McsRwLock *lock, McsBlockIndex block_index)
 

Static Public Member Functions

static bool does_support_try_rw_reader ()
 

Member Function Documentation

template<typename ADAPTOR >
AcquireAsyncRet foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::acquire_async_rw_reader ( McsRwLock lock)
inline

Async acquire methods, passing timeout 0 will avoid cancelling upon timeout in the internal rountines; caller should explicitly cancel when needed.

Definition at line 804 of file xct_mcs_impl.cpp.

References ASSERT_ND, foedus::kErrorCodeLockRequested, foedus::kErrorCodeOk, and foedus::xct::McsRwExtendedBlock::kTimeoutZero.

804  {
805  McsBlockIndex block_index = 0;
806  auto ret = acquire_reader_lock(lock, &block_index, McsRwExtendedBlock::kTimeoutZero);
808 #ifndef NDEBUG
809  auto* my_block = adaptor_.get_rw_my_block(block_index);
810  if (ret == kErrorCodeOk) {
811  ASSERT_ND(my_block->pred_flag_is_granted());
812  ASSERT_ND(my_block->next_flag_is_granted());
813  } else {
815  ASSERT_ND(!my_block->next_flag_is_granted());
816  }
817 #endif
818  ASSERT_ND(block_index);
819  return {ret == kErrorCodeOk, block_index};
820  }
0x0AA3 : "XCTION : Lock acquire requested." .
Definition: error_code.hpp:208
static const int32_t kTimeoutZero
Definition: xct_id.hpp:552
0 means no-error.
Definition: error_code.hpp:87
uint32_t McsBlockIndex
Index in thread-local MCS block.
Definition: xct_id.hpp:153
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
template<typename ADAPTOR >
AcquireAsyncRet foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::acquire_async_rw_writer ( McsRwLock lock)
inline

Definition at line 821 of file xct_mcs_impl.cpp.

References ASSERT_ND, foedus::kErrorCodeLockRequested, foedus::kErrorCodeOk, and foedus::xct::McsRwExtendedBlock::kTimeoutZero.

821  {
822  McsBlockIndex block_index = 0;
823  auto ret = acquire_writer_lock(lock, &block_index, McsRwExtendedBlock::kTimeoutZero);
825  ASSERT_ND(block_index);
826 #ifndef NDEBUG
827  auto* my_block = adaptor_.get_rw_my_block(block_index);
828  if (ret == kErrorCodeOk) {
829  ASSERT_ND(my_block->pred_flag_is_granted());
830  ASSERT_ND(my_block->next_flag_is_granted());
831  } else {
833  ASSERT_ND(!my_block->next_flag_is_granted());
834  }
835 #endif
836  return {ret == kErrorCodeOk, block_index};
837  }
0x0AA3 : "XCTION : Lock acquire requested." .
Definition: error_code.hpp:208
static const int32_t kTimeoutZero
Definition: xct_id.hpp:552
0 means no-error.
Definition: error_code.hpp:87
uint32_t McsBlockIndex
Index in thread-local MCS block.
Definition: xct_id.hpp:153
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
template<typename ADAPTOR >
McsBlockIndex foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::acquire_try_rw_reader ( McsRwLock lock)
inline

Definition at line 756 of file xct_mcs_impl.cpp.

References ASSERT_ND, foedus::kErrorCodeLockCancelled, and foedus::kErrorCodeOk.

756  {
757  // This is a bit special, we do an async acquire with a very short timeout:
758  // giving 0 timeout might cause unnecessary cancelling because of delay in
759  // lock granting from reader predecessor. Note that there is a delay even if
760  // there are only readers, the last requester has to wait for its predecessor
761  // to notify about the granting of the lock.
762  McsBlockIndex block_index = 0;
763  auto ret = acquire_reader_lock(lock, &block_index, 10);
765  ASSERT_ND(block_index);
766  if (ret == kErrorCodeOk) {
767  return block_index;
768  } else {
769  // NOTE: In this case, we CANNOT do this. Extended version's try-reader
770  // actually inserts the qnode. So others might have observed it.
771  // // adaptor_.cancel_new_block(block_index);
772  // To avoid using up 2^16 qnodes, we might want a "peek" check to
773  // exit before putting qnode when obviously there is a writer.
774  return 0;
775  }
776 
777  /* The old version that uses 0 timeout:
778  McsBlockIndex block_index = 0;
779  auto ret = acquire_reader_lock(lock, &block_index, McsRwExtendedBlock::kTimeoutZero);
780  ASSERT_ND(ret == kErrorCodeOk || ret == kErrorCodeLockRequested);
781  ASSERT_ND(block_index);
782  if (ret == kErrorCodeOk) {
783  return block_index;
784  }
785  ASSERT_ND(ret == kErrorCodeLockRequested);
786  uint32_t my_tail_int =
787  xct::McsRwLock::to_tail_int(static_cast<uint32_t>(adaptor_.get_my_id()), block_index);
788  // check once
789  if (retry_async_rw_reader(lock, block_index) ||
790  cancel_reader_lock(lock, my_tail_int) == kErrorCodeOk) {
791  return block_index;
792  }
793  return 0;
794  */
795  }
0 means no-error.
Definition: error_code.hpp:87
uint32_t McsBlockIndex
Index in thread-local MCS block.
Definition: xct_id.hpp:153
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
0x0AA2 : "XCTION : Lock acquire cancelled." .
Definition: error_code.hpp:207
template<typename ADAPTOR >
McsBlockIndex foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::acquire_try_rw_writer ( McsRwLock lock)
inline

Instant-try versions, won't leave node in the queue if failed.

Different from SimpleRWLock, here we use the async try/retry/cancel trio.

Definition at line 705 of file xct_mcs_impl.cpp.

References foedus::xct::McsRwLock::tail_, and foedus::xct::McsRwLock::to_tail_int().

705  {
706  const thread::ThreadId id = adaptor_.get_my_id();
707  McsBlockIndex block_index = 0;
708  auto* my_block = init_block(&block_index, true);
709 
710  McsRwLock tmp;
711  uint64_t expected = *reinterpret_cast<uint64_t*>(&tmp);
712  McsRwLock tmp2;
713  tmp2.tail_ = McsRwLock::to_tail_int(id, block_index);
714  uint64_t desired = *reinterpret_cast<uint64_t*>(&tmp2);
715  my_block->set_flags_granted();
716  if (assorted::raw_atomic_compare_exchange_weak<uint64_t>(
717  reinterpret_cast<uint64_t*>(lock), &expected, desired)) {
718  return block_index;
719  } else {
720  // The block is never observed. reuse
721  adaptor_.cancel_new_block(block_index);
722  return 0;
723  }
724 
725  /*
726  * XXX(tzwang, Feb 2016): it turns out the above CAS-try is better than using the trio -
727  * the difference could be as much as 10x under high contention (DL580). The reason
728  * I think is under high contention, often we need to cancel anyway, which is much
729  * more expensive than a simple weak CAS.
730  *
731  * But the case for readers is a bit different: the trio wins especially with a lot of
732  * reads because it allows real reader-sharing.
733  */
734  /*
735  McsBlockIndex block_index = 0;
736  //auto ret = acquire_writer_lock(lock, &block_index, McsRwExtendedBlock::kTimeoutZero);
737  auto ret = acquire_writer_lock(lock, &block_index, 1000);
738  ASSERT_ND(ret == kErrorCodeOk || ret == kErrorCodeLockRequested);
739  ASSERT_ND(block_index);
740  if (ret == kErrorCodeOk) {
741  return block_index;
742  }
743  return 0;
744 
745  ASSERT_ND(ret == kErrorCodeLockRequested);
746  uint32_t my_tail_int =
747  xct::McsRwLock::to_tail_int(static_cast<uint32_t>(adaptor_.get_my_id()), block_index);
748  // check once
749  if (retry_async_rw_writer(lock, block_index) ||
750  cancel_writer_lock(lock, my_tail_int) == kErrorCodeOk) {
751  return block_index;
752  }
753  return 0;
754  */
755  }
static uint32_t to_tail_int(thread::ThreadId tail_waiter, McsBlockIndex tail_waiter_block)
Definition: xct_id.hpp:848
uint32_t McsBlockIndex
Index in thread-local MCS block.
Definition: xct_id.hpp:153
uint16_t ThreadId
Typedef for a global ID of Thread (core), which is unique across NUMA nodes.
Definition: thread_id.hpp:80

Here is the call graph for this function:

template<typename ADAPTOR >
McsBlockIndex foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::acquire_unconditional_rw_reader ( McsRwLock lock)
inline

Definition at line 679 of file xct_mcs_impl.cpp.

References ASSERT_ND, foedus::kErrorCodeOk, and foedus::xct::McsRwExtendedBlock::kTimeoutNever.

679  {
680  McsBlockIndex block_index = 0;
681  auto ret = acquire_reader_lock(lock, &block_index, McsRwExtendedBlock::kTimeoutNever);
682  ASSERT_ND(block_index);
683  ASSERT_ND(ret == kErrorCodeOk);
684 #ifndef NDEBUG
685  auto* my_block = adaptor_.get_rw_my_block(block_index);
686  ASSERT_ND(my_block->next_flag_is_granted());
687  ASSERT_ND(my_block->pred_flag_is_granted());
688 #endif
689  return block_index;
690  }
0 means no-error.
Definition: error_code.hpp:87
static const int32_t kTimeoutNever
Definition: xct_id.hpp:551
uint32_t McsBlockIndex
Index in thread-local MCS block.
Definition: xct_id.hpp:153
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
template<typename ADAPTOR >
McsBlockIndex foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::acquire_unconditional_rw_writer ( McsRwLock lock)
inline

Definition at line 691 of file xct_mcs_impl.cpp.

References ASSERT_ND, foedus::kErrorCodeOk, and foedus::xct::McsRwExtendedBlock::kTimeoutNever.

691  {
692  McsBlockIndex block_index = 0;
693  auto ret = acquire_writer_lock(lock, &block_index, McsRwExtendedBlock::kTimeoutNever);
694  ASSERT_ND(block_index);
695  ASSERT_ND(ret == kErrorCodeOk);
696 #ifndef NDEBUG
697  auto* my_block = adaptor_.get_rw_my_block(block_index);
698  ASSERT_ND(my_block->next_flag_is_granted());
699  ASSERT_ND(my_block->pred_flag_is_granted());
700 #endif
701  return block_index;
702  }
0 means no-error.
Definition: error_code.hpp:87
static const int32_t kTimeoutNever
Definition: xct_id.hpp:551
uint32_t McsBlockIndex
Index in thread-local MCS block.
Definition: xct_id.hpp:153
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
template<typename ADAPTOR >
void foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::cancel_async_rw_reader ( McsRwLock lock,
McsBlockIndex  block_index 
)
inline

Definition at line 867 of file xct_mcs_impl.cpp.

References foedus::kErrorCodeOk, foedus::xct::McsImpl< ADAPTOR, RW_BLOCK >::retry_async_rw_reader(), and foedus::xct::McsRwLock::to_tail_int().

867  {
868  if (!retry_async_rw_reader(lock, block_index)) {
869  uint32_t my_tail_int = McsRwLock::to_tail_int(adaptor_.get_my_id(), block_index);
870  if (cancel_reader_lock(lock, my_tail_int) == kErrorCodeOk) {
871  // actually got the lock, have to release then
872  release_reader_lock(lock, block_index);
873  }
874  } else {
875  release_reader_lock(lock, block_index);
876  }
877  }
static uint32_t to_tail_int(thread::ThreadId tail_waiter, McsBlockIndex tail_waiter_block)
Definition: xct_id.hpp:848
0 means no-error.
Definition: error_code.hpp:87
bool retry_async_rw_reader(McsRwLock *lock, McsBlockIndex block_index)

Here is the call graph for this function:

template<typename ADAPTOR >
void foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::cancel_async_rw_writer ( McsRwLock lock,
McsBlockIndex  block_index 
)
inline

Definition at line 878 of file xct_mcs_impl.cpp.

References foedus::kErrorCodeOk, and foedus::xct::McsRwLock::to_tail_int().

878  {
879  uint32_t my_tail_int = McsRwLock::to_tail_int(adaptor_.get_my_id(), block_index);
880  if (cancel_writer_lock(lock, my_tail_int) == kErrorCodeOk) {
881  release_writer_lock(lock, block_index);
882  }
883  }
static uint32_t to_tail_int(thread::ThreadId tail_waiter, McsBlockIndex tail_waiter_block)
Definition: xct_id.hpp:848
0 means no-error.
Definition: error_code.hpp:87

Here is the call graph for this function:

template<typename ADAPTOR >
static bool foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::does_support_try_rw_reader ( )
inlinestatic

Definition at line 678 of file xct_mcs_impl.cpp.

678 { return true; }
template<typename ADAPTOR >
void foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::release_rw_reader ( McsRwLock lock,
McsBlockIndex  block_index 
)
inline

Definition at line 796 of file xct_mcs_impl.cpp.

796  {
797  release_reader_lock(lock, block_index);
798  }
template<typename ADAPTOR >
void foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::release_rw_writer ( McsRwLock lock,
McsBlockIndex  block_index 
)
inline

Definition at line 799 of file xct_mcs_impl.cpp.

799  {
800  release_writer_lock(lock, block_index);
801  }
template<typename ADAPTOR >
bool foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::retry_async_rw_reader ( McsRwLock lock,
McsBlockIndex  block_index 
)
inline

Definition at line 838 of file xct_mcs_impl.cpp.

References ASSERT_ND, foedus::kErrorCodeOk, and foedus::xct::McsRwLock::to_tail_int().

838  {
839  auto* block = adaptor_.get_rw_my_block(block_index);
840  if (block->pred_flag_is_granted()) {
841  // checking me.next.flags.granted is ok - we're racing with ourself
842  if (!block->next_flag_is_granted()) {
843  auto ret = finish_acquire_reader_lock(lock, block,
844  xct::McsRwLock::to_tail_int(static_cast<uint32_t>(adaptor_.get_my_id()), block_index));
845  ASSERT_ND(ret == kErrorCodeOk);
846  }
847  ASSERT_ND(block->next_flag_is_granted());
848  return true;
849  }
850  ASSERT_ND(!block->next_flag_is_granted());
851  return false;
852  }
static uint32_t to_tail_int(thread::ThreadId tail_waiter, McsBlockIndex tail_waiter_block)
Definition: xct_id.hpp:848
0 means no-error.
Definition: error_code.hpp:87
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72

Here is the call graph for this function:

template<typename ADAPTOR >
bool foedus::xct::McsImpl< ADAPTOR, McsRwExtendedBlock >::retry_async_rw_writer ( McsRwLock lock,
McsBlockIndex  block_index 
)
inline

Definition at line 853 of file xct_mcs_impl.cpp.

References ASSERT_ND.

853  {
854  auto* block = adaptor_.get_rw_my_block(block_index);
855  if (block->pred_flag_is_granted()) {
856  // checking me.next.flags.granted is ok - we're racing with ourself
857  if (!block->next_flag_is_granted()) {
858  block->set_next_flag_granted();
859  adaptor_.remove_rw_async_mapping(lock);
860  }
861  ASSERT_ND(block->next_flag_is_granted());
862  return true;
863  }
864  ASSERT_ND(!block->next_flag_is_granted());
865  return false;
866  }
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72

The documentation for this class was generated from the following file: