/*! ========================================================================
** Extended Template Library
**
** $Id$
**
** Copyright (c) 2002 Robert B. Quattlebaum Jr.
**
** This package is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License as
** published by the Free Software Foundation; either version 2 of
** the License, or (at your option) any later version.
**
** This package is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** General Public License for more details.
**
** === N O T E S ===========================================================
**
** This is an internal header file, included by other ETL headers.
** You should not attempt to use it directly.
**
** ========================================================================= */

/* === S T A R T =========================================================== */

#ifndef __ETL__REF_COUNT_H
#define __ETL__REF_COUNT_H

/* === H E A D E R S ======================================================= */

#include <cassert>
#include <atomic>

/* === M A C R O S ========================================================= */

/* === T Y P E D E F S ===================================================== */

/* === C L A S S E S & S T R U C T S ======================================= */

namespace etl {

// ========================================================================
/*!	\class	reference_counter	_ref_count.h	ETL/ref_count
**	\brief	Reference counter
**	\writeme
*/
class reference_counter
{
public:
	typedef std::atomic<int> counter_type;

private:
	counter_type *counter;

public:
	explicit reference_counter(const bool &x = true):
		counter()
		{ if (x) reset(); }
	reference_counter(const reference_counter &x):
		reference_counter(false)
		{ *this = x; }
	~reference_counter() { detach(); }

	void reset() {
		detach();
		counter = new counter_type(1);
	}

	void detach() {
		if (counter) {
			int count = --(*counter);
			assert(count >= 0);
			if (count <= 0) delete counter;
			counter = 0;
		}
	}

	reference_counter& operator=(const reference_counter &other) {
		if (other.counter != counter) {
			detach();
			if (other.counter) {
				counter = other.counter;
				(*counter)++;
				assert(count() > 1);
			}
		}
		return *this;
	}


	int count() const { return counter ? (int)*counter: 0; }
	bool unique() const { return count() == 1; }
	operator int() const { return count(); }
}; // END of class reference_counter

};

/* === E X T E R N S ======================================================= */

/* === E N D =============================================================== */

#endif
