xref: /haiku/src/servers/media/Queue.cpp (revision 51978af14a173e7fae0563b562be5603bc652aeb)
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