Merge pull request #166 from KyleScharnhorst/add-circular-buffer
Add: circular buffer implementation.
This commit is contained in:
commit
7555d9e12f
124
data_structures/Buffers/CircularBuffer.java
Normal file
124
data_structures/Buffers/CircularBuffer.java
Normal file
@ -0,0 +1,124 @@
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class CircularBuffer {
|
||||
private char[] _buffer;
|
||||
public final int _buffer_size;
|
||||
private int _write_index = 0;
|
||||
private int _read_index = 0;
|
||||
private AtomicInteger _readable_data = new AtomicInteger(0);
|
||||
|
||||
public CircularBuffer(int buffer_size) {
|
||||
if(!IsPowerOfTwo(buffer_size)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this._buffer_size = buffer_size;
|
||||
_buffer = new char[buffer_size];
|
||||
}
|
||||
|
||||
private boolean IsPowerOfTwo(int i) {
|
||||
return (i & (i - 1)) == 0;
|
||||
}
|
||||
|
||||
private int getTrueIndex(int i) {
|
||||
return i % _buffer_size;
|
||||
}
|
||||
|
||||
public Character readOutChar() {
|
||||
Character result = null;
|
||||
|
||||
//if we have data to read
|
||||
if(_readable_data.get() > 0) {
|
||||
result = new Character(_buffer[getTrueIndex(_read_index)]);
|
||||
_readable_data.decrementAndGet();
|
||||
_read_index++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean writeToCharBuffer(char c) {
|
||||
boolean result = false;
|
||||
|
||||
//if we can write to the buffer
|
||||
if(_readable_data.get() < _buffer_size) {
|
||||
//write to buffer
|
||||
_buffer[getTrueIndex(_write_index)] = c;
|
||||
_readable_data.incrementAndGet();
|
||||
_write_index++;
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class TestWriteWorker implements Runnable {
|
||||
String _alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
Random _random = new Random();
|
||||
CircularBuffer _buffer;
|
||||
public TestWriteWorker(CircularBuffer cb) {
|
||||
this._buffer = cb;
|
||||
}
|
||||
|
||||
private char getRandomChar() {
|
||||
return _alphabet.charAt(_random.nextInt(_alphabet.length()));
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while(!Thread.interrupted()) {
|
||||
if(!_buffer.writeToCharBuffer(getRandomChar())){
|
||||
Thread.yield();
|
||||
try{
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestReadWorker implements Runnable {
|
||||
CircularBuffer _buffer;
|
||||
public TestReadWorker(CircularBuffer cb) {
|
||||
this._buffer = cb;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
System.out.println("Printing Buffer:");
|
||||
while(!Thread.interrupted()) {
|
||||
Character c = _buffer.readOutChar();
|
||||
if(c != null) {
|
||||
System.out.print(c.charValue());
|
||||
} else {
|
||||
Thread.yield();
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
int buffer_size = 1024;
|
||||
//create circular buffer
|
||||
CircularBuffer cb = new CircularBuffer(buffer_size);
|
||||
|
||||
//create threads that read and write the buffer.
|
||||
Thread write_thread = new Thread(new TestWriteWorker(cb));
|
||||
Thread read_thread = new Thread(new TestReadWorker(cb));
|
||||
read_thread.start();
|
||||
write_thread.start();
|
||||
|
||||
//wait some amount of time
|
||||
Thread.sleep(10000);
|
||||
|
||||
//interrupt threads and exit
|
||||
write_thread.interrupt();
|
||||
read_thread.interrupt();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user