proxygen
folly::FlatCombining< T, Mutex, Atom, Req > Class Template Reference

#include <FlatCombining.h>

Classes

class  Rec
 Combining request record. More...
 

Public Types

using Pool = folly::IndexedMemPool< Rec, 32, 4, Atom, IndexedMemPoolTraitsLazyRecycle< Rec >>
 

Public Member Functions

 FlatCombining (const bool dedicated=true, const uint32_t numRecs=0, const uint32_t maxOps=0)
 
 ~FlatCombining ()
 
void drainAll ()
 
void acquireExclusive ()
 
bool tryExclusive ()
 
void releaseExclusive ()
 
template<typename LockHolder >
void holdLock (LockHolder &l)
 
template<typename LockHolder >
void holdLock (LockHolder &l, std::defer_lock_t)
 
template<typename OpFunc >
void requestNoFC (OpFunc &opFn)
 
template<typename OpFunc >
void requestFC (OpFunc &&opFn, Rec *rec=nullptr, bool syncop=true)
 
template<typename OpFunc , typename FillFunc >
void requestFC (OpFunc &&opFn, const FillFunc &fillFn, Rec *rec=nullptr, bool syncop=true)
 
template<typename OpFunc , typename FillFunc , typename ResFn >
void requestFC (OpFunc &&opFn, const FillFunc &fillFn, const ResFn &resFn, Rec *rec=nullptr)
 
RecallocRec ()
 
void freeRec (Rec *rec)
 
uint64_t getNumUncombined () const
 
uint64_t getNumCombined () const
 
uint64_t getNumPasses () const
 
uint64_t getNumSessions () const
 

Protected Member Functions

template<typename OpFunc , typename FillFunc , typename ResFn >
void requestOp (OpFunc &&opFn, const FillFunc &fillFn, const ResFn &resFn, Rec *rec, bool syncop, const bool custom)
 
void pushRec (size_t idx)
 
size_t getRecsHead ()
 
size_t nextIndex (size_t idx)
 
void clearPending ()
 
void setPending ()
 
bool isPending () const
 
void awaitPending ()
 
uint64_t combiningSession ()
 
void tryCombining ()
 
void dedicatedCombining ()
 
void awaitDone (Rec &rec)
 
void awaitDoneTryLock (Rec &rec)
 
void shutdown ()
 
void combinedOp (Req &)
 The following member functions may be overridden for customization. More...
 
void processReq (Rec &rec)
 
uint64_t combiningPass ()
 

Protected Attributes

const size_t NULL_INDEX = 0
 
const uint32_t kDefaultMaxOps = 100
 
const uint64_t kDefaultNumRecs = 64
 
const uint64_t kIdleThreshold = 10
 
Mutex m_
 
folly::SaturatingSemaphore< true, Atompending_
 
Atom< bool > shutdown_ {false}
 
uint32_t numRecs_
 
uint32_t maxOps_
 
Atom< size_t > recs_
 
bool dedicated_
 
std::thread combiner_
 
Pool recsPool_
 
uint64_t uncombined_ = 0
 
uint64_t combined_ = 0
 
uint64_t passes_ = 0
 
uint64_t sessions_ = 0
 

Private Types

using SavedFn = folly::Function< void()>
 

Detailed Description

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
class folly::FlatCombining< T, Mutex, Atom, Req >

Flat combining (FC) was introduced in the SPAA 2010 paper Flat Combining and the Synchronization-Parallelism Tradeoff, by Danny Hendler, Itai Incze, Nir Shavit, and Moran Tzafrir. http://mcg.cs.tau.ac.il/projects/projects/flat-combining

FC is an alternative to coarse-grained locking for making sequential data structures thread-safe while minimizing the synchronization overheads and cache coherence traffic associated with locking.

Under FC, when a thread finds the lock contended, it can request (using a request record) that the lock holder execute its operation on the shared data structure. There can be a designated combiner thread or any thread can act as the combiner when it holds the lock.

Potential advantages of FC include:

  • Reduced cache coherence traffic
  • Reduced synchronization overheads, as the overheads of releasing and acquiring the lock are eliminated from the critical path of operating on the data structure.
  • Opportunities for smart combining, where executing multiple operations together may take less time than executing the operations separately, e.g., K delete_min operations on a priority queue may be combined to take O(K + log N) time instead of O(K * log N).

This implementation of flat combining supports: - A simple interface that requires minimal extra code by the user. To use this interface efficiently the user-provided functions must be copyable to folly::Function without dynamic allocation. If this is impossible or inconvenient, the user is encouraged to use the custom interface described below.

  • A custom interface that supports custom combining and custom request structure, either for the sake of smart combining or for efficiently supporting operations that are not be copyable to folly::Function without dynamic allocation.
  • Both synchronous and asynchronous operations.
  • Request records with and without thread-caching.
  • Combining with and without a dedicated combiner thread.

This implementation differs from the algorithm in the SPAA 2010 paper:

  • It does not require thread caching of request records
  • It supports a dedicated combiner
  • It supports asynchronous operations

The generic FC class template supports generic data structures and utilities with arbitrary operations. The template supports static polymorphism for the combining function to enable custom smart combining.

A simple example of using the FC template: class ConcurrentFoo : public FlatCombining<ConcurrentFoo> { Foo foo_; // sequential data structure public: T bar(V& v) { // thread-safe execution of foo_.bar(v) T result; // Note: fn must be copyable to folly::Function without dynamic // allocation. Otherwise, it is recommended to use the custom // interface and manage the function arguments and results // explicitly in a custom request structure. auto fn = [&] { result = foo_.bar(v); }; this->requestFC(fn); return result; } };

See test/FlatCombiningExamples.h for more examples. See the comments for requestFC() below for a list of simple and custom variants of that function.

Definition at line 109 of file FlatCombining.h.

Member Typedef Documentation

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
using folly::FlatCombining< T, Mutex, Atom, Req >::Pool = folly:: IndexedMemPool<Rec, 32, 4, Atom, IndexedMemPoolTraitsLazyRecycle<Rec>>

Definition at line 230 of file FlatCombining.h.

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
using folly::FlatCombining< T, Mutex, Atom, Req >::SavedFn = folly::Function<void()>
private

Definition at line 110 of file FlatCombining.h.

Constructor & Destructor Documentation

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
folly::FlatCombining< T, Mutex, Atom, Req >::FlatCombining ( const bool  dedicated = true,
const uint32_t  numRecs = 0,
const uint32_t  maxOps = 0 
)
inlineexplicit

The constructor takes three optional arguments:

  • Optional dedicated combiner thread (default true)
  • Number of records (if 0, then kDefaultNumRecs)
  • A hint for the max. number of combined operations per combining session that is checked at the beginning of each pass on the request records (if 0, then kDefaultMaxops)

Definition at line 239 of file FlatCombining.h.

244  : numRecs_(numRecs == 0 ? kDefaultNumRecs : numRecs),
245  maxOps_(maxOps == 0 ? kDefaultMaxOps : maxOps),
246  recs_(NULL_INDEX),
249  if (dedicated_) {
250  // dedicated combiner thread
251  combiner_ = std::thread([this] { dedicatedCombining(); });
252  }
253  }
const uint32_t kDefaultMaxOps
static bool dedicated
const uint64_t kDefaultNumRecs
const size_t NULL_INDEX
Atom< size_t > recs_
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
folly::FlatCombining< T, Mutex, Atom, Req >::~FlatCombining ( )
inline

Destructor: If there is a dedicated combiner, the destructor flags it to shutdown. Otherwise, the destructor waits for all pending asynchronous requests to be completed.

Definition at line 258 of file FlatCombining.h.

258  {
259  if (dedicated_) {
260  shutdown();
261  combiner_.join();
262  } else {
263  drainAll();
264  }
265  }

Member Function Documentation

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::acquireExclusive ( )
inline

Definition at line 278 of file FlatCombining.h.

278  {
279  m_.lock();
280  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
Rec* folly::FlatCombining< T, Mutex, Atom, Req >::allocRec ( )
inline

Definition at line 379 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::requestOp().

379  {
380  auto idx = recsPool_.allocIndex();
381  if (idx == NULL_INDEX) {
382  return nullptr;
383  }
384  Rec& rec = recsPool_[idx];
385  rec.setIndex(idx);
386  return &rec;
387  }
uint32_t allocIndex(Args &&...args)
const size_t NULL_INDEX
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::awaitDone ( Rec rec)
inlineprotected

Definition at line 594 of file FlatCombining.h.

594  {
595  if (dedicated_) {
596  rec.awaitDone();
597  } else {
598  awaitDoneTryLock(rec);
599  }
600  }
void awaitDoneTryLock(Rec &rec)
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::awaitDoneTryLock ( Rec rec)
inlineprotected

Waits for the request to be done and occasionally tries to acquire the lock and to do combining. Used only in the absence of a dedicated combiner.

Definition at line 605 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::awaitDone().

605  {
606  assert(!dedicated_);
607  int count = 0;
608  while (!rec.isDone()) {
609  if (count == 0) {
610  std::unique_lock<Mutex> l(m_, std::defer_lock);
611  if (l.try_lock()) {
612  setPending();
613  tryCombining();
614  }
615  } else {
617  if (++count == 1000) {
618  count = 0;
619  }
620  }
621  }
622  }
int * count
void asm_volatile_pause()
Definition: Asm.h:37
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::awaitPending ( )
inlineprotected

Definition at line 545 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::dedicatedCombining().

545  {
546  pending_.wait();
547  }
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
folly::SaturatingSemaphore< true, Atom > pending_
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::clearPending ( )
inlineprotected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::combinedOp ( Req )
inlineprotected

The following member functions may be overridden for customization.

Definition at line 631 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::processReq().

631  {
632  throw std::runtime_error(
633  "FlatCombining::combinedOp(Req&) must be overridden in the derived"
634  " class if called.");
635  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::combiningPass ( )
inlineprotected

Definition at line 651 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::combiningSession().

651  {
652  uint64_t count = 0;
653  auto idx = getRecsHead();
654  Rec* prev = nullptr;
655  while (idx != NULL_INDEX) {
656  Rec& rec = recsPool_[idx];
657  auto next = rec.getNext();
658  bool valid = rec.isValid();
659  if (!valid && (passes_ - rec.getLast() > kIdleThreshold) &&
660  (prev != nullptr)) {
661  // Disconnect
662  prev->setNext(next);
663  rec.setDisconnected();
664  // store-load order setDisconnected before isValid
665  std::atomic_thread_fence(std::memory_order_seq_cst);
666  valid = rec.isValid();
667  } else {
668  prev = &rec;
669  }
670  if (valid) {
671  processReq(rec);
672  ++count;
673  }
674  idx = next;
675  }
676  return count;
677  }
void processReq(Rec &rec)
const uint64_t kIdleThreshold
int * count
const size_t NULL_INDEX
def next(obj)
Definition: ast.py:58
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::combiningSession ( )
inlineprotected

Definition at line 549 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::dedicatedCombining(), and folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::tryCombining().

549  {
550  uint64_t combined = 0;
551  do {
552  uint64_t count = static_cast<T*>(this)->combiningPass();
553  if (count == 0) {
554  break;
555  }
556  combined += count;
557  ++this->passes_;
558  } while (combined < this->maxOps_);
559  return combined;
560  }
folly::std T
int * count
uint64_t combiningPass()
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::dedicatedCombining ( )
inlineprotected

Definition at line 572 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::FlatCombining().

572  {
573  while (true) {
574  awaitPending();
575  clearPending();
576  if (shutdown_.load()) {
577  break;
578  }
579  while (true) {
580  uint64_t count;
581  ++sessions_;
582  {
583  std::lock_guard<Mutex> guard(m_);
584  count = combiningSession();
585  combined_ += count;
586  }
587  if (count < maxOps_) {
588  break;
589  }
590  }
591  }
592  }
uint64_t combiningSession()
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
int * count
Atom< bool > shutdown_
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::drainAll ( )
inline

Definition at line 270 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::~FlatCombining().

270  {
271  for (size_t i = getRecsHead(); i != NULL_INDEX; i = nextIndex(i)) {
272  Rec& rec = recsPool_[i];
273  awaitDone(rec);
274  }
275  }
size_t nextIndex(size_t idx)
const size_t NULL_INDEX
void awaitDone(Rec &rec)
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::freeRec ( Rec rec)
inline

Definition at line 390 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::requestOp().

390  {
391  if (rec == nullptr) {
392  return;
393  }
394  auto idx = rec->getIndex();
395  recsPool_.recycleIndex(idx);
396  }
void recycleIndex(uint32_t idx)
Gives up ownership previously granted by alloc()
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::getNumCombined ( ) const
inline

Definition at line 404 of file FlatCombining.h.

404  {
405  return combined_;
406  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::getNumPasses ( ) const
inline

Definition at line 409 of file FlatCombining.h.

409  {
410  return passes_;
411  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::getNumSessions ( ) const
inline

Definition at line 414 of file FlatCombining.h.

414  {
415  return sessions_;
416  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::getNumUncombined ( ) const
inline

Definition at line 399 of file FlatCombining.h.

399  {
400  return uncombined_;
401  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
size_t folly::FlatCombining< T, Mutex, Atom, Req >::getRecsHead ( )
inlineprotected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
template<typename LockHolder >
void folly::FlatCombining< T, Mutex, Atom, Req >::holdLock ( LockHolder &  l)
inline

Definition at line 295 of file FlatCombining.h.

295  {
296  l = LockHolder(m_);
297  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
template<typename LockHolder >
void folly::FlatCombining< T, Mutex, Atom, Req >::holdLock ( LockHolder &  l,
std::defer_lock_t   
)
inline

Definition at line 303 of file FlatCombining.h.

303  {
304  l = LockHolder(m_, std::defer_lock);
305  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
bool folly::FlatCombining< T, Mutex, Atom, Req >::isPending ( ) const
inlineprotected

Definition at line 541 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::tryCombining().

541  {
542  return pending_.ready();
543  }
FOLLY_ALWAYS_INLINE bool ready() const noexcept
folly::SaturatingSemaphore< true, Atom > pending_
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
size_t folly::FlatCombining< T, Mutex, Atom, Req >::nextIndex ( size_t  idx)
inlineprotected

Definition at line 529 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::drainAll().

529  {
530  return recsPool_[idx].getNext();
531  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::processReq ( Rec rec)
inlineprotected

Definition at line 637 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::combiningPass().

637  {
638  SavedFn& opFn = rec.getFn();
639  if (opFn) {
640  // simple interface
641  opFn();
642  } else {
643  // custom interface
644  Req& req = rec.getReq();
645  static_cast<T*>(this)->combinedOp(req); // defined in derived class
646  }
647  rec.setLast(passes_);
648  rec.complete();
649  }
folly::Function< void()> SavedFn
folly::std T
void combinedOp(Req &)
The following member functions may be overridden for customization.
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::pushRec ( size_t  idx)
inlineprotected

Definition at line 514 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::requestOp().

514  {
515  Rec& rec = recsPool_[idx];
516  while (true) {
517  auto head = recs_.load(std::memory_order_acquire);
518  rec.setNext(head); // there shouldn't be a data race here
519  if (recs_.compare_exchange_weak(head, idx)) {
520  return;
521  }
522  }
523  }
Atom< size_t > recs_
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::releaseExclusive ( )
inline

Definition at line 288 of file FlatCombining.h.

288  {
289  m_.unlock();
290  }
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
template<typename OpFunc >
void folly::FlatCombining< T, Mutex, Atom, Req >::requestFC ( OpFunc &&  opFn,
Rec rec = nullptr,
bool  syncop = true 
)
inline

Definition at line 337 of file FlatCombining.h.

337  {
338  auto dummy = [](Req&) {};
339  requestOp(
340  std::forward<OpFunc>(opFn),
341  dummy /* fillFn */,
342  dummy /* resFn */,
343  rec,
344  syncop,
345  false /* simple */);
346  }
void dummy()
void requestOp(OpFunc &&opFn, const FillFunc &fillFn, const ResFn &resFn, Rec *rec, bool syncop, const bool custom)
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
template<typename OpFunc , typename FillFunc >
void folly::FlatCombining< T, Mutex, Atom, Req >::requestFC ( OpFunc &&  opFn,
const FillFunc &  fillFn,
Rec rec = nullptr,
bool  syncop = true 
)
inline

Definition at line 348 of file FlatCombining.h.

352  {
353  auto dummy = [](Req&) {};
354  requestOp(
355  std::forward<OpFunc>(opFn),
356  fillFn,
357  dummy /* resFn */,
358  rec,
359  syncop,
360  true /* custom */);
361  }
void dummy()
void requestOp(OpFunc &&opFn, const FillFunc &fillFn, const ResFn &resFn, Rec *rec, bool syncop, const bool custom)
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
template<typename OpFunc , typename FillFunc , typename ResFn >
void folly::FlatCombining< T, Mutex, Atom, Req >::requestFC ( OpFunc &&  opFn,
const FillFunc &  fillFn,
const ResFn &  resFn,
Rec rec = nullptr 
)
inline

Definition at line 363 of file FlatCombining.h.

367  {
368  // must wait for result to execute resFn -- so it must be synchronous
369  requestOp(
370  std::forward<OpFunc>(opFn),
371  fillFn,
372  resFn,
373  rec,
374  true /* sync */,
375  true /* custom*/);
376  }
void requestOp(OpFunc &&opFn, const FillFunc &fillFn, const ResFn &resFn, Rec *rec, bool syncop, const bool custom)
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
template<typename OpFunc >
void folly::FlatCombining< T, Mutex, Atom, Req >::requestNoFC ( OpFunc &  opFn)
inline

Definition at line 309 of file FlatCombining.h.

309  {
310  std::lock_guard<Mutex> guard(m_);
311  opFn();
312  }
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
template<typename OpFunc , typename FillFunc , typename ResFn >
void folly::FlatCombining< T, Mutex, Atom, Req >::requestOp ( OpFunc &&  opFn,
const FillFunc &  fillFn,
const ResFn &  resFn,
Rec rec,
bool  syncop,
const bool  custom 
)
inlineprotected

Definition at line 443 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::requestFC().

449  {
450  std::unique_lock<Mutex> l(this->m_, std::defer_lock);
451  if (l.try_lock()) {
452  // No contention
453  ++uncombined_;
454  tryCombining();
455  opFn();
456  return;
457  }
458 
459  // Try FC
460  bool tc = (rec != nullptr);
461  if (!tc) {
462  // if an async op doesn't have a thread-cached record then turn
463  // it into a synchronous op.
464  syncop = true;
465  rec = allocRec();
466  }
467  if (rec == nullptr) {
468  // Can't use FC - Must acquire lock
469  l.lock();
470  ++uncombined_;
471  tryCombining();
472  opFn();
473  return;
474  }
475 
476  // Use FC
477  // Wait if record is in use
478  awaitDone(*rec);
479  rec->clearDone();
480  // Fill record
481  if (custom) {
482  // Fill the request (custom)
483  Req& req = rec->getReq();
484  fillFn(req);
485  rec->clearFn();
486  } else {
487  rec->setFn(std::forward<OpFunc>(opFn));
488  }
489  // Indicate that record is valid
490  assert(!rec->isValid());
491  rec->setValid();
492  // end of combining critical path
493  setPending();
494  // store-load order setValid before isDisconnected
495  std::atomic_thread_fence(std::memory_order_seq_cst);
496  if (rec->isDisconnected()) {
497  rec->clearDisconnected();
498  pushRec(rec->getIndex());
499  setPending();
500  }
501  // If synchronous wait for the request to be completed
502  if (syncop) {
503  awaitDone(*rec);
504  if (custom) {
505  Req& req = rec->getReq();
506  resFn(req); // Extract the result (custom)
507  }
508  if (!tc) {
509  freeRec(rec); // Free the temporary record.
510  }
511  }
512  }
void pushRec(size_t idx)
void freeRec(Rec *rec)
static bool tc
void awaitDone(Rec &rec)
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::setPending ( )
inlineprotected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::shutdown ( )
inlineprotected

Definition at line 624 of file FlatCombining.h.

Referenced by folly::FlatCombining< FcSimpleExample< Mutex, Atom >, Mutex, Atom >::~FlatCombining().

624  {
625  shutdown_.store(true);
626  setPending();
627  }
Atom< bool > shutdown_
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
void folly::FlatCombining< T, Mutex, Atom, Req >::tryCombining ( )
inlineprotected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
bool folly::FlatCombining< T, Mutex, Atom, Req >::tryExclusive ( )
inline

Definition at line 283 of file FlatCombining.h.

283  {
284  return m_.try_lock();
285  }

Member Data Documentation

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::combined_ = 0
protected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
std::thread folly::FlatCombining< T, Mutex, Atom, Req >::combiner_
protected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
bool folly::FlatCombining< T, Mutex, Atom, Req >::dedicated_
protected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
const uint32_t folly::FlatCombining< T, Mutex, Atom, Req >::kDefaultMaxOps = 100
protected

Definition at line 420 of file FlatCombining.h.

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
const uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::kDefaultNumRecs = 64
protected

Definition at line 421 of file FlatCombining.h.

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
const uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::kIdleThreshold = 10
protected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint32_t folly::FlatCombining< T, Mutex, Atom, Req >::maxOps_
protected

Definition at line 431 of file FlatCombining.h.

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
const size_t folly::FlatCombining< T, Mutex, Atom, Req >::NULL_INDEX = 0
protected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint32_t folly::FlatCombining< T, Mutex, Atom, Req >::numRecs_
protected

Definition at line 430 of file FlatCombining.h.

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::passes_ = 0
protected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
Atom<size_t> folly::FlatCombining< T, Mutex, Atom, Req >::recs_
protected

Definition at line 432 of file FlatCombining.h.

template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
Pool folly::FlatCombining< T, Mutex, Atom, Req >::recsPool_
protected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
Atom<bool> folly::FlatCombining< T, Mutex, Atom, Req >::shutdown_ {false}
protected
template<typename T, typename Mutex = std::mutex, template< typename > class Atom = std::atomic, typename Req = bool>
uint64_t folly::FlatCombining< T, Mutex, Atom, Req >::uncombined_ = 0
protected

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