Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«QNX/UNIX: Анатомия ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌΠ°Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 15

Автор ОлСг Π¦ΠΈΠ»ΡŽΡ€ΠΈΠΊ

POSIX.1 Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ Π² Π½Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π±Ρ‹Π»ΠΈ максимально бСзопасными Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС. Но ΠΏΠ΅Ρ€Π΅Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° всСх Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ - Ρ‚Ρ€ΡƒΠ΄ΠΎΠ΅ΠΌΠΊΠΈΠΉ ΠΈ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ процСсс. API QNX (ΠΈ Ρ‚Π°ΠΊ поступили ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΠΈ ΠΌΠ½ΠΎΠ³ΠΈΡ… POSIX-совмСстимых ОБ) для ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ нСбСзопасных Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π²Π²Π΅Π»ΠΈ ΠΈΡ… эквивалСнты, ΠΎΡ‚Π»ΠΈΡ‡Π°ΡŽΡ‰ΠΈΠ΅ΡΡ суффиксом Β«_rΒ», Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€: localtime() β€” localtime_r(), rand() β€” rand_r() ΠΈ Ρ‚.Π΄. ΠŸΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΈΠ°Π»ΡŒΠ½ΠΎ нСбСзопасна Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС ΠΎΠ΄Π½Π° ΠΈΠ· самых Β«Π»ΡŽΠ±ΠΈΠΌΡ‹Ρ…Β» Π² UNIX функция β€” select().

БобствСнныС Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠ°

Описанной Π²Ρ‹ΡˆΠ΅ схСмС ΠΎΠ±Ρ‰ΠΈΡ… Π΄Π°Π½Π½Ρ‹Ρ… прилоТСния ΠΈ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°, достаточных для Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π° Β«ΠΎΡ€Π΄ΠΈΠ½Π°Ρ€Π½Ρ‹Ρ…Β» ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, всС-Ρ‚Π°ΠΊΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎ Π½Π΅ Ρ…Π²Π°Ρ‚Π°Π΅Ρ‚ гибкости, ΠΏΠΎΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ всС потрСбности. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π² Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡΡ… POSIX Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ вводится Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ спСцифичный ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ создания ΠΈ манипулирования с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅ β€” собствСнныС Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠ° (thread-specific data). ИспользованиС собствСнных Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ° β€” самый простой ΠΈ эффСктивный способ манипулирования Π΄Π°Π½Π½Ρ‹ΠΌΠΈ, прСдставлСнными ΠΈΠ½Π΄ΠΈΠ²ΠΈΠ΄ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ экзСмплярами Π΄Π°Π½Π½Ρ‹Ρ… для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°.

Богласно POSIX опСрационная систСма Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½ΠΎΠ΅ количСство ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² собствСнных Π΄Π°Π½Π½Ρ‹Ρ… (POSIX.1 Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ этот ΠΏΡ€Π΅Π΄Π΅Π» Π½Π΅ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ°Π» 128 ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π½Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ процСсс). Π―Π΄Ρ€ΠΎΠΌ систСмы поддСрТиваСтся массив ΠΈΠ· этого количСства ΠΊΠ»ΡŽΡ‡Π΅ΠΉ (Ρ‚ΠΈΠΏ pthread_key_t; это абстрактный Ρ‚ΠΈΠΏ, ΠΈ стандарт прСдписываСт Π½Π΅ Π°ΡΡΠΎΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π³ΠΎ с Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ, Π½ΠΎ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎ это нСбольшиС Ρ†Π΅Π»Ρ‹Π΅ значСния, ΠΈ Π² Ρ‚Π°ΠΊΠΎΠΌ Π²ΠΈΠ΄Π΅ вся схСма Π³ΠΎΡ€Π°Π·Π΄ΠΎ ΠΏΡ€ΠΎΡ‰Π΅ для понимания). ΠšΠ°ΠΆΠ΄ΠΎΠΌΡƒ ΠΊΠ»ΡŽΡ‡Ρƒ сопоставлСн Ρ„Π»Π°Π³, ΠΎΡ‚ΠΌΠ΅Ρ‡Π°ΡŽΡ‰ΠΈΠΉ, занят этот ΠΊΠ»ΡŽΡ‡ ΠΈΠ»ΠΈ свободСн, Π½ΠΎ это Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠ΅ Π΄Π΅Ρ‚Π°Π»ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, Π½Π΅ доступныС программисту. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, ΠΏΡ€ΠΈ создании ΠΊΠ»ΡŽΡ‡Π° с Π½ΠΈΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ связан адрСс Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ дСструктора, которая Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈ ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ΅Π½ΠΈΠΈ Π΅Π³ΠΎ экзСмпляра Π΄Π°Π½Π½Ρ‹Ρ… (рис. 2.4).

Рис. 2.4. ΠšΠ»ΡŽΡ‡ΠΈ экзСмпляров Π΄Π°Π½Π½Ρ‹Ρ…

Когда ΠΏΠΎΡ‚ΠΎΠΊ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ pthread_key_create() для создания Π½ΠΎΠ²ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° собствСнных Π΄Π°Π½Π½Ρ‹Ρ…, систСма разыскиваСт ΠΏΠ΅Ρ€Π²ΠΎΠ΅ нСзанятоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠ»ΡŽΡ‡Π° ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π΅Π³ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (0...127). Для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° процСсса (Π² составС описатСля ΠΏΠΎΡ‚ΠΎΠΊΠ°) хранится массив ΠΈΠ· 128 ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ (void*) Π±Π»ΠΎΠΊΠΎΠ² собствСнных Π΄Π°Π½Π½Ρ‹Ρ…, ΠΈ ΠΏΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠΌΡƒ ΠΊΠ»ΡŽΡ‡Ρƒ ΠΏΠΎΡ‚ΠΎΠΊ, индСксируя этот массив, ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ доступ ΠΊ своСму экзСмпляру Π΄Π°Π½Π½Ρ‹Ρ…, ассоциированных со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠ»ΡŽΡ‡Π°. ΠΠ°Ρ‡Π°Π»ΡŒΠ½Ρ‹Π΅ значСния всСх ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ Π±Π»ΠΎΠΊΠΎΠ² Π΄Π°Π½Π½Ρ‹Ρ… - NULL, Π° фактичСскоС Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΈ освобоТдСниС Π±Π»ΠΎΠΊΠΎΠ² Π΄Π°Π½Π½Ρ‹Ρ… выполняСт ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠ°Ρ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° (рис. 2.5).

Рис. 2.5. ΠŸΠΎΡ‚ΠΎΠΊ ΠΈ Π΅Π³ΠΎ собствСнныС Π΄Π°Π½Π½Ρ‹Π΅

На рис. 2.5 прСдставлСн массив структур, создаваСмый Π² Π΅Π΄ΠΈΠ½ΠΈΡ‡Π½ΠΎΠΌ экзСмплярС для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ процСсса Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт ΠΊΠ»ΡŽΡ‡Π° Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ pthread_key_create() (ΠΎΠ΄Π½ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎ для всСго процСсса). ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ элСмСнт массива опрСдСляСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Π΅Π΄ΠΈΠ½ΠΎΠ³ΠΎ класса Π²ΠΎ всСх ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΡ… ΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠ°Ρ…, поэтому для Π½ΠΈΡ… здСсь ΠΆΠ΅ опрСдСляСтся дСструктор (это Π² Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΎΠ»ΠΎΠ³ΠΈΠΈ языка Π‘!). ДСструктор β€” Π΅Π΄ΠΈΠ½Ρ‹ΠΉ для экзСмпляров Π΄Π°Π½Π½Ρ‹Ρ… Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅. Π”Π°ΠΆΠ΅ для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π° Π² качСствС дСструктора ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΡƒΠΊΠ°Π·Π°Π½ NULL, ΠΏΡ€ΠΈ этом Π½ΠΈΠΊΠ°ΠΊΠΈΠ΅ дСструктивныС дСйствия ΠΏΡ€ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π½Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ.

ПослС размСщСния Π±Π»ΠΎΠΊΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π²Ρ‹Π·ΠΎΠ² pthread_setspecific(). Для связывания адрСса своСго экзСмпляра Π΄Π°Π½Π½Ρ‹Ρ… с элСмСнтом массива ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ, индСксируСмого ΠΊΠ»ΡŽΡ‡ΠΎΠΌ. Π’ дальнСйшСм ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ pthread_getspecific() для доступа ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΊ своСму экзСмпляру Π΄Π°Π½Π½Ρ‹Ρ…. Π­Ρ‚ΠΎ схСма, Π° Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ посмотрим, ΠΊΠ°ΠΊ ΠΎΠ½Π° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚.

ПолоТим, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ трСбуСтся ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ N ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ ΠΈΡΠΏΠΎΠ»Π½ΡΡŽΡ‰ΠΈΡ…ΡΡ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ‡Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² (ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΡ… Π΅Π΄ΠΈΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΏΠΎΡ‚ΠΎΠΊΠ°), ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ со своСй ΠΊΠΎΠΏΠΈΠ΅ΠΉ экзСмпляра Π΄Π°Π½Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠ° DataBlock:

class DataBlock {

 ~DataBlock() { ... }

 ...

};


void* ThreadProc(void *data) {

 // ... здСсь Π±ΡƒΠ΄Π΅Ρ‚ ΠΊΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ рассмотрим

 return NULL;

}

...

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

 pthread_create(NULL, NULL, &ThreadProc, NULL);

ΠŸΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ дСйствий ΠΏΠΎΡ‚ΠΎΠΊΠ° выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

1. ΠŸΠΎΡ‚ΠΎΠΊ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ pthread_key_create() β€” созданиС ΠΊΠ»ΡŽΡ‡Π° для доступа ΠΊ Π±Π»ΠΎΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ… DataBlock. Если ΠΏΠΎΡ‚ΠΎΠΊΡƒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΈΠΌΠ΅Ρ‚ΡŒ нСсколько (m) Π±Π»ΠΎΠΊΠΎΠ² собствСнных Π΄Π°Π½Π½Ρ‹Ρ… Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΎΠΉ Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ (ΠΈ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΎΠ³ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ назначСния): DataBlock_1, DataBlock_2 β€¦ DataBlock_m, Ρ‚ΠΎ ΠΎΠ½ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ значСния ΠΊΠ»ΡŽΡ‡Π΅ΠΉ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ число Ρ€Π°Π· для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° (m).

2. ΠΠ΅ΠΏΡ€ΠΈΡΡ‚Π½ΠΎΡΡ‚ΡŒ здСсь состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π·Π°ΠΏΡ€ΠΎΡΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠ»ΡŽΡ‡Π° для DataBlock Π΄ΠΎΠ»ΠΆΠ΅Π½ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΡ€ΠΈΡˆΠ΅Π΄ΡˆΠΈΠΉ ΠΊ этому мСсту ΠΏΠΎΡ‚ΠΎΠΊ (ΠΊΠΎΠ³Π΄Π° ΠΊΠ»ΡŽΡ‡ Π΅Ρ‰Π΅ Π½Π΅ распрСдСлСн). ΠŸΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ, Π΄ΠΎΡΡ‚ΠΈΠ³ΡˆΠΈΠ΅ этого мСста, Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Ρ€Π°Π½Π΅Π΅ распрСдСлСнным Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠ»ΡŽΡ‡Π° для Ρ‚ΠΈΠΏΠ° DataBlock. Для Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ этой слоТности Π² систСму Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ собствСнных Π΄Π°Π½Π½Ρ‹Ρ… Π²Π²Π΅Π΄Π΅Π½Π° функция pthread_once().

3. ΠŸΠΎΡΠ»Π΅ этого ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ (ΠΊΠ°ΠΊ создавший ΠΊΠ»ΡŽΡ‡, Ρ‚Π°ΠΊ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠΉ Π΅Π³ΠΎ) Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π°ΠΏΡ€ΠΎΡΠΈΡ‚ΡŒ ΠΏΠΎ pthread_getspecific() адрСс Π±Π»ΠΎΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ, ΡƒΠ±Π΅Π΄ΠΈΠ²ΡˆΠΈΡΡŒ, Ρ‡Ρ‚ΠΎ это NULL, динамичСски Ρ€Π°ΡΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΎΠ±Π»Π°ΡΡ‚ΡŒ памяти для своСго экзСмпляра Π΄Π°Π½Π½Ρ‹Ρ…, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π·Π°Ρ„ΠΈΠΊΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎ pthread_setspecific() этот адрСс Π² массивС экзСмпляров для дальнСйшСго использования.

4. Π”Π°Π»ΡŒΡˆΠ΅ ΠΏΠΎΡ‚ΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с собствСнным экзСмпляром Π΄Π°Π½Π½Ρ‹Ρ… (ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ экзСмпляр Π½Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ), ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ для доступа ΠΊ Π½Π΅ΠΌΡƒ pthread_getspecific().

5. ΠŸΡ€ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ любого ΠΏΠΎΡ‚ΠΎΠΊΠ° систСма ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠΈΡ‚ ΠΈ Π΅Π³ΠΎ экзСмпляр Π΄Π°Π½Π½Ρ‹Ρ…, Π²Ρ‹Π·Π²Π°Π² для Π½Π΅Π³ΠΎ дСструктор, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±Ρ‹Π» установлСн Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ pthread_key_create(), Π΅Π΄ΠΈΠ½Ρ‹ΠΌ для всСх экзСмпляров Π΄Π°Π½Π½Ρ‹Ρ…, ассоциированных с этим Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠ»ΡŽΡ‡Π°.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ запишСм это Π² ΠΊΠΎΠ΄Π΅, Π·Π°ΠΎΠ΄Π½ΠΎ трансформировав Π² Π½ΠΎΠ²ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ThreadProc() ΠΊΠΎΠ΄ Ρ€Π°Π½Π΅Π΅ созданной вСрсии этой ΠΆΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ SingleProc() для исполнСния Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅, Π½Π΅ ΡΠ²Π»ΡΡŽΡ‰ΠΈΠΉΡΡ Ρ€Π΅Π΅Π½Ρ‚Π΅Ρ€Π°Π±Π΅Π»ΡŒΠ½Ρ‹ΠΌ ΠΈ бСзопасным Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС. (О вопросах Ρ€Π΅Π΅Π½Ρ‚Π΅Ρ€Π°Π±Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΌΡ‹ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ ΠΏΠΎΠ·ΠΆΠ΅.)

void* SingleProc(void *data) {

 static DataBlock db( ... );

 // ... ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с полями DataBlock

 return NULL;

}

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

To, Ρ‡Ρ‚ΠΎ Ρ‚ΠΈΠΏΡ‹ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ SingleProc() Β«ΠΏΠΎΠ΄ΠΎΠ³Π½Π°Π½Ρ‹Β» ΠΏΠΎΠ΄ синтаксис Π΅Π΅ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ·Π΄Π½Π΅Π³ΠΎ эквивалСнта ThreadProc(), Π½Π΅ являСтся ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΌ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ΠΌ - Π²Ρ…ΠΎΠ΄Π½ΡƒΡŽ ΠΈ Π²Ρ‹Ρ…ΠΎΠ΄Π½ΡƒΡŽ трансформации Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ² Π΄Π°Π½Π½Ρ‹Ρ… Ρ€Π΅Π°Π»ΡŒΠ½ΠΎ ΠΎΡΡƒΡ‰Π΅ΡΡ‚Π²Π»ΡΡŽΡ‚ ΠΈΠΌΠ΅Π½Π½ΠΎ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΌ эквивалСнтС. Нам здСсь Π²Π°ΠΆΠ½ΠΎ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΈΠ°Π»ΡŒΠ½ΠΎ Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ ΠΎΠ±Ρ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΡƒΡŽ Ρ‚Π΅Ρ…Π½ΠΈΠΊΡƒ трансформации Π½Π΅Ρ€Π΅Π΅Π½Ρ‚Π΅Ρ€Π°Π±Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π° Π² Ρ€Π΅Π΅Π½Ρ‚Π΅Ρ€Π°Π±Π΅Π»ΡŒΠ½Ρ‹ΠΉ.

Π”Π°Π»Π΅Π΅ слСдуСт ΠΊΠΎΠ΄ SingleProc(), ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½Ρ‹ΠΉ Π²ΠΈΠ΄:

static pthread_key_t key;

static pthread_once_t once = PTHREAD_ONCE_INIT;


static void destructor(void* db) {

 delete (DataBlock*)db;

}


static void once_creator(void) {

 // создаСтся Π΅Π΄ΠΈΠ½Ρ‹ΠΉ Π½Π° процСсс ΠΊΠ»ΡŽΡ‡ для Π΄Π°Π½Π½Ρ‹Ρ… DataBlock:

 pthread_key_create(&key, destructor);

}


void* ThreadProc(void *data) {

 // гарантия Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ ΠΊΠ»ΡŽΡ‡ инициализируСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ 1 Ρ€Π°Π· Π½Π° процСсс!

 pthread_once(&once, once_creator);

 if (pthread_getspecific(key) == NULL)

  pthread_setspecific(key, new DataBlock(...));

 // Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· Π² Ρ‚Π΅Π»Π΅ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌΡ‹Ρ…

 // ΠΈΠ· Π½Π΅Π΅, ΠΌΡ‹ всСгда ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ экзСмпляру Π΄Π°Π½Π½Ρ‹Ρ…

 DataBlock* pdb = pthread_getspecific(key);

 // ... всС Ρ‚Π΅ ΠΆΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с полями pdb->(DataBlock)

 return NULL;

}

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ вся описанная Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ° прСобразования ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π² Ρ€Π΅Π΅Π½Ρ‚Π΅Ρ€Π°Π±Π΅Π»ΡŒΠ½Ρ‹Π΅ (ΠΊΠ°ΠΊ ΠΈ всС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹Π΅ интСрфСйсы POSIX) ΠΎΡ‚Ρ‡Π΅Ρ‚Π»ΠΈΠ²ΠΎ ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π° Π½Π° сСмантику классичСского Π‘, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ всС своС ΠΈΠ·Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΡ‹ ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ ΠΈ ΠΈΠ»Π»ΡŽΡΡ‚Ρ€ΠΈΡ€ΡƒΠ΅ΠΌ Π½Π° Π‘++. ΠŸΡ€ΠΈ создании экзСмпляра собствСнных Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ€Π°Π·Ρ€ΡƒΡˆΠ°Π΅Ρ‚ΡΡ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ: Ρ€Π°Π·Π½Ρ‹Π΅ экзСмпляры ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² Π²ΠΏΠΎΠ»Π½Π΅ ΠΌΠΎΠ³Π»ΠΈ Π±Ρ‹ ΠΏΡ€ΠΈΡΠ²ΠΎΠΈΡ‚ΡŒ своим указатСлям Π΄Π°Π½Π½Ρ‹Π΅ (Ρ‚ΠΈΠΏΠ° void*), ассоциированныС с ΠΎΠ΄Π½ΠΈΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ key. Π­Ρ‚ΠΎ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹ Π΄Π°Π½Π½Ρ‹Ρ…, скаТСм DataBlock_1* ΠΈ DataBlock_2*. Но ΠΏΡ€ΠΎΡΠ²ΠΈΠ»ΠΎΡΡŒ Π±Ρ‹ это нСсоотвСтствиС Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈ ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ΅Π½ΠΈΠΈ экзСмпляров Π΄Π°Π½Π½Ρ‹Ρ…, ΠΊΠΎΠ³Π΄Π° ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ Ρ€Π°Π·Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° Π±Ρ‹Π» Π±Ρ‹ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ ΠΎΠ΄ΠΈΠ½ дСструктор, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΏΡ€ΠΈ Π²Ρ‹Π΄Π΅Π»Π΅Π½ΠΈΠΈ ΠΊΠ»ΡŽΡ‡Π°. Ошибки Ρ‚Π°ΠΊΠΎΠ³ΠΎ Ρ€ΠΎΠ΄Π° ΠΊΡ€Π°ΠΉΠ½Π΅ слоТны Π² Π»ΠΎΠΊΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

Особая ΠΎΠ±Π»Π°ΡΡ‚ΡŒ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ собствСнныС Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΌΠΎΠ³ΡƒΡ‚ Π½Π°ΠΉΡ‚ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈ Π³Π΄Π΅ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ (стСковыС) ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Ρ‹, β€” это асинхронноС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π° ΠΊΠΎΠ΄Π° Π² контСкстС ΠΏΠΎΡ‚ΠΎΠΊΠ°, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ сигнала.