summaryrefslogtreecommitdiff
path: root/absl/synchronization/internal
diff options
context:
space:
mode:
Diffstat (limited to 'absl/synchronization/internal')
-rw-r--r--absl/synchronization/internal/create_thread_identity.cc35
-rw-r--r--absl/synchronization/internal/create_thread_identity.h7
-rw-r--r--absl/synchronization/internal/graphcycles.cc6
-rw-r--r--absl/synchronization/internal/graphcycles.h6
-rw-r--r--absl/synchronization/internal/graphcycles_benchmark.cc2
-rw-r--r--absl/synchronization/internal/graphcycles_test.cc6
-rw-r--r--absl/synchronization/internal/kernel_timeout.h12
-rw-r--r--absl/synchronization/internal/mutex_nonprod.cc6
-rw-r--r--absl/synchronization/internal/mutex_nonprod.inc7
-rw-r--r--absl/synchronization/internal/per_thread_sem.cc7
-rw-r--r--absl/synchronization/internal/per_thread_sem.h7
-rw-r--r--absl/synchronization/internal/per_thread_sem_test.cc23
-rw-r--r--absl/synchronization/internal/thread_pool.h9
-rw-r--r--absl/synchronization/internal/waiter.cc65
-rw-r--r--absl/synchronization/internal/waiter.h26
15 files changed, 158 insertions, 66 deletions
diff --git a/absl/synchronization/internal/create_thread_identity.cc b/absl/synchronization/internal/create_thread_identity.cc
index f27f16da..65f6d8fc 100644
--- a/absl/synchronization/internal/create_thread_identity.cc
+++ b/absl/synchronization/internal/create_thread_identity.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -27,12 +27,13 @@
#include "absl/synchronization/internal/per_thread_sem.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
// ThreadIdentity storage is persistent, we maintain a free-list of previously
// released ThreadIdentity objects.
-static base_internal::SpinLock freelist_lock(base_internal::kLinkerInitialized);
+static base_internal::SpinLock freelist_lock(
+ base_internal::kLinkerInitialized);
static base_internal::ThreadIdentity* thread_identity_freelist;
// A per-thread destructor for reclaiming associated ThreadIdentity objects.
@@ -68,6 +69,30 @@ static intptr_t RoundUp(intptr_t addr, intptr_t align) {
return (addr + align - 1) & ~(align - 1);
}
+static void ResetThreadIdentity(base_internal::ThreadIdentity* identity) {
+ base_internal::PerThreadSynch* pts = &identity->per_thread_synch;
+ pts->next = nullptr;
+ pts->skip = nullptr;
+ pts->may_skip = false;
+ pts->waitp = nullptr;
+ pts->suppress_fatal_errors = false;
+ pts->readers = 0;
+ pts->priority = 0;
+ pts->next_priority_read_cycles = 0;
+ pts->state.store(base_internal::PerThreadSynch::State::kAvailable,
+ std::memory_order_relaxed);
+ pts->maybe_unlocking = false;
+ pts->wake = false;
+ pts->cond_waiter = false;
+ pts->all_locks = nullptr;
+ identity->waiter_state = {};
+ identity->blocked_count_ptr = nullptr;
+ identity->ticker.store(0, std::memory_order_relaxed);
+ identity->wait_start.store(0, std::memory_order_relaxed);
+ identity->is_idle.store(false, std::memory_order_relaxed);
+ identity->next = nullptr;
+}
+
static base_internal::ThreadIdentity* NewThreadIdentity() {
base_internal::ThreadIdentity* identity = nullptr;
@@ -91,7 +116,7 @@ static base_internal::ThreadIdentity* NewThreadIdentity() {
RoundUp(reinterpret_cast<intptr_t>(allocation),
base_internal::PerThreadSynch::kAlignment));
}
- memset(identity, 0, sizeof(*identity));
+ ResetThreadIdentity(identity);
return identity;
}
@@ -108,7 +133,7 @@ base_internal::ThreadIdentity* CreateThreadIdentity() {
}
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_LOW_LEVEL_ALLOC_MISSING
diff --git a/absl/synchronization/internal/create_thread_identity.h b/absl/synchronization/internal/create_thread_identity.h
index 1132d516..d743cc3b 100644
--- a/absl/synchronization/internal/create_thread_identity.h
+++ b/absl/synchronization/internal/create_thread_identity.h
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -29,7 +29,7 @@
#include "absl/base/port.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
// Allocates and attaches a ThreadIdentity object for the calling thread.
@@ -50,6 +50,7 @@ inline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() {
}
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
diff --git a/absl/synchronization/internal/graphcycles.cc b/absl/synchronization/internal/graphcycles.cc
index 139be0f5..f4fbeadd 100644
--- a/absl/synchronization/internal/graphcycles.cc
+++ b/absl/synchronization/internal/graphcycles.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -44,7 +44,7 @@
// Do not use STL. This module does not use standard memory allocation.
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
namespace {
@@ -691,7 +691,7 @@ int GraphCycles::GetStackTrace(GraphId id, void*** ptr) {
}
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_LOW_LEVEL_ALLOC_MISSING
diff --git a/absl/synchronization/internal/graphcycles.h b/absl/synchronization/internal/graphcycles.h
index 6609ea06..208527c3 100644
--- a/absl/synchronization/internal/graphcycles.h
+++ b/absl/synchronization/internal/graphcycles.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -41,7 +41,7 @@
#include <cstdint>
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
// Opaque identifier for a graph node.
@@ -133,7 +133,7 @@ class GraphCycles {
};
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif
diff --git a/absl/synchronization/internal/graphcycles_benchmark.cc b/absl/synchronization/internal/graphcycles_benchmark.cc
index a239c25c..54823e0b 100644
--- a/absl/synchronization/internal/graphcycles_benchmark.cc
+++ b/absl/synchronization/internal/graphcycles_benchmark.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
diff --git a/absl/synchronization/internal/graphcycles_test.cc b/absl/synchronization/internal/graphcycles_test.cc
index 4dc2bdc5..fca86219 100644
--- a/absl/synchronization/internal/graphcycles_test.cc
+++ b/absl/synchronization/internal/graphcycles_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -25,7 +25,7 @@
#include "absl/base/macros.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
// We emulate a GraphCycles object with a node vector and an edge vector.
@@ -460,5 +460,5 @@ TEST_F(GraphCyclesTest, ManyEdges) {
}
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index 34ae94ec..e0f01e06 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -34,7 +34,7 @@
#include "absl/time/time.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
class Futex;
@@ -54,6 +54,7 @@ class KernelTimeout {
// We explicitly do not support other custom formats: timespec, int64_t nanos.
// Unify on this and absl::Time, please.
+
bool has_timeout() const { return ns_ != 0; }
private:
@@ -101,8 +102,8 @@ class KernelTimeout {
if (n < 0) n = 0;
struct timespec abstime;
- int64_t seconds = std::min(n / kNanosPerSecond,
- int64_t{(std::numeric_limits<time_t>::max)()});
+ int64_t seconds = (std::min)(n / kNanosPerSecond,
+ int64_t{(std::numeric_limits<time_t>::max)()});
abstime.tv_sec = static_cast<time_t>(seconds);
abstime.tv_nsec =
static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
@@ -148,6 +149,7 @@ class KernelTimeout {
};
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
diff --git a/absl/synchronization/internal/mutex_nonprod.cc b/absl/synchronization/internal/mutex_nonprod.cc
index 4b0b8bcd..aa1ed83b 100644
--- a/absl/synchronization/internal/mutex_nonprod.cc
+++ b/absl/synchronization/internal/mutex_nonprod.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -31,7 +31,7 @@
#include "absl/time/time.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
namespace {
@@ -316,5 +316,5 @@ bool Condition::Eval() const {
void RegisterSymbolizer(bool (*)(const void*, char*, int)) {}
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc
index 0ae4c0ea..ac10879b 100644
--- a/absl/synchronization/internal/mutex_nonprod.inc
+++ b/absl/synchronization/internal/mutex_nonprod.inc
@@ -36,7 +36,7 @@
#endif
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
class Condition;
namespace synchronization_internal {
@@ -215,6 +215,9 @@ class SynchronizationStorage {
// stack) should use this constructor.
explicit SynchronizationStorage(base_internal::LinkerInitialized) {}
+ constexpr explicit SynchronizationStorage(absl::ConstInitType)
+ : is_dynamic_(false), once_(), space_{{0}} {}
+
SynchronizationStorage(SynchronizationStorage&) = delete;
SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
@@ -254,5 +257,5 @@ class SynchronizationStorage {
};
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/synchronization/internal/per_thread_sem.cc b/absl/synchronization/internal/per_thread_sem.cc
index 9de2d136..284a5df4 100644
--- a/absl/synchronization/internal/per_thread_sem.cc
+++ b/absl/synchronization/internal/per_thread_sem.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -25,7 +25,7 @@
#include "absl/synchronization/internal/waiter.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
void PerThreadSem::SetThreadBlockedCounter(std::atomic<int> *counter) {
@@ -59,7 +59,7 @@ void PerThreadSem::Tick(base_internal::ThreadIdentity *identity) {
}
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
extern "C" {
@@ -91,6 +91,7 @@ ABSL_ATTRIBUTE_WEAK bool AbslInternalPerThreadSemWait(
if (identity->blocked_count_ptr != nullptr) {
identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed);
}
+
identity->is_idle.store(false, std::memory_order_relaxed);
identity->wait_start.store(0, std::memory_order_relaxed);
return !timeout;
diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h
index 6efd5951..5bb0978b 100644
--- a/absl/synchronization/internal/per_thread_sem.h
+++ b/absl/synchronization/internal/per_thread_sem.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -32,7 +32,7 @@
#include "absl/synchronization/internal/kernel_timeout.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
class Mutex;
@@ -81,7 +81,7 @@ class PerThreadSem {
};
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
// In some build configurations we pass --detect-odr-violations to the
@@ -106,4 +106,5 @@ bool absl::synchronization_internal::PerThreadSem::Wait(
absl::synchronization_internal::KernelTimeout t) {
return AbslInternalPerThreadSemWait(t);
}
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
diff --git a/absl/synchronization/internal/per_thread_sem_test.cc b/absl/synchronization/internal/per_thread_sem_test.cc
index 18b2458b..93bc4244 100644
--- a/absl/synchronization/internal/per_thread_sem_test.cc
+++ b/absl/synchronization/internal/per_thread_sem_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -33,7 +33,7 @@
// primitives which might use PerThreadSem, most notably absl::Mutex.
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
class SimpleSemaphore {
@@ -115,10 +115,9 @@ class PerThreadSemTest : public testing::Test {
min_cycles = std::min(min_cycles, cycles);
total_cycles += cycles;
}
- std::string out =
- StrCat(msg, "min cycle count=", min_cycles, " avg cycle count=",
- absl::SixDigits(static_cast<double>(total_cycles) /
- kNumIterations));
+ std::string out = StrCat(
+ msg, "min cycle count=", min_cycles, " avg cycle count=",
+ absl::SixDigits(static_cast<double>(total_cycles) / kNumIterations));
printf("%s\n", out.c_str());
partner_thread.join();
@@ -153,12 +152,16 @@ TEST_F(PerThreadSemTest, WithTimeout) {
}
TEST_F(PerThreadSemTest, Timeouts) {
- absl::Time timeout = absl::Now() + absl::Milliseconds(50);
+ const absl::Duration delay = absl::Milliseconds(50);
+ const absl::Time start = absl::Now();
+ EXPECT_FALSE(Wait(start + delay));
+ const absl::Duration elapsed = absl::Now() - start;
// Allow for a slight early return, to account for quality of implementation
// issues on various platforms.
const absl::Duration slop = absl::Microseconds(200);
- EXPECT_FALSE(Wait(timeout));
- EXPECT_LE(timeout, absl::Now() + slop);
+ EXPECT_LE(delay - slop, elapsed)
+ << "Wait returned " << delay - elapsed
+ << " early (with " << slop << " slop), start time was " << start;
absl::Time negative_timeout = absl::UnixEpoch() - absl::Milliseconds(100);
EXPECT_FALSE(Wait(negative_timeout));
@@ -173,5 +176,5 @@ TEST_F(PerThreadSemTest, Timeouts) {
} // namespace
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/synchronization/internal/thread_pool.h b/absl/synchronization/internal/thread_pool.h
index 66c7546b..8941be68 100644
--- a/absl/synchronization/internal/thread_pool.h
+++ b/absl/synchronization/internal/thread_pool.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -16,6 +16,7 @@
#define ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
#include <cassert>
+#include <cstddef>
#include <functional>
#include <queue>
#include <thread> // NOLINT(build/c++11)
@@ -25,7 +26,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
// A simple ThreadPool implementation for tests.
@@ -43,7 +44,7 @@ class ThreadPool {
~ThreadPool() {
{
absl::MutexLock l(&mu_);
- for (int i = 0; i < threads_.size(); ++i) {
+ for (size_t i = 0; i < threads_.size(); i++) {
queue_.push(nullptr); // Shutdown signal.
}
}
@@ -86,7 +87,7 @@ class ThreadPool {
};
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc
index 76fdd861..17c6a506 100644
--- a/absl/synchronization/internal/waiter.cc
+++ b/absl/synchronization/internal/waiter.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -40,13 +40,16 @@
#include <atomic>
#include <cassert>
#include <cstdint>
+#include <new>
+#include <type_traits>
+
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/thread_identity.h"
#include "absl/base/optimization.h"
#include "absl/synchronization/internal/kernel_timeout.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
static void MaybeBecomeIdle() {
@@ -82,6 +85,7 @@ static void MaybeBecomeIdle() {
#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
#endif
#endif
+
class Futex {
public:
static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
@@ -327,6 +331,43 @@ void Waiter::Poke() {
#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32
+class Waiter::WinHelper {
+ public:
+ static SRWLOCK *GetLock(Waiter *w) {
+ return reinterpret_cast<SRWLOCK *>(&w->mu_storage_);
+ }
+
+ static CONDITION_VARIABLE *GetCond(Waiter *w) {
+ return reinterpret_cast<CONDITION_VARIABLE *>(&w->cv_storage_);
+ }
+
+ static_assert(sizeof(SRWLOCK) == sizeof(Waiter::SRWLockStorage),
+ "SRWLockStorage does not have the same size as SRWLOCK");
+ static_assert(
+ alignof(SRWLOCK) == alignof(Waiter::SRWLockStorage),
+ "SRWLockStorage does not have the same alignment as SRWLOCK");
+
+ static_assert(sizeof(CONDITION_VARIABLE) ==
+ sizeof(Waiter::ConditionVariableStorage),
+ "ABSL_CONDITION_VARIABLE_STORAGE does not have the same size "
+ "as CONDITION_VARIABLE");
+ static_assert(alignof(CONDITION_VARIABLE) ==
+ alignof(Waiter::ConditionVariableStorage),
+ "ConditionVariableStorage does not have the same "
+ "alignment as CONDITION_VARIABLE");
+
+ // The SRWLOCK and CONDITION_VARIABLE types must be trivially constuctible
+ // and destructible because we never call their constructors or destructors.
+ static_assert(std::is_trivially_constructible<SRWLOCK>::value,
+ "The SRWLOCK type must be trivially constructible");
+ static_assert(std::is_trivially_constructible<CONDITION_VARIABLE>::value,
+ "The CONDITION_VARIABLE type must be trivially constructible");
+ static_assert(std::is_trivially_destructible<SRWLOCK>::value,
+ "The SRWLOCK type must be trivially destructible");
+ static_assert(std::is_trivially_destructible<CONDITION_VARIABLE>::value,
+ "The CONDITION_VARIABLE type must be trivially destructible");
+};
+
class LockHolder {
public:
explicit LockHolder(SRWLOCK* mu) : mu_(mu) {
@@ -345,14 +386,19 @@ class LockHolder {
};
void Waiter::Init() {
- InitializeSRWLock(&mu_);
- InitializeConditionVariable(&cv_);
+ auto *mu = ::new (static_cast<void *>(&mu_storage_)) SRWLOCK;
+ auto *cv = ::new (static_cast<void *>(&cv_storage_)) CONDITION_VARIABLE;
+ InitializeSRWLock(mu);
+ InitializeConditionVariable(cv);
waiter_count_.store(0, std::memory_order_relaxed);
wakeup_count_.store(0, std::memory_order_relaxed);
}
bool Waiter::Wait(KernelTimeout t) {
- LockHolder h(&mu_);
+ SRWLOCK *mu = WinHelper::GetLock(this);
+ CONDITION_VARIABLE *cv = WinHelper::GetCond(this);
+
+ LockHolder h(mu);
waiter_count_.fetch_add(1, std::memory_order_relaxed);
// Loop until we find a wakeup to consume or timeout.
@@ -370,8 +416,7 @@ bool Waiter::Wait(KernelTimeout t) {
}
// No wakeups available, time to wait.
- if (!SleepConditionVariableSRW(
- &cv_, &mu_, t.InMillisecondsFromNow(), 0)) {
+ if (!SleepConditionVariableSRW(cv, mu, t.InMillisecondsFromNow(), 0)) {
// GetLastError() returns a Win32 DWORD, but we assign to
// unsigned long to simplify the ABSL_RAW_LOG case below. The uniform
// initialization guarantees this is not a narrowing conversion.
@@ -398,11 +443,11 @@ void Waiter::Poke() {
return;
}
// Potentially a waker. Take the lock and check again.
- LockHolder h(&mu_);
+ LockHolder h(WinHelper::GetLock(this));
if (waiter_count_.load(std::memory_order_relaxed) == 0) {
return;
}
- WakeConditionVariable(&cv_);
+ WakeConditionVariable(WinHelper::GetCond(this));
}
#else
@@ -410,5 +455,5 @@ void Waiter::Poke() {
#endif
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h
index 2b737260..06032642 100644
--- a/absl/synchronization/internal/waiter.h
+++ b/absl/synchronization/internal/waiter.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -18,9 +18,7 @@
#include "absl/base/config.h"
-#ifdef _WIN32
-#include <windows.h>
-#else
+#ifndef _WIN32
#include <pthread.h>
#endif
@@ -53,7 +51,7 @@
#endif
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace synchronization_internal {
// Waiter is an OS-specific semaphore.
@@ -124,8 +122,20 @@ class Waiter {
// primivitives. We are using SRWLOCK and CONDITION_VARIABLE
// because they don't require a destructor to release system
// resources.
- SRWLOCK mu_;
- CONDITION_VARIABLE cv_;
+ //
+ // However, we can't include Windows.h in our headers, so we use aligned
+ // storage buffers to define the storage.
+ using SRWLockStorage =
+ typename std::aligned_storage<sizeof(void*), alignof(void*)>::type;
+ using ConditionVariableStorage =
+ typename std::aligned_storage<sizeof(void*), alignof(void*)>::type;
+
+ // WinHelper - Used to define utilities for accessing the lock and
+ // condition variable storage once the types are complete.
+ class WinHelper;
+
+ SRWLockStorage mu_storage_;
+ ConditionVariableStorage cv_storage_;
std::atomic<int> waiter_count_;
std::atomic<int> wakeup_count_;
@@ -135,7 +145,7 @@ class Waiter {
};
} // namespace synchronization_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_