X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fexperimental%2FLockFreeRingBuffer.h;h=f8c76e4174a17fe2dd8bc30ad204dad1c4245f10;hb=ebcef6dcbcd0c0c7a532d8a477e2af14627832d2;hp=f8dff773c317eafb3af13bb26bebd7da09c13815;hpb=6f8699fc809889f748c2f83a9b042a497f81d32a;p=folly.git diff --git a/folly/experimental/LockFreeRingBuffer.h b/folly/experimental/LockFreeRingBuffer.h index f8dff773..f8c76e41 100644 --- a/folly/experimental/LockFreeRingBuffer.h +++ b/folly/experimental/LockFreeRingBuffer.h @@ -70,16 +70,24 @@ public: struct Cursor { explicit Cursor(uint64_t initialTicket) noexcept : ticket(initialTicket) {} - void moveForward(uint64_t steps = 1) noexcept { + /// Returns true if this cursor now points to a different + /// write, false otherwise. + bool moveForward(uint64_t steps = 1) noexcept { + uint64_t prevTicket = ticket; ticket += steps; + return prevTicket != ticket; } - void moveBackward(uint64_t steps = 1) noexcept { + /// Returns true if this cursor now points to a previous + /// write, false otherwise. + bool moveBackward(uint64_t steps = 1) noexcept { + uint64_t prevTicket = ticket; if (steps > ticket) { ticket = 0; } else { ticket -= steps; } + return prevTicket != ticket; } protected: // for test visibility reasons @@ -87,7 +95,7 @@ public: friend class LockFreeRingBuffer; }; - explicit LockFreeRingBuffer(size_t capacity) noexcept + explicit LockFreeRingBuffer(uint32_t capacity) noexcept : capacity_(capacity) , slots_(new detail::RingBufferSlot[capacity]) , ticket_(0) @@ -101,6 +109,16 @@ public: slots_[idx(ticket)].write(turn(ticket), value); } + /// Perform a single write of an object of type T. + /// Writes can block iff a previous writer has not yet completed a write + /// for the same slot (before the most recent wrap-around). + /// Returns a Cursor pointing to the just-written T. + Cursor writeAndGetCursor(T& value) noexcept { + uint64_t ticket = ticket_.fetch_add(1); + slots_[idx(ticket)].write(turn(ticket), value); + return Cursor(ticket); + } + /// Read the value at the cursor. /// Returns true if the read succeeded, false otherwise. If the return /// value is false, dest is to be considered partially read and in an @@ -145,7 +163,7 @@ public: } private: - const size_t capacity_; + const uint32_t capacity_; const std::unique_ptr[]> slots_; @@ -156,7 +174,7 @@ private: } uint32_t turn(uint64_t ticket) noexcept { - return (ticket / capacity_); + return (uint32_t)(ticket / capacity_); } }; // LockFreeRingBuffer