1 /* 2 * Copyright 2002, Marcus Overhagen. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 /* This is a simple multi thread save queue. 6 * 7 * One thread calls AddItem() to add items, and when it 8 * is finished doing so, it calls Terminate(). Another 9 * thread calls RemoveItem() to remove items from the 10 * queue. RemoveItem() blocks when no items are available. 11 * As soon as Terminate() is called and the queue is empty, 12 * RemoveItem() returns NULL. 13 */ 14 15 #include <List.h> 16 #include <OS.h> 17 #include <Locker.h> 18 19 #include "Queue.h" 20 21 Queue::Queue() 22 : fList(new BList), 23 fLocker(new BLocker("queue locker")), 24 fSem(create_sem(0, "queue sem")) 25 { 26 } 27 28 Queue::~Queue() 29 { 30 if (fSem > 0) 31 delete_sem(fSem); 32 delete fLocker; 33 delete fList; 34 } 35 36 status_t 37 Queue::Terminate() 38 { 39 status_t rv; 40 41 fLocker->Lock(); 42 if (fSem < 0) { 43 rv = B_ERROR; 44 } else { 45 delete_sem(fSem); 46 fSem = -1; 47 rv = B_OK; 48 } 49 fLocker->Unlock(); 50 return rv; 51 } 52 53 status_t 54 Queue::AddItem(void *item) 55 { 56 status_t rv; 57 58 fLocker->Lock(); 59 if (fSem < 0) { 60 rv = B_ERROR; 61 } else { 62 if (fList->AddItem(item)) { // AddItem returns a bool 63 release_sem(fSem); 64 rv = B_OK; 65 } else { 66 rv = B_ERROR; 67 } 68 } 69 fLocker->Unlock(); 70 return rv; 71 } 72 73 void * 74 Queue::RemoveItem() 75 { 76 void *item; 77 78 // if the semaphore is deleted by Terminate(), 79 // this will no longer block 80 while (acquire_sem(fSem) == B_INTERRUPTED) 81 ; 82 83 // if the list is empty, which can only happen after 84 // Terminate() was called, item will be NULL 85 fLocker->Lock(); 86 item = fList->RemoveItem((int32)0); 87 fLocker->Unlock(); 88 89 return item; 90 } 91