Рассмотрим этот пример:
#include
#include
#include
int main() {
std::atomic key;
auto t1 = std::thread([&]() {
auto now = std::chrono::steady_clock::now();
auto duration = now.time_since_epoch();
auto seconds =
std::chrono::duration_cast(duration).count();
key.store(seconds); // #1 occurred at timepoint `T1`
});
auto t2 = std::thread([&]() {
auto now = std::chrono::steady_clock::now();
auto duration = now.time_since_epoch();
auto seconds =
std::chrono::duration_cast(duration).count();
key.store(seconds); // #2 occurred at timepoint `T2`
});
auto t3 = std::thread([&]() {
std::this_thread::sleep_for(std::chrono::milliseconds(300)); // debounce
auto search_key = key.load(); // #3 occurred at timepoint `T3`
// request(search_key);
});
t1.join();
t2.join();
t3.join();
}
Предполагая, что каждый ввод пользователя будет создавать поток и вычислять ввод пользователя для создания ключа поиска, а затем записывать его в ключ, существует поток для чтения ввода пользователя и выполнения сетевого запроса для загруженного ключа. Чтобы избежать частых сетевых запросов во время ввода пользователя, в потоке поиска также предусмотрен механизм устранения дребезга.
В этом примере он моделирует два таких события ввода пользователя, а именно t1 и t2. Предполагается, что каждое событие произошло в момент времени, указанный в комментарии, и T1 < T2 < T3. Несмотря на то, что каждая атомарная операция использует seq_cst и формирует единый общий порядок, а моменты времени T1 и T2 предшествуют T3, #3 все равно может загрузить #1 и упорядочить по связности до #2.
Это не линеаризуемость, поскольку T1 < T2 < T3 и загрузка в T3 не прочитали хранилище, которое произошло в T2. (Я не уверен, можно ли назвать согласованность на временной шкале линеаризуемостью).
Итак, с точки зрения стандарта C++, правда ли, что только один поток может гарантировать линеаризуемость? То есть операция загрузки гарантированно всегда считывает хранилище, которое произошло ближе всего к временной шкале до того, как произошла операция загрузки.
Пример обновления
#include
#include
#include
int main() {
std::atomic key;
auto t3 = std::thread([&]() {
std::this_thread::sleep_for(std::chrono::milliseconds(300)); // debounce
auto search_key = key.load(); // C
// request(search_key);
if(search_key==key.load()){ // D
// use the response
}
});
key.store(1); // A first input
key.store(2); // B second input
t3.join();
}
A и B обозначают двойной быстрый ввод пользователя, очевидно, B обозначает последний ввод пользователя, C пытается прочитать последний ввод пользователя после времени устранения дребезга и выполнить сетевой запрос в потоке t3. C не гарантируется чтение из B в соответствии со стандартом C++.
В полном случае создается задача поиска для каждого ввода пользователя и отбрасывается ответ, если значение изменилось, чтобы смоделировать то, что происходит в javascript
#include
#include
#include
#include
#include
#include
#include
#include
// =================================================================
// 1. TASK DISPATCHER (The "Event Loop")
// This class mimics the JavaScript Task Queue. It allows background
// threads to "post" work back to the main thread for execution.
// =================================================================
class Dispatcher {
std::queue tasks;
std::mutex mtx;
public:
// Pushes a function into the queue. Safe to call from any thread.
void post(std::function task) {
std::lock_guard lock(mtx);
tasks.push(task);
}
// Executes all pending tasks. Should be called by the Main Thread.
void processEvents() {
std::queue toExecute;
{
// Swap content to minimize lock time (prevents blocking posters)
std::lock_guard lock(mtx);
std::swap(toExecute, tasks);
}
while (!toExecute.empty()) {
toExecute.front()(); // Execute the callback
toExecute.pop();
}
}
};
Dispatcher g_dispatcher; // Global dispatcher acting as our event loop
// =================================================================
// 2. MOCK NETWORK FUNCTION
// Simulates an asynchronous network request.
// =================================================================
void fetchNetworkData(int inputValue, std::function callback) {
// Start a background thread to simulate network latency
std::thread([inputValue, callback]() {
// Simulate a 2-second delay
std::this_thread::sleep_for(std::chrono::seconds(2));
std::string result = "Data_for_" + std::to_string(inputValue);
// IMPORTANT: Instead of running the callback here (in the background thread),
// we post it back to the dispatcher so it runs on the Main Thread.
g_dispatcher.post([callback, result]() {
callback(result);
});
}).detach();
}
// =================================================================
// 3. SEARCH COMPONENT
// Handles the core logic: capturing input and validating responses.
// =================================================================
class SearchComponent {
int m_latestValue = -1; // State: holds the most recent input from the user
public:
void onUserInput(int newValue) {
m_latestValue = newValue;
std::cout
Подробнее здесь: https://stackoverflow.com/questions/798 ... rizability
Правда ли, что только один поток может гарантировать линеаризуемость? ⇐ C++
Программы на C++. Форум разработчиков
1767419328
Anonymous
Рассмотрим этот пример:
#include
#include
#include
int main() {
std::atomic key;
auto t1 = std::thread([&]() {
auto now = std::chrono::steady_clock::now();
auto duration = now.time_since_epoch();
auto seconds =
std::chrono::duration_cast(duration).count();
key.store(seconds); // #1 occurred at timepoint `T1`
});
auto t2 = std::thread([&]() {
auto now = std::chrono::steady_clock::now();
auto duration = now.time_since_epoch();
auto seconds =
std::chrono::duration_cast(duration).count();
key.store(seconds); // #2 occurred at timepoint `T2`
});
auto t3 = std::thread([&]() {
std::this_thread::sleep_for(std::chrono::milliseconds(300)); // debounce
auto search_key = key.load(); // #3 occurred at timepoint `T3`
// request(search_key);
});
t1.join();
t2.join();
t3.join();
}
Предполагая, что каждый ввод пользователя будет создавать поток и вычислять ввод пользователя для создания ключа поиска, а затем записывать его в ключ, существует поток для чтения ввода пользователя и выполнения сетевого запроса для загруженного ключа. Чтобы избежать частых сетевых запросов во время ввода пользователя, в потоке поиска также предусмотрен механизм устранения дребезга.
В этом примере он моделирует два таких события ввода пользователя, а именно t1 и t2. Предполагается, что каждое событие произошло в момент времени, указанный в комментарии, и T1 < T2 < T3. Несмотря на то, что каждая атомарная операция использует seq_cst и формирует единый общий порядок, а моменты времени T1 и T2 предшествуют T3, #3 все равно может загрузить #1 и упорядочить по связности до #2.
Это не линеаризуемость, поскольку T1 < T2 < T3 и загрузка в T3 не прочитали хранилище, которое произошло в T2. (Я не уверен, можно ли назвать согласованность на временной шкале линеаризуемостью).
Итак, с точки зрения стандарта C++, правда ли, что только один поток может гарантировать линеаризуемость? То есть операция загрузки гарантированно всегда считывает хранилище, которое произошло ближе всего к временной шкале до того, как произошла операция загрузки.
Пример обновления
#include
#include
#include
int main() {
std::atomic key;
auto t3 = std::thread([&]() {
std::this_thread::sleep_for(std::chrono::milliseconds(300)); // debounce
auto search_key = key.load(); // C
// request(search_key);
if(search_key==key.load()){ // D
// use the response
}
});
key.store(1); // A first input
key.store(2); // B second input
t3.join();
}
A и B обозначают двойной быстрый ввод пользователя, очевидно, B обозначает последний ввод пользователя, C пытается прочитать последний ввод пользователя после времени устранения дребезга и выполнить сетевой запрос в потоке t3. C не гарантируется чтение из B в соответствии со стандартом C++.
В полном случае создается задача поиска для каждого ввода пользователя и отбрасывается ответ, если значение изменилось, чтобы смоделировать то, что происходит в javascript
#include
#include
#include
#include
#include
#include
#include
#include
// =================================================================
// 1. TASK DISPATCHER (The "Event Loop")
// This class mimics the JavaScript Task Queue. It allows background
// threads to "post" work back to the main thread for execution.
// =================================================================
class Dispatcher {
std::queue tasks;
std::mutex mtx;
public:
// Pushes a function into the queue. Safe to call from any thread.
void post(std::function task) {
std::lock_guard lock(mtx);
tasks.push(task);
}
// Executes all pending tasks. Should be called by the Main Thread.
void processEvents() {
std::queue toExecute;
{
// Swap content to minimize lock time (prevents blocking posters)
std::lock_guard lock(mtx);
std::swap(toExecute, tasks);
}
while (!toExecute.empty()) {
toExecute.front()(); // Execute the callback
toExecute.pop();
}
}
};
Dispatcher g_dispatcher; // Global dispatcher acting as our event loop
// =================================================================
// 2. MOCK NETWORK FUNCTION
// Simulates an asynchronous network request.
// =================================================================
void fetchNetworkData(int inputValue, std::function callback) {
// Start a background thread to simulate network latency
std::thread([inputValue, callback]() {
// Simulate a 2-second delay
std::this_thread::sleep_for(std::chrono::seconds(2));
std::string result = "Data_for_" + std::to_string(inputValue);
// IMPORTANT: Instead of running the callback here (in the background thread),
// we post it back to the dispatcher so it runs on the Main Thread.
g_dispatcher.post([callback, result]() {
callback(result);
});
}).detach();
}
// =================================================================
// 3. SEARCH COMPONENT
// Handles the core logic: capturing input and validating responses.
// =================================================================
class SearchComponent {
int m_latestValue = -1; // State: holds the most recent input from the user
public:
void onUserInput(int newValue) {
m_latestValue = newValue;
std::cout
Подробнее здесь: [url]https://stackoverflow.com/questions/79857222/is-it-true-that-only-a-single-thread-can-guarantee-the-linearizability[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия