2015-01-30 4 views
1

Я пишу часть кода C для Node.js и хочу отличить синхронные от асинхронных вызовов. Другими словами, я хочу определить, работает ли мой код в потоке отправки событий V8, вызванном из цикла основного события или вызван ли он из некоторого отдельного рабочего потока. В первом случае я мог сразу перезвонить JavaScript, а в последнем мне пришлось бы использовать более сложный асинхронный обратный вызов.Определить, является ли текущий поток основным потоком цикла событий libuv по умолчанию

libuv threading API предоставляет uv_thread_self для идентификации текущей темы и uv_thread_equal для сравнения тем для равенства. Поэтому мне нужно найти uv_thread_t основного цикла событий.

+0

Я запутался, как это возможно, чтобы иметь код, который не знает, что нить его пробежал. Любой обратный вызов будет запускаться в том же потоке, что и в очереди, и libuv не является потокобезопасным, так что вы не можете ставить очередь обратных вызовов из потока, который не является потоком цикла событий. –

+0

Я работаю над функциями расширения libxslt (https://github.com/albanm/node-libxslt/issues/2). Поэтому я пишу C-код, который будет зарегистрирован в глобальной структуре данных библиотеки XSLT и который будет вызываться из XSLT-процессора, который, в свою очередь, может быть вызван синхронно или асинхронно. Моя лучшая ставка на данный момент заключается в сохранении результата из 'uv_thread_self' в момент регистрации функции, предполагая, что это всегда будет поток основного события цикла. Но мне все еще интересно, есть ли что-то более элегантное, чем это. – MvG

ответ

1

Я полагаю, его так же легко, как захватывая uv_thread_self() из v8 нити инициализации модуля (как вы упомянули, вы используете node.js)? Этот код инициализации модуля должен запускаться из основного потока v8, так как это require() 'd из пакета Javascript вашей библиотеки.

uv_thread_t main_thread; 

extern "C" void init(Handle<Object> target, Handle<Object> module) { 

    Nan::HandleScope scope; 

    main_thread = uv_thread_self(); 

, то вы можете использовать uv_thread_equal, чтобы определить, является ли код выполняется в главном потоке или нет:

void ozw_watcher_callback(OpenZWave::Notification const *cb, void *ctx) 
// =================================================================== 
{ 
    uv_thread_t this_thread = uv_thread_self(); 
    std::cout << "~~~~ ozw_watcher_callback : main thread? " << (uv_thread_equal(&main_thread, &this_thread)) << "\n"; 
0

В Linux (и, возможно, MacOS и Solaris), вы могли бы посмотреть на backtrace():

backtrace() возвращает трассировку для вызывающей программы, в массиве , на которую указывает buffer. Backtrace - это серия активных активных вызовов для программы.

и это друг, backtrace_symbols():

Учитывая набор адресов, возвращаемый backtrace() в буфере, backtrace_symbols() переводит адреса в массив строк , описывающих адреса символически. Аргумент size указывает количество адресов в буфере. Символическое представление каждого адреса состоит из имени функции (если это может быть определено), шестнадцатеричного смещения в функции и фактического адреса возврата (в шестнадцатеричном формате).

http://linux.die.net/man/3/backtrace

В Windows я думаю, следующий вопрос показывает, как добиться подобного: http://bewitchingkitchen.com/2010/01/30/slow-roasted-chicken-thighs-an-ice-breaker/

+0

Спасибо за этот ответ. Я все еще надеюсь на что-то более портативное. – MvG

+0

Я также нашел ответ на аналогичный вопрос для Windows: http://stackoverflow.com/questions/5693192/win32-backtrace-from-c-code - и я думаю, что 'backtrace' также может быть доступен на MacOS и Solaris. – Squirrel