summaryrefslogblamecommitdiff
path: root/src/kernel/lib/earray.cpp
blob: 5760822e793cd1f0339ed7e70c13899e435e89d1 (plain) (tree)





























































































































































                                                                                        
#include "earray.h"

#include <mem/mem.h>
#include <core/sys.h>
#include <lib/cpp.h>

template <typename T>
earray<T>::earray(int rvil, int vl) {
	ref_vect_init_len = rvil;
	vect_len = vl;

	ref_vect_len = ref_vect_init_len;
	elements = 0;
	mutex = MUTEX_UNLOCKED;

	data = (T***)kmalloc(ref_vect_len * sizeof(T**));

	for (int i = 0; i < ref_vect_len; i++) {
		data[i] = 0;
	}
}

template <typename T>
earray<T>::~earray() {
	mutex_lock(&mutex);

	for (int i = 0; i < ref_vect_len; i++) {
		if (data[i] != 0) kfree(data[i]);
	}
	kfree(data);

	//no need to unlock, the structure is never to be used again
}

template <typename T>
int earray<T>::add(T* ptr) {
	if (ptr == 0) return -1;

	mutex_lock(&mutex);

	for (int i = 0; i < ref_vect_len; i++) {
		if (data[i] == 0) {
			// Allocate here
			data[i] = (T**)kmalloc(vect_len * sizeof(T*));;
			data[i][0] = ptr;
			for (int j = 1; j < vect_len; j++) data[i][j] = 0;

			int ret = i * vect_len;

			if (elements <= ret) elements = ret + 1;

			mutex_unlock(&mutex);
			return ret;
		} else {
			// Look for free space
			for (int j = 0; j < vect_len; j++) {
				if (data[i][j] == 0) {
					data[i][j] = ptr;

					int ret = i * vect_len + j;	
					if (elements <= ret) elements = ret + 1;

					mutex_unlock(&mutex);
					return ret;
				}
			}
		}
	}
	// Nothing was allocated, we need MORE SPACE
	T ***new_data = (T***)kmalloc((ref_vect_len + ref_vect_init_len) * sizeof(T**));
	for (int i = 0; i < ref_vect_len; i++) {
		new_data[i] = data[i];
	}
	new_data[ref_vect_len] = (T**)kmalloc(vect_len * sizeof(T*));
	new_data[ref_vect_len][0] = ptr;
	int ret = ref_vect_len * vect_len;
	for (int i = 1; i < vect_len; i++) {
		new_data[ref_vect_len][i] = 0;
	}
	for (int i = ref_vect_len + 1; i < ref_vect_len + ref_vect_init_len; i++) {
		new_data[i] = 0;
	}
	kfree(data);
	data = new_data;
	ref_vect_len += ref_vect_init_len;

	ASSERT(ret >= elements);
	elements = ret + 1;

	mutex_unlock(&mutex);
	return ret;

}

template <typename T>
T *earray<T>::at(int num) {
	mutex_lock(&mutex);

	int i = num / vect_len, j = num % vect_len;
	if (i >= ref_vect_len || data[i] == 0) {
		mutex_unlock(&mutex);
		return 0;
	}
	void* ret = data[i][j];
	mutex_unlock(&mutex);
	return ret;
}

template <typename T>
void earray<T>::set(int num, T* ptr) {
	mutex_lock(&mutex);

	int a = num / vect_len, b = num % vect_len, i, j;
	if (a >= ref_vect_len) {
		if (ptr == 0) {
			mutex_unlock(&mutex);
			return;
		}
		int new_vect_len = ref_vect_len;
		while (a >= ref_vect_len) new_vect_len += ref_vect_init_len;

		T ***new_data = (T***)kmalloc(new_vect_len * sizeof(T**));
		for (i = 0; i < ref_vect_len; i++) {
			new_data[i] = data[i];
		}
		for (i = ref_vect_len; i < new_vect_len; i++) {
			new_data[i] = 0;
		}
		kfree(data);
		data = new_data;
		ref_vect_len = new_vect_len;
	}
	if (ptr == 0) {
		if (data[a] != 0) {
			if (data[a][b] != 0) {
				data[a][b] = 0;
				j = 1;
				for (i = 0; i < vect_len; i++) {
					if (data[a][i] != 0) j = 0;
				}
				if (j == 1) {
					kfree(data[a]);
					data[a] = 0;
				}
			}
		}
	} else {
		if (data[a] = 0) {
			data[a] = (T**)kmalloc(vect_len * sizeof(T*));
			for (i = 0; i < vect_len; i++) data[a][i] = 0;
		}
		data[a][b] = ptr;
		
		if (num >= elements) elements = num + 1;
	}

	mutex_unlock(&mutex);
}