/*
    PIP - Platform Independent Primitives
    Introspection module - implementation of containers
    Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "piintrospection_containers_p.h"

#include "piintrospection_containers.h"

#include <stdio.h>


PIIntrospectionContainers::PIIntrospectionContainers() {
	// printf("PIIntrospectionContainers %p\n", this);
}


void PIIntrospectionContainers::containerNew(const PIIntrospectionContainersType & ti, uint isz) {
	PISpinlockLocker _ml(mutex);
	// printf("containerNew lock\n");
	PIIntrospectionContainersType & t(types[ti.id]);
	_Type & d(data[ti.id]);
	if (!t.inited) {
		t           = ti;
		d.id        = ti.id;
		d.item_size = isz;
	}
	d.count++;
	// printf("containerNew unlock\n");
}


void PIIntrospectionContainers::containerDelete(const PIIntrospectionContainersType & ti) {
	PISpinlockLocker _ml(mutex);
	data[ti.id].count--;
}


void PIIntrospectionContainers::containerAlloc(const PIIntrospectionContainersType & ti, ullong cnt) {
	// printf(" alloc %s %d\n", tn, cnt);
	if (cnt == 0) return;
	PISpinlockLocker _ml(mutex);
	data[ti.id].allocated += cnt;
}


void PIIntrospectionContainers::containerFree(const PIIntrospectionContainersType & ti, ullong cnt) {
	// printf("  free %s %d\n", tn, cnt);
	if (cnt == 0) return;
	PISpinlockLocker _ml(mutex);
	data[ti.id].allocated -= cnt;
}


void PIIntrospectionContainers::containerUsed(const PIIntrospectionContainersType & ti, ullong cnt) {
	// printf("  used %s %d\n", tn, cnt);
	if (cnt == 0) return;
	PISpinlockLocker _ml(mutex);
	data[ti.id].used += cnt;
}


void PIIntrospectionContainers::containerUnused(const PIIntrospectionContainersType & ti, ullong cnt) {
	// printf("unused %s %d\n", tn, cnt);
	if (cnt == 0) return;
	PISpinlockLocker _ml(mutex);
	data[ti.id].used -= cnt;
}


PIVector<PIIntrospectionContainers::TypeInfo> PIIntrospectionContainers::getInfo() const {
	PIVector<PIIntrospectionContainers::TypeInfo> ret;
	mutex.lock();
	std::map<uint, PIIntrospectionContainers::_Type> d = data;
	std::map<uint, PIIntrospectionContainersType> t    = types;
	mutex.unlock();
	ret.reserve(t.size());
	for (typename std::map<uint, PIIntrospectionContainersType>::const_iterator i = t.begin(); i != t.end(); ++i) {
		ret.push_back(TypeInfo());
		TypeInfo & ti(ret.back());
		_Type & _t(d[i->first]);
		memcpy((void *)&ti, (const void *)&_t, sizeof(_t));
		ti.name = PIStringAscii(i->second.demangled);
	}
	return ret;
}
