Как распечатать pthread_t

В зависимости от того, как Вы кодируете, Вы можете видеть, что производительность увеличивается. Для фона я - также давний пользователь энергии, но я изучил emacs приблизительно 2 года назад, и теперь используйте их попеременно.

то, Что управляло мной на грани фактического изучения emacs, было его полезной способностью иметь большое количество файлов, открытых сразу и легко переключиться между ними. Я был посреди представления функции, которая добавила и коснулась большого количества классов. (Это было C++, таким образом, обычно было два файла в классе.), Так как я все еще уплотнял интерфейс, я обычно буду посреди обновления одного файла, когда я понял бы, что должен был изменить другого.

С gvim, было самым легким открыть новое окно для каждого файла, который начинал становиться громоздким. С Emacs, тем не менее, было просто открыть новый файл в том же окне (Ctrl-x, Ctrl-f). Как только Emacs имеет открытый файл, очень легко переключиться назад и вперед между открытыми буферами (Ctrl-x, Ctrl-b).

Взятие, что один шаг вперед, единственная emacs сессия может открыть много окон, таким образом, в дополнение к разделению окна вертикально, я мог решить, не прерывая работу над файлом, для открытия другого рядом с ним, позволив мне эффективно работать бок о бок, все еще сохраняя каждое окно в 80 ширине символов по умолчанию.

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

, Если бы Вы все еще не уверены, я предложил бы испытать его. Пробегите учебное руководство Emacs и затем используйте его для записи кода в течение утра или дня, склоняясь в большой степени на справке. Если Вам все еще не нравится то, что Вы видите, остаетесь с энергией. Независимо от того, что редактор приносит к таблице, Ваше знакомство и знание инструмента безусловно будут наиболее важным фактором в Вашей производительности.

50
задан Roman Nikitchenko 8 July 2013 в 22:36
поделиться

7 ответов

Это распечатает шестнадцатеричное представление pthread_t , независимо от того, что это на самом деле:

void fprintPt(FILE *f, pthread_t pt) {
  unsigned char *ptc = (unsigned char*)(void*)(&pt);
  fprintf(f, "0x");
  for (size_t i=0; i<sizeof(pt); i++) {
    fprintf(f, "%02x", (unsigned)(ptc[i]));
  }
}

Чтобы просто напечатать небольшой идентификатор для каждого pthread_t , что-то вроде этого может (на этот раз с использованием iostreams):

void printPt(std::ostream &strm, pthread_t pt) {
  static int nextindex = 0;
  static std::map<pthread_t, int> ids;
  if (ids.find(pt) == ids.end()) {
    ids[pt] = nextindex++;
  }
  strm << ids[pt];
}

В зависимости от платформы и фактического представления pthread_t здесь может потребоваться определение оператора < для pthread_t , потому что std :: map требует упорядочения элементов:

bool operator<(const pthread_t &left, const pthread_t &right) {
  ...
}
34
ответ дан 7 November 2019 в 10:53
поделиться

GDB использует идентификатор потока (он же идентификатор ядра, он же LWP) для коротких номеров в Linux. Попробуйте:

  #include <syscall.h>
  ...

    printf("tid = %d\n", syscall(SYS_gettid));
24
ответ дан 7 November 2019 в 10:53
поделиться

Хорошо, кажется, это мой окончательный ответ. У нас есть 2 актуальные проблемы:

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

1. Распечатать идентификатор POSIX (pthread_t)

Вы можете просто рассматривать pthread_t как массив байтов с шестнадцатеричными цифрами, напечатанными для каждого байта. Таким образом, вы не ограничены каким-то фиксированным размером. Единственная проблема - это порядок байтов. Вам, вероятно, понравится, если порядок ваших печатаемых байтов такой же, как и для простого напечатанного int. Вот пример прямого порядка байтов, и только порядок должен быть изменен (ниже определения?) Для прямого порядка байтов:

#include <pthread.h>
#include <stdio.h>

void print_thread_id(pthread_t id)
{
    size_t i;
    for (i = sizeof(i); i; --i)
        printf("%02x", *(((unsigned char*) &id) + i - 1));
}

int main()
{
    pthread_t id = pthread_self();

    printf("%08x\n", id);
    print_thread_id(id);

    return 0;
}

2. Получите более короткий печатаемый идентификатор потока

В любом из предложенных случаев вы должны преобразовать реальный идентификатор потока (posix) в индекс некоторой таблицы. Но есть 2 существенно разных подхода:

2.1. Отслеживание потоков.

Вы можете отслеживать идентификаторы потоков всех существующих потоков в таблице (их вызовы pthread_create () должны быть обернуты) и иметь «перегруженную» функцию идентификатора, которая дает вам только индекс таблицы, а не реальный идентификатор потока. Эта схема также очень полезна для любой внутренней отладки, связанной с потоками, и отслеживания ресурсов. Очевидным преимуществом является побочный эффект средства трассировки / отладки на уровне потоков с возможным расширением в будущем. Недостатком является требование отслеживать создание / уничтожение любого потока.

Вот пример частичного псевдокода:

pthread_create_wrapper(...)
{
   id = pthread_create(...)
   add_thread(id);
}

pthread_destruction_wrapper()
{
   /* Main problem is it should be called.
      pthread_cleanup_*() calls are possible solution. */
   remove_thread(pthread_self());
}

unsigned thread_id(pthread_t known_pthread_id)
{
  return seatch_thread_index(known_pthread_id);
}

/* user code */
printf("04x", thread_id(pthread_self()));

2.2. Если поток с таким идентификатором был создан, используется его индекс (или повторно используется из предыдущего потока, на самом деле это не имеет значения, поскольку нет двух одинаковых идентификаторов для одного и того же момента). Если идентификатор потока еще не известен, создается новая запись, поэтому создается / используется новый индекс.

Преимущество - простота. Недостаток - отсутствие отслеживания создания / уничтожения потоков. Поэтому для отслеживания этого требуется некоторая внешняя механика.

7
ответ дан 7 November 2019 в 10:53
поделиться

Вы можете сделать что-то вроде этого:

int thread_counter = 0;
pthread_mutex_t thread_counter_lock = PTHREAD_MUTEX_INITIALIZER;

int new_thread_id() {
    int rv;
    pthread_mutex_lock(&thread_counter_lock);
    rv = ++thread_counter;
    pthread_mutex_unlock(&thread_counter_lock);
    return rv;
}

static void *threadproc(void *data) {
    int thread_id = new_thread_id();
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

Если вы можете полагаться на наличие GCC (clang также работает в этом случае), вы также можете сделать это:

int thread_counter = 0;

static void *threadproc(void *data) {
    int thread_id = __sync_add_and_fetch(&thread_counter, 1);
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

Если ваша платформа поддерживает это , аналогичный вариант:

int thread_counter = 0;
int __thread thread_id = 0;

static void *threadproc(void *data) {
    thread_id = __sync_add_and_fetch(&thread_counter, 1);
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

Это имеет то преимущество, что вам не нужно передавать thread_id в вызовах функций, но он не работает, например, в Mac OS.

3
ответ дан 7 November 2019 в 10:53
поделиться

Вы можете попробовать преобразовать его в беззнаковый короткий, а затем вывести только последние четыре шестнадцатеричные цифры. Полученное значение может быть достаточно уникальным для ваших нужд.

1
ответ дан 7 November 2019 в 10:53
поделиться

В этом случае это зависит от операционной системы, поскольку стандарт POSIX больше не требует, чтобы pthread_t был арифметическим типом :

IEEE Std 1003.1-2001 / Cor 2-2004, применяется элемент XBD / TC2 / D6 / 26, добавляющий pthread_t в список типов, которые не обязательно должны быть арифметическими типами, таким образом позволяя определить pthread_t как структуру.

Вам нужно будет заглянуть в заголовок sys / types.h и увидеть, как реализован pthread_t ; затем вы можете распечатать его так, как считаете нужным. Поскольку нет портативного способа сделать это, и вы не говорите, какую операционную систему вы используете, особо нечего сказать.

Изменить: , чтобы ответить на ваш новый вопрос, GDB присваивает свои собственные идентификаторы потока каждый раз, когда запускается новый поток :

В целях отладки GDB связывает свой собственный номер потока - всегда одно целое число - с каждым потоком в вашей программе.

Если вы хотите напечатать уникальный номер внутри каждого потока, самым лучшим вариантом будет, вероятно, указать каждому потоку, какой номер использовать при запуске.

16
ответ дан 7 November 2019 в 10:53
поделиться

В Centos 5.4 x86_64 pthread_t является typedef для беззнакового long.

Следовательно, мы могли бы сделать это ...

#include <iostream>
#include <pthread.h>

int main() {
    pthread_t x;
    printf("%li\n", (unsigned long int) x);
    std::cout << (unsigned long int) x << "\n";
}
4
ответ дан 7 November 2019 в 10:53
поделиться