int main(int argc, char *argv[]) {

 int opt, val;

 while ((opt = getopt(argc, argv, 'n,v')) != -1) {

  switch (opt) {

   case 'n':

   if (sscanf(optarg, '%i', &val) != 1)

    cout << 'parse command line error' << endl, exit(EXIT_FAILURE);

   if (val > 0) N = val;

   break;

  case 'v':

   debug = true;

   break;

  default:

   exit(EXIT_FAILURE);

  }

 }

 if (debug) str = new char[2 * N + 1];

 const int T = 2;

 pthread_t tid[T];

 if (pthread_barrier_init(&bstart, NULL, T) != EOK)

  perror('barrier init'), exit(EXIT_FAILURE);

 for (int i = 0; i < T; i++)

  if (pthread_create(tid + i, NULL, threadfunc, NULL) != EOK)

   perror('thread create'), exit(EXIT_FAILURE);

 for (int i = 0; i < T; i++)

  pthread_join(tid[i], NULL);

 if (debug) {

  str[ind] = '';

  cout << str << endl;

  delete [] str;

 }

 exit(EXIT_SUCCESS);

}

Результаты выполнения этого теста:

# sy20m -n100000

3       : cycles - 14644442, on mutex - 146

2       : cycles - 14614219; on mutex - 146

# sy20m -n1000000

3       : cycles - 146505047; on mutex - 146

2       : cycles - 146388673; on mutex - 146

Модифицируем программу, используя вместо мьютекса неименованный бинарный семафор. Для того чтобы не загромождать текст практически тем же кодом, перечислим только необходимые при этом изменения (файл sy20s.cc):

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

static sem_t sem;

...

if (sem_init(&sem, 0, 1) != 0)

 perror('semaphore init'), exit(EXIT_FAILURE);

2. Функция потока принимает вид:

void* threadfunc(void* data) {

 ...

 while (i++ != N) {

  t1 = ClockCycles();

  sem_wait(&sem);

  if (debug) str[ind++] = *tid;

  sem_post(&sem);

  t += ClockCycles() - t1;

  sched_yield();

 }

 ...

}

В результате исполнения на этот раз мы получим:

# sy20s -n100000

3       : cycles - 87048886; on semaphore - 870

2       : cycles - 87077787; on semaphore - 870

# sy20s -n1000000

3       : cycles - 869638168; on semaphore — 869

2       : cycles - 868725494, on semaphore - 868

Делаем последнюю модификацию в этой группе тестов, теперь используем специфику именованного семафора (файл sy20n.cc):

1. Вместо оператора динамической инициализации неименованного семафора мы теперь должны создать именованный семафор:

static sem_t* sem;

...

const char semname[] = '/duble';

if ((sem = sem_open(semname, O_CREAT, S_IRWX0, 1)) == SEM_FAILED)

 perror('semaphore init'), exit(EXIT_FAILURE);

Примечание

Последний оператор заслуживает отдельного комментария. Техническая документация утверждает, что функция sem_open(), нормально возвращающая указатель созданного дескриптора семафора типа sem_t, в случае ошибки возвращает -1 (так было записано и в самых ранних редакциях POSIX). Но использование конструкции вида:

if (sem_open( ... ) == -1)

просто вызовет синтаксическую ошибку (несоответствие типов) и не пройдет компиляцию! Естественнее было бы для такой функции возвращать NULL в случае ошибки, но... так определено в POSIX. Кроме того, во многих реализациях UNIX определяется константа:

#define SEM_FAILED ((sem_t*)(-1))

В документации QNX она нигде не упоминается, но, как мы видим, она определена, и все прекрасно работает!

2. Функция потока принимает вид (теперь sem, в отличие от предшествующего случая, ведь теперь это уже указатель на переменную типа sem_t):

void* threadfunc(void* data) {

 ...

 while (i++ != N) {

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату