История изменений
Исправление LINUX-ORG-RU, (текущая версия) :
mutex будет блокировать тебе всё. На то он и mutex. Если декодирование занимает 80 ms то всё это время будет ждать кодировщик если захочет сделать pthread_mutex_lock(&mutex); перед обращением к данным. И когда он это сделает если декодировщик снова захочет передать ему данные и тоже сделает pthread_mutex_lock(&mutex); то он будет ждать, так и будут они ждать друг дружку как только будут притрагиваться к mutex дрыгание которого означает для тебя что несколько параллельных штук должны обращаться к чему то одному по очереди, а значит они будут ждать. кодировщик не получит данные от декодировщика раньше так как он ждёт pthread_mutex_unlock(&mutex); от него.
мутексы создают последовательную работу в паралельных процессах при доступе к общему ресурсу. Как то так
не компилял, писал в слепую псевдокод
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
enum
{
HAPPY,
ENCODER_ERROR,
DECODER_ERROR,
DECODER,
ENCODER,
OBSERVER,
};
typedef struct {
uint8_t * data;
size_t size;
struct
{
uint8_t owner;
uint8_t status;
}metadata;
}shared_memory_t;
static shared_memory_t shared_memory = {NULL,0,OBSERVER,HAPPY};
pthread_mutex_t mutex;
void observer(void)
{
pthread_mutex_lock(&mutex);
switch(shared_memory.metadata.status)
{
case HAPPY:
{
pthread_mutex_unlock(&mutex);
}break;
default: switch(shared_memory.metadata.owner)
{
case DECODER:
{
fprintf(stderr,"DECODER ERROR code %d",shared_memory.metadata.status);
//делаешь что-то
exit(1);
}break;
case ENCODER:
{
fprintf(stderr,"ENCODER ERROR code %d",shared_memory.metadata.status);
//делаешь что-то
exit(2);
}break;
}
}
}
void * decoder(void * args)
{
while(1)
{
//делает что-то
//теперь хочет память скопировать для encoder
pthread_mutex_lock(&mutex);
if(shared_memory.data == NULL && shared_memory.size == 0 &&
shared_memory.metadata.owner == OBSERVER &&
shared_memory.metadata.status == HAPPY)
{
shared_memory.data = malloc(100500);
shared_memory.size = 100500;
//копирует данные в эту память для encoder
shared_memory.metadata.owner = DECODER;
shared_memory.metadata.status = HAPPY;
}else{
shared_memory.metadata.owner = DECODER;
shared_memory.metadata.status = DECODER_ERROR;
}
observer();
//дальше что-то делает
}
}
void * encoder(void * args)
{
while(1)
{
//вдруг хочет шареных данных
pthread_mutex_lock(&mutex);
if(shared_memory.size !=0 && shared_memory.data != NULL &&
shared_memory.metadata.owner == OBSERVER &&
shared_memory.metadata.status == HAPPY)
{
//обрабатывает данные после decoder и потом
free(shared_memory.data);
shared_memory.size = 0;
shared_memory.metadata.owner = ENCODER;
shared_memory.metadata.status = HAPPY;
}else{
shared_memory.metadata.owner = ENCODER;
shared_memory.metadata.status = ENCODER_ERROR;
}
observer();
//дальше что-то делает
}
}
int main(int argc, char *argv[])
{
pthread_t threads[2];
pthread_mutex_init(&mutex, NULL);
pthread_create(&threads[0], NULL, encoder , NULL);
pthread_create(&threads[1], NULL, decoder , NULL);
pthread_mutex_destroy(&mutex);
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
// ну короче ты понял
return 0;
}
В самом начале тебе предложили очереди. Суть в том что ты выделяешь кусочки памяти в декодере копируешь туда данные и отправляешь в очередь (массив) а енкодер по мере поступления от туда эти кусочки берёт и делает что-то с ними.
В виде очереди может быть стек,пулл,кольцевой буфер или типа того. Таким образом получится неблокируемая работа всего, сделал pthread_mutex_lock(&mutex);
передал в стек указатель на кусок памяти сделал сразу pthread_mutex_unlock(&mutex);
и поехал дальше, другая нить захочет данные просто сделает pthread_mutex_lock(&mutex);data=pop() pthread_mutex_unlock(&mutex);
и всё. Только надо не LIFO а FIFO стек.
Но если хочешь именно доступ к 1 кусочку памяти и шарить его то либо как сказал выкинуть треды нафиг и делать последовательно или вешать 1 лок на всё и опять делать последовательно. Помойму иначе никак.
ПЫСЫ я не программист может и не прав, но имхо прав =)
Исправление LINUX-ORG-RU, :
mutex будет блокировать тебе всё. На то он и mutex. Если декодирование занимает 80 ms то всё это время будет ждать кодировщик если захочет сделать pthread_mutex_lock(&mutex); перед обращением к данным. И когда он это сделает если декодировщик снова захочет передать ему данные и тоже сделает pthread_mutex_lock(&mutex); то он будет ждать, так и будут они ждать друг дружку как только будут притрагиваться к mutex дрыгание которого означает для тебя что несколько параллельных штук должны обращаться к чему то одному по очереди, а значит они будут ждать. кодировщик не получит данные от декодировщика раньше так как он ждёт pthread_mutex_unlock(&mutex); от него.
мутексы создают последовательную работу в паралельных процессах при доступе к общему ресурсу. Как то так
не компилял, писал в слепую псевдокод
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
enum
{
HAPPY,
ENCODER_ERROR,
DECODER_ERROR,
DECODER,
ENCODER,
OBSERVER,
};
typedef struct {
uint8_t * data;
size_t size;
struct
{
uint8_t owner;
uint8_t status;
}metadata;
}shared_memory_t;
static shared_memory_t shared_memory = {NULL,0,OBSERVER,HAPPY};
pthread_mutex_t mutex;
void observer(void)
{
pthread_mutex_lock(&mutex);
switch(shared_memory.metadata.status)
{
case HAPPY:
{
pthread_mutex_unlock(&mutex);
}break;
default: switch(shared_memory.metadata.owner)
{
case DECODER:
{
fprintf(stderr,"DECODER ERROR code %d",shared_memory.metadata.status);
//делаешь что-то
exit(1);
}break;
case ENCODER:
{
fprintf(stderr,"DECODER ERROR code %d",shared_memory.metadata.status);
//делаешь что-то
exit(2);
}break;
}
}
}
void * decoder(void * args)
{
while(1)
{
//делает что-то
//теперь хочет память скопировать для encoder
pthread_mutex_lock(&mutex);
if(shared_memory.data == NULL && shared_memory.size == 0 &&
shared_memory.metadata.owner == OBSERVER &&
shared_memory.metadata.status == HAPPY)
{
shared_memory.data = malloc(100500);
shared_memory.size = 100500;
//копирует данные в эту память для encoder
shared_memory.metadata.owner = DECODER;
shared_memory.metadata.status = HAPPY;
}else{
shared_memory.metadata.owner = DECODER;
shared_memory.metadata.status = DECODER_ERROR;
}
observer();
//дальше что-то делает
}
}
void * encoder(void * args)
{
while(1)
{
//вдруг хочет шареных данных
pthread_mutex_lock(&mutex);
if(shared_memory.size !=0 && shared_memory.data != NULL &&
shared_memory.metadata.owner == OBSERVER &&
shared_memory.metadata.status == HAPPY)
{
//обрабатывает данные после decoder и потом
free(shared_memory.data);
shared_memory.size = 0;
shared_memory.metadata.owner = ENCODER;
shared_memory.metadata.status = HAPPY;
}else{
shared_memory.metadata.owner = ENCODER;
shared_memory.metadata.status = ENCODER_ERROR;
}
observer();
//дальше что-то делает
}
}
int main(int argc, char *argv[])
{
pthread_t threads[2];
pthread_mutex_init(&mutex, NULL);
pthread_create(&threads[0], NULL, encoder , NULL);
pthread_create(&threads[1], NULL, decoder , NULL);
pthread_mutex_destroy(&mutex);
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
// ну короче ты понял
return 0;
}
В самом начале тебе предложили очереди. Суть в том что ты выделяешь кусочки памяти в декодере копируешь туда данные и отправляешь в очередь (массив) а енкодер по мере поступления от туда эти кусочки берёт и делает что-то с ними.
В виде очереди может быть стек,пулл,кольцевой буфер или типа того. Таким образом получится неблокируемая работа всего, сделал pthread_mutex_lock(&mutex);
передал в стек указатель на кусок памяти сделал сразу pthread_mutex_unlock(&mutex);
и поехал дальше, другая нить захочет данные просто сделает pthread_mutex_lock(&mutex);data=pop() pthread_mutex_unlock(&mutex);
и всё. Только надо не LIFO а FIFO стек.
Но если хочешь именно доступ к 1 кусочку памяти и шарить его то либо как сказал выкинуть треды нафиг и делать последовательно или вешать 1 лок на всё и опять делать последовательно. Помойму иначе никак.
ПЫСЫ я не программист может и не прав, но имхо прав =)
Исходная версия LINUX-ORG-RU, :
mutex будет блокировать тебе всё. На то он и mutex. Если декодирование занимает 80 ms то всё это время будет ждать кодировщик если захочет сделать pthread_mutex_lock(&mutex); перед обращением к данным. И когда он это сделает если декодировщик снова захочет передать ему данные и тоже сделает pthread_mutex_lock(&mutex); то он будет ждать, так и будут они ждать друг дружку как только будут притрагиваться к mutex дрыгание которого означает для тебя что несколько параллельных штук должны обращаться к чему то одному по очереди, а значит они будут ждать. кодировщик не получит данные от декодировщика раньше так как он ждёт pthread_mutex_unlock(&mutex); от него.
мутексы создают последовательную работу в паралельных процессах при доступе к общему ресурсу. Как то так
не компилял, писал в слепую псевдокод
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
enum
{
HAPPY,
ENCODER_ERROR,
DECODER_ERROR,
DECODER,
ENCODER,
OBSERVER,
};
typedef struct {
uint8_t * data;
size_t size;
struct
{
uint8_t owner;
uint8_t status;
}metadata;
}shared_memory_t;
static shared_memory_t shared_memory = {NULL,0,OBSERVER,HAPPY};
pthread_mutex_t mutex;
void observer(void)
{
pthread_mutex_lock(&mutex);
switch(shared_memory.metadata.status)
{
case HAPPY:
{
pthread_mutex_unlock(&mutex);
}break;
default: switch(shared_memory.metadata.owner)
{
case DECODER:
{
fprintf(stderr,"DECODER ERROR code %d",shared_memory.metadata.status);
//делаешь что-то
exit(1);
}break;
case ENCODER:
{
fprintf(stderr,"DECODER ERROR code %d",shared_memory.metadata.status);
//делаешь что-то
exit(2);
}break;
}
}
}
void * decoder(void * args)
{
while(1)
{
//делает что-то
//теперь хочет память скопировать для encoder
pthread_mutex_lock(&mutex);
if(shared_memory.data == NULL && shared_memory.size == 0 &&
shared_memory.metadata.owner == OBSERVER &&
shared_memory.metadata.status == HAPPY)
{
shared_memory.data = malloc(100500);
shared_memory.size = 100500;
//копирует данные в эту память для encoder
shared_memory.metadata.owner = DECODER;
shared_memory.metadata.status = HAPPY;
}else{
shared_memory.metadata.owner = DECODER;
shared_memory.metadata.status = DECODER_ERROR;
}
observer();
//дальше что-то делает
}
}
void * encoder(void * args)
{
while(1)
{
//вдруг хочет шареных данных
pthread_mutex_lock(&mutex);
if(shared_memory.size !=0 && shared_memory.data != NULL &&
shared_memory.metadata.owner == OBSERVER &&
shared_memory.metadata.status == HAPPY)
{
//обрабатывает данные после decoder и потом
free(shared_memory.data);
shared_memory.size = 0;
shared_memory.metadata.owner = ENCODER;
shared_memory.metadata.status = HAPPY;
}else{
shared_memory.metadata.owner = ENCODER;
shared_memory.metadata.status = ENCODER_ERROR;
}
observer();
//дальше что-то делает
}
}
int main(int argc, char *argv[])
{
pthread_t threads[2];
pthread_mutex_init(&mutex, NULL);
pthread_create(&threads[0], NULL, encoder , NULL);
pthread_create(&threads[1], NULL, decoder , NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
В самом начале тебе предложили очереди. Суть в том что ты выделяешь кусочки памяти в декодере копируешь туда данные и отправляешь в очередь (массив) а енкодер по мере поступления от туда эти кусочки берёт и делает что-то с ними.
В виде очереди может быть стек,пулл,кольцевой буфер или типа того. Таким образом получится неблокируемая работа всего, сделал pthread_mutex_lock(&mutex);
передал в стек указатель на кусок памяти сделал сразу pthread_mutex_unlock(&mutex);
и поехал дальше, другая нить захочет данные просто сделает pthread_mutex_lock(&mutex);data=pop() pthread_mutex_unlock(&mutex);
и всё. Только надо не LIFO а FIFO стек.
Но если хочешь именно доступ к 1 кусочку памяти и шарить его то либо как сказал выкинуть треды нафиг и делать последовательно или вешать 1 лок на всё и опять делать последовательно. Помойму иначе никак.
ПЫСЫ я не программист может и не прав, но имхо прав =)