Re[5]: внутренняя реализация std::mutex?
От: barney  
Дата: 17.05.18 10:24
Оценка:
N>Именно. И если CF=0, то надо не идти на цикл, а считать действие lock завершённым. Поэтому jc должно идти на цикл, а противоположность (прямой ход исполнения или jnc) — выходить из цикла.
N>Но дальше второе — чтобы не задрочить кэш, шины и всю систему постоянными попытками записи, если bts или аналог сорвались, снова идут на циклическое чтение, в ожидании, пока не появится 0.

Вот сделал без ассемблера, с std::atomic_flag по стопам приведенной тут в ссылках статьи

#include <iostream>
#include <thread>
#include <atomic>

class SpinLock
{
public:
    void lock()
    {
        while(lck.test_and_set(std::memory_order_acquire))
        {}
    }
    
    void unlock()
    {
        lck.clear(std::memory_order_release);
    }
    
private:
    std::atomic_flag lck = ATOMIC_FLAG_INIT;
};

//int mutex = 0;
SpinLock lock;

inline void Lock(int * flag) {
    
    int spins_count = 0;
    
//    __asm {
//    outer:
//        mov rbx,flag
//        mov eax,[rbx]
//        cmp eax,0
//        jne outer
//
//        xor ecx,ecx
//        xor eax, eax
//        mov rbx,flag
//    loop:
//        inc ecx
//        lock bts [rbx], eax   // lock + bts atomic test-and-set
//        jnc loop
//        mov spins_count,ecx
//    }
    
    lock.lock();
    
    // locked
    std::cout << "\nINSIDE_THE_LOCK:" << spins_count << "\n";
    
    lock.unlock();

//    __asm {
//        mov rbx,flag
//        xor eax,eax
//        mov [rbx],eax
//    }
}

void spinner(char * id) {
    while (true) {
        Lock(&mutex);
        // not locked
        std::cout << "·" << "SPINNER:" << id << "·";
    }
}

int main() {
    
    char * Q = "Q";
    char * W = "W";
    
    std::thread t1(spinner, Q);
    std::thread t2(spinner, W);
    
    while (true) {
        // not locked
        std::cout << "•";
    }
}



Все равно SPINNER разрывает вывод inside the lock
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.