diff options
108 files changed, 534 insertions, 765 deletions
diff --git a/jstests/core/currentop_waiting_for_latch.js b/jstests/core/currentop_waiting_for_latch.js index 383ba32a643..c584e0d98bf 100644 --- a/jstests/core/currentop_waiting_for_latch.js +++ b/jstests/core/currentop_waiting_for_latch.js @@ -26,7 +26,10 @@ const getCurrentOp = function() { return result; }; -const blockedOpClientName = "DiagnosticCaptureTest"; +const blockedOpClients = { + "DiagnosticCaptureTestLatch": {"seen": false}, + "DiagnosticCaptureTestInterruptible": {"seen": false}, +}; const getClientName = function() { let myUri = adminDB.runCommand({whatsmyuri: 1}).you; @@ -46,34 +49,43 @@ try { }, })); - let result = null; + const verifyResult = function(result) { + jsTestLog("Verifying " + tojson(result)); + assert(result); + assert(result.hasOwnProperty("waitingForLatch")); + assert(result["waitingForLatch"].hasOwnProperty("timestamp")); + assert(result["waitingForLatch"].hasOwnProperty("captureName")); + + /* Absent until we have efficient enough backtracing + assert(result["waitingForLatch"].hasOwnProperty("backtrace")); + result["waitingForLatch"]["backtrace"].forEach(function(frame) { + assert(frame.hasOwnProperty("addr")); + assert(typeof frame["addr"] === "string"); + assert(frame.hasOwnProperty("path")); + assert(typeof frame["path"] === "string"); + }); + */ + }; getCurrentOp().forEach(function(op) { - jsTestLog(tojson(op)); - if (op["desc"] == blockedOpClientName) { - result = op; + const name = op["desc"]; + if (name in blockedOpClients) { + jsTestLog("Verifying " + op["desc"]); + verifyResult(op); + blockedOpClients[name].seen = true; } }); - assert(result); - assert(result.hasOwnProperty("waitingForLatch")); - assert(result["waitingForLatch"].hasOwnProperty("timestamp")); - assert(result["waitingForLatch"].hasOwnProperty("captureName")); - /* Absent until we have efficient enough backtracing - assert(result["waitingForLatch"].hasOwnProperty("backtrace")); - result["waitingForLatch"]["backtrace"].forEach(function(frame) { - assert(frame.hasOwnProperty("addr")); - assert(typeof frame["addr"] === "string"); - assert(frame.hasOwnProperty("path")); - assert(typeof frame["path"] === "string"); - }); - */ + // Make sure we saw the ops we expected + for (const name in blockedOpClients) { + assert(blockedOpClients[name].seen); + } } finally { assert.commandWorked(db.adminCommand( {"configureFailPoint": 'currentOpSpawnsThreadWaitingForLatch', "mode": 'off'})); getCurrentOp().forEach(function(op) { - jsTestLog(tojson(op)); - if (op["desc"] == blockedOpClientName) { + const name = op["desc"]; + if (name in blockedOpClients) { assert(!op.hasOwnProperty("waitingForLatch")); } }); diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 77c87f51dc7..3ae639f83c7 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -123,7 +123,6 @@ baseEnv.Library( 'logv2/log_severity.cpp', 'logv2/log_tag.cpp', 'logv2/ramlog.cpp', - 'platform/condition_variable.cpp', 'platform/decimal128.cpp', 'platform/mutex.cpp', 'platform/posix_fadvise.cpp', diff --git a/src/mongo/client/connpool.h b/src/mongo/client/connpool.h index 4fb06c6057a..1d39268d588 100644 --- a/src/mongo/client/connpool.h +++ b/src/mongo/client/connpool.h @@ -35,7 +35,7 @@ #include "mongo/client/dbclient_base.h" #include "mongo/client/mongo_uri.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/background.h" #include "mongo/util/concurrency/mutex.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/client/connpool_integration_test.cpp b/src/mongo/client/connpool_integration_test.cpp index 41323e41584..8daada412a3 100644 --- a/src/mongo/client/connpool_integration_test.cpp +++ b/src/mongo/client/connpool_integration_test.cpp @@ -31,8 +31,8 @@ #include "mongo/client/connpool.h" #include "mongo/client/global_conn_pool.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/unittest/integration_test.h" #include "mongo/unittest/unittest.h" diff --git a/src/mongo/client/fetcher.h b/src/mongo/client/fetcher.h index 0a2abbd12fe..bd4556d0ee4 100644 --- a/src/mongo/client/fetcher.h +++ b/src/mongo/client/fetcher.h @@ -42,8 +42,8 @@ #include "mongo/db/clientcursor.h" #include "mongo/db/namespace_string.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/net/hostandport.h" namespace mongo { diff --git a/src/mongo/client/remote_command_retry_scheduler.h b/src/mongo/client/remote_command_retry_scheduler.h index c0718b8408f..d466a3b217b 100644 --- a/src/mongo/client/remote_command_retry_scheduler.h +++ b/src/mongo/client/remote_command_retry_scheduler.h @@ -37,8 +37,8 @@ #include "mongo/base/error_codes.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/time_support.h" namespace mongo { diff --git a/src/mongo/client/replica_set_monitor.cpp b/src/mongo/client/replica_set_monitor.cpp index 05f8d7d63e5..9d24576d312 100644 --- a/src/mongo/client/replica_set_monitor.cpp +++ b/src/mongo/client/replica_set_monitor.cpp @@ -46,8 +46,8 @@ #include "mongo/db/repl/bson_extract_optime.h" #include "mongo/db/server_options.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/background.h" #include "mongo/util/debug_util.h" #include "mongo/util/exit.h" diff --git a/src/mongo/client/replica_set_monitor_internal.h b/src/mongo/client/replica_set_monitor_internal.h index 9f7812f1ff3..f65b1306200 100644 --- a/src/mongo/client/replica_set_monitor_internal.h +++ b/src/mongo/client/replica_set_monitor_internal.h @@ -44,9 +44,9 @@ #include "mongo/client/read_preference.h" #include "mongo/client/replica_set_monitor.h" #include "mongo/db/jsobj.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/platform/random.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/net/hostandport.h" namespace mongo { diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h index 035d797f48d..21380460468 100644 --- a/src/mongo/db/auth/authorization_manager.h +++ b/src/mongo/db/auth/authorization_manager.h @@ -49,8 +49,8 @@ #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" #include "mongo/db/server_options.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" namespace mongo { diff --git a/src/mongo/db/auth/authorization_manager_impl.h b/src/mongo/db/auth/authorization_manager_impl.h index 725bb27b7d8..d80d0b668f6 100644 --- a/src/mongo/db/auth/authorization_manager_impl.h +++ b/src/mongo/db/auth/authorization_manager_impl.h @@ -50,8 +50,8 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/server_options.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/invalidating_lru_cache.h" diff --git a/src/mongo/db/background.cpp b/src/mongo/db/background.cpp index 62afb3e099b..14da56c02ec 100644 --- a/src/mongo/db/background.cpp +++ b/src/mongo/db/background.cpp @@ -35,8 +35,8 @@ #include <string> #include "mongo/db/operation_context.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/assert_util.h" #include "mongo/util/map_util.h" diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h index 492b0628e32..2da11684f68 100644 --- a/src/mongo/db/catalog/collection.h +++ b/src/mongo/db/catalog/collection.h @@ -51,8 +51,8 @@ #include "mongo/db/storage/capped_callback.h" #include "mongo/db/storage/record_store.h" #include "mongo/db/storage/snapshot.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/decorable.h" namespace mongo { diff --git a/src/mongo/db/collection_index_builds_tracker.h b/src/mongo/db/collection_index_builds_tracker.h index 8d43dbd96bc..81c25fe73d3 100644 --- a/src/mongo/db/collection_index_builds_tracker.h +++ b/src/mongo/db/collection_index_builds_tracker.h @@ -33,7 +33,7 @@ #include <string> #include "mongo/db/repl_index_build_state.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/with_lock.h" #include "mongo/util/uuid.h" diff --git a/src/mongo/db/commands/fsync.cpp b/src/mongo/db/commands/fsync.cpp index 27691749ac6..25bedb64ba5 100644 --- a/src/mongo/db/commands/fsync.cpp +++ b/src/mongo/db/commands/fsync.cpp @@ -49,7 +49,7 @@ #include "mongo/db/service_context.h" #include "mongo/db/storage/backup_cursor_hooks.h" #include "mongo/db/storage/storage_engine.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/assert_util.h" #include "mongo/util/background.h" #include "mongo/util/exit.h" diff --git a/src/mongo/db/concurrency/flow_control_ticketholder.h b/src/mongo/db/concurrency/flow_control_ticketholder.h index 39413477937..8247318a842 100644 --- a/src/mongo/db/concurrency/flow_control_ticketholder.h +++ b/src/mongo/db/concurrency/flow_control_ticketholder.h @@ -31,8 +31,8 @@ #include "mongo/bson/bsonobjbuilder.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { diff --git a/src/mongo/db/concurrency/lock_manager.h b/src/mongo/db/concurrency/lock_manager.h index d6bed91bc9f..b464c0f85c8 100644 --- a/src/mongo/db/concurrency/lock_manager.h +++ b/src/mongo/db/concurrency/lock_manager.h @@ -40,8 +40,8 @@ #include "mongo/db/concurrency/lock_request_list.h" #include "mongo/platform/atomic_word.h" #include "mongo/platform/compiler.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/concurrency/mutex.h" diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index 4767acb9f26..b8df781916f 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -311,11 +311,13 @@ void CurOp::reportCurrentOpForClient(OperationContext* opCtx, waitingForLatchBuilder.append("captureName", diagnostic->getCaptureName()); if (backtraceMode) { BSONArrayBuilder backtraceBuilder(waitingForLatchBuilder.subarrayStart("backtrace")); + /** This branch becomes useful again with SERVER-44091 for (const auto& frame : diagnostic->makeStackTrace().frames) { BSONObjBuilder backtraceObj(backtraceBuilder.subobjStart()); backtraceObj.append("addr", integerToHex(frame.instructionOffset)); backtraceObj.append("path", frame.objectPath); } + */ } } } diff --git a/src/mongo/db/database_index_builds_tracker.h b/src/mongo/db/database_index_builds_tracker.h index 372f5f08210..8b2eb4ea474 100644 --- a/src/mongo/db/database_index_builds_tracker.h +++ b/src/mongo/db/database_index_builds_tracker.h @@ -33,7 +33,7 @@ #include <string> #include "mongo/db/repl_index_build_state.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/with_lock.h" #include "mongo/util/uuid.h" diff --git a/src/mongo/db/default_baton.h b/src/mongo/db/default_baton.h index c406741e332..74fd724fae1 100644 --- a/src/mongo/db/default_baton.h +++ b/src/mongo/db/default_baton.h @@ -32,8 +32,8 @@ #include <vector> #include "mongo/db/baton.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/functional.h" namespace mongo { diff --git a/src/mongo/db/free_mon/free_mon_message.h b/src/mongo/db/free_mon/free_mon_message.h index 11fab7c8501..9b7fc83a05b 100644 --- a/src/mongo/db/free_mon/free_mon_message.h +++ b/src/mongo/db/free_mon/free_mon_message.h @@ -33,8 +33,8 @@ #include <vector> #include "mongo/db/free_mon/free_mon_protocol_gen.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/duration.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/db/ftdc/controller.cpp b/src/mongo/db/ftdc/controller.cpp index 11f80503acd..947fd004dfe 100644 --- a/src/mongo/db/ftdc/controller.cpp +++ b/src/mongo/db/ftdc/controller.cpp @@ -39,8 +39,8 @@ #include "mongo/db/ftdc/collector.h" #include "mongo/db/ftdc/util.h" #include "mongo/db/jsobj.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/concurrency/idle_thread_block.h" #include "mongo/util/exit.h" diff --git a/src/mongo/db/ftdc/controller.h b/src/mongo/db/ftdc/controller.h index 949117cbc79..50d6ae48886 100644 --- a/src/mongo/db/ftdc/controller.h +++ b/src/mongo/db/ftdc/controller.h @@ -37,8 +37,8 @@ #include "mongo/db/ftdc/config.h" #include "mongo/db/ftdc/file_manager.h" #include "mongo/db/jsobj.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" namespace mongo { diff --git a/src/mongo/db/index_builds_coordinator.h b/src/mongo/db/index_builds_coordinator.h index 1c22bf9fec9..7f582b0c684 100644 --- a/src/mongo/db/index_builds_coordinator.h +++ b/src/mongo/db/index_builds_coordinator.h @@ -43,8 +43,8 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/repl_index_build_state.h" #include "mongo/db/storage/durable_catalog.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/with_lock.h" #include "mongo/util/fail_point.h" #include "mongo/util/future.h" diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h index 7ebef518aec..9a7fb8c17ad 100644 --- a/src/mongo/db/operation_context.h +++ b/src/mongo/db/operation_context.h @@ -41,8 +41,8 @@ #include "mongo/db/storage/write_unit_of_work.h" #include "mongo/db/write_concern_options.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/transport/session.h" #include "mongo/util/decorable.h" #include "mongo/util/interruptible.h" diff --git a/src/mongo/db/pipeline/document_source_exchange.h b/src/mongo/db/pipeline/document_source_exchange.h index df423ff28bb..f77e5d14bde 100644 --- a/src/mongo/db/pipeline/document_source_exchange.h +++ b/src/mongo/db/pipeline/document_source_exchange.h @@ -36,8 +36,8 @@ #include "mongo/db/pipeline/document_source.h" #include "mongo/db/pipeline/exchange_spec_gen.h" #include "mongo/db/pipeline/field_path.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { diff --git a/src/mongo/db/repl/abstract_async_component.h b/src/mongo/db/repl/abstract_async_component.h index c5ce2da5afa..5b0e6426900 100644 --- a/src/mongo/db/repl/abstract_async_component.h +++ b/src/mongo/db/repl/abstract_async_component.h @@ -37,8 +37,8 @@ #include "mongo/base/static_assert.h" #include "mongo/base/status.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { namespace repl { diff --git a/src/mongo/db/repl/base_cloner_test_fixture.h b/src/mongo/db/repl/base_cloner_test_fixture.h index d0e5a9b9289..328bfdb27d2 100644 --- a/src/mongo/db/repl/base_cloner_test_fixture.h +++ b/src/mongo/db/repl/base_cloner_test_fixture.h @@ -41,8 +41,8 @@ #include "mongo/db/service_context_test_fixture.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/net/hostandport.h" diff --git a/src/mongo/db/repl/bgsync.h b/src/mongo/db/repl/bgsync.h index 0bacdc71d29..b418c935492 100644 --- a/src/mongo/db/repl/bgsync.h +++ b/src/mongo/db/repl/bgsync.h @@ -43,8 +43,8 @@ #include "mongo/db/repl/rollback_impl.h" #include "mongo/db/repl/sync_source_resolver.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/net/hostandport.h" diff --git a/src/mongo/db/repl/collection_cloner.h b/src/mongo/db/repl/collection_cloner.h index ba8139dd98f..4f0ddfd23a8 100644 --- a/src/mongo/db/repl/collection_cloner.h +++ b/src/mongo/db/repl/collection_cloner.h @@ -48,8 +48,8 @@ #include "mongo/db/repl/storage_interface.h" #include "mongo/db/repl/task_runner.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/net/hostandport.h" #include "mongo/util/progress_meter.h" diff --git a/src/mongo/db/repl/database_cloner.h b/src/mongo/db/repl/database_cloner.h index 666f23610fb..96c9e6b4c06 100644 --- a/src/mongo/db/repl/database_cloner.h +++ b/src/mongo/db/repl/database_cloner.h @@ -41,8 +41,8 @@ #include "mongo/db/repl/base_cloner.h" #include "mongo/db/repl/collection_cloner.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/net/hostandport.h" diff --git a/src/mongo/db/repl/databases_cloner.h b/src/mongo/db/repl/databases_cloner.h index e5ea692d8bc..f4a8662883d 100644 --- a/src/mongo/db/repl/databases_cloner.h +++ b/src/mongo/db/repl/databases_cloner.h @@ -42,8 +42,8 @@ #include "mongo/db/repl/collection_cloner.h" #include "mongo/db/repl/database_cloner.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/net/hostandport.h" diff --git a/src/mongo/db/repl/initial_syncer.h b/src/mongo/db/repl/initial_syncer.h index 406c89352bb..cce4018d1e1 100644 --- a/src/mongo/db/repl/initial_syncer.h +++ b/src/mongo/db/repl/initial_syncer.h @@ -53,8 +53,8 @@ #include "mongo/db/repl/rollback_checker.h" #include "mongo/db/repl/sync_source_selector.h" #include "mongo/dbtests/mock/mock_dbclient_connection.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/fail_point.h" #include "mongo/util/net/hostandport.h" diff --git a/src/mongo/db/repl/multiapplier.h b/src/mongo/db/repl/multiapplier.h index 406888746b1..22023e6eafc 100644 --- a/src/mongo/db/repl/multiapplier.h +++ b/src/mongo/db/repl/multiapplier.h @@ -43,8 +43,8 @@ #include "mongo/db/repl/oplog_entry.h" #include "mongo/db/service_context.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { namespace repl { diff --git a/src/mongo/db/repl/replication_coordinator_external_state_mock.h b/src/mongo/db/repl/replication_coordinator_external_state_mock.h index 5cebab1e820..0f1ed300583 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_mock.h +++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.h @@ -37,8 +37,8 @@ #include "mongo/db/jsobj.h" #include "mongo/db/repl/last_vote.h" #include "mongo/db/repl/replication_coordinator_external_state.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/net/hostandport.h" diff --git a/src/mongo/db/repl/reporter.h b/src/mongo/db/repl/reporter.h index caa67aaa528..824ae59b17e 100644 --- a/src/mongo/db/repl/reporter.h +++ b/src/mongo/db/repl/reporter.h @@ -36,8 +36,8 @@ #include "mongo/db/jsobj.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/time_support.h" namespace mongo { diff --git a/src/mongo/db/repl/sync_source_feedback.h b/src/mongo/db/repl/sync_source_feedback.h index 3688de9a0ed..fdec94bff72 100644 --- a/src/mongo/db/repl/sync_source_feedback.h +++ b/src/mongo/db/repl/sync_source_feedback.h @@ -32,8 +32,8 @@ #include "mongo/base/status.h" #include "mongo/db/repl/replication_coordinator.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { struct HostAndPort; diff --git a/src/mongo/db/repl/sync_source_resolver.h b/src/mongo/db/repl/sync_source_resolver.h index 2b2734d2c70..a98db3d8773 100644 --- a/src/mongo/db/repl/sync_source_resolver.h +++ b/src/mongo/db/repl/sync_source_resolver.h @@ -38,8 +38,8 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/repl/optime.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/net/hostandport.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/db/repl/task_runner.h b/src/mongo/db/repl/task_runner.h index c1db72bdba5..4f7303e3ad6 100644 --- a/src/mongo/db/repl/task_runner.h +++ b/src/mongo/db/repl/task_runner.h @@ -33,8 +33,8 @@ #include <list> #include "mongo/db/service_context.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/functional.h" diff --git a/src/mongo/db/repl/task_runner_test.cpp b/src/mongo/db/repl/task_runner_test.cpp index 96ad44916aa..d71dc3c42e8 100644 --- a/src/mongo/db/repl/task_runner_test.cpp +++ b/src/mongo/db/repl/task_runner_test.cpp @@ -34,8 +34,8 @@ #include "mongo/db/operation_context_noop.h" #include "mongo/db/repl/task_runner.h" #include "mongo/db/repl/task_runner_test_fixture.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/unittest/barrier.h" #include "mongo/util/concurrency/thread_pool.h" diff --git a/src/mongo/db/repl_index_build_state.h b/src/mongo/db/repl_index_build_state.h index f5e14beb4cc..66ab914807c 100644 --- a/src/mongo/db/repl_index_build_state.h +++ b/src/mongo/db/repl_index_build_state.h @@ -39,7 +39,7 @@ #include "mongo/db/catalog/commit_quorum_options.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/namespace_string.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/future.h" #include "mongo/util/net/hostandport.h" #include "mongo/util/uuid.h" diff --git a/src/mongo/db/s/balancer/balancer.h b/src/mongo/db/s/balancer/balancer.h index 4e22590bf1d..1df09000920 100644 --- a/src/mongo/db/s/balancer/balancer.h +++ b/src/mongo/db/s/balancer/balancer.h @@ -32,8 +32,8 @@ #include "mongo/db/s/balancer/balancer_chunk_selection_policy.h" #include "mongo/db/s/balancer/balancer_random.h" #include "mongo/db/s/balancer/migration_manager.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" namespace mongo { diff --git a/src/mongo/db/s/balancer/migration_manager.h b/src/mongo/db/s/balancer/migration_manager.h index 0e517b7e067..b321b361e79 100644 --- a/src/mongo/db/s/balancer/migration_manager.h +++ b/src/mongo/db/s/balancer/migration_manager.h @@ -38,10 +38,10 @@ #include "mongo/db/s/balancer/balancer_policy.h" #include "mongo/db/s/balancer/type_migration.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/s/catalog/dist_lock_manager.h" #include "mongo/s/request_types/migration_secondary_throttle_options.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/concurrency/notification.h" #include "mongo/util/concurrency/with_lock.h" diff --git a/src/mongo/db/s/config/namespace_serializer.h b/src/mongo/db/s/config/namespace_serializer.h index f0e6c4b158c..f5b7dbbac3a 100644 --- a/src/mongo/db/s/config/namespace_serializer.h +++ b/src/mongo/db/s/config/namespace_serializer.h @@ -36,8 +36,8 @@ #include "mongo/base/status.h" #include "mongo/base/status_with.h" #include "mongo/db/namespace_string.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/string_map.h" namespace mongo { diff --git a/src/mongo/db/s/implicit_create_collection.cpp b/src/mongo/db/s/implicit_create_collection.cpp index dfc8cd97cb2..62b086eebc5 100644 --- a/src/mongo/db/s/implicit_create_collection.cpp +++ b/src/mongo/db/s/implicit_create_collection.cpp @@ -46,8 +46,8 @@ #include "mongo/s/grid.h" #include "mongo/s/request_types/create_collection_gen.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/scopeguard.h" namespace mongo { diff --git a/src/mongo/db/s/metadata_manager_test.cpp b/src/mongo/db/s/metadata_manager_test.cpp index e5d3480fa3d..1e367cf7aea 100644 --- a/src/mongo/db/s/metadata_manager_test.cpp +++ b/src/mongo/db/s/metadata_manager_test.cpp @@ -42,10 +42,10 @@ #include "mongo/db/server_options.h" #include "mongo/db/service_context.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/s/catalog/type_chunk.h" #include "mongo/s/client/shard_registry.h" #include "mongo/s/shard_server_test_fixture.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/unittest/unittest.h" #include "mongo/util/assert_util.h" diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy.h b/src/mongo/db/s/migration_chunk_cloner_source_legacy.h index 34b41503bec..8e5809093af 100644 --- a/src/mongo/db/s/migration_chunk_cloner_source_legacy.h +++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy.h @@ -40,10 +40,10 @@ #include "mongo/db/s/migration_chunk_cloner_source.h" #include "mongo/db/s/migration_session_id.h" #include "mongo/db/s/session_catalog_migration_source.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/s/request_types/move_chunk_request.h" #include "mongo/s/shard_key_pattern.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/net/hostandport.h" namespace mongo { diff --git a/src/mongo/db/s/migration_destination_manager.h b/src/mongo/db/s/migration_destination_manager.h index 607eec9a68a..910e259fc98 100644 --- a/src/mongo/db/s/migration_destination_manager.h +++ b/src/mongo/db/s/migration_destination_manager.h @@ -41,9 +41,9 @@ #include "mongo/db/s/collection_sharding_runtime.h" #include "mongo/db/s/migration_session_id.h" #include "mongo/db/s/session_catalog_migration_destination.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/s/shard_id.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/concurrency/with_lock.h" #include "mongo/util/timer.h" diff --git a/src/mongo/db/s/session_catalog_migration_destination.h b/src/mongo/db/s/session_catalog_migration_destination.h index 185eecbb9ba..b5a85fd6998 100644 --- a/src/mongo/db/s/session_catalog_migration_destination.h +++ b/src/mongo/db/s/session_catalog_migration_destination.h @@ -36,9 +36,9 @@ #include "mongo/bson/bsonobj.h" #include "mongo/db/repl/oplog_entry.h" #include "mongo/db/s/migration_session_id.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/s/shard_id.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/concurrency/with_lock.h" diff --git a/src/mongo/db/s/shard_server_catalog_cache_loader.h b/src/mongo/db/s/shard_server_catalog_cache_loader.h index 4cbdc31e3e0..2adfe15d9b7 100644 --- a/src/mongo/db/s/shard_server_catalog_cache_loader.h +++ b/src/mongo/db/s/shard_server_catalog_cache_loader.h @@ -31,8 +31,8 @@ #include "mongo/db/operation_context_group.h" #include "mongo/db/s/namespace_metadata_change_notifications.h" -#include "mongo/platform/condition_variable.h" #include "mongo/s/catalog_cache_loader.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/thread_pool.h" namespace mongo { diff --git a/src/mongo/db/s/transaction_coordinator_catalog.h b/src/mongo/db/s/transaction_coordinator_catalog.h index 375fc33d1d9..057c5dfb575 100644 --- a/src/mongo/db/s/transaction_coordinator_catalog.h +++ b/src/mongo/db/s/transaction_coordinator_catalog.h @@ -33,7 +33,7 @@ #include <map> #include "mongo/db/s/transaction_coordinator.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/with_lock.h" namespace mongo { diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h index 178a3ff19a6..7a9270061d2 100644 --- a/src/mongo/db/service_context.h +++ b/src/mongo/db/service_context.h @@ -39,8 +39,8 @@ #include "mongo/db/logical_session_id.h" #include "mongo/db/storage/storage_engine.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_set.h" #include "mongo/transport/service_executor.h" #include "mongo/transport/session.h" diff --git a/src/mongo/db/service_liaison_mock.h b/src/mongo/db/service_liaison_mock.h index 72512cbb95b..76af1a8ebf0 100644 --- a/src/mongo/db/service_liaison_mock.h +++ b/src/mongo/db/service_liaison_mock.h @@ -33,8 +33,8 @@ #include "mongo/db/service_liaison.h" #include "mongo/executor/async_timer_mock.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/periodic_runner.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/db/session_catalog.h b/src/mongo/db/session_catalog.h index ea5226915c7..025fab44676 100644 --- a/src/mongo/db/session_catalog.h +++ b/src/mongo/db/session_catalog.h @@ -37,8 +37,8 @@ #include "mongo/db/operation_context.h" #include "mongo/db/session.h" #include "mongo/db/session_killer.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/concurrency/with_lock.h" diff --git a/src/mongo/db/session_killer.h b/src/mongo/db/session_killer.h index 8e9cd89cdfa..231fd01dc12 100644 --- a/src/mongo/db/session_killer.h +++ b/src/mongo/db/session_killer.h @@ -37,8 +37,8 @@ #include "mongo/base/status_with.h" #include "mongo/db/kill_sessions.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/stdx/unordered_set.h" #include "mongo/util/net/hostandport.h" diff --git a/src/mongo/db/storage/biggie/biggie_visibility_manager.h b/src/mongo/db/storage/biggie/biggie_visibility_manager.h index 8370ba0c990..e0d798aa13b 100644 --- a/src/mongo/db/storage/biggie/biggie_visibility_manager.h +++ b/src/mongo/db/storage/biggie/biggie_visibility_manager.h @@ -31,7 +31,7 @@ #include "mongo/db/operation_context.h" #include "mongo/db/record_id.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/mutex.h" namespace mongo { diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.h b/src/mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.h index 09258c657f2..d4ee1cbf83b 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_oplog_manager.h @@ -30,8 +30,8 @@ #pragma once #include "mongo/db/storage/wiredtiger/wiredtiger_record_store.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/concurrency/with_lock.h" diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h index cf82a514969..e647af70929 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h @@ -43,8 +43,8 @@ #include "mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h" #include "mongo/db/storage/wiredtiger/wiredtiger_size_storer.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/fail_point.h" diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_oplog_stones.h b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_oplog_stones.h index 9553ee9f56a..0dcb844f1d0 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_oplog_stones.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_oplog_stones.h @@ -33,8 +33,8 @@ #include "mongo/db/storage/wiredtiger/wiredtiger_record_store.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { diff --git a/src/mongo/executor/async_multicaster.cpp b/src/mongo/executor/async_multicaster.cpp index 3962f8f551d..eb13a1ce385 100644 --- a/src/mongo/executor/async_multicaster.cpp +++ b/src/mongo/executor/async_multicaster.cpp @@ -37,8 +37,8 @@ #include "mongo/base/status.h" #include "mongo/db/operation_context.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/assert_util.h" namespace mongo { diff --git a/src/mongo/executor/network_interface_mock.h b/src/mongo/executor/network_interface_mock.h index af1af78bf5b..2fb1d313500 100644 --- a/src/mongo/executor/network_interface_mock.h +++ b/src/mongo/executor/network_interface_mock.h @@ -36,9 +36,9 @@ #include <vector> #include "mongo/executor/network_interface.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/rpc/metadata/metadata_hook.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" #include "mongo/stdx/unordered_set.h" #include "mongo/util/clock_source.h" diff --git a/src/mongo/executor/network_interface_thread_pool.h b/src/mongo/executor/network_interface_thread_pool.h index 946519b56f1..3a295b26a5b 100644 --- a/src/mongo/executor/network_interface_thread_pool.h +++ b/src/mongo/executor/network_interface_thread_pool.h @@ -32,8 +32,8 @@ #include <cstdint> #include <vector> -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/thread_pool_interface.h" namespace mongo { diff --git a/src/mongo/executor/scoped_task_executor.h b/src/mongo/executor/scoped_task_executor.h index 1582e654002..5b624e10f64 100644 --- a/src/mongo/executor/scoped_task_executor.h +++ b/src/mongo/executor/scoped_task_executor.h @@ -34,8 +34,8 @@ #include "mongo/base/status.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/fail_point.h" diff --git a/src/mongo/executor/task_executor.h b/src/mongo/executor/task_executor.h index f84321a46b7..d36f5c9bac6 100644 --- a/src/mongo/executor/task_executor.h +++ b/src/mongo/executor/task_executor.h @@ -38,7 +38,7 @@ #include "mongo/base/string_data.h" #include "mongo/executor/remote_command_request.h" #include "mongo/executor/remote_command_response.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/transport/baton.h" #include "mongo/util/future.h" #include "mongo/util/out_of_line_executor.h" diff --git a/src/mongo/executor/thread_pool_task_executor.h b/src/mongo/executor/thread_pool_task_executor.h index 445c5fc610d..746bfbb3eef 100644 --- a/src/mongo/executor/thread_pool_task_executor.h +++ b/src/mongo/executor/thread_pool_task_executor.h @@ -33,8 +33,8 @@ #include <memory> #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/transport/baton.h" #include "mongo/util/fail_point.h" diff --git a/src/mongo/platform/SConscript b/src/mongo/platform/SConscript index 910d1388223..648445c0746 100644 --- a/src/mongo/platform/SConscript +++ b/src/mongo/platform/SConscript @@ -8,7 +8,6 @@ env.CppUnitTest( 'atomic_proxy_test.cpp', 'atomic_word_test.cpp', 'bits_test.cpp', - 'condition_variable_test.cpp', 'endian_test.cpp', 'mutex_test.cpp', 'process_id_test.cpp', diff --git a/src/mongo/platform/condition_variable.cpp b/src/mongo/platform/condition_variable.cpp deleted file mode 100644 index ef6e64aaff7..00000000000 --- a/src/mongo/platform/condition_variable.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/platform/condition_variable.h" - -namespace mongo { - -std::unique_ptr<ConditionVariableActions> ConditionVariable::_conditionVariableActions; - -void ConditionVariable::notify_one() noexcept { - _condvar.notify_one(); -} - -void ConditionVariable::notify_all() noexcept { - _condvar.notify_all(); -} - -void ConditionVariable::setConditionVariableActions( - std::unique_ptr<ConditionVariableActions> actions) { - _conditionVariableActions = std::move(actions); -} -} // namespace mongo diff --git a/src/mongo/platform/condition_variable.h b/src/mongo/platform/condition_variable.h deleted file mode 100644 index beca4f4dda9..00000000000 --- a/src/mongo/platform/condition_variable.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include <chrono> - -#include "mongo/platform/mutex.h" -#include "mongo/stdx/condition_variable.h" -#include "mongo/util/duration.h" -#include "mongo/util/scopeguard.h" - -namespace mongo { - -class Mutex; - -class ConditionVariableActions { -public: - virtual ~ConditionVariableActions() = default; - virtual void onUnfulfilledConditionVariable(const StringData& name) = 0; - virtual void onFulfilledConditionVariable() = 0; -}; - -class ConditionVariable { -public: - static constexpr Milliseconds kUnfulfilledConditionVariableTimeout = Milliseconds(100); - - template <class Lock> - void wait(Lock& lock); - - template <class Lock, class Predicate> - void wait(Lock& lock, Predicate pred); - - template <class Lock, class Rep, class Period> - stdx::cv_status wait_for(Lock& lock, const stdx::chrono::duration<Rep, Period>& rel_time); - - template <class Lock, class Rep, class Period, class Predicate> - bool wait_for(Lock& lock, const stdx::chrono::duration<Rep, Period>& rel_time, Predicate pred); - - template <class Lock, class Clock, class Duration> - stdx::cv_status wait_until(Lock& lock, - const stdx::chrono::time_point<Clock, Duration>& timeout_time); - - template <class Lock, class Clock, class Duration, class Predicate> - bool wait_until(Lock& lock, - const stdx::chrono::time_point<Clock, Duration>& timeout_time, - Predicate pred); - - void notify_one() noexcept; - void notify_all() noexcept; - - static void setConditionVariableActions(std::unique_ptr<ConditionVariableActions> actions); - -protected: - template <typename Callback> - friend void runWithNotifyable(ConditionVariable& cv, - Notifyable& notifyable, - Callback&& cb) noexcept { - runWithNotifyable(cv._condvar, notifyable, std::forward<Callback>(cb)); - } - -private: - const Seconds _conditionVariableTimeout = Seconds(604800); - stdx::condition_variable_any _condvar; - - static std::unique_ptr<ConditionVariableActions> _conditionVariableActions; - - template <class Lock, class Duration> - auto _wait(Lock& lock, const Duration& rel_time) { - const auto guard = makeGuard([&] { - if (_conditionVariableActions) { - _conditionVariableActions->onFulfilledConditionVariable(); - } - }); - - if (auto cvstatus = _condvar.wait_for( - lock, std::min(rel_time, kUnfulfilledConditionVariableTimeout.toSystemDuration())); - cvstatus == stdx::cv_status::no_timeout || - rel_time <= kUnfulfilledConditionVariableTimeout.toSystemDuration()) { - return cvstatus; - } - - if (_conditionVariableActions) { - if constexpr (std::is_same<decltype(lock), mongo::Mutex>::value) { - _conditionVariableActions->onUnfulfilledConditionVariable(lock.getName()); - } else { - _conditionVariableActions->onUnfulfilledConditionVariable("AnonymousLock"); - } - } - - if (auto cvstatus = _condvar.wait_for( - lock, rel_time - kUnfulfilledConditionVariableTimeout.toSystemDuration()); - cvstatus == stdx::cv_status::no_timeout) { - return cvstatus; - } - - uasserted(ErrorCodes::InternalError, "Unable to take latch, wait time exceeds set timeout"); - } - - template <class Lock, class Duration, class Predicate> - auto _waitWithPredicate(Lock& lock, const Duration& rel_time, Predicate pred) { - while (!pred()) { - if (_wait(lock, rel_time) == stdx::cv_status::timeout) { - return pred(); - } - } - return true; - } -}; - -template <class Lock> -void ConditionVariable::wait(Lock& lock) { - _wait(lock, _conditionVariableTimeout.toSystemDuration()); -} - -template <class Lock, class Predicate> -void ConditionVariable::wait(Lock& lock, Predicate pred) { - _waitWithPredicate(lock, _conditionVariableTimeout.toSystemDuration(), std::move(pred)); -} - -template <class Lock, class Rep, class Period> -stdx::cv_status ConditionVariable::wait_for(Lock& lock, - const stdx::chrono::duration<Rep, Period>& rel_time) { - return _wait(lock, rel_time); -} - -template <class Lock, class Rep, class Period, class Predicate> -bool ConditionVariable::wait_for(Lock& lock, - const stdx::chrono::duration<Rep, Period>& rel_time, - Predicate pred) { - return _waitWithPredicate(lock, rel_time, pred); -} - -template <class Lock, class Clock, class Duration> -stdx::cv_status ConditionVariable::wait_until( - Lock& lock, const stdx::chrono::time_point<Clock, Duration>& timeout_time) { - return _wait(lock, timeout_time - stdx::chrono::steady_clock::now()); -} - -template <class Lock, class Clock, class Duration, class Predicate> -bool ConditionVariable::wait_until(Lock& lock, - const stdx::chrono::time_point<Clock, Duration>& timeout_time, - Predicate pred) { - return _waitWithPredicate(lock, timeout_time - stdx::chrono::steady_clock::now(), pred); -} - -} // namespace mongo diff --git a/src/mongo/platform/condition_variable_test.cpp b/src/mongo/platform/condition_variable_test.cpp deleted file mode 100644 index 69631e233f2..00000000000 --- a/src/mongo/platform/condition_variable_test.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/unittest/unittest.h" - -#include "mongo/platform/condition_variable.h" -#include "mongo/platform/mutex.h" -#include "mongo/stdx/thread.h" -#include "mongo/unittest/barrier.h" - -namespace mongo { - -TEST(ConditionVariable, BasicSingleThread) { - unittest::Barrier barrier(2U); - ConditionVariable cv; - stdx::mutex m; // NOLINT - bool done = false; - - stdx::thread worker([&]() { - stdx::unique_lock<stdx::mutex> lk(m); - barrier.countDownAndWait(); - ASSERT(!done); - cv.wait(lk, [&] { return done; }); - ASSERT(done); - }); - - barrier.countDownAndWait(); - { - stdx::unique_lock<stdx::mutex> lk(m); - done = true; - } - cv.notify_one(); - worker.join(); -} -} // namespace mongo diff --git a/src/mongo/platform/mutex.cpp b/src/mongo/platform/mutex.cpp index ba7230f8e94..3f2a18fe58a 100644 --- a/src/mongo/platform/mutex.cpp +++ b/src/mongo/platform/mutex.cpp @@ -32,27 +32,60 @@ namespace mongo { void Mutex::lock() { - auto hasLock = _mutex.try_lock(); - if (hasLock) { + if (_mutex.try_lock()) { + _onQuickLock(_name); return; } - if (auto actions = LockActions::getState().actions.load()) { - actions->onContendedLock(_name); - } + + _onContendedLock(_name); _mutex.lock(); + _onSlowLock(_name); } void Mutex::unlock() { - if (auto actions = LockActions::getState().actions.load()) { - actions->onUnlock(_name); - } + _onUnlock(_name); _mutex.unlock(); } bool Mutex::try_lock() { - return _mutex.try_lock(); + if (!_mutex.try_lock()) { + return false; + } + + _onQuickLock(_name); + return true; +} + +void Mutex::addLockListener(LockListener* listener) { + auto& state = _getListenerState(); + + state.list.push_back(listener); +} + +void Mutex::_onContendedLock(const StringData& name) noexcept { + auto& state = _getListenerState(); + for (auto listener : state.list) { + listener->onContendedLock(name); + } +} + +void Mutex::_onQuickLock(const StringData& name) noexcept { + auto& state = _getListenerState(); + for (auto listener : state.list) { + listener->onQuickLock(name); + } } -void Mutex::LockActions::add(LockActions* actions) { - getState().actions.store(actions); +void Mutex::_onSlowLock(const StringData& name) noexcept { + auto& state = _getListenerState(); + for (auto listener : state.list) { + listener->onSlowLock(name); + } +} + +void Mutex::_onUnlock(const StringData& name) noexcept { + auto& state = _getListenerState(); + for (auto listener : state.list) { + listener->onUnlock(name); + } } } // namespace mongo diff --git a/src/mongo/platform/mutex.h b/src/mongo/platform/mutex.h index fe72b201d3a..dd6bd4996a0 100644 --- a/src/mongo/platform/mutex.h +++ b/src/mongo/platform/mutex.h @@ -46,11 +46,18 @@ public: virtual void lock() = 0; virtual void unlock() = 0; virtual bool try_lock() = 0; + + virtual StringData getName() const { + return "AnonymousLatch"_sd; + } }; class Mutex : public Latch { + class LockNotifier; + public: - class LockActions; + class LockListener; + static constexpr auto kAnonymousMutexStr = "AnonymousMutex"_sd; Mutex() : Mutex(kAnonymousMutexStr) {} @@ -61,11 +68,36 @@ public: void lock() override; void unlock() override; bool try_lock() override; - const StringData& getName() const { + StringData getName() const override { return _name; } + /** + * This function adds a LockListener subclass to the triggers for certain actions. + * + * LockListeners can only be added and not removed. If you wish to deactivate a LockListeners + * subclass, please provide the switch on that subclass to noop its functions. It is only safe + * to add a LockListener during a MONGO_INITIALIZER. + */ + static void addLockListener(LockListener* listener); + private: + static auto& _getListenerState() noexcept { + struct State { + std::vector<LockListener*> list; + }; + + // Note that state should no longer be mutated after init-time (ala MONGO_INITIALIZERS). If + // this changes, than this state needs to be synchronized. + static State state; + return state; + } + + static void _onContendedLock(const StringData& name) noexcept; + static void _onQuickLock(const StringData& name) noexcept; + static void _onSlowLock(const StringData& name) noexcept; + static void _onUnlock(const StringData& name) noexcept; + const StringData _name; stdx::mutex _mutex; // NOLINT }; @@ -73,40 +105,31 @@ private: /** * A set of actions to happen upon notable events on a Lockable-conceptualized type */ -class Mutex::LockActions { +class Mutex::LockListener { friend class Mutex; public: - virtual ~LockActions() = default; + virtual ~LockListener() = default; + /** * Action to do when a lock cannot be immediately acquired */ virtual void onContendedLock(const StringData& name) = 0; /** - * Action to do when a lock is unlocked + * Action to do when a lock was acquired without blocking */ - virtual void onUnlock(const StringData& name) = 0; + virtual void onQuickLock(const StringData& name) = 0; /** - * This function adds a LockActions subclass to the triggers for certain actions. - * - * Note that currently there is only one LockActions in use at a time. As part of SERVER-42895, - * this will change so that there is a list of LockActions maintained. - * - * LockActions can only be added and not removed. If you wish to deactivate a LockActions - * subclass, please provide the switch on that subclass to noop its functions. + * Action to do when a lock was acquired after blocking */ - static void add(LockActions* actions); + virtual void onSlowLock(const StringData& name) = 0; -private: - static auto& getState() { - struct State { - AtomicWord<LockActions*> actions{nullptr}; - }; - static State state; - return state; - } + /** + * Action to do when a lock is unlocked + */ + virtual void onUnlock(const StringData& name) = 0; }; } // namespace mongo diff --git a/src/mongo/s/catalog/replset_dist_lock_manager.h b/src/mongo/s/catalog/replset_dist_lock_manager.h index 38176244f33..1dfd878703b 100644 --- a/src/mongo/s/catalog/replset_dist_lock_manager.h +++ b/src/mongo/s/catalog/replset_dist_lock_manager.h @@ -34,12 +34,12 @@ #include <string> #include "mongo/base/string_data.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/s/catalog/dist_lock_catalog.h" #include "mongo/s/catalog/dist_lock_manager.h" #include "mongo/s/catalog/dist_lock_ping_info.h" #include "mongo/stdx/chrono.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/stdx/unordered_map.h" diff --git a/src/mongo/s/catalog/replset_dist_lock_manager_test.cpp b/src/mongo/s/catalog/replset_dist_lock_manager_test.cpp index 89a420f50d5..4b7a38b7d21 100644 --- a/src/mongo/s/catalog/replset_dist_lock_manager_test.cpp +++ b/src/mongo/s/catalog/replset_dist_lock_manager_test.cpp @@ -36,7 +36,6 @@ #include <vector> #include "mongo/bson/json.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/s/balancer_configuration.h" #include "mongo/s/catalog/dist_lock_catalog_mock.h" @@ -46,6 +45,7 @@ #include "mongo/s/catalog/type_locks.h" #include "mongo/s/grid.h" #include "mongo/s/shard_server_test_fixture.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/unittest/unittest.h" #include "mongo/util/system_tick_source.h" #include "mongo/util/tick_source_mock.h" diff --git a/src/mongo/s/client/shard_registry.h b/src/mongo/s/client/shard_registry.h index 22a08cef941..2b9e839394f 100644 --- a/src/mongo/s/client/shard_registry.h +++ b/src/mongo/s/client/shard_registry.h @@ -36,9 +36,9 @@ #include "mongo/db/jsobj.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/s/client/shard.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/concurrency/with_lock.h" diff --git a/src/mongo/s/cluster_identity_loader.h b/src/mongo/s/cluster_identity_loader.h index 6b6d394f9e1..df2ed8b40d6 100644 --- a/src/mongo/s/cluster_identity_loader.h +++ b/src/mongo/s/cluster_identity_loader.h @@ -33,8 +33,8 @@ #include "mongo/bson/oid.h" #include "mongo/db/repl/read_concern_args.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { diff --git a/src/mongo/s/sharding_task_executor.h b/src/mongo/s/sharding_task_executor.h index e370a5425a5..3f763d120cd 100644 --- a/src/mongo/s/sharding_task_executor.h +++ b/src/mongo/s/sharding_task_executor.h @@ -34,8 +34,8 @@ #include "mongo/base/status_with.h" #include "mongo/executor/task_executor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { namespace executor { diff --git a/src/mongo/scripting/deadline_monitor.h b/src/mongo/scripting/deadline_monitor.h index 39862ebf58c..40c8217cb07 100644 --- a/src/mongo/scripting/deadline_monitor.h +++ b/src/mongo/scripting/deadline_monitor.h @@ -31,8 +31,8 @@ #include <cstdint> #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/concurrency/idle_thread_block.h" diff --git a/src/mongo/scripting/mozjs/PosixNSPR.cpp b/src/mongo/scripting/mozjs/PosixNSPR.cpp index 6df76f4ef13..77f0aedd07f 100644 --- a/src/mongo/scripting/mozjs/PosixNSPR.cpp +++ b/src/mongo/scripting/mozjs/PosixNSPR.cpp @@ -17,9 +17,9 @@ #include <js/Utility.h> #include <vm/PosixNSPR.h> -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/stdx/chrono.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/concurrency/thread_name.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/scripting/mozjs/countdownlatch.cpp b/src/mongo/scripting/mozjs/countdownlatch.cpp index f50735c734c..d9100b4bde0 100644 --- a/src/mongo/scripting/mozjs/countdownlatch.cpp +++ b/src/mongo/scripting/mozjs/countdownlatch.cpp @@ -31,10 +31,10 @@ #include "mongo/scripting/mozjs/countdownlatch.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/objectwrapper.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" namespace mongo { diff --git a/src/mongo/scripting/mozjs/jsthread.cpp b/src/mongo/scripting/mozjs/jsthread.cpp index fcd3549d21e..d39172bb02b 100644 --- a/src/mongo/scripting/mozjs/jsthread.cpp +++ b/src/mongo/scripting/mozjs/jsthread.cpp @@ -38,11 +38,11 @@ #include <vm/PosixNSPR.h> #include "mongo/db/jsobj.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/valuereader.h" #include "mongo/scripting/mozjs/valuewriter.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/log.h" #include "mongo/util/stacktrace.h" diff --git a/src/mongo/scripting/mozjs/proxyscope.h b/src/mongo/scripting/mozjs/proxyscope.h index 8d3269c7474..85be843b22d 100644 --- a/src/mongo/scripting/mozjs/proxyscope.h +++ b/src/mongo/scripting/mozjs/proxyscope.h @@ -32,9 +32,9 @@ #include "vm/PosixNSPR.h" #include "mongo/client/dbclient_cursor.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/scripting/mozjs/engine.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/functional.h" diff --git a/src/mongo/shell/bench.h b/src/mongo/shell/bench.h index ea714789d3c..170023917ac 100644 --- a/src/mongo/shell/bench.h +++ b/src/mongo/shell/bench.h @@ -38,8 +38,8 @@ #include "mongo/db/logical_session_id.h" #include "mongo/db/ops/write_ops_parsers.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/timer.h" diff --git a/src/mongo/transport/service_entry_point_impl.h b/src/mongo/transport/service_entry_point_impl.h index 1788ef8a146..58fcb6cf998 100644 --- a/src/mongo/transport/service_entry_point_impl.h +++ b/src/mongo/transport/service_entry_point_impl.h @@ -32,8 +32,8 @@ #include <list> #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/variant.h" #include "mongo/transport/service_entry_point.h" #include "mongo/transport/service_executor_reserved.h" diff --git a/src/mongo/transport/service_executor_adaptive.h b/src/mongo/transport/service_executor_adaptive.h index a0def9da063..bf3b55b2c5c 100644 --- a/src/mongo/transport/service_executor_adaptive.h +++ b/src/mongo/transport/service_executor_adaptive.h @@ -35,7 +35,7 @@ #include "mongo/db/service_context.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/transport/service_executor.h" #include "mongo/transport/service_executor_task_names.h" diff --git a/src/mongo/transport/service_executor_reserved.h b/src/mongo/transport/service_executor_reserved.h index 53bd3b00ade..8a71090bf63 100644 --- a/src/mongo/transport/service_executor_reserved.h +++ b/src/mongo/transport/service_executor_reserved.h @@ -33,8 +33,8 @@ #include "mongo/base/status.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/transport/service_executor.h" #include "mongo/transport/service_executor_task_names.h" diff --git a/src/mongo/transport/service_executor_synchronous.h b/src/mongo/transport/service_executor_synchronous.h index 192583bded7..1f0e2f6dd33 100644 --- a/src/mongo/transport/service_executor_synchronous.h +++ b/src/mongo/transport/service_executor_synchronous.h @@ -33,8 +33,8 @@ #include "mongo/base/status.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/transport/service_executor.h" #include "mongo/transport/service_executor_task_names.h" diff --git a/src/mongo/transport/transport_layer_asio.h b/src/mongo/transport/transport_layer_asio.h index 67ffbc11f0f..77a8e5e555b 100644 --- a/src/mongo/transport/transport_layer_asio.h +++ b/src/mongo/transport/transport_layer_asio.h @@ -36,8 +36,8 @@ #include "mongo/base/status_with.h" #include "mongo/config.h" #include "mongo/db/server_options.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/transport/transport_layer.h" #include "mongo/transport/transport_mode.h" diff --git a/src/mongo/unittest/barrier.h b/src/mongo/unittest/barrier.h index 4332b2480d7..de21587ea3b 100644 --- a/src/mongo/unittest/barrier.h +++ b/src/mongo/unittest/barrier.h @@ -29,8 +29,8 @@ #pragma once -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { namespace unittest { diff --git a/src/mongo/util/alarm_runner_background_thread.h b/src/mongo/util/alarm_runner_background_thread.h index 5f2b5d486cc..251b6ad89cd 100644 --- a/src/mongo/util/alarm_runner_background_thread.h +++ b/src/mongo/util/alarm_runner_background_thread.h @@ -28,7 +28,7 @@ */ #pragma once -#include "mongo/platform/condition_variable.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/alarm.h" #include "mongo/util/concurrency/with_lock.h" diff --git a/src/mongo/util/background.cpp b/src/mongo/util/background.cpp index 7f34141dfad..e0bda9a55d9 100644 --- a/src/mongo/util/background.cpp +++ b/src/mongo/util/background.cpp @@ -36,8 +36,8 @@ #include <functional> #include "mongo/config.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/concurrency/idle_thread_block.h" #include "mongo/util/concurrency/mutex.h" diff --git a/src/mongo/util/background_thread_clock_source.h b/src/mongo/util/background_thread_clock_source.h index b7c8feed705..4835ef9eae1 100644 --- a/src/mongo/util/background_thread_clock_source.h +++ b/src/mongo/util/background_thread_clock_source.h @@ -34,8 +34,8 @@ #include <thread> #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/clock_source.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/util/concurrency/notification.h b/src/mongo/util/concurrency/notification.h index 50e6b5e2302..379b6e10d9a 100644 --- a/src/mongo/util/concurrency/notification.h +++ b/src/mongo/util/concurrency/notification.h @@ -32,8 +32,8 @@ #include <boost/optional.hpp> #include "mongo/db/operation_context.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/assert_util.h" #include "mongo/util/duration.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/util/concurrency/thread_pool.h b/src/mongo/util/concurrency/thread_pool.h index c382df9544d..91981d1c808 100644 --- a/src/mongo/util/concurrency/thread_pool.h +++ b/src/mongo/util/concurrency/thread_pool.h @@ -34,8 +34,8 @@ #include <string> #include <vector> -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/concurrency/thread_pool_interface.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/util/concurrency/thread_pool_test.cpp b/src/mongo/util/concurrency/thread_pool_test.cpp index 5812a860eab..9545ce99cdb 100644 --- a/src/mongo/util/concurrency/thread_pool_test.cpp +++ b/src/mongo/util/concurrency/thread_pool_test.cpp @@ -34,8 +34,8 @@ #include <boost/optional.hpp> #include "mongo/base/init.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/unittest/barrier.h" #include "mongo/unittest/death_test.h" diff --git a/src/mongo/util/concurrency/thread_pool_test_common.cpp b/src/mongo/util/concurrency/thread_pool_test_common.cpp index 169f5154c18..98c03f8a5d4 100644 --- a/src/mongo/util/concurrency/thread_pool_test_common.cpp +++ b/src/mongo/util/concurrency/thread_pool_test_common.cpp @@ -35,8 +35,8 @@ #include <memory> -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/unittest/death_test.h" #include "mongo/util/assert_util.h" #include "mongo/util/concurrency/thread_pool_interface.h" diff --git a/src/mongo/util/concurrency/ticketholder.h b/src/mongo/util/concurrency/ticketholder.h index d67e6bd04d1..af9baa934ed 100644 --- a/src/mongo/util/concurrency/ticketholder.h +++ b/src/mongo/util/concurrency/ticketholder.h @@ -33,8 +33,8 @@ #endif #include "mongo/db/operation_context.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/mutex.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/util/diagnostic_info.cpp b/src/mongo/util/diagnostic_info.cpp index ea6cbe376df..e6bf99a15bf 100644 --- a/src/mongo/util/diagnostic_info.cpp +++ b/src/mongo/util/diagnostic_info.cpp @@ -33,25 +33,16 @@ #include "mongo/util/diagnostic_info.h" -#include "mongo/config.h" - -#if defined(__linux__) -#include <elf.h> -#include <link.h> -#endif - -#if defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE) -#include <execinfo.h> -#endif +#include <forward_list> #include <fmt/format.h> #include <fmt/ostream.h> #include "mongo/base/init.h" #include "mongo/db/client.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/util/clock_source.h" +#include "mongo/util/interruptible.h" #include "mongo/util/log.h" using namespace fmt::literals; @@ -61,25 +52,37 @@ namespace mongo { namespace { MONGO_FAIL_POINT_DEFINE(currentOpSpawnsThreadWaitingForLatch); -constexpr auto kBlockedOpMutexName = "BlockedOpForTest"_sd; +constexpr auto kBlockedOpMutexName = "BlockedOpForTestLatch"_sd; +constexpr auto kBlockedOpInterruptibleName = "BlockedOpForTestInterruptible"_sd; class BlockedOp { public: void start(ServiceContext* serviceContext); void join(); void setIsContended(bool value); + void setIsWaiting(bool value); private: - Mutex _testMutex = MONGO_MAKE_LATCH(kBlockedOpMutexName); - stdx::condition_variable _cv; stdx::mutex _m; // NOLINT - struct State { + struct LatchState { bool isContended = false; boost::optional<stdx::thread> thread{boost::none}; + + Mutex mutex = MONGO_MAKE_LATCH(kBlockedOpMutexName); }; - State _state; + LatchState _latchState; + + struct InterruptibleState { + bool isWaiting = false; + boost::optional<stdx::thread> thread{boost::none}; + + stdx::condition_variable cv; + Mutex mutex = MONGO_MAKE_LATCH(kBlockedOpInterruptibleName); + bool isDone = false; + }; + InterruptibleState _interruptibleState; } gBlockedOp; // This function causes us to make an additional thread with a self-contended lock so that @@ -88,62 +91,94 @@ private: void BlockedOp::start(ServiceContext* serviceContext) { stdx::unique_lock<stdx::mutex> lk(_m); - invariant(!_state.thread); + invariant(!_latchState.thread); + invariant(!_interruptibleState.thread); - _testMutex.lock(); - _state.thread = stdx::thread([this, serviceContext]() mutable { - ThreadClient tc("DiagnosticCaptureTest", serviceContext); + _latchState.mutex.lock(); + _latchState.thread = stdx::thread([this, serviceContext]() mutable { + ThreadClient tc("DiagnosticCaptureTestLatch", serviceContext); log() << "Entered currentOpSpawnsThreadWaitingForLatch thread"; - stdx::lock_guard testLock(_testMutex); + stdx::lock_guard testLock(_latchState.mutex); log() << "Joining currentOpSpawnsThreadWaitingForLatch thread"; }); - _cv.wait(lk, [this] { return _state.isContended; }); - log() << "Started thread for currentOpSpawnsThreadWaitingForLatch"; + _interruptibleState.thread = stdx::thread([this, serviceContext]() mutable { + ThreadClient tc("DiagnosticCaptureTestInterruptible", serviceContext); + auto opCtx = tc->makeOperationContext(); + + log() << "Entered currentOpSpawnsThreadWaitingForLatch thread for interruptibles"; + stdx::unique_lock lk(_interruptibleState.mutex); + opCtx->waitForConditionOrInterrupt( + _interruptibleState.cv, lk, [&] { return _interruptibleState.isDone; }); + _interruptibleState.isDone = false; + + log() << "Joining currentOpSpawnsThreadWaitingForLatch thread for interruptibles"; + }); + + + _cv.wait(lk, [this] { return _latchState.isContended && _interruptibleState.isWaiting; }); + log() << "Started threads for currentOpSpawnsThreadWaitingForLatch"; } // This function unlocks testMutex and joins if there are no more callers of BlockedOp::start() // remaining void BlockedOp::join() { - auto thread = [&] { + decltype(_latchState.thread) latchThread; + decltype(_interruptibleState.thread) interruptibleThread; + { stdx::lock_guard<stdx::mutex> lk(_m); - invariant(_state.thread); + invariant(_latchState.thread); + invariant(_interruptibleState.thread); - _testMutex.unlock(); + _latchState.mutex.unlock(); + _latchState.isContended = false; - _state.isContended = false; - _cv.notify_one(); + { + stdx::lock_guard lk(_interruptibleState.mutex); + _interruptibleState.isDone = true; + _interruptibleState.cv.notify_one(); + } + _interruptibleState.isWaiting = false; + + std::swap(_latchState.thread, latchThread); + std::swap(_interruptibleState.thread, interruptibleThread); + } - return std::exchange(_state.thread, boost::none); - }(); - thread->join(); + latchThread->join(); + interruptibleThread->join(); } void BlockedOp::setIsContended(bool value) { log() << "Setting isContended to " << (value ? "true" : "false"); stdx::lock_guard lk(_m); - _state.isContended = value; + _latchState.isContended = value; + _cv.notify_one(); +} + +void BlockedOp::setIsWaiting(bool value) { + log() << "Setting isWaiting to " << (value ? "true" : "false"); + stdx::lock_guard lk(_m); + _interruptibleState.isWaiting = value; _cv.notify_one(); } struct DiagnosticInfoHandle { stdx::mutex mutex; // NOLINT - boost::optional<DiagnosticInfo> maybeInfo = boost::none; + std::forward_list<DiagnosticInfo> list; }; const auto getDiagnosticInfoHandle = Client::declareDecoration<DiagnosticInfoHandle>(); -MONGO_INITIALIZER(LockActions)(InitializerContext* context) { - class LockActionsSubclass : public Mutex::LockActions { +MONGO_INITIALIZER(LockListener)(InitializerContext* context) { + class LockListener : public Mutex::LockListener { void onContendedLock(const StringData& name) override { - auto client = Client::getCurrent(); - if (client) { + if (auto client = Client::getCurrent()) { auto& handle = getDiagnosticInfoHandle(client); stdx::lock_guard<stdx::mutex> lk(handle.mutex); - handle.maybeInfo.emplace(DiagnosticInfo::capture(name)); + handle.list.emplace_front(DiagnosticInfo::capture(name)); if (currentOpSpawnsThreadWaitingForLatch.shouldFail() && (name == kBlockedOpMutexName)) { @@ -151,197 +186,98 @@ MONGO_INITIALIZER(LockActions)(InitializerContext* context) { } } } - void onUnlock(const StringData& name) override { - auto client = Client::getCurrent(); - if (client) { + + void onQuickLock(const StringData&) override { + // Do nothing + } + + void onSlowLock(const StringData& name) override { + if (auto client = Client::getCurrent()) { auto& handle = getDiagnosticInfoHandle(client); stdx::lock_guard<stdx::mutex> lk(handle.mutex); - handle.maybeInfo.reset(); + + invariant(!handle.list.empty()); + handle.list.pop_front(); } } + + void onUnlock(const StringData&) override { + // Do nothing + } }; // Intentionally leaked, people use Latches in detached threads - static auto& actions = *new LockActionsSubclass; - Mutex::LockActions::add(&actions); + static auto& listener = *new LockListener; + Mutex::addLockListener(&listener); return Status::OK(); } -/* -MONGO_INITIALIZER(ConditionVariableActions)(InitializerContext* context) { +MONGO_INITIALIZER(InterruptibleWaitListener)(InitializerContext* context) { + class WaitListener : public Interruptible::WaitListener { + using WakeReason = Interruptible::WakeReason; + using WakeSpeed = Interruptible::WakeSpeed; - class ConditionVariableActionsSubclass : public ConditionVariableActions { - void onUnfulfilledConditionVariable(const StringData& name) override { - if (haveClient()) { - DiagnosticInfo::Diagnostic::set( - Client::getCurrent(), - std::make_shared<DiagnosticInfo>(capture(name))); + void addInfo(const StringData& name) { + if (auto client = Client::getCurrent()) { + auto& handle = getDiagnosticInfoHandle(client); + stdx::lock_guard<stdx::mutex> lk(handle.mutex); + handle.list.emplace_front(DiagnosticInfo::capture(name)); + + if (currentOpSpawnsThreadWaitingForLatch.shouldFail() && + (name == kBlockedOpInterruptibleName)) { + gBlockedOp.setIsWaiting(true); + } } } - void onFulfilledConditionVariable() override { - DiagnosticInfo::Diagnostic::clearDiagnostic(); - } - }; - - std::unique_ptr<ConditionVariableActions> conditionVariablePointer = - std::make_unique<ConditionVariableActionsSubclass>(); - ConditionVariable::setConditionVariableActions(std::move(conditionVariablePointer)); - return Status::OK(); -} -*/ + void removeInfo(const StringData& name) { + if (auto client = Client::getCurrent()) { + auto& handle = getDiagnosticInfoHandle(client); + stdx::lock_guard<stdx::mutex> lk(handle.mutex); -} // namespace + invariant(!handle.list.empty()); + handle.list.pop_front(); + } + } -#if defined(__linux__) -namespace { + void onLongSleep(const StringData& name) override { + addInfo(name); + } -class DynamicObjectMap { -public: - struct Section { - StringData objectPath; - uintptr_t sectionOffset = 0; - size_t sectionSize = 0; + void onWake(const StringData& name, WakeReason, WakeSpeed speed) override { + if (speed == WakeSpeed::kSlow) { + removeInfo(name); + } + } }; - // uses dl_iterate_phdr to retrieve information on the shared objects that have been loaded in - // the form of a map from segment address to object - void init() { - ::dl_iterate_phdr(addToMap, &_map); - } - - // return a StackFrame object located at the header address in the map that is immediately - // preceding or equal to the instruction pointer address - DiagnosticInfo::StackFrame getFrame(void* instructionPtr) const; - - // callback function in dl_iterate_phdr that iterates through the shared objects and creates a - // map from the section address to object - static int addToMap(dl_phdr_info* info, size_t size, void* data); - -private: - std::map<uintptr_t, Section> _map; -} gDynamicObjectMap; + // Intentionally leaked, people can use in detached threads + static auto& listener = *new WaitListener(); + Interruptible::addWaitListener(&listener); -MONGO_INITIALIZER(InitializeDynamicObjectMap)(InitializerContext* context) { - gDynamicObjectMap.init(); return Status::OK(); -}; - -int DynamicObjectMap::addToMap(dl_phdr_info* info, size_t size, void* data) { - auto& addr_map = *reinterpret_cast<decltype(DynamicObjectMap::_map)*>(data); - for (int j = 0; j < info->dlpi_phnum; j++) { - auto& header = info->dlpi_phdr[j]; - auto addr = info->dlpi_addr + header.p_vaddr; - switch (header.p_type) { - case PT_LOAD: - case PT_DYNAMIC: - break; - default: - continue; - } - auto frame = Section{ - info->dlpi_name, // object name - static_cast<uintptr_t>(header.p_offset), // section offset in file - header.p_memsz, // section size in memory - }; - addr_map.emplace(addr, frame); - } - return 0; -} - -DiagnosticInfo::StackFrame DynamicObjectMap::getFrame(void* instructionPtr) const { - auto address = reinterpret_cast<uintptr_t>(instructionPtr); - - // instructionPtr < it->first - auto it = _map.upper_bound(address); - // instuctionPtr >= it->first - --it; - - auto& [headerAddress, frame] = *it; - dassert(address < (headerAddress + frame.sectionSize)); - - auto fileOffset = address - headerAddress + frame.sectionOffset; - return DiagnosticInfo::StackFrame{frame.objectPath, fileOffset}; } } // namespace -#endif // linux - -#if defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE) && defined(__linux__) -// iterates through the backtrace instruction pointers to -// find the instruction pointer that refers to a segment in the addr_map -DiagnosticInfo::StackTrace DiagnosticInfo::makeStackTrace() const { - DiagnosticInfo::StackTrace trace; - for (auto address : _backtrace.data) { - trace.frames.emplace_back(gDynamicObjectMap.getFrame(address)); - } - return trace; -} - -auto DiagnosticInfo::getBacktrace() -> Backtrace { - Backtrace list; - auto len = ::backtrace(list.data.data(), list.data.size()); - list.data.resize(len); - return list; -} -#else -DiagnosticInfo::StackTrace DiagnosticInfo::makeStackTrace() const { - return DiagnosticInfo::StackTrace(); -} - -auto DiagnosticInfo::getBacktrace() -> Backtrace { - return {}; -} -#endif - -bool operator==(const DiagnosticInfo::StackFrame& frame1, - const DiagnosticInfo::StackFrame& frame2) { - return frame1.objectPath == frame2.objectPath && - frame1.instructionOffset == frame2.instructionOffset; -} - -bool operator==(const DiagnosticInfo::StackTrace& trace1, - const DiagnosticInfo::StackTrace& trace2) { - return trace1.frames == trace2.frames; -} bool operator==(const DiagnosticInfo& info1, const DiagnosticInfo& info2) { return info1._captureName == info2._captureName && info1._timestamp == info2._timestamp && info1._backtrace.data == info2._backtrace.data; } -std::string DiagnosticInfo::StackFrame::toString() const { - return "{{ \"path\": \"{}\", \"addr\": \"0x{:x}\" }}"_format(objectPath, instructionOffset); -} - -std::string DiagnosticInfo::StackTrace::toString() const { - str::stream stream; - stream << "{ \"backtrace\": [ "; - bool isFirst = true; - for (auto& frame : frames) { - if (!std::exchange(isFirst, false)) { - // Sadly, JSON doesn't allow trailing commas - stream << ", "; - } - stream << frame.toString(); - } - stream << "] }"; - return stream; -} - std::string DiagnosticInfo::toString() const { return "{{ \"name\": \"{}\", \"time\": \"{}\", \"backtraceSize\": {} }}"_format( _captureName.toString(), _timestamp.toString(), _backtrace.data.size()); } DiagnosticInfo DiagnosticInfo::capture(const StringData& captureName, Options options) { - // uses backtrace to retrieve an array of instruction pointers for currently active - // function calls of the program - return DiagnosticInfo(getGlobalServiceContext()->getFastClockSource()->now(), - captureName, - options.shouldTakeBacktrace ? DiagnosticInfo::getBacktrace() - : Backtrace{{}}); + // Since we don't have a fast enough backtrace implementation at the moment, the Backtrace is + // always empty. If SERVER-44091 happens, this should branch on options.shouldTakeBacktrace + auto backtrace = Backtrace{}; + auto currentTime = getGlobalServiceContext()->getFastClockSource()->now(); + + return DiagnosticInfo(currentTime, captureName, std::move(backtrace)); } DiagnosticInfo::BlockedOpGuard::~BlockedOpGuard() { @@ -366,7 +302,12 @@ auto DiagnosticInfo::maybeMakeBlockedOpForTest(Client* client) -> std::unique_pt boost::optional<DiagnosticInfo> DiagnosticInfo::get(Client& client) { auto& handle = getDiagnosticInfoHandle(client); stdx::lock_guard<stdx::mutex> lk(handle.mutex); - return handle.maybeInfo; + + if (handle.list.empty()) { + return boost::none; + } + + return handle.list.front(); } } // namespace mongo diff --git a/src/mongo/util/diagnostic_info.h b/src/mongo/util/diagnostic_info.h index 4c4eb15c7ea..2b457fc50fe 100644 --- a/src/mongo/util/diagnostic_info.h +++ b/src/mongo/util/diagnostic_info.h @@ -31,8 +31,8 @@ #include "mongo/base/string_data.h" #include "mongo/db/client.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/fail_point.h" #include "mongo/util/time_support.h" @@ -43,6 +43,12 @@ namespace mongo { */ class DiagnosticInfo { public: + // Maximum number of stack frames to appear in a DiagnosticInfo::Backtrace. + static constexpr size_t kMaxBackTraceFrames = 100ull; + struct Backtrace { + std::vector<void*> data = std::vector<void*>(kMaxBackTraceFrames, nullptr); + }; + /** * A simple RAII guard to attempt to join a blocked op once it is no longer needed * @@ -57,32 +63,6 @@ public: virtual ~DiagnosticInfo() = default; - // Maximum number of stack frames to appear in a backtrace. - static constexpr size_t kMaxBackTraceFrames = 100ull; - struct Backtrace { - std::vector<void*> data = std::vector<void*>(kMaxBackTraceFrames, nullptr); - }; - - struct StackFrame { - std::string toString() const; - friend bool operator==(const StackFrame& frame1, const StackFrame& frame2); - friend bool operator!=(const StackFrame& frame1, const StackFrame& frame2) { - return !(frame1 == frame2); - } - - StringData objectPath; - uintptr_t instructionOffset = 0; - }; - struct StackTrace { - std::string toString() const; - friend bool operator==(const StackTrace& trace1, const StackTrace& trace2); - friend bool operator!=(const StackTrace& trace1, const StackTrace& trace2) { - return !(trace1 == trace2); - } - - std::vector<StackFrame> frames; - }; - Date_t getTimestamp() const { return _timestamp; } @@ -91,10 +71,6 @@ public: return _captureName; } - StackTrace makeStackTrace() const; - - static Backtrace getBacktrace(); - std::string toString() const; /** @@ -117,6 +93,10 @@ public: */ static std::unique_ptr<BlockedOpGuard> maybeMakeBlockedOpForTest(Client* client); + friend std::ostream& operator<<(std::ostream& s, const DiagnosticInfo& info) { + return s << info.toString(); + } + private: friend bool operator==(const DiagnosticInfo& info1, const DiagnosticInfo& info2); friend bool operator!=(const DiagnosticInfo& info1, const DiagnosticInfo& info2) { @@ -133,12 +113,4 @@ private: }; -inline std::ostream& operator<<(std::ostream& s, const DiagnosticInfo::StackFrame& frame) { - return s << frame.toString(); -} - -inline std::ostream& operator<<(std::ostream& s, const DiagnosticInfo& info) { - return s << info.toString(); -} - } // namespace mongo diff --git a/src/mongo/util/diagnostic_info_test.cpp b/src/mongo/util/diagnostic_info_test.cpp index dc8ebdda058..3c054d685dc 100644 --- a/src/mongo/util/diagnostic_info_test.cpp +++ b/src/mongo/util/diagnostic_info_test.cpp @@ -65,94 +65,4 @@ TEST(DiagnosticInfo, BasicSingleThread) { clockSourcePointer->advance(Seconds(1)); ASSERT_LT(capture2.getTimestamp(), clockSourcePointer->now()); } - -using MaybeDiagnosticInfo = boost::optional<DiagnosticInfo>; -void recurseAndCaptureInfo(MaybeDiagnosticInfo& info, AtomicWord<int>& i); - -TEST(DiagnosticInfo, StackTraceTest) { - // set up serviceContext and clock source - auto serviceContext = ServiceContext::make(); - auto clockSource = std::make_unique<ClockSourceMock>(); - serviceContext->setFastClockSource(std::move(clockSource)); - setGlobalServiceContext(std::move(serviceContext)); - - MaybeDiagnosticInfo infoRecurse0; - { - AtomicWord<int> i{0}; - recurseAndCaptureInfo(infoRecurse0, i); - } - - ASSERT(infoRecurse0); - log() << *infoRecurse0; - auto trace0 = infoRecurse0->makeStackTrace(); - log() << trace0; - -#ifdef __linux__ - auto testRecursion = [&](size_t i, const MaybeDiagnosticInfo& infoRecurse) { - ASSERT(infoRecurse); - log() << *infoRecurse; - - auto trace = infoRecurse->makeStackTrace(); - log() << trace; - ASSERT_EQ(trace0.frames.size() + i, trace.frames.size()); - - auto it = trace.frames.begin(); - auto it0 = trace0.frames.begin(); - - for (; *it == *it0; ++it, ++it0) { - // The begining of the trace should be the same - } - - size_t j = 0; - auto recursiveFrame = *it; - for (; *it == recursiveFrame; ++it, ++j) { - // Advance the recursive trace through the recursion - ASSERT_NE(*it, *it0); - - // The recursive frame should always be on the main executable - ASSERT_EQ(it->objectPath, ""); - } - ASSERT_EQ(j, i); - - // The frame right above the recursion will be a different return - ASSERT_NE(*it, *it0); - ++it, ++it0; - - for (; it0 != trace0.frames.end() && *it == *it0; ++it, ++it0) { - // The end of the trace should be the same - } - - ASSERT(it == trace.frames.end()); - }; - - { - constexpr auto k = 3; - AtomicWord<int> i{k}; - MaybeDiagnosticInfo infoRecurse; - recurseAndCaptureInfo(infoRecurse, i); - testRecursion(k, infoRecurse); - } - - { - constexpr auto k = 10; - AtomicWord<int> i{k}; - MaybeDiagnosticInfo infoRecurse; - recurseAndCaptureInfo(infoRecurse, i); - testRecursion(k, infoRecurse); - } -#else - ASSERT_TRUE(trace0.frames.empty()); -#endif -} - -MONGO_COMPILER_NOINLINE void recurseAndCaptureInfo(MaybeDiagnosticInfo& info, AtomicWord<int>& i) { - if (i.fetchAndSubtract(1) == 0) { - DiagnosticInfo::Options options; - options.shouldTakeBacktrace = true; - info = DiagnosticInfo::capture("Recursion!"_sd, std::move(options)); - return; - } - - recurseAndCaptureInfo(info, i); -} } // namespace mongo diff --git a/src/mongo/util/exit.cpp b/src/mongo/util/exit.cpp index 49b741c4493..d79c9fde1c8 100644 --- a/src/mongo/util/exit.cpp +++ b/src/mongo/util/exit.cpp @@ -37,8 +37,8 @@ #include <functional> #include <stack> -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/log.h" #include "mongo/util/quick_exit.h" diff --git a/src/mongo/util/future_impl.h b/src/mongo/util/future_impl.h index db83f1c0cbc..a08516191f4 100644 --- a/src/mongo/util/future_impl.h +++ b/src/mongo/util/future_impl.h @@ -38,8 +38,8 @@ #include "mongo/base/status.h" #include "mongo/base/status_with.h" #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/type_traits.h" #include "mongo/stdx/utility.h" #include "mongo/util/assert_util.h" diff --git a/src/mongo/util/interruptible.h b/src/mongo/util/interruptible.h index d72be7b77d0..3a036f55201 100644 --- a/src/mongo/util/interruptible.h +++ b/src/mongo/util/interruptible.h @@ -29,9 +29,13 @@ #pragma once +#include <vector> + +#include "mongo/platform/mutex.h" #include "mongo/stdx/condition_variable.h" -#include "mongo/stdx/mutex.h" +#include "mongo/util/concepts.h" #include "mongo/util/lockable_adapter.h" +#include "mongo/util/scopeguard.h" #include "mongo/util/time_support.h" #include "mongo/util/waitable.h" @@ -201,6 +205,36 @@ private: } public: + class WaitListener; + + /** + * Enum to convey why an Interruptible woke up + */ + enum class WakeReason { + kPredicate, + kTimeout, + kInterrupt, + }; + + static constexpr auto kFastWakeTimeout = Milliseconds(100); + + /** + * Enum to convey if an Interruptible woke up before or after kFastWakeTimeout + */ + enum class WakeSpeed { + kFast, + kSlow, + }; + + /** + * This function adds a WaitListener subclass to the triggers for certain actions. + * + * WaitListeners can only be added and not removed. If you wish to deactivate a WaitListeners + * subclass, please provide the switch on that subclass to noop its functions. It is only safe + * to add a WaitListener during a MONGO_INITIALIZER. + */ + static void addWaitListener(WaitListener* listnener); + /** * Returns a statically allocated instance that cannot be interrupted. Useful as a default * argument to Interruptible-taking methods. @@ -257,6 +291,23 @@ public: } /** + * Get the name for a Latch + */ + TEMPLATE(typename LatchT) + REQUIRES(std::is_base_of_v<Latch, LatchT>) // + static StringData getLatchName(const stdx::unique_lock<LatchT>& lk) { + return lk.mutex()->getName(); + } + + /** + * Get a placeholder name for an arbitrary type + */ + template <typename LockT> + static constexpr StringData getLatchName(const LockT&) { + return "AnonymousLockable"_sd; + } + + /** * Waits on condition "cv" for "pred" until "pred" returns true, or the given "deadline" * expires, or this operation is interrupted, or this operation's own deadline expires. * @@ -267,20 +318,73 @@ public: template <typename LockT, typename PredicateT> bool waitForConditionOrInterruptUntil(stdx::condition_variable& cv, LockT& m, - Date_t deadline, + Date_t finalDeadline, PredicateT pred) { - auto waitUntil = [&](Date_t deadline) { - // Wrapping this in a lambda because it's a mouthful - return uassertStatusOK(waitForConditionOrInterruptNoAssertUntil(cv, m, deadline)); + auto latchName = getLatchName(m); + + auto waitUntil = [&](Date_t deadline, WakeSpeed speed) -> boost::optional<WakeReason> { + // If the result of waitForConditionOrInterruptNoAssertUntil() is non-spurious, return + // a WakeReason. Otherwise, return boost::none + + auto swResult = waitForConditionOrInterruptNoAssertUntil(cv, m, deadline); + if (!swResult.isOK()) { + _onWake(latchName, WakeReason::kInterrupt, speed); + uassertStatusOK(std::move(swResult)); + } + + if (pred()) { + _onWake(latchName, WakeReason::kPredicate, speed); + return WakeReason::kPredicate; + } + + if (swResult.getValue() == stdx::cv_status::timeout) { + _onWake(latchName, WakeReason::kTimeout, speed); + return WakeReason::kTimeout; + } + + return boost::none; }; - while (!pred()) { - if (waitUntil(deadline) == stdx::cv_status::timeout) { - return pred(); + auto waitUntilNonSpurious = [&](Date_t deadline, WakeSpeed speed) -> WakeReason { + // Check waitUntil() in a loop until it says it has a genuine WakeReason + + if (pred()) { + // Check for the predicate first, just in case + _onWake(latchName, WakeReason::kPredicate, speed); + return WakeReason::kPredicate; } + + auto maybeWakeReason = waitUntil(deadline, speed); + while (!maybeWakeReason) { + maybeWakeReason = waitUntil(deadline, speed); + }; + + return *maybeWakeReason; }; - return true; + const auto traceDeadline = getExpirationDateForWaitForValue(kFastWakeTimeout); + const auto firstDeadline = std::min(traceDeadline, finalDeadline); + + // Wait for the first deadline + if (auto wakeReason = waitUntilNonSpurious(firstDeadline, WakeSpeed::kFast); + wakeReason == WakeReason::kPredicate) { + // If our first wait fulfilled our predicate then return true + return true; + } else if (firstDeadline == finalDeadline) { + // If we didn't fulfill our predicate but finalDeadline was less than traceDeadline, + // then the wait should return false + return false; + } + + _onLongSleep(latchName); + + // Wait for the final deadline + if (auto wakeReason = waitUntilNonSpurious(finalDeadline, WakeSpeed::kSlow); + wakeReason == WakeReason::kPredicate) { + return true; + } else { + return false; + } } /** @@ -329,9 +433,67 @@ public: protected: class NotInterruptible; + + void _onLongSleep(const StringData& name); + void _onWake(const StringData& name, WakeReason reason, WakeSpeed speed); + + static auto& _getListenerState() { + struct State { + std::vector<WaitListener*> list; + }; + + // Note that state should no longer be mutated after init-time (ala MONGO_INITIALIZERS). If + // this changes, than this state needs to be synchronized. + static State state; + return state; + } }; /** + * A set of event handles for an Interruptible type + */ +class Interruptible::WaitListener { +public: + /** + * Action to do when a wait does not resolve quickly + * + * Any implementation of this function must be safe to invoke when an Interruptible-associated + * latch is held. As this is hard to reason about, avoid external latches whenever possible. + */ + virtual void onLongSleep(const StringData& name) = 0; + + /** + * Action to do when a wait resolves after a sleep + * + * Any implementation of this function must be safe to invoke when an Interruptible-associated + * latch is held. As this is hard to reason about, avoid external latches whenever possible. + */ + virtual void onWake(const StringData& name, WakeReason reason, WakeSpeed speed) = 0; +}; + +inline void Interruptible::addWaitListener(WaitListener* listener) { + auto& state = _getListenerState(); + + state.list.push_back(listener); +} + +inline void Interruptible::_onLongSleep(const StringData& name) { + auto& state = _getListenerState(); + + for (auto listener : state.list) { + listener->onLongSleep(name); + } +} + +inline void Interruptible::_onWake(const StringData& name, WakeReason reason, WakeSpeed speed) { + auto& state = _getListenerState(); + + for (auto listener : state.list) { + listener->onWake(name, reason, speed); + } +} + +/** * A non-interruptible type which can be used as a lightweight default arg for Interruptible-taking * functions. */ diff --git a/src/mongo/util/invalidating_lru_cache.h b/src/mongo/util/invalidating_lru_cache.h index 6cef29f63c8..9a52136ac4a 100644 --- a/src/mongo/util/invalidating_lru_cache.h +++ b/src/mongo/util/invalidating_lru_cache.h @@ -34,8 +34,8 @@ #include <boost/optional.hpp> -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/assert_util.h" #include "mongo/util/concurrency/with_lock.h" diff --git a/src/mongo/util/periodic_runner_impl.h b/src/mongo/util/periodic_runner_impl.h index 07ed7db0ebd..4a89b4b6a05 100644 --- a/src/mongo/util/periodic_runner_impl.h +++ b/src/mongo/util/periodic_runner_impl.h @@ -32,8 +32,8 @@ #include <memory> #include <vector> -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/clock_source.h" #include "mongo/util/future.h" diff --git a/src/mongo/util/periodic_runner_impl_test.cpp b/src/mongo/util/periodic_runner_impl_test.cpp index 21018ea09b7..185d3d2706a 100644 --- a/src/mongo/util/periodic_runner_impl_test.cpp +++ b/src/mongo/util/periodic_runner_impl_test.cpp @@ -34,8 +34,8 @@ #include "mongo/util/periodic_runner_impl.h" #include "mongo/db/service_context_test_fixture.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/clock_source_mock.h" namespace mongo { diff --git a/src/mongo/util/producer_consumer_queue.h b/src/mongo/util/producer_consumer_queue.h index 44a87f93aec..0836bbb28c5 100644 --- a/src/mongo/util/producer_consumer_queue.h +++ b/src/mongo/util/producer_consumer_queue.h @@ -35,8 +35,8 @@ #include <numeric> #include "mongo/db/operation_context.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/util/concurrency/with_lock.h" #include "mongo/util/interruptible.h" #include "mongo/util/scopeguard.h" diff --git a/src/mongo/util/producer_consumer_queue_test.cpp b/src/mongo/util/producer_consumer_queue_test.cpp index d474c7bb7f9..5ba6a4d43de 100644 --- a/src/mongo/util/producer_consumer_queue_test.cpp +++ b/src/mongo/util/producer_consumer_queue_test.cpp @@ -34,8 +34,8 @@ #include "mongo/util/producer_consumer_queue.h" #include "mongo/db/service_context.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/assert_util.h" diff --git a/src/mongo/util/queue.h b/src/mongo/util/queue.h index af652dcb40c..320f036e9ff 100644 --- a/src/mongo/util/queue.h +++ b/src/mongo/util/queue.h @@ -34,9 +34,9 @@ #include <limits> #include <queue> -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" #include "mongo/stdx/chrono.h" +#include "mongo/stdx/condition_variable.h" namespace mongo { diff --git a/src/mongo/watchdog/watchdog.h b/src/mongo/watchdog/watchdog.h index 289d2dadac9..d7b6c74580f 100644 --- a/src/mongo/watchdog/watchdog.h +++ b/src/mongo/watchdog/watchdog.h @@ -35,8 +35,8 @@ #include <vector> #include "mongo/platform/atomic_word.h" -#include "mongo/platform/condition_variable.h" #include "mongo/platform/mutex.h" +#include "mongo/stdx/condition_variable.h" #include "mongo/stdx/thread.h" #include "mongo/util/duration.h" |