SubzonePartition.h [plain text]
#ifndef __AUTO_SUBZONE_PARTITION__
#define __AUTO_SUBZONE_PARTITION__
#include "Admin.h"
#include "Locks.h"
namespace Auto {
class SubzonePartition {
enum {
kPartitionUnscanned = 1,
kPartitionRetained = 2,
kPartitionCount = 4
};
Admin _small[kPartitionCount];
Admin _medium[kPartitionCount];
public:
void initialize(Zone *zone);
Admin &admin(const size_t size, const usword_t layout, bool refcount_is_one) {
usword_t partion = ((layout & AUTO_UNSCANNED) ? kPartitionUnscanned : 0) | (refcount_is_one ? kPartitionRetained : 0);
return (size < allocate_quantum_medium ? _small[partion] : _medium[partion]);
}
void lock() {
for (usword_t i = 0; i < kPartitionCount; ++i) {
spin_lock(_small[i].lock());
spin_lock(_medium[i].lock());
}
}
void unlock() {
for (usword_t i = kPartitionCount; i > 0; --i) {
spin_unlock(_medium[i - 1].lock());
spin_unlock(_small[i - 1].lock());
}
}
bool locked() {
for (usword_t i = 0; i < kPartitionCount; ++i) {
TrySpinLock smallAttempt(_small[i].lock());
if (!smallAttempt) return true;
TrySpinLock mediumAttempt(_medium[i].lock());
if (!mediumAttempt) return true;
}
return false;
}
void for_each(void (^block) (Admin &admin)) {
for (usword_t i = 0; i < kPartitionCount; ++i) {
block(_small[i]);
block(_medium[i]);
}
}
usword_t purge_free_space() {
usword_t bytes_purged = 0;
for (usword_t i = 0; i < kPartitionCount; ++i) {
bytes_purged += _small[i].purge_free_space();
bytes_purged += _medium[i].purge_free_space();
}
return bytes_purged;
}
usword_t purge_free_space_no_lock() {
usword_t bytes_purged = 0;
for (usword_t i = 0; i < kPartitionCount; ++i) {
bytes_purged += _small[i].purge_free_space_no_lock();
bytes_purged += _medium[i].purge_free_space_no_lock();
}
return bytes_purged;
}
class Lock {
SubzonePartition &_partition;
public:
Lock(SubzonePartition &partition) : _partition(partition) { _partition.lock(); }
~Lock() { _partition.unlock(); }
};
};
};
#endif