2015-03-03 1 views
0

Я использую libcurl с OpenSSL в многопоточной программе. На основе любезного ответа от Daniel Стенберг и примерыМногопоточность OpenSSL

Я попытался следующий код:

static std::mutex* aMutex; 

void locking_function(int mode, int n, const char* file, int line) 
{ 
    if(mode & CRYPTO_LOCK){ 
     std::cout << "Mutex locking\n"; 
     aMutex[n].lock(); 
    } 
    else{ 
     std::cout << "Mutex unlocking\n"; 
     aMutex[n].unlock(); 
    } 
} 

unsigned long id_function() 
{ 
    return (unsigned long)std::hash<std::thread::id>() (std::this_thread::get_id()); 
} 

int thread_setup() 
{ 
    aMutex = new std::mutex[CRYPTO_num_locks()]; 
    if(!aMutex) 
     return 0; 
    else{ 
     CRYPTO_set_id_callback(id_function); 
     CRYPTO_set_locking_callback(locking_function); 
    } 
    return 1; 
} 

int thread_cleanup() 
{ 
    if(!aMutex) 
     return 0; 

    CRYPTO_set_id_callback(NULL); 
    CRYPTO_set_locking_callback(NULL); 
    delete[] aMutex; 
    aMutex = NULL; 
    return 1; 
} 

Так что обеспечить блокировку функции, функции идентификатора потока и пусть функция блокировки использует глобальный массив мьютексов.

Предложения «Блокировка Mutex» и «Разблокировка Mutex» (которые печатаются в функции lock_function) печатаются снова и снова очень быстро. Когда я уничтожаю ручку CURL, она останавливается. Это нормально/правильно?

Я называю

thread_setup 

когда мой запуск приложения и

thread_cleanup 

при завершении приложения.

Спасибо за любую помощь.

ответ

0
The sentences "Mutex locking" and "Mutex unlocking" (which are printed in the locking_function) gets printed over and over really fast. 

блокировки мьютекса/разблокировки используются для обеспечения только один поток получает доступ к критической секции в одно время (именно поэтому его называют взаимное исключение). В многопоточной программе, где вы используете массив мьютексов и используете те же методы для их блокировки/разблокировки, эти два, которые я ожидаю, будут вызваны много раз. Кроме того, выполнение критического раздела обычно выполняется быстро (несколько строк кода).

Так, чтобы дать вам прямой ответ, да, то, что вы видите, это нормально

+0

Спасибо! У меня есть достойное понимание мьютексов и многопоточности в целом, но очень мало опыта работы с OpenSSL и libcurl, поэтому на самом деле не знаю, какое поведение ожидать от OpenSSL. – jensa

0

Пожалуйста, обратите внимание, что на некоторых платформах этот код может иметь ошибку:

(unsigned long)std::hash<std::thread::id>() (std::this_thread::get_id()); 

std::hash() возвращается size_t и вы разыгрываете это до unsigned long. На платформе Win-64 size_t - 64 бит, а unsigned long - 32 бит.

+0

Даже больше - std :: hassh не гарантирует отсутствие столкновений - он может возвращать одно и то же значение для двух разных значений 'thread_id', потенциально вызывающих UB. –