try_lock in that way on GitHub; you won't find code like this. No
one uses try_lock.
Am 29.09.2024 um 11:01 schrieb [email protected]:
On Sun, 29 Sep 2024 08:15:23 +0200
Bonita Montero <[email protected]> boringly babbled:
try_lock in that way on GitHub; you won't find code like this. No
one uses try_lock.
Translation: "I don't use try_lock"
Tell me under which circumstances the mentioned two constraints
don't matter.
On 9/28/2024 12:53 AM, Paavo Helde wrote:
Nice! Thanks for taking the time to give it a go Paavo. Basically, the
main "pattern" is in the ct_shared::work_a_lock() function: >_____________________
void work_a_lock()
{
while (! m_lock_a.try_lock())
{
if (! work_b_try(1))
{
m_lock_a.lock();
break;
}
}
}
_____________________
This is just a quick test of my try_lock pattern thing. ct_shared::m_b
counts how many times extra work was able to be done instead of spinning
on the ct_shared::m_lock_a mutex. Take careful notice of the ct_shared::work_a_lock() function.
Can you test it out? A large number for ct_shared::m_b is ideal. It
means extra work was being done. Avoids spinning in an interesting way.
my crude code, can you compile and run it okay? Thanks: _________________________
#include <cassert>
#include <iostream>
#include <atomic>
#include <mutex>
#include <functional>
#include <thread>
#define CT_THREADS 10
#define CT_ITERS 1000000
// Test Threads...
struct ct_shared
{
long m_a;
unsigned long m_b;
std::mutex m_lock_a;
std::mutex m_lock_b;
ct_shared() : m_a(0), m_b(0) {}
bool work_b_try(unsigned long addend)
{
if (! m_lock_b.try_lock())
{
return false;
}
{
m_b += addend;
}
m_lock_b.unlock();
return true;
}
// The main pattern...
void work_a_lock()
{
while (! m_lock_a.try_lock())
{
if (! work_b_try(1))
{
m_lock_a.lock();
break;
}
}
}
void work_a_unlock()
{
m_lock_a.unlock();
}
void work_a(long addend)
{
work_a_lock();
{
m_a += addend;
}
work_a_unlock();
}
};
// Test out a pattern...
void
ct_thread(
ct_shared& shared
) {
for (unsigned long i = 0; i < CT_ITERS; ++i)
{
shared.work_a(1);
std::this_thread::yield();
shared.work_a(-1);
}
}
// Get things going...
int
main()
{
std::cout << "ct try_lock pattern Test...\n\n";
{
ct_shared shared;
std::thread threads[CT_THREADS];
// Create threads...
std::cout << "launching threads..." << std::endl;
for (unsigned long i = 0; i < CT_THREADS; ++i)
{
threads[i] = std::thread(ct_thread, std::ref(shared));
}
std::cout << "processing...\n" << std::endl;
// Join threads...
for (unsigned long i = 0; i < CT_THREADS; ++i)
{
threads[i].join();
}
// Sanity check...
{
std::cout << "shared.m_a = " << shared.m_a << "\n";
std::cout << "shared.m_b = " << shared.m_b << "\n";
if (shared.m_a != 0)
{
std::cout << "\n\nAAHHHH SHHHIIITT!!\n";
}
}
}
std::cout << "\nct try_lock pattern Test completed.\n\n";
return 0;
}
_________________________
What results do you get for ct_shared::m_b? Here is a result I get: _____________________________
ct try_lock pattern Test...
launching threads...
processing...
shared.m_a = 0
shared.m_b = 8664093
ct try_lock pattern Test completed.
_____________________________
Well, shared.m_b is a high number... That is a lot potential kernel
calls that were skipped in favor of real work.
Any thoughts? Thanks.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (0 / 16) |
| Uptime: | 167:21:40 |
| Calls: | 12,096 |
| Calls today: | 4 |
| Files: | 15,003 |
| Messages: | 6,517,812 |