1// readerWriter.c
2
3#include "betalk.h"
4#include "readerWriter.h"
5
6
7void btLock(sem_id semaphore, int32 *atomic)
8{
9	int32 previous = atomic_add(atomic, 1);
10	if (previous >= 1)
11		while (acquire_sem(semaphore) == B_INTERRUPTED);
12}
13
14void btUnlock(sem_id semaphore, int32 *atomic)
15{
16	int32 previous = atomic_add(atomic, -1);
17	if (previous > 1)
18		release_sem(semaphore);
19}
20
21bool initManagedData(bt_managed_data *data)
22{
23	data->readCount = 0;
24	data->writeCount = 0;
25
26	data->readCountVar = 0;
27	data->writeCountVar = 0;
28	data->readerQueueVar = 0;
29	data->readerVar = 0;
30	data->writerVar = 0;
31
32	if ((data->readCountSem = create_sem(1, "Read Counter")) < 0)
33		return false;
34
35	if ((data->writeCountSem = create_sem(1, "Write Counter")) < 0)
36	{
37		delete_sem(data->readCountSem);
38		return false;
39	}
40
41	if ((data->readerQueue = create_sem(1, "Read Queue")) < 0)
42	{
43		delete_sem(data->writeCountSem);
44		delete_sem(data->readCountSem);
45		return false;
46	}
47
48	if ((data->reader = create_sem(1, "Single Reader")) < 0)
49	{
50		delete_sem(data->readerQueue);
51		delete_sem(data->writeCountSem);
52		delete_sem(data->readCountSem);
53		return false;
54	}
55
56	if ((data->writer = create_sem(1, "Writer")) < 0)
57	{
58		delete_sem(data->reader);
59		delete_sem(data->readerQueue);
60		delete_sem(data->writeCountSem);
61		delete_sem(data->readCountSem);
62		return false;
63	}
64
65	return true;
66}
67
68void closeManagedData(bt_managed_data *data)
69{
70	data->readCount = data->writeCount = 0;
71
72	delete_sem(data->writer);
73	delete_sem(data->reader);
74	delete_sem(data->readerQueue);
75	delete_sem(data->writeCountSem);
76	delete_sem(data->readCountSem);
77}
78
79void beginReading(bt_managed_data *data)
80{
81	btLock(data->readerQueue, &data->readerQueueVar);
82	btLock(data->reader, &data->readerVar);
83	btLock(data->readCountSem, &data->readCountVar);
84
85	data->readCount++;
86	if (data->readCount == 1)
87		btLock(data->writer, &data->writerVar);
88
89	btUnlock(data->readCountSem, &data->readCountVar);
90	btUnlock(data->reader, &data->readerVar);
91	btUnlock(data->readerQueue, &data->readerQueueVar);
92}
93
94void endReading(bt_managed_data *data)
95{
96	btLock(data->readCountSem, &data->readCountVar);
97
98	data->readCount--;
99	if (data->readCount == 0)
100		btUnlock(data->writer, &data->writerVar);
101
102	btUnlock(data->readCountSem, &data->readCountVar);
103}
104
105void beginWriting(bt_managed_data *data)
106{
107	btLock(data->writeCountSem, &data->writeCountVar);
108
109	data->writeCount++;
110	if (data->writeCount == 1)
111		btLock(data->reader, &data->readerVar);
112
113	btUnlock(data->writeCountSem, &data->writeCountVar);
114	btLock(data->writer, &data->writerVar);
115}
116
117void endWriting(bt_managed_data *data)
118{
119	btUnlock(data->writer, &data->writerVar);
120	btLock(data->writeCountSem, &data->writeCountVar);
121
122	data->writeCount--;
123	if (data->writeCount == 0)
124		btUnlock(data->reader, &data->readerVar);
125
126	btUnlock(data->writeCountSem, &data->writeCountVar);
127}
128