Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- struct ConceptualBlock
- {
- struct ConceptualBlock* next;
- };
- struct scond
- {
- #ifdef USE_WIN32_THREADS
- HANDLE event, atomic_lock;
- volatile int waiters;
- volatile bool waiting_ack;
- volatile struct ConceptualBlock* volatile root;
- HANDLE ack;
- #else
- pthread_cond_t cond;
- #endif
- };
- void scond_wait(scond_t *cond, slock_t *lock)
- {
- #ifdef USE_WIN32_THREADS
- printf("SCW B %p\n",cond);
- //setup a queue (linked list) of blocked threads
- volatile struct ConceptualBlock myblock;
- myblock.next = NULL;
- volatile struct ConceptualBlock* volatile * ptr = &cond->root;
- while(*ptr != NULL)
- ptr = &((*ptr)->next);
- *ptr = &myblock;
- //now the conceptual lock release and condition block are supposed to be atomic.
- //we can't do that in windows, but we can simulate the effects by using the queue, by the following analysis:
- //What happens if they aren't atomic?
- //1. a signaller can rush in and signal, expecting a waiter to get it; but the waiter wouldn't, because he isn't blocked yet
- //solution: win32 events make this easy. the event will sit there enabled
- //2. a signaller can rush in and signal, and then turn right around and wait
- //solution: the signaller will get queued behind the waiter, who's enqueued before he releases the mutex
- for(;;)
- {
- ReleaseMutex(lock->lock);
- bool myturn = (cond->root == &myblock);
- ReleaseMutex(lock->lock);
- if(myturn)
- {
- WaitForSingleObject(cond->event, INFINITE);
- break;
- }
- else
- {
- //otherwise, go to sleep (TODO: do something better than that)
- Sleep(1);
- }
- }
- //re-acquire mutex
- WaitForSingleObject(lock->lock, INFINITE);
- //remove ourselves from the queue
- cond->root = myblock.next;
- #else
- pthread_cond_wait(&cond->cond, &lock->lock);
- #endif
- }
- /**
- * scond_signal:
- * @cond : pointer to condition variable object
- *
- * Signal a condition. Unblocks at least one of the threads currently blocked
- * on the specified condition variable @cond.
- **/
- void scond_signal(scond_t *cond)
- {
- #ifdef USE_WIN32_THREADS
- //printf("DOOBOO %p\n",cond);
- printf("SCS A %p\n",cond);
- /* remember: we currently have mutex */
- if(cond->root == NULL) return;
- printf("SCS B %p\n",cond);
- /* OK, someone is waiting for a signal */
- /* We're supposed to wake up someone--anyone. It could even be ourselves, if we scond_wait() again in a minute. No guarantees. */
- SetEvent(cond->event);
- printf("SCS C %p\n",cond);
- //printf("DOOBOO %p\n",cond);
- #else
- pthread_cond_signal(&cond->cond);
- #endif
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement