Использование Windows Slim блокировки чтения / записи - PullRequest
2 голосов
/ 07 октября 2011
/*language C code*/

#include "windows.h"

typedef struct object_s
{
    SRWLOCK lock;
    int data;
} object_t, *object_p; /*own and pointer type*/

void thread(object_p x)
{
    AcquireSRWLockExclusive(&x->lock);
    //...do something that could probably change x->data value to 0
    if(x->data==0)
        free(x);
    else
        ReleaseSRWLockExclusive(&x->lock);
}

void main()
{
    int i;
    object_p object=(object_p)malloc(sizeof(object_t));

    InitializeSRWLock(&object->lock);

    for(i=0;i<3;i++)
     CreateThread(0,0,thread,object,0);
}

Как вы можете понять из приведенных выше кодов, я должен дать одному потоку условно освободить объект, на котором могут блокироваться два других.Вышеприведенные коды явно ошибочны, потому что если объект освобождается вместе с блокировкой, все блокирующие потоки не дают нам ничего, кроме ошибки.

Решение ниже

/*language C code*/

#include "windows.h"

typedef struct object_s
{
    /*change: move lock to stack in main()*/
    int data;
} object_t, *object_p; /*own and pointer type*/

void thread(void * x)
{
    struct {
    PSRWLOCK l;
    object_p o;
    } * _x=x;
    AcquireSRWLockExclusive(_x->l);
    //...do something that could probably change x->data value to 0
    if(_x->o->data==0)
        free(_x->o);
    ReleaseSRWLockExclusive(&x->lock);
}

void main()
{
    int i;
    SRWLOCK lock; /*lock over here*/
    object_p object=(object_p)malloc(sizeof(object_t));

    InitializeSRWLock(&lock);

    /*pack for thread context*/
    struct
    {
        PSRWLOCK l;
        object_p o;
    } context={&lock, object};

    for(i=0;i<3;i++)
     CreateThread(0,0,thread,&context,0);
}

работает в этом случае, но не применимооднако, в моем последнем проекте, потому что на самом деле есть динамический связанный список объектов.Применение этого решения означает, что должен быть соответствующий список блокировок, каждая блокировка для объекта и, более того, когда определенный объект освобождается, его блокировка должна быть одновременно снята.Нет ничего нового по сравнению с первым разделом кода.

Теперь мне интересно, есть ли альтернативное решение для этого.Большое спасибо!

1 Ответ

2 голосов
/ 07 октября 2011

Решение состоит в том, чтобы не выделять блокировку вместе с данными.Я бы посоветовал вам переместить данные из этой структуры и заменить их указателем на данные.Ваш связанный список может затем освободить данные, а затем и узел, без каких-либо проблем.Вот некоторый псевдокод:

typedef struct 
{
  lock_t lock;
  int*   data_ptr;
} something_t;

void init_something (something_t* thing, ...)
{
  thing->lock = init_lock();
  thing->data_ptr = malloc(...);  // whatever the data is supposed to be
}

void free_something (somthing_t* thing)
{
  lock(thing->lock);
    free(thing->data_ptr);
    thing->data_ptr = NULL;
  unlock(thing->lock);
}

...

void linked_list_delete_node (...)
{
  free_something(node_to_delete->thing);
  free(node_to_delete);
}

...

void thread (void* x)
{
  lock(x->lock);
    //...do something that could probably change x->data_ptr->data... to 0
    if(x->data_ptr->data == 0)
    {
      free_something(x->data_ptr->data);
    }
  unlock(x->lock);
}



 AcquireSRWLockExclusive(lock);
  if(_x->o->data==0)
    free(_x);
 ReleaseSRWLockExclusive(lock);

В качестве sidenote, программа на C для Windows никогда не сможет вернуть void.Размещенная программа на C всегда должна возвращать int.Ваша программа не будет компилироваться на компиляторе C.

Кроме того, CreateThread () ожидает указатель на функцию, возвращающую 32-битное значение и принимающую пустой указатель в качестве параметра.Вы передаете другой тип указателя на функцию, приведение указателя на функцию не разрешено в C, и я не уверен, какое безумие Windows выполнит, если получит указатель на функцию, отличную от ожидаемой.Вы вызываете неопределенное поведение.Это может привести к аварийному завершению работы вашей программы или непредвиденным случайным действиям.

Вам необходимо изменить функцию потока на DWORD WINAPI thread (LPVOID param);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...