diff --git a/persistent-data/block.h b/persistent-data/block.h index 21df2d9..4aaf8f9 100644 --- a/persistent-data/block.h +++ b/persistent-data/block.h @@ -78,17 +78,17 @@ namespace persistent_data { class write_ref : public read_ref { public: write_ref(block_cache::block &b); + write_ref(block_cache::block &b, unsigned &ref_count); + write_ref(write_ref const &rhs); + ~write_ref(); + + write_ref const &operator =(write_ref const &rhs); using read_ref::data; void *data(); - }; - class super_ref : public write_ref { - public: - super_ref(block_cache::block &b); - - using read_ref::data; - using write_ref::data; + private: + unsigned *ref_count_; }; // Locking methods @@ -140,6 +140,7 @@ namespace persistent_data { int fd_; mutable block_cache bc_; + unsigned superblock_ref_count_; }; // A little utility to help build validators diff --git a/persistent-data/block.tcc b/persistent-data/block.tcc index d23ff99..faafe67 100644 --- a/persistent-data/block.tcc +++ b/persistent-data/block.tcc @@ -152,10 +152,51 @@ namespace persistent_data { template block_manager::write_ref::write_ref(block_cache::block &b) - : read_ref(b) + : read_ref(b), + ref_count_(NULL) { } + template + block_manager::write_ref::write_ref(block_cache::block &b, unsigned &ref_count) + : read_ref(b), + ref_count_(&ref_count) { + if (*ref_count_) + throw std::runtime_error("superblock already locked"); + (*ref_count_)++; + } + + template + block_manager::write_ref::write_ref(write_ref const &rhs) + : read_ref(rhs), + ref_count_(rhs.ref_count_) { + if (ref_count_) + (*ref_count_)++; + } + + template + block_manager::write_ref::~write_ref() + { + if (ref_count_) { + if (!*ref_count_) + throw std::runtime_error("write_ref ref_count going below zero"); + + (*ref_count_)--; + } + } + + template + typename block_manager::write_ref const & + block_manager::write_ref::operator =(write_ref const &rhs) + { + if (&rhs != this) { + read_ref::operator =(rhs); + ref_count_ = rhs.ref_count_; + if (ref_count_) + (*ref_count_)++; + } + } + template void * block_manager::write_ref::data() @@ -163,14 +204,6 @@ namespace persistent_data { return read_ref::b_.get_data(); } - //-------------------------------- - - template - block_manager::super_ref::super_ref(block_cache::block &b) - : write_ref(b) - { - } - //---------------------------------------------------------------- template @@ -179,7 +212,8 @@ namespace persistent_data { unsigned max_concurrent_blocks, mode m) : fd_(open_or_create_block_file(path, nr_blocks * BlockSize, m)), - bc_(fd_, BlockSize >> SECTOR_SHIFT, nr_blocks, 1024u * 1024u * 16) + bc_(fd_, BlockSize >> SECTOR_SHIFT, nr_blocks, 1024u * 1024u * 16), + superblock_ref_count_(0) { } @@ -235,7 +269,7 @@ namespace persistent_data { typename bcache::validator::ptr v) { block_cache::block &b = bc_.get(location, block_cache::GF_BARRIER, v); - return super_ref(b); + return write_ref(b, superblock_ref_count_); } template @@ -244,7 +278,7 @@ namespace persistent_data { typename bcache::validator::ptr v) { block_cache::block &b = bc_.get(location, block_cache::GF_ZERO | block_cache::GF_BARRIER, v); - return super_ref(b); + return write_ref(b, superblock_ref_count_); } template