<commit_before>/*
	OpenLieroX
	code under LGPL
	27-12-2007 <NAME>
*/

#ifndef __SMARTPOINTER_H__
#define __SMARTPOINTER_H__

#include <limits.h>
#include <assert.h>
#ifdef DEBUG_SMARTPTR
#include <map>
#ifdef __GLIBC__
#include <execinfo.h>
#endif
#endif


#include <SDL_thread.h>
#include "Utils.h"

template < typename _Type, typename _SpecificInitFunctor >
class SmartPointer;

// Default de-initialization action is to call operator delete, for each object type.
template < typename _Type >
void SmartPointer_ObjectDeinit( _Type * obj )
{
	delete obj;
};

// these forward-declaration are needed here
struct SDL_Surface;
struct SoundSample;
class CMap;
class CGameScript;

// Specialized de-init functions, for each simple struct-like type that has no destructor
template <> void SmartPointer_ObjectDeinit<SDL_Surface> ( SDL_Surface * obj ); // Calls gfxFreeSurface(obj);
template <> void SmartPointer_ObjectDeinit<SoundSample> ( SoundSample * obj ); // Calls FreeSoundSample(obj);
template <> void SmartPointer_ObjectDeinit<CMap> ( CMap * obj ); // Requires to be defined elsewhere
template <> void SmartPointer_ObjectDeinit<CGameScript> ( CGameScript * obj ); // Requires to be defined elsewhere


/*
	standard smartpointer based on simple refcounting

	The refcounting is multithreading safe in this class,
	you can have copies of this object in different threads.
	Though it's not designed to operate with the same
	object in different threads. Also there is absolutly no
	thread safty on the pointer itself, you have to care
	about this yourself.
*/

#ifdef DEBUG_SMARTPTR
extern std::map< void *, SDL_mutex * > SmartPointer_CollisionDetector;
#endif

template < typename _Type, typename _SpecificInitFunctor = NopFunctor<void*> >
class SmartPointer {
private:
	_Type* obj;
	int* refCount;
	SDL_mutex* mutex;

	void init(_Type* newObj) {
		#ifdef DEBUG_SMARTPTR
		printf("SmartPointer::init    (%10p %10p %10p %10p %3i) newObj %10p\n", this, obj, refCount, mutex, refCount?*refCount:-99, newObj);
		#endif
		if( newObj == NULL )
			return;
		if(!mutex) {
			mutex = SDL_CreateMutex();
			obj = newObj;
			refCount = new int;
			*refCount = 1;
			#ifdef DEBUG_SMARTPTR
			if( SmartPointer_CollisionDetector.find(obj) != SmartPointer_CollisionDetector.end() )
			{
				printf("ERROR! SmartPointer collision detected, old mutex %10p, new ptr (%10p %10p %10p %10p %3i) new %10p\n", SmartPointer_CollisionDetector[obj], this, obj, refCount, mutex, refCount?*refCount:-99, newObj);
				#ifdef __GLIBC__
				void *buffer[100];
				int nptrs = backtrace(buffer, 100);
				printf("backtrace() returned %d addresses\n", nptrs);
				backtrace_symbols_fd(buffer, nptrs, fileno(stdout));
				#endif
			}
			else
				SmartPointer_CollisionDetector.insert( std::make_pair( obj, mutex ) );
			#endif
		}
	}

	void reset() {
		#ifdef DEBUG_SMARTPTR
		printf("SmartPointer::reset   (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		#endif
		if(mutex) {
			lock();
			(*refCount)--;
			if(*refCount == 0) {
				#ifdef DEBUG_SMARTPTR
				if( SmartPointer_CollisionDetector.find(obj) == SmartPointer_CollisionDetector.end() )
				{
					printf("ERROR! SmartPointer already deleted reference (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
					#ifdef __GLIBC__
					void *buffer[100];
					int nptrs = backtrace(buffer, 100);
					printf("backtrace() returned %d addresses\n", nptrs);
					backtrace_symbols_fd(buffer, nptrs, fileno(stdout));
					#endif
				}
				else
					SmartPointer_CollisionDetector.erase(obj);
				#endif
				SmartPointer_ObjectDeinit( obj );
				delete refCount; // save, because there is no other ref anymore
				obj = NULL;
				refCount = NULL;
				unlock();
				SDL_DestroyMutex(mutex); // save because there is no other ref anymore
		 	} else
		 		unlock();
		}
		obj = NULL;
		refCount = NULL;
		mutex = NULL;
	}

	void incCounter() {
		assert(*refCount > 0 && *refCount < INT_MAX);
		(*refCount)++;
	}

	void lock() {
		//printf("SmartPointer::lock    (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		SDL_mutexP(mutex);
	}
	void unlock() {
		//printf("SmartPointer::unlock  (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		SDL_mutexV(mutex);
	}

public:
	SmartPointer() : obj(NULL), refCount(NULL), mutex(NULL) {
		//printf("SmartPointer::construc(%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		_SpecificInitFunctor()(this);
	}
	~SmartPointer() {
		//printf("SmartPointer::destruct(%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		reset();
	}<commit_msg>Safety hack in smartpointer (there's a crash somewhere, dunno if this fixes it though)<commit_after>/*
	OpenLieroX
	code under LGPL
	27-12-2007 <NAME>
*/

#ifndef __SMARTPOINTER_H__
#define __SMARTPOINTER_H__

#include <limits.h>
#include <assert.h>
#ifdef DEBUG_SMARTPTR
#include <map>
#ifdef __GLIBC__
#include <execinfo.h>
#endif
#endif


#include <SDL_thread.h>
#include "Utils.h"

template < typename _Type, typename _SpecificInitFunctor >
class SmartPointer;

// Default de-initialization action is to call operator delete, for each object type.
template < typename _Type >
void SmartPointer_ObjectDeinit( _Type * obj )
{
	delete obj;
};

// these forward-declaration are needed here
struct SDL_Surface;
struct SoundSample;
class CMap;
class CGameScript;

// Specialized de-init functions, for each simple struct-like type that has no destructor
template <> void SmartPointer_ObjectDeinit<SDL_Surface> ( SDL_Surface * obj ); // Calls gfxFreeSurface(obj);
template <> void SmartPointer_ObjectDeinit<SoundSample> ( SoundSample * obj ); // Calls FreeSoundSample(obj);
template <> void SmartPointer_ObjectDeinit<CMap> ( CMap * obj ); // Requires to be defined elsewhere
template <> void SmartPointer_ObjectDeinit<CGameScript> ( CGameScript * obj ); // Requires to be defined elsewhere


/*
	standard smartpointer based on simple refcounting

	The refcounting is multithreading safe in this class,
	you can have copies of this object in different threads.
	Though it's not designed to operate with the same
	object in different threads. Also there is absolutly no
	thread safty on the pointer itself, you have to care
	about this yourself.
*/

#ifdef DEBUG_SMARTPTR
extern std::map< void *, SDL_mutex * > SmartPointer_CollisionDetector;
#endif

template < typename _Type, typename _SpecificInitFunctor = NopFunctor<void*> >
class SmartPointer {
private:
	_Type* obj;
	int* refCount;
	SDL_mutex* mutex;

	void init(_Type* newObj) {
		#ifdef DEBUG_SMARTPTR
		printf("SmartPointer::init    (%10p %10p %10p %10p %3i) newObj %10p\n", this, obj, refCount, mutex, refCount?*refCount:-99, newObj);
		#endif
		if( newObj == NULL )
			return;
		if(!mutex) {
			mutex = SDL_CreateMutex();
			obj = newObj;
			refCount = new int;
			*refCount = 1;
			#ifdef DEBUG_SMARTPTR
			if( SmartPointer_CollisionDetector.find(obj) != SmartPointer_CollisionDetector.end() )
			{
				printf("ERROR! SmartPointer collision detected, old mutex %10p, new ptr (%10p %10p %10p %10p %3i) new %10p\n", SmartPointer_CollisionDetector[obj], this, obj, refCount, mutex, refCount?*refCount:-99, newObj);
				#ifdef __GLIBC__
				void *buffer[100];
				int nptrs = backtrace(buffer, 100);
				printf("backtrace() returned %d addresses\n", nptrs);
				backtrace_symbols_fd(buffer, nptrs, fileno(stdout));
				#endif
			}
			else
				SmartPointer_CollisionDetector.insert( std::make_pair( obj, mutex ) );
			#endif
		}
	}

	void reset() {
		#ifdef DEBUG_SMARTPTR
		printf("SmartPointer::reset   (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		#endif
		if(mutex) {
			lock();
			(*refCount)--;
			if(*refCount == 0) {
				#ifdef DEBUG_SMARTPTR
				if( SmartPointer_CollisionDetector.find(obj) == SmartPointer_CollisionDetector.end() )
				{
					printf("ERROR! SmartPointer already deleted reference (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
					#ifdef __GLIBC__
					void *buffer[100];
					int nptrs = backtrace(buffer, 100);
					printf("backtrace() returned %d addresses\n", nptrs);
					backtrace_symbols_fd(buffer, nptrs, fileno(stdout));
					#endif
				}
				else
					SmartPointer_CollisionDetector.erase(obj);
				#endif
				SmartPointer_ObjectDeinit( obj );
				delete refCount; // save, because there is no other ref anymore
				obj = NULL;
				refCount = NULL;
				unlock();
				SDL_DestroyMutex(mutex); // save because there is no other ref anymore
				mutex = NULL;
		 	} else
		 		unlock();
		}
		obj = NULL;
		refCount = NULL;
		mutex = NULL;
	}

	void incCounter() {
		assert(*refCount > 0 && *refCount < INT_MAX);
		(*refCount)++;
	}

	void lock() {
		//printf("SmartPointer::lock    (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		SDL_mutexP(mutex);
	}
	void unlock() {
		//printf("SmartPointer::unlock  (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		SDL_mutexV(mutex);
	}

public:
	SmartPointer() : obj(NULL), refCount(NULL), mutex(NULL) {
		//printf("SmartPointer::construc(%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		_SpecificInitFunctor()(this);
	}
	~SmartPointer() {
		//printf("SmartPointer::destruct(%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
		reset();
	}
{'fraction_non_alphanumeric': 0.12699418911780244, 'fraction_numerical': 0.024722662440570524, 'mean_word_length': 4.357102433503113, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1839763', 'n_tokens_mistral': 3733, 'n_tokens_neox': 3218, 'n_words': 889}