/*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);
}
As you can figure out in the codes above, what I have to accomplish is to let one thread conditionally free the object on which the other two may block. Codes above are obviously flawed because if object is set free along with the lock, all blocking threads give us nowhere but wrong.
A solution below
/*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);
}
works in this case but not applicable however, in my final project because there is actually a dynamic linked list of objects. By applying this solution it means that there must be a list of locks accordingly, each lock for an object and moreover, when a certain object is set free, its lock must be set free at the same time. There is nothing new compared with the first code section.
Now I wonder if there is an alternative solution to this. Thank you very much!
The solution is to not allocate the lock together with the data. I would suggest that you move the data out of that struct and replace it with a pointer to the data. Your linked list can then free the data first, and then the node, without any problems. Here’s some pseudo code:
As a sidenote, a C program for Windows can never return void. A hosted C program must always return int. Your program will not compile on a C compiler.
Also, CreateThread() expects a function pointer to a function returning a 32-bit value and taking a void pointer as parameter. You pass a different kind of function pointer, function pointer casts aren’t allowed in C, nor am I sure what sort of madness Windows will execute if it gets a different function pointer than what it expects. You invoke undefined behavior. This can cause your program to crash or behave in unexpected or random ways.
You need to change your thread function to
DWORD WINAPI thread (LPVOID param);