From: Yedidya Feldblum Date: Mon, 6 Nov 2017 23:22:31 +0000 (-0800) Subject: Move folly/LifoSem.h X-Git-Tag: v2017.11.13.00~29 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=c593d8eda8eea90818908fce46409b970ca1f540;p=folly.git Move folly/LifoSem.h Summary: [Folly] Move `folly/LifoSem.h` to `folly/synchronization/`. Reviewed By: meyering Differential Revision: D6245444 fbshipit-source-id: 14ffa012fa92b8c6aaf5900c930156894a492003 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index a3721612..37152974 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -505,6 +505,7 @@ if (BUILD_TESTS) DIRECTORY synchronization/test/ TEST call_once_test SOURCES CallOnceTest.cpp + TEST lifo_sem_test SOURCES LifoSemTests.cpp DIRECTORY system/test/ TEST memory_mapping_test SOURCES MemoryMappingTest.cpp @@ -569,7 +570,6 @@ if (BUILD_TESTS) SOURCES JsonOtherTest.cpp TEST lazy_test SOURCES LazyTest.cpp - TEST lifosem_test SOURCES LifoSemTests.cpp TEST lock_traits_test SOURCES LockTraitsTest.cpp TEST locks_test SOURCES SmallLocksTest.cpp SpinLockTest.cpp TEST logging_test SOURCES LoggingTest.cpp diff --git a/folly/LifoSem.cpp b/folly/LifoSem.cpp deleted file mode 100644 index d3fa5065..00000000 --- a/folly/LifoSem.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2017 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -/// Raw node storage is preallocated in a contiguous memory segment, -/// but we use an anonymous mmap so the physical memory used (RSS) will -/// only reflect the maximum number of waiters that actually existed -/// concurrently. For blocked threads the max node count is limited by the -/// number of threads, so we can conservatively estimate that this will be -/// < 10k. For LifoEventSem, however, we could potentially have many more. -/// -/// On a 64-bit architecture each LifoSemRawNode takes 16 bytes. We make -/// the pool 1 million entries. - -LIFOSEM_DECLARE_POOL(std::atomic, 1000000) - -namespace folly { - -ShutdownSemError::ShutdownSemError(const std::string& msg) - : std::runtime_error(msg) -{} - -ShutdownSemError::~ShutdownSemError() noexcept { -} - -} // namespace folly diff --git a/folly/LifoSem.h b/folly/LifoSem.h deleted file mode 100644 index 90176094..00000000 --- a/folly/LifoSem.h +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright 2017 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace folly { - -template < - template class Atom = std::atomic, - class BatonType = Baton> -struct LifoSemImpl; - -/// LifoSem is a semaphore that wakes its waiters in a manner intended to -/// maximize performance rather than fairness. It should be preferred -/// to a mutex+condvar or POSIX sem_t solution when all of the waiters -/// are equivalent. It is faster than a condvar or sem_t, and it has a -/// shutdown state that might save you a lot of complexity when it comes -/// time to shut down your work pipelines. LifoSem is larger than sem_t, -/// but that is only because it uses padding and alignment to avoid -/// false sharing. -/// -/// LifoSem allows multi-post and multi-tryWait, and provides a shutdown -/// state that awakens all waiters. LifoSem is faster than sem_t because -/// it performs exact wakeups, so it often requires fewer system calls. -/// It provides all of the functionality of sem_t except for timed waiting. -/// It is called LifoSem because its wakeup policy is approximately LIFO, -/// rather than the usual FIFO. -/// -/// The core semaphore operations provided are: -/// -/// -- post() -- if there is a pending waiter, wake it up, otherwise -/// increment the value of the semaphore. If the value of the semaphore -/// is already 2^32-1, does nothing. Compare to sem_post(). -/// -/// -- post(n) -- equivalent to n calls to post(), but much more efficient. -/// sem_t has no equivalent to this method. -/// -/// -- bool tryWait() -- if the semaphore's value is positive, decrements it -/// and returns true, otherwise returns false. Compare to sem_trywait(). -/// -/// -- uint32_t tryWait(uint32_t n) -- attempts to decrement the semaphore's -/// value by n, returning the amount by which it actually was decremented -/// (a value from 0 to n inclusive). Not atomic. Equivalent to n calls -/// to tryWait(). sem_t has no equivalent to this method. -/// -/// -- wait() -- waits until tryWait() can succeed. Compare to sem_wait(). -/// -/// LifoSem also has the notion of a shutdown state, in which any calls -/// that would block (or are already blocked) throw ShutdownSemError. -/// Note the difference between a call to wait() and a call to wait() -/// that might block. In the former case tryWait() would succeed, and no -/// isShutdown() check is performed. In the latter case an exception is -/// thrown. This behavior allows a LifoSem controlling work distribution -/// to drain. If you want to immediately stop all waiting on shutdown, -/// you can just check isShutdown() yourself (preferrably wrapped in -/// an UNLIKELY). This fast-stop behavior is easy to add, but difficult -/// to remove if you want the draining behavior, which is why we have -/// chosen the former. Since wait() is the only method that can block, -/// it is the only one that is affected by the shutdown state. -/// -/// All LifoSem operations operations except valueGuess() are guaranteed -/// to be linearizable. -typedef LifoSemImpl<> LifoSem; - - -/// The exception thrown when wait()ing on an isShutdown() LifoSem -struct ShutdownSemError : public std::runtime_error { - explicit ShutdownSemError(const std::string& msg); - ~ShutdownSemError() noexcept override; -}; - -namespace detail { - -// Internally, a LifoSem is either a value or a linked list of wait nodes. -// This union is captured in the LifoSemHead type, which holds either a -// value or an indexed pointer to the list. LifoSemHead itself is a value -// type, the head is a mutable atomic box containing a LifoSemHead value. -// Each wait node corresponds to exactly one waiter. Values can flow -// through the semaphore either by going into and out of the head's value, -// or by direct communication from a poster to a waiter. The former path -// is taken when there are no pending waiters, the latter otherwise. The -// general flow of a post is to try to increment the value or pop-and-post -// a wait node. Either of those have the effect of conveying one semaphore -// unit. Waiting is the opposite, either a decrement of the value or -// push-and-wait of a wait node. The generic LifoSemBase abstracts the -// actual mechanism by which a wait node's post->wait communication is -// performed, which is why we have LifoSemRawNode and LifoSemNode. - -/// LifoSemRawNode is the actual pooled storage that backs LifoSemNode -/// for user-specified Handoff types. This is done so that we can have -/// a large static IndexedMemPool of nodes, instead of per-type pools -template