LINUX.ORG.RU

История изменений

Исправление 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 лок на всё и опять делать последовательно. Помойму иначе никак.

ПЫСЫ я не программист может и не прав, но имхо прав =)