// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2007 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.
#ident "$XORP: xorp/libxorp/ref_ptr.cc,v 1.13 2007/02/16 22:46:22 pavlin Exp $"
#include "libxorp/xorp.h"
#include "ref_ptr.hh"
///////////////////////////////////////////////////////////////////////////////
//
// Debugging macro's
//
#define POOL_PARANOIA(x) /* x */
#define VERBOSE_POOL_PARANOIA(x) /* x */
///////////////////////////////////////////////////////////////////////////////
//
// ref_counter_pool implementation
//
ref_counter_pool ref_counter_pool::_the_instance;
ref_counter_pool&
ref_counter_pool::instance()
{
return ref_counter_pool::_the_instance;
}
void
ref_counter_pool::grow()
{
size_t old_size = _counters.size();
_counters.resize(old_size + old_size / 8 + 1);
for (size_t i = old_size; i < _counters.size(); i++) {
_counters[i] = _free_index;
_free_index = i;
}
POOL_PARANOIA(check());
}
void
ref_counter_pool::check()
{
int32_t i = _free_index;
size_t n = 0;
VERBOSE_POOL_PARANOIA(cout << "L: ");
while (_counters[i] != LAST_FREE) {
VERBOSE_POOL_PARANOIA(cout << i << " ");
i = _counters[i];
n++;
if (n == _counters.size()) {
dump();
abort();
}
}
VERBOSE_POOL_PARANOIA(cout << endl);
}
bool
ref_counter_pool::on_free_list(int32_t index)
{
int32_t i = _free_index;
size_t n = 0;
while (_counters[i] != LAST_FREE) {
if (i == index) {
return true;
}
i = _counters[i];
n++;
if (n == _counters.size()) {
dump();
abort();
}
}
return false;
}
void
ref_counter_pool::dump()
{
for (size_t i = 0; i < _counters.size(); i++) {
cout << i << " " << _counters[i] << endl;
}
cout << "Free index: " << _free_index << endl;
cout << "Balance: " << _balance << endl;
}
ref_counter_pool::ref_counter_pool()
{
const size_t n = 1;
_counters.resize(n);
_counters[n - 1] = LAST_FREE;
_free_index = 0;
grow();
grow();
VERBOSE_POOL_PARANOIA(dump());
}
int32_t
ref_counter_pool::new_counter()
{
VERBOSE_POOL_PARANOIA(dump());
if (_counters[_free_index] == LAST_FREE) {
grow();
}
POOL_PARANOIA(assert(_counters[_free_index] != LAST_FREE));
POOL_PARANOIA(check());
int32_t new_counter = _free_index;
_free_index = _counters[_free_index];
_counters[new_counter] = 1;
++_balance;
POOL_PARANOIA(check());
return new_counter;
}
int32_t
ref_counter_pool::incr_counter(int32_t index)
{
POOL_PARANOIA(assert(on_free_list(index) == false));
POOL_PARANOIA(check());
assert((size_t)index < _counters.size());
++_counters[index];
++_balance;
POOL_PARANOIA(check());
return _counters[index];
}
int32_t
ref_counter_pool::decr_counter(int32_t index)
{
POOL_PARANOIA(assert((size_t)index < _counters.size()));
int32_t c = --_counters[index];
--_balance;
if (c == 0) {
POOL_PARANOIA(check());
/* recycle */
_counters[index] = _free_index;
_free_index = index;
VERBOSE_POOL_PARANOIA(dump());
POOL_PARANOIA(check());
}
assert(c >= 0);
return c;
}
int32_t
ref_counter_pool::count(int32_t index)
{
POOL_PARANOIA(assert((size_t)index < _counters.size()));
return _counters[index];
}
///////////////////////////////////////////////////////////////////////////////
//
// cref_counter_pool implementation
//
cref_counter_pool cref_counter_pool::_the_instance;
cref_counter_pool&
cref_counter_pool::instance()
{
return cref_counter_pool::_the_instance;
}
void
cref_counter_pool::grow()
{
size_t old_size = _counters.size();
_counters.resize(2 * old_size);
for (size_t i = old_size; i < _counters.size(); i++) {
_counters[i].count = _free_index;
_free_index = i;
}
}
void
cref_counter_pool::check()
{
int32_t i = _free_index;
size_t n = 0;
VERBOSE_POOL_PARANOIA(cout << "L: ");
while (_counters[i].count != LAST_FREE) {
VERBOSE_POOL_PARANOIA(cout << i << " ");
i = _counters[i].count;
n++;
if (n == _counters.size()) {
dump();
abort();
}
}
VERBOSE_POOL_PARANOIA(cout << endl);
}
void
cref_counter_pool::dump()
{
for (size_t i = 0; i < _counters.size(); i++) {
cout << i << " " << _counters[i].count << endl;
}
cout << "Free index: " << _free_index << endl;
}
cref_counter_pool::cref_counter_pool()
{
const size_t n = 1;
_counters.resize(n);
_free_index = 0; // first free item
_counters[n - 1].count = LAST_FREE;
grow();
grow();
VERBOSE_POOL_PARANOIA(dump());
}
int32_t
cref_counter_pool::new_counter(void* data)
{
VERBOSE_POOL_PARANOIA(dump());
if (_counters[_free_index].count == LAST_FREE) {
grow();
}
POOL_PARANOIA(assert(_counters[_free_index].count != LAST_FREE));
POOL_PARANOIA(check());
int32_t new_counter = _free_index;
_free_index = _counters[_free_index].count;
_counters[new_counter].count = 1;
_counters[new_counter].data = data;
POOL_PARANOIA(check());
return new_counter;
}
int32_t
cref_counter_pool::incr_counter(int32_t index)
{
POOL_PARANOIA(check());
assert((size_t)index < _counters.size());
_counters[index].count++;
POOL_PARANOIA(check());
return _counters[index].count;
}
int32_t
cref_counter_pool::decr_counter(int32_t index)
{
POOL_PARANOIA(assert((size_t)index < _counters.size()));
int32_t c = --_counters[index].count;
if (c == 0) {
POOL_PARANOIA(check());
/* recycle */
_counters[index].count = _free_index;
_free_index = index;
VERBOSE_POOL_PARANOIA(dump());
POOL_PARANOIA(check());
}
assert(c >= 0);
return c;
}
int32_t
cref_counter_pool::count(int32_t index)
{
POOL_PARANOIA(assert((size_t)index < _counters.size()));
return _counters[index].count;
}
void*
cref_counter_pool::data(int32_t index)
{
POOL_PARANOIA(assert((size_t)index < _counters.size()));
return _counters[index].data;
}
syntax highlighted by Code2HTML, v. 0.9.1