class Buffercache;
class Bufferhead : public LRUObject {
+ // reference counter
+ int ref;
+ void get() {
+ if (ref == 0) lru_pin();
+ ++ref;
+ }
+ void put() {
+ --ref;
+ if (ref == 0) lru_unpin();
+ }
+
public: // FIXME: make more private and write some accessors
off_t offset;
size_t len;
// cons/destructors
Bufferhead(inodeno_t ino, off_t off, size_t len, Buffercache *bc, int state=BUFHD_STATE_CLEAN) {
+ this->ref = 0;
this->ino = ino;
this->offset = off;
this->len = len;
}
~Bufferhead() {
- list<bufferptr> bl = bh->bl.buffers();
- for (list<bufferptr>::iterator it == bl.begin();
- it != bl.end();
- it++) {
- delete *it;
- }
+ // no need to delete bufferlist bufferptr's explicitly; ~list() does that (since it's list<bufferptr>, not list<bufferptr*>)
}
//Bufferhead(inodeno_t ino, off_t off, size_t len, int state);
// ~Bufferhead(); FIXME: need to mesh with allocator scheme
- void add_read_waiter(Cond *cond) {
- read_waiters->push_back(cond);
- lru_pin();
+
+ // -- wait for read, write: these will block
+ // i think this will work okay? and reference coutning in the waiter makes sure the wakeup fn doesn't
+ // inadvertantly unpin the bufferhead before the waiters get to go
+ void wait_for_read(Mutex& lock) {
+ Cond cond; // on local stack
+ get();
+ read_waiters.push_back(&cond);
+ cond.Wait(lock);
+ put();
}
-
- void add_write_waiter(Cond *cond) {
- write_waiters->push_back(cond);
- lru_pin();
+ void wait_for_write(Mutex& lock) {
+ Cond cond; // on local stack
+ get();
+ write_waiters.push_back(&cond);
+ cond.Wait(lock);
+ put();
}
-
+
void wakeup_read_waiters() {
for (list<Cond*>::iterator it = read_waiters.begin();
it != read_waiters.end();
(*it)->Signal();
}
read_waiters.clear();
- if (write_waiters.empty()) lru_unpin();
}
void wakeup_write_waiters() {
it++) {
(*it)->Signal();
}
- write_waiters.clear();
- if (read_waiters.empty()) lru_unpin();
}
void miss_start() {