class KWICDB
implements KWICDBInterface
private DBWriterClient writerClient
private DBReaderClient readerClient
private KWICDatabase kwicdb
public String []
query(String keywords[])
readerClient.enter()
String [] entries = kwicdb.get(keywords)
readerClient.exit()
return entries
public void
write(String description)
writerClient.enter()
kwicdb.put(description)
writerClient.exit()
abstract class DBClientTemplate
protected DatabaseAccess dba
abstract boolean databaseSafe()
abstract void databaseWait()
abstract void databaseEnter()
abstract void databaseExit()
DBClientTemplate(DatabaseAccess dba)
this.dba = dba
void enter()
dba.mutex.lock()
if (!databaseSafe()) databaseWait()
databaseEnter()
void exit()
try dba.mutex.lock()
catch (InterruptedException ie)
Thread.currentThread().interrupt()
databaseExit()
See the complete code.
class DBClient
extends DBClientTemplate
DBClient(DatabaseAccess dba)
super(dba)
boolean databaseSafe()
return true
void databaseWait()
assert false
void databaseEnter() {
}
void databaseExit()
dba.mutex.unlock()
void exit()
databaseExit()
class DatabaseAccess Mutex lock = new Mutex(Mutex.unlocked)
class DatabaseAccess
Mutex mutex = new Mutex(Mutex.unlocked)
HandoffConditionVariable
emptyDatabase = new HandoffConditionVariable(mutex)
noWriterInDB = new HandoffConditionVariable(mutex)
boolean writerInDB = false
int readersInDB = 0
class DBReaderClient
extends DBClientTemplate
boolean databaseSafe()
return !dba.writerInDB
void databaseWait()
dba.emptyDatabase.pause()
void databaseEnter()
dba.readersInDB++
if dba.noWriterInDB.waiting()
dba.noWriterInDB.resume()
else
dba.mutex.unlock()
void databaseExit()
dba.readersInDB--
if dba.emptyDatabase.waiting()
dba.emptyDatabase.resume()
else if dba.noWriterInDB.waiting()
dba.noWriterInDB.resume()
else
dba.mutex.unlock()
See the complete code.
init() and term()init() prevents database entry and exit.
term() Allows database exit and prevents entry.
class DBInvalidWriterClient
extends DBWriterClient
void enter()
throws InterruptedException
throw new Error("The database is not accepting clients.")
// exit() inherited from DBWriterClient.
DBInvalidReaderClient is defined similarly.
init().
init() classes that
explode on exit too.
init() and term()init() changes them to valid clients.
term() changes them back to invalid clients.
class KWICDB
implements KWICDBInterface
private DatabaseAccess dba = new DatabaseAccess()
private DBClientTemplate
invalidWriterClient = new DBInvalidWriterClient(dba)
invalidReaderClient = new DBInvalidReaderClient(dba)
readerClient = invalidReaderClient
writerClient = invalidWriterClient
public KWICDBInterface init()
readerClient = new DBReaderClient(dba)
writerClient = new DBWriterClient(dba)
return this
public void term()
readerClient = invalidReaderClient
writerClient = invalidWriterClient
See the complete code.
class QueueElement Mutex delay(Mutex.locked) boolean isReader boolean byPassed = false QueueElement next = null
class DatabaseAccess Mutex mutex = new Mutex(Mutex.unlocked) Queue waiters = new Queue() boolean writerInDB = false int readersInDB = 0
class DBReaderClient
void entry()
dba.mutex.lock()
if !dba.waiters.empty() || dba.writerInDB
QueueElement qe = dba.waiters.enq(true)
dba.mutex.unlock()
qe.delay.lock()
dba.mutex.lock()
if dba.waiters.head() != null
if dba.waiters.head().isReader
dba.waiters.deq().delay.unlock()
readersInDB++
dba.mutex.unlock()
void exit()
dba.mutex.lock()
if --readersInDB == 0
if dba.waiters.head() != null
if dba.waiters.head().isWriter
dba.waiters.deq().delay.unlock()
dba.mutex.unlock
class DBWriterClient
void enter()
dba.mutex.lock()
if !dba.waiters.empty()
|| dba.writerInDB || dba.readersInDB > 0
QueueElement qe = dba.waiters.enq(false)
dba.mutex.unlock()
qe.delay.lock()
dba.mutex.lock()
writerInDB = true
dba.mutex.unlock()
void exit()
dba.mutex.lock()
writerInDB = false
if dba.waiters.head() != null
dba.waiters.deq().delay.unlock()
dba.mutex.unlock()
class DBWriterClient
void enter()
dba.mutex.lock()
if !databaseSafe()
QueueElement qe = dba.waiters.enq(true)
dba.mutex.unlock()
qe.delay.lock()
dba.mutex.lock()
writerInDB = true
dba.mutex.unlock()
void exit()
dba.mutex.lock()
writerInDB = false
if dba.waiters.head() != null
dba.waiters.deq().delay.unlock()
else
dba.mutex.unlock()
class QueueElement
QueueElement next = null
final KWICIndexEntryGroup entries
QueueElement(KWICIndexEntryGroup entries)
this.entries = entries
interface QueueTraverser
void forEach(KWICIndexEntryGroup entries)
class Queue
private QueueElement qhead = null
boolean empty() { ... }
void enq(QueueElement qe) { ... }
QueueElement head() { ... }
void traverse(QueueTraverser qt)
QueueElement qe
for (qe = qhead; qe != null; qe = qe.next)
qt.forEach(qe.entries)
class KWICDB
private KWICDatabase KWICDB = new KWICDatabase()
private boolean entryOk = false
public KWICDBInterface init()
entryOk = true
public String [] query(String keywords[])
if entryOk return KWICDB.get(keywords)
else throw new Error()
public void term()
entryOk = false
public void write(String description)
if entryOk KWICDB.put(description)
else throw new Error()
init() and term().
This page last modified on 13 August 2002.