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

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

Автор Π¦ΠΈΠ»ΡŽΡ€ΠΈΠΊ ОлСг Π˜Π²Π°Π½ΠΎΠ²ΠΈΡ‡

Π”Π°Π»Π΅Π΅ слСдуСт ΠΊΠΎΠ΄

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) ΠΎΡ‚Ρ‡Π΅Ρ‚Π»ΠΈΠ²ΠΎ ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π° Π½Π° сСмантику классичСского Π‘, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ всС своС ΠΈΠ·Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΡ‹ ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ ΠΈ ΠΈΠ»Π»ΡŽΡΡ‚Ρ€ΠΈΡ€ΡƒΠ΅ΠΌ Π½Π° Π‘++. ΠŸΡ€ΠΈ создании экзСмпляра собствСнных Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ€Π°Π·Ρ€ΡƒΡˆΠ°Π΅Ρ‚ΡΡ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠΈ: Ρ€Π°Π·Π½Ρ‹Π΅ экзСмпляры ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² Π²ΠΏΠΎΠ»Π½Π΅ ΠΌΠΎΠ³Π»ΠΈ Π±Ρ‹ ΠΏΡ€ΠΈΡΠ²ΠΎΠΈΡ‚ΡŒ своим указатСлям Π΄Π°Π½Π½Ρ‹Π΅ (Ρ‚ΠΈΠΏΠ° v

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

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

Π•Ρ‰Π΅ ΠΎΠ΄Π½ΠΎ совсСм Π½Π΅ ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ собствСнных Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ° (ΠΌΡ‹ Π½Π΅ встрСчали Π² Π»ΠΈΡ‚Π΅Ρ€Π°Ρ‚ΡƒΡ€Π΅ ΡƒΠΏΠΎΠΌΠΈΠ½Π°Π½ΠΈΠΉ ΠΎ Π½Π΅ΠΌ), ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ особо ΠΎΡ€Π³Π°Π½ΠΈΡ‡Π½ΠΎ вписываСтся Π² использованиС ΠΈΠΌΠ΅Π½Π½ΠΎ Π‘++, β€” это Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ способ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° Π² Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ…. ΠŸΡ€ΠΈ этом Π½Π΅Π²Π°ΠΆΠ½ΠΎ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ - ΠΊΠ°ΠΊ присоСдинСнныС ΠΈΠ»ΠΈ ΠΊΠ°ΠΊ отсоСдинСнныС (ΠΌΡ‹ обсуТдали это Ρ€Π°Π½Π΅Π΅); Ρ‚Π°ΠΊΠΎΠ΅ использованиС Π² Π·Π°ΠΌΠ΅Ρ‚Π½ΠΎΠΉ ΠΌΠ΅Ρ€Π΅ Π½ΠΈΠ²Π΅Π»ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΡ… Ρ€Π°Π·Π½ΠΈΡ†Ρƒ. Π­Ρ‚Π° Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ° состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ:

‒ Если ΠΏΡ€ΠΈ создании ΠΊΠ»ΡŽΡ‡Π° Π½Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ дСструктор экзСмпляра Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°

pthread_key_create(..., NULL)
, Ρ‚ΠΎ ΠΏΡ€ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π½Π°Π΄ экзСмпляром Π΅Π³ΠΎ Π΄Π°Π½Π½Ρ‹Ρ… Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Π½ΠΈΠΊΠ°ΠΊΠΈΠ΅ дСструктивныС дСйствия ΠΈ созданныС ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ экзСмпляры Π΄Π°Π½Π½Ρ‹Ρ… Π±ΡƒΠ΄ΡƒΡ‚ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ послС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ².

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

Π’ ΠΊΠΎΠ΄Π΅ (Ρ‡Ρ‚ΠΎ Π³ΠΎΡ€Π°Π·Π΄ΠΎ нагляднСС) это ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ Ρ‚Π°ΠΊ (ΠΊΠΎΠ΄ с Π·Π°ΠΌΠ΅Ρ‚Π½Ρ‹ΠΌΠΈ упрощСниями взят ΠΈΠ· Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°):

// описаниС экзСмпляра Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°

struct throwndata {

Β ...

};

static pthread_once_t once = PTHREAD_ONCE_INIT;

static pthread_key_t key;

void createkey(void) { pthread_key_create(&key, NULL); }

// STL-ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ Π½Π° экзСмпляры Π΄Π°Π½Π½Ρ‹Ρ…

queue<throwndata*> result;

// функция ΠΏΠΎΡ‚ΠΎΠΊΠ°

void* GetBlock(void*) {

Β pthread_once(&once, createkey);

Β throwndata *td;

Β if ((td = (throwndata*)pthread_getspecific(key)) == NULL) {

Β  td = new throwndata();

Β  pthread_setspecific(key, (void*)td);

Β  // Π²ΠΎΡ‚ ΠΎΠ½ - Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹ΠΉ ΠΏΡƒΡ‚ΡŒ доступа:

Β  result.push(td);

Β }

Β // Π΄Π°Π»Π΅Π΅ ΠΈΠ΄Π΅Ρ‚ плодотворная Ρ€Π°Π±ΠΎΡ‚Π° Π½Π°Π΄ Π±Π»ΠΎΠΊΠΎΠΌ Π΄Π°Π½Π½Ρ‹Ρ… *td

Β // . . . . . . . . .

}

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

Β // . . . . . .

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

Β Β pthread_create(NULL, NULL, GetBlock, NULL);

Β // . . . . . . ΠΊ этому Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΈΡΡŒ;

Β // Π½ΠΈ Π² ΠΊΠΎΠ΅ΠΌ случаС нСльзя ΠΏΠΎΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ result.size()

Β // нСпосрСдствСнно Π² ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Ρ†ΠΈΠΊΠ»Π°!

Β int n = result.size();

Β for (int i = 0; i < n; i++) {

Β Β throwndata *d = result.front();

Β  // ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ° *d ...

Β  result pop();

Β  delete d;

Β }

Β return EXIT_SUCCESS;

}

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

Π’ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ… ΠΊΠΎΠ΄Π° ΠΌΡ‹ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π»ΠΈ Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€

pthread_create()
Π² Π²ΠΈΠ΄Π΅
&GetBlock
(адрСса Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ°), Π½ΠΎ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ ΡΠΎΠ·Π½Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ записали
GetBlock
. И Ρ‚ΠΎ ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠ΅ Π²Π΅Ρ€Π½ΠΎ, ΠΈΠ±ΠΎ компилятор достаточно ΡƒΠΌΠ΅Π½, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈ ΡƒΠΊΠ°Π·Π°Π½ΠΈΠΈ ΠΈΠΌΠ΅Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²Π·ΡΡ‚ΡŒ Π΅Π΅ адрСс.