Hey, just a quick question: How can you tell if a critical section has been deleted or not? Apparently checking if it's NULL won't work since it's a struct, and we're supposed to treat it as 'logically opaque'.
Hey, just a quick question: How can you tell if a critical section has been deleted or not? Apparently checking if it's NULL won't work since it's a struct, and we're supposed to treat it as 'logically opaque'.
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
As usual, use a flag variable. Wrap the flag variable and the CRITICAL_SECTION in a single structure if you like. Use a C++ class. Of course, access to the flag variable may also have to be synchronized.
http://cboard.cprogramming.com/showt...5&pagenumber=2
Ah haaaha, I love those things that go a full circle in orbit and then whack you in the back of the head.Wrap the flag variable and the CRITICAL_SECTION in a single structure if you like. Use a C++ class. Of course, access to the flag variable may also have to be synchronized.
Ah well, I'm using 2 events and 2 CRITICAL_SECTIONS together, and they should all be created/deleted at the same time anyways; I guess I'll just test to see if one of the events is non-NULL, and if it is, then free all 4 of the objects at the same time and set that event to NULL. It seems to work fine from the (very) limited testing I've done, but it'd be great if you could tell me if you spot any problem.
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
It sounds like you have a race condition with your current method.
The best bet is to initialise sync objects in your main thread before you create worker threads. However, if that is not possible there is a simple, fast and cheap way to do it.
As the InterlockedIncrement will only return 0 once, this guarantees that the code in the block will only be executed the first time it is reached. It also guarantees that the resources will not be used before they are created.Code:static volatile LONG fStartInit = -1; static volatile LONG fEndInit = -1; static volatile LONG fStartDestroy = -1; void CreateSyncObjects( void ) { if (InterlockedIncrement(&fStartInit) == 0) { // Initialise resources... fEndInit = 0; } else { // Wait for resources to be finished initialising... while(fEndInit != 0) Sleep(1); } } void DestroySyncObjects( void ) { if (InterlockedIncrement(&fStartDestroy) == 0) { // Cleanup resources... } }
[edit]
Of course, after you call DestroySyncObjects, you must make sure the objects are no longer used by any thread. If you really need to call DestroySyncObjects from a worker thread then you need to implement a reference counting system.
[/edit]Code:static volatile LONG fStartInit = -1; static volatile LONG fEndInit = -1; static volatile LONG nRefCount = 0; void CreateSyncObjects( void ) { InterlockedIncrement(&nRefCount); if (InterlockedIncrement(&fStartInit) == 0) { // Initialise resources... fEndInit = 0; } else { // Wait for resources to be finished initialising... while(fEndInit != 0) Sleep(0); } } void DestroySyncObjects( void ) { if (InterlockedDecrement(&nRefCount) == 0) { // Cleanup resources... } }
[edit2]
Still not perfect. If you call Create, Destroy, Create you will run into trouble. This sync stuff is mind destroying.
[/edit2]
I learnt this method from someone on the board.
Another option that may be helpful is spin locks. Here is an example.
Last edited by anonytmouse; 03-19-2004 at 07:49 AM.
>>It sounds like you have a race condition with your current method.
Come again? What's a race condition?
Well, my sync. stuff is for my async. event-notified Winsock wrapper. I have a class, with a static startup() and cleanup() function, which should be called only at program start and end, in which I initialize the sync objects and spawn a thread to wait on events (startup()), and kill the thread and delete the sync objects (cleanup()). I just figured, in my cleanup() i'd prefer if i could test each sync object individually to see if they've been deleted already, or aren't initialized or whatever, to prevent accidentally deleting something that shouldn't be deleted.
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
A race condition is where, under certain conditions, multi threaded code instructions execute in the wrong order. Search for more information.
From your description I don't see why you have a sync issue at all. Are startup() and cleanup() not called from the same thread?
I seriously doubt there is any problem calling DeleteCriticalSection() on a CRITICAL_SECTION that is zeroed out. So you could just:
This is not thread safe, but neither is testing and setting to NULL.Code:// declare: static CRITICAL_SECTION myCs = { 0 }; // and delete: DeleteCriticalSection(&myCs); memset(&myCs, 0, sizeof(myCs));
>>A race condition is where, under certain conditions, multi threaded code instructions execute in the wrong order.
So basically, it's a 'race' between 2 threads: there's no guarantee of them not being side by side?
>>I don't see why you have a sync issue at all.
There must've been a misunderstanding I'm not worrying about more than one thread trying to delete the critical section, I'm thinking of what happens if the user calls cleanup() twice in a row (or, for that matter, just once without calling startup()). One of those code-level idiotproofing things I just wanted to ensure that if anything that should get destroyed in cleanup() is already gone, it doesn't get deleted again.
You mean deleting a 'dead' critical section won't get you runtime errors? Or is that only a zeroed out critical section?Code:// declare: static CRITICAL_SECTION myCs = { 0 }; // and delete: DeleteCriticalSection(&myCs); memset(&myCs, 0, sizeof(myCs));
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
>>So basically, it's a 'race' between 2 threads: there's no guarantee of them not being side by side?<<
Example race condition.
>>I'm thinking of what happens if the user calls cleanup() twice in a row (or, for that matter, just once without calling startup()). <<
So we are back to the beginning, you can just use a flag variable. static BOOL bInitialized - set it in startup() and cleanup().
>>You mean deleting a 'dead' critical section won't get you runtime errors? Or is that only a zeroed out critical section?<<
I don't really know. I'm just guessing that a zeroed out one wouldn't cause problems. I'd try to avoid either if possible.
Ok, thanks. If that's the case, then what I have will suffice for a flag variable (check if the WSAEVENT is initialized).
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.