From 05ac30a59e64418b3d86661863b21ca24e47cced Mon Sep 17 00:00:00 2001
From: llea <llea>
Date: Thu, 14 Jul 2005 16:11:33 +0000
Subject: [PATCH] Fix tone by Jerome Oufella

---
 ChangeLog                           |   6 +
 src/audio/audiolayer.cpp            |   2 +-
 src/audio/ringbuffer.cpp            |   4 +-
 src/audio/tonegenerator.cpp         |  86 ++-
 src/gui/qt/qtGUImainwindow.cpp      |   5 +-
 src/manager.cpp                     | 864 ----------------------------
 src/sipvoiplink.cpp                 |   4 +-
 utilspp/lifetime_default.hpp        |  56 ++
 utilspp/lifetime_with_longevity.hpp |  59 ++
 utilspp/lifetime_with_longevity.inl |  67 +++
 utilspp/null_type.hpp               |  33 ++
 utilspp/private_members.hpp         |  98 ++++
 utilspp/private_members.inl         |  31 +
 utilspp/singleton_holder.inl~       | 124 ----
 utilspp/threading_single.hpp        |  74 +++
 15 files changed, 497 insertions(+), 1016 deletions(-)
 delete mode 100644 src/manager.cpp
 create mode 100644 utilspp/lifetime_default.hpp
 create mode 100644 utilspp/lifetime_with_longevity.hpp
 create mode 100644 utilspp/lifetime_with_longevity.inl
 create mode 100644 utilspp/null_type.hpp
 create mode 100644 utilspp/private_members.hpp
 create mode 100644 utilspp/private_members.inl
 delete mode 100644 utilspp/singleton_holder.inl~
 create mode 100644 utilspp/threading_single.hpp

diff --git a/ChangeLog b/ChangeLog
index 9b838436c7..20cc6cab3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Jerome OUFELLA (13 July 2005) version 0.4
+- Fix tone.
+
+Jean-Philippe Barette-LaPierre (13 July 2005) version 0.4
+- Change "Manager" to a singleton
+
 Laurielle LEA (13 July 2005) version 0.4
 - Fix bug if network is not available.
 - Fix apply skin feature
diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp
index 6f110b7056..9fdf1278f4 100644
--- a/src/audio/audiolayer.cpp
+++ b/src/audio/audiolayer.cpp
@@ -148,7 +148,7 @@ AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer,
 		}
 		_urgentRingBuffer.Get(out, SAMPLES_SIZE(toGet));
 		
-		// Consume the regular one as well
+		// Consume the regular one as well (same amount of bytes)
 		_mainSndRingBuffer.Discard(SAMPLES_SIZE(toGet));
 	}  
 	else {
diff --git a/src/audio/ringbuffer.cpp b/src/audio/ringbuffer.cpp
index 258e1d5108..71318875ba 100644
--- a/src/audio/ringbuffer.cpp
+++ b/src/audio/ringbuffer.cpp
@@ -10,6 +10,7 @@
   overestimate.
 
 **********************************************************************/
+#include <iostream>  //debug
 #include <assert.h>
 #include <stdlib.h> 
 #include <string.h>  
@@ -138,8 +139,7 @@ RingBuffer::Get(void *buffer, int toCopy) {
       if (block > mBufferSize - mStart)
          block = mBufferSize - mStart;
 
-	  bcopy (mBuffer + mStart, dest, block);
-
+      bcopy (mBuffer + mStart, dest, block);
       dest += block;
       mStart = (mStart + block) % mBufferSize;
       toCopy -= block;
diff --git a/src/audio/tonegenerator.cpp b/src/audio/tonegenerator.cpp
index 8a62cf23c9..197eb880f5 100644
--- a/src/audio/tonegenerator.cpp
+++ b/src/audio/tonegenerator.cpp
@@ -20,7 +20,7 @@
 #include <math.h> 
 #include <iostream>
 #include <fstream>
-#include <stdlib.h>  
+#include <stdlib.h>
  
 #include "audiolayer.h"
 #include "audiortp.h"
@@ -55,19 +55,31 @@ void
 ToneThread::run (void) {
 	int k;
 	int spkrVolume;
+	bool started = false;
+
+	// How long do 'size' samples play ?
+	unsigned int play_time = (size * 1000) / SAMPLING_RATE;
+
+	// Create a new stereo buffer with the volume adjusted
+	spkrVolume = mngr->getSpkrVolume();
+	for (int j = 0; j < size; j++) {
+		k = j*2;
+		buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = buffer[j] * spkrVolume/100;
+	}
+
 	while (Manager::instance().getZonetone()) {
-	  spkrVolume = Manager::instance().getSpkrVolume();
-		// control volume + mono->stereo
-		for (int j = 0; j < size; j++) {
-			k = j*2;
-			buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = buffer[j] * spkrVolume/100;
+		// Push the tone to the audio FIFO
+		Manager::instance().getAudioDriver()->mainSndRingBuffer().Put(buf_ctrl_vol, 
+			SAMPLES_SIZE(size));
+
+		// The first iteration will start the audio stream if not already.
+		if (!started) {
+			started = true;
+			Manager::instance().getAudioDriver()->startStream();
 		}
 		
-		if (Manager::instance().getAudioDriver()->mainSndRingBuffer().Len() == 0) {
-			Manager::instance().getAudioDriver()->mainSndRingBuffer().Put(buf_ctrl_vol, 
-					SAMPLES_SIZE(size));
-		}
-		Manager::instance().getAudioDriver()->startStream();
+		// next iteration later, sound is playing.
+		this->sleep (play_time);
 	}
 }
 
@@ -164,7 +176,7 @@ ToneGenerator::buildTone (int idCountry, int idTones, int16* temp) {
 	int	byte = 0,
 		byte_temp = 0;
 	static int	nbcomma = 0;
-	int16 *buffer = new int16[SIZEBUF];
+	int16 *buffer = new int16[SIZEBUF]; //1kb
 	int pos;
 
 	string str(toneZone[idCountry][idTones]);
@@ -172,35 +184,67 @@ ToneGenerator::buildTone (int idCountry, int idTones, int16* temp) {
 
 	// Number of format sections 
 	for (int i = 0; i < nbcomma + 1; i++) {
+		// Sample string: "350+440" or "350+440/2000,244+655/2000"
 		pos = str.find(',');
-		s = str.substr(0, pos);
-		pos = s.find('+');
+		if (pos < 0) { // no comma found
+			pos = str.length();
+		}
+
+		s = str.substr(0, pos); // 
+
+		// The 1st frequency is before the first +
+		int pos_freq2;	
+		pos_freq2 = pos = s.find('+');
+		if (pos < 0) {
+			pos = s.length(); // no + found
+		}
 		freq1 = atoi((s.substr(0, pos)).data());
-		freq2 = atoi((s.substr(pos + 1, s.find('/'))).data());
+
+		int pos2 = s.find('/');
+		if (pos2 < 0) {
+			pos2 = s.length();
+		}
+		if (pos_freq2 < 0) {
+			// freq2 was not found
+			freq2 = 0;
+		} else {
+			// freq2 was found and is after the +
+			freq2 = atoi( s.substr(pos + 1, pos2).data() );
+		}
+
 		pos = s.find('/');
-		time = atoi((s.substr(pos + 1, s.length())).data());
+		if (pos < 0) {
+			time = 0; // No time specified, tone will last forever.
+		} else {
+			time = atoi((s.substr(pos + 1, s.length())).data());
+		}
 		
-		// Generate sinus, buffer is the result
+		// Generate SAMPLING_RATE samples of sinus, buffer is the result
 		generateSin(freq1, freq2, buffer);
 		
 		// If there is time or if it's unlimited
-		if (time) {
-			byte = (SAMPLING_RATE*2*time)/1000;
+		if (time > 0) {
+			byte = (SAMPLING_RATE * 2 * time) / 1000;
 		} else {
 			byte = SAMPLING_RATE;
 		}
 		
 		// To concatenate the different buffers for each section.
+		count = 0;
 		for (int j = byte_temp * i; j < byte + (byte_temp * i); j++) {
 			temp[j] = buffer[count++];
 		}		
 		byte_temp = byte;
-		count = 0;
 		
 		str = str.substr(str.find(',') + 1, str.length());
 	}
+
 	// Total number in final buffer
-	totalbytes = byte + (byte_temp * (nbcomma+1));
+	if (byte != SAMPLING_RATE) {
+		totalbytes = byte + (byte_temp * (nbcomma+1));
+	} else {
+		totalbytes = byte;
+	}
 	delete[] buffer;
 }
 
diff --git a/src/gui/qt/qtGUImainwindow.cpp b/src/gui/qt/qtGUImainwindow.cpp
index 718b318f85..94edb06a61 100644
--- a/src/gui/qt/qtGUImainwindow.cpp
+++ b/src/gui/qt/qtGUImainwindow.cpp
@@ -1562,7 +1562,7 @@ QtGUIMainWindow::pressedKeySlot (int id) {
 	int k, spkrVolume;
 	int16* buf_ctrl_vol;
                                                                                 
-    // Stop dial tone
+    // Stop dial tone because we started dialing.
     if (_dialtone) {
         dialtone(false);
     }
@@ -1606,14 +1606,15 @@ QtGUIMainWindow::pressedKeySlot (int id) {
 		buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = _buf[j] * spkrVolume/100;
 	}
 		
-	// Counters  reset 
 	Manager::instance().getAudioDriver()->urgentRingBuffer().flush();
 	// Put buffer to urgentRingBuffer 
 	Manager::instance().getAudioDriver()->urgentRingBuffer().Put(buf_ctrl_vol, 
 			size * CHANNELS);
+
 	Manager::instance().getAudioDriver()->startStream();
 	Manager::instance().getAudioDriver()->sleep(pulselen);
 	Manager::instance().getAudioDriver()->stopStream();
+	Manager::instance().getAudioDriver()->urgentRingBuffer().flush();
 		
 	delete[] buf_ctrl_vol;
 }
diff --git a/src/manager.cpp b/src/manager.cpp
deleted file mode 100644
index b233778872..0000000000
--- a/src/manager.cpp
+++ /dev/null
@@ -1,864 +0,0 @@
-/**
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
- *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
- *                                                                              
- *  This program 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 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 General Public License for more details.
- *                                                                              
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <errno.h>
-#include <time.h>
-
-# include <sys/types.h> // mkdir(2)
-# include <sys/stat.h>	// mkdir(2)
-
-#include <sys/socket.h> // inet_ntoa()
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <cc++/thread.h>
-#include <cstdlib> 
-#include <iostream>
-#include <fstream> 
-#include <string>
-#include <vector>
-
-#include "manager.h"
-#include "audio/audiocodec.h"
-#include "audio/audiolayer.h"
-#include "audio/codecDescriptor.h"
-#include "audio/ringbuffer.h"
-#include "audio/tonegenerator.h"
-#include "call.h"
-#include "configuration.h"  
-#include "configurationtree.h" 
-#include "error.h"
-#include "sipvoiplink.h"
-#include "skin.h" 
-#include "user_cfg.h"
-#include "voIPLink.h" 
-#include "gui/guiframework.h"
-
-using namespace std;
-using namespace ost;
- 
-device_t Manager::deviceParam;
-
-Manager::Manager (void)
-{
-	// initialize random generator  
-  	srand (time(NULL));
-
-	// Init private variables 
-	_callVector = new CallVector();
-	_voIPLinkVector = new VoIPLinkVector();	
-	_error = new Error(this);
-	_tone = new ToneGenerator(this);	
-
-	// Set a sip voip link by default
-	_voIPLinkVector->push_back(new SipVoIPLink(DFT_VOIP_LINK, this));
-
-	_nCalls = 0;
-	_nCodecs = 0;
-	_currentCallId = 0;
-	_startTime = 0;
-	_endTime = 0;
-	_path = ""; 
-	_zonetone = false;
-	_congestion = false;
-	_ringtone = false;
-	_ringback = false;
-	_exist = 0;
-	_loaded = false;
-	
-	initConfigFile();
-	_exist = createSettingsPath();
-	if (_exist == 0) {
-		_debug("Cannot create config file in your home directory\n");
-	} 
-}
-
-Manager::~Manager (void) 
-{
-	delete _callVector;
-	delete _voIPLinkVector;			
-	delete _error;
-	delete _tone;
-	delete _codecDescVector; 
-	delete _audiodriverPA;
-} 
-
-void 
-Manager::init (void) 
-{
-	if (_exist == 2) {
-		// If config-file doesn't exist, launch configuration setup
-		_gui->setup();
-	}
-	initAudioCodec();
-
-	try {
-		selectAudioDriver();
-		loaded(true);
-	}
-	catch (const portaudio::PaException &e)
-	{
-		displayErrorText(e.paErrorText());
-	}
-	catch (const portaudio::PaCppException &e)
-	{
-		displayErrorText(e.what());
-	}
-	catch (const exception &e)
-	{
-		displayErrorText(e.what());
-	}
-	catch (...)
-	{ 
-		displayErrorText("An unknown exception occured.");
-	}
-	
-	_voIPLinkVector->at(DFT_VOIP_LINK)->init();
-
-	if (_voIPLinkVector->at(DFT_VOIP_LINK)->checkNetwork()) {
-	// If network is available
-		if (get_config_fields_int(SIGNALISATION, AUTO_REGISTER) == YES and 
-				_exist == 1) {
-			if (registerVoIPLink() != 1) {
-				_debug("Registration failed\n");
-				displayErrorText("Check your configuration fields");
-			}
-		} 
-	}
-}
-
-void
-Manager::setGui (GuiFramework* gui)
-{
-	_gui = gui;
-}
-
-ToneGenerator*
-Manager::getTonegenerator (void) 
-{
-	return _tone;
-}
-
-Error*
-Manager::error (void) 
-{
-	return _error;
-}
-
-AudioLayer*
-Manager::getAudioDriver(void) 
-{
-	return _audiodriverPA;
-}
-
-unsigned int 
-Manager::getNumberOfCalls (void)
-{
-	return _nCalls;
-}
-
-void 
-Manager::setNumberOfCalls (unsigned int nCalls)
-{
-	_nCalls = nCalls;
-}
-
-short
-Manager::getCurrentCallId (void)
-{
-	return _currentCallId;
-}
-
-void 
-Manager::setCurrentCallId (short currentCallId)
-{
-	_currentCallId = currentCallId;
-}
-
-CallVector* 
-Manager::getCallVector (void)
-{
-	return _callVector;
-}
-
-Call*
-Manager::getCall (short id)
-{
-	if (id > 0 and _callVector->size() > 0) {
-		for (unsigned int i = 0; i < _nCalls; i++) {
-			if (_callVector->at(i)->getId() == id) {
-				return _callVector->at(i);
-			}
-		}
-		return NULL;
-	} else {
-		return NULL;
-	}
-}
-
-
-unsigned int
-Manager::getNumberOfCodecs (void)
-{
-	return _nCodecs;
-}
-
-void
-Manager::setNumberOfCodecs (unsigned int nb_codec)
-{
-	_nCodecs = nb_codec;
-}
-
-VoIPLinkVector* 
-Manager::getVoIPLinkVector (void)
-{
-	return _voIPLinkVector;
-}
-
-CodecDescriptorVector*
-Manager::getCodecDescVector (void)
-{
-	return _codecDescVector;
-}
-
-void
-Manager::pushBackNewCall (short id, enum CallType type)
-{
-	Call* call = new Call(this, id, type, _voIPLinkVector->at(DFT_VOIP_LINK));
-	// Set the wanted voip-link (first of the list)
-	_callVector->push_back(call);
-}
-
-void
-Manager::deleteCall (short id)
-{
-	unsigned int i = 0;
-	while (i < _callVector->size()) {
-		if (_callVector->at(i)->getId() == id) {
-			_callVector->erase(_callVector->begin()+i);
-			return;
-		} else {
-			i++;
-		}
-	}
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Management of events' IP-phone user
-///////////////////////////////////////////////////////////////////////////////
-int 
-Manager::outgoingCall (const string& to)
-{	
-	short id;
-	Call* call;
-	
-	id = generateNewCallId();
-	pushBackNewCall(id, Outgoing);
-	
-	_debug("Outgoing Call with identifiant %d\n", id);
-	call = getCall(id);
-	if (call == NULL)
-		return 0;
-	
-	call->setStatus(string(TRYING_STATUS));
-	call->setState(Progressing);
-	if (call->outgoingCall(id, to) == 0) {
-		return id;
-	} else {
-		return 0;
-	}
-}
-
-int 
-Manager::hangupCall (short id)
-{
-	Call* call;
-
-	call = getCall(id);
-	if (call == NULL)
-		return -1;
-	call->setStatus(string(HUNGUP_STATUS));
-	call->setState(Hungup);
-	_mutex.enterMutex();
-	_nCalls -= 1;
-	_mutex.leaveMutex();
-	deleteCall(id);
-	if (getbRingback()) {
-		ringback(false);
-	}
-	return call->hangup();
-}
-
-int
-Manager::cancelCall (short id)
-{
-	Call* call;
-
-	call = getCall(id);
-	if (call == NULL)
-		return -1;
-	call->setStatus(string(HUNGUP_STATUS));
-	call->setState(Hungup);
-	_mutex.enterMutex();
-	_nCalls -= 1;
-	_mutex.leaveMutex();
-	deleteCall(id);
-	if (getbRingback()) {
-		ringback(false);
-	}
-	return call->cancel();
-}
-
-int 
-Manager::answerCall (short id)
-{
-	Call* call;
-
-	call = getCall(id);
-	if (call == NULL)
-		return -1;
-	call->setStatus(string(CONNECTED_STATUS));
-	call->setState(Answered);
-	ringtone(false);
-	return call->answer();
-}
-
-int 
-Manager::onHoldCall (short id)
-{
-	Call* call;
-	call = getCall(id);
-	if (call == NULL)
-		return -1;
-	call->setStatus(string(ONHOLD_STATUS));
-	call->setState(OnHold);
-	return call->onHold();
-}
-
-int 
-Manager::offHoldCall (short id)
-{
-	Call* call;
-	call = getCall(id);
-	if (call == NULL)
-		return -1;
-	call->setStatus(string(CONNECTED_STATUS));
-	call->setState(OffHold);
-	return call->offHold();	
-}
-
-int 
-Manager::transferCall (short id, const string& to)
-{
-	Call* call;
-	call = getCall(id);
-	if (call == NULL)
-		return -1;
-	call->setStatus(string(TRANSFER_STATUS));
-	call->setState(Transfered);
-	if (call->transfer(to) != 0) {
-		return -1;
-	} else {
-		return 1;
-	}
-}
-
-void 
-Manager::muteOn (short id)
-{
-	Call* call;
-	call = getCall(id);
-	if (call == NULL)
-		return;
-	call->setStatus(string(MUTE_ON_STATUS));
-	call->setState(MuteOn);
-}
-
-void 
-Manager::muteOff (short id)
-{
-	Call* call;
-	call = getCall(id);
-	if (call == NULL)
-		return;
-	call->setStatus(string(CONNECTED_STATUS));
-	call->setState(MuteOff);
-}
-
-int 
-Manager::refuseCall (short id)
-{
-	Call *call;
-	call = getCall(id);
-	if (call == NULL)
-		return -1;
-	call->setStatus(string(HUNGUP_STATUS));
-	call->setState(Refused);	
-	ringtone(false);
-	delete call;
-	return call->refuse();
-}
-
-int
-Manager::saveConfig (void)
-{
-	return (Config::tree()->saveToFile(_path.data()) ? 1 : 0);
-}
-
-int 
-Manager::registerVoIPLink (void)
-{
-	if (_voIPLinkVector->at(DFT_VOIP_LINK)->setRegister() == 0) {
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-int 
-Manager::quitApplication (void)
-{
-	// Quit VoIP-link library
-	_voIPLinkVector->at(DFT_VOIP_LINK)->quit();
-	if (saveConfig()) {
-		Config::deleteTree();
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-int 
-Manager::sendTextMessage (short , const string& )
-{
-	return 1;
-}
-
-int 
-Manager::accessToDirectory (void)
-{
-	return 1;
-}
-
-int 
-Manager::sendDtmf (short id, char code)
-{
-	int sendType = get_config_fields_int(SIGNALISATION, SEND_DTMF_AS);
-                                                                                
-    switch (sendType) {
-        // SIP INFO
-        case 0:
-			_voIPLinkVector->at(DFT_VOIP_LINK)->carryingDTMFdigits(id, code);
-			return 1;
-            break;
-                                                                                
-        // Audio way
-        case 1:
-			return 1;
-            break;
-                                                                                
-        // rfc 2833
-        case 2:
-			return 1;
-            break;
-                                                                                
-        default:
-			return -1;
-            break;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Management of event peer IP-phone 
-///////////////////////////////////////////////////////////////////////////////
-
-int 
-Manager::incomingCall (short id)
-{
-	Call* call;
-	call = getCall(id);
-	if (call == NULL)
-		return -1;
-	call->setType(Incoming);
-	call->setStatus(string(RINGING_STATUS));
-	call->setState(Progressing);
-	ringtone(true);
-	displayStatus(RINGING_STATUS);
-	return _gui->incomingCall(id);
-}
-
-// L'autre personne a repondu
-void 
-Manager::peerAnsweredCall (short id)
-{
-	Call* call;
-
-	if (getbRingback()) {
-		ringback(false);
-	}	
-	call = getCall(id);
-	call->setStatus(string(CONNECTED_STATUS));
-
-	call->setState(Answered);
-	if (isCurrentId(id)) {
-		_gui->peerAnsweredCall(id);
-	}
-}
-
-int 
-Manager::peerRingingCall (short id)
-{
-	Call* call;
-
-	call = getCall(id);
-	call->setStatus(string(RINGING_STATUS));
-	call->setState(Ringing);
-
-	ringback(true);
-	_gui->peerRingingCall(id);
-	displayStatus(RINGING_STATUS);	
-	return 1;
-}
-
-int 
-Manager::peerHungupCall (short id)
-{
-	Call* call;
-
-	call = getCall(id);
-	call->setStatus(string(HUNGUP_STATUS));
-	call->setState(Hungup);
-	_gui->peerHungupCall(id);
-	if (getbRingback()) {
-		ringback(false);
-	}
-	_mutex.enterMutex();
-	_nCalls -= 1;
-	_mutex.leaveMutex();
-	deleteCall(id);
-	return 1;
-}
-
-void 
-Manager::displayTextMessage (short id, const string& message)
-{
-	_gui->displayTextMessage(id, message);
-}
-
-void 
-Manager::displayErrorText (const string& message)
-{
-	_gui->displayErrorText(message);
-}
-
-void 
-Manager::displayError (const string& error)
-{
-	_gui->displayStatus(error);
-}
-
-void 
-Manager::displayStatus (const string& status)
-{
-	_gui->displayStatus(status);
-}
-
-int
-Manager::selectedCall (void) 
-{
-	return _gui->selectedCall();
-}
-
-bool
-Manager::isCurrentId (short id)
-{
-	return _gui->isCurrentId(id);
-}
-
-void
-Manager::congestion (bool var) {
-	if (isDriverLoaded()) {
-		if (_congestion != var) {
-			_congestion = var;
-		}
-		_zonetone = var;
-		_tone->toneHandle(ZT_TONE_CONGESTION);
-	} else {
-        _error->errorName(OPEN_FAILED_DEVICE);
-    }
-}
-
-void
-Manager::ringback (bool var) {
-	if (isDriverLoaded()) {
-		if (_ringback != var) {
-			_ringback = var;
-		}
-		_zonetone = var;
-		_tone->toneHandle(ZT_TONE_RINGTONE);
-	} else {
-        _error->errorName(OPEN_FAILED_DEVICE);
-    }
-}
-
-void
-Manager::ringtone (bool var) 
-{ 
-	if (isDriverLoaded()) {
-		if (getNumberOfCalls() > 1 and _zonetone and var == false) {
-			// If more than one line is ringing
-			_zonetone = false;
-			_tone->playRingtone((_gui->getRingtoneFile()).data());
-		}
-		
-		if (_ringtone != var) {
-			_ringtone = var;
-		}
-																					
-		_zonetone = var;
-		if (getNumberOfCalls() == 1) {
-			// If just one line is ringing
-			_tone->playRingtone((_gui->getRingtoneFile()).data());
-		} 
-	} else {
-        _error->errorName(OPEN_FAILED_DEVICE);
-    }
-}
-
-void
-Manager::notificationIncomingCall (void) {
-    int16* buf_ctrl_vol;
-    int16* buffer = new int16[SAMPLING_RATE];
-	int size = SAMPLING_RATE/2;
-	int k, spkrVolume;
-                                                                                
-    _tone->generateSin(440, 0, buffer);
-           
-	// Control volume
-	buf_ctrl_vol = new int16[size];
-	spkrVolume = getSpkrVolume();
-	for (int j = 0; j < size; j++) {
-		k = j*2;
-		buf_ctrl_vol[k] = buf_ctrl_vol[k+1] = buffer[j] * spkrVolume/100;
-	}
-	
-	getAudioDriver()->urgentRingBuffer()->Put(buf_ctrl_vol, 
-			size * CHANNELS);
-
-	getAudioDriver()->startStream();
-	getAudioDriver()->sleep(NOTIFICATION_LEN);
-	getAudioDriver()->stopStream();
-	
-    delete[] buffer;
-    delete[] buf_ctrl_vol;
-}
-
-void
-Manager::getStunInfo (StunAddress4& stunSvrAddr) {
-    StunAddress4 mappedAddr;
-	struct in_addr in;
-	char* addr;
-	char to[16];
-	bzero (to, 16);
-                                                                                
-    int fd3, fd4;
-    bool ok = stunOpenSocketPair(stunSvrAddr,
-                                      &mappedAddr,
-                                      &fd3,
-                                      &fd4);
-    if (ok) {
-        closesocket(fd3);
-        closesocket(fd4);
-        _debug("Got port pair at %d\n", mappedAddr.port);
-        _firewallPort = mappedAddr.port;
-		
-		// Convert ipv4 address to host byte ordering
-		in.s_addr = ntohl (mappedAddr.addr);
-		addr = inet_ntoa(in);
-        _firewallAddr = string(addr);
-        _debug("address firewall = %s\n",_firewallAddr.data());
-    } else {
-        _debug("Opened a stun socket pair FAILED\n");
-    }
-}
-
-device_t
-Manager::deviceList (int index)
-{
-	portaudio::AutoSystem autoSys;
-	portaudio::System &sys = portaudio::System::instance(); 
-	deviceParam.hostApiName = sys.deviceByIndex(index).hostApi().name();
-	deviceParam.deviceName = sys.deviceByIndex(index).name();
-	return deviceParam;
-}
-
-int
-Manager::deviceCount (void)
-{
-	int numDevices = 0;
-	
-	portaudio::AutoSystem autoSys;
-	portaudio::System &sys = portaudio::System::instance();
-	numDevices = sys.deviceCount();
-	return numDevices;	
-}
-
-bool
-Manager::defaultDevice (int index) 
-{
-	bool defaultDisplayed = false;
-
-	portaudio::AutoSystem autoSys;
-	portaudio::System &sys = portaudio::System::instance(); 
-	if (sys.deviceByIndex(index).isSystemDefaultInputDevice()) {
-		defaultDisplayed = true;
-	}
-	return defaultDisplayed;
-}
-
-bool
-Manager::useStun (void) {
-    if (get_config_fields_int(SIGNALISATION, USE_STUN) == YES) {
-        return true;
-    } else {
-        return false;
-    }
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Private functions
-///////////////////////////////////////////////////////////////////////////////
-
-short 
-Manager::generateNewCallId (void)
-{
-	short random_id = rand();  
-	
-	// Check if already a call with this id exists 
-	while (getCall(random_id) != NULL or random_id <= 0) {
-		random_id = rand();
-	}
-	_mutex.enterMutex();
-	_nCalls += 1;
-	_mutex.leaveMutex();
-	// If random_id is not attributed, returns it.
-	return random_id;
-}
-
-unsigned int 
-Manager::callVectorSize (void)
-{
-	return _callVector->size();
-}
-
-int
-Manager::createSettingsPath (void) {
-	int exist = 1;
-  	_path = string(HOMEDIR) + "/." + PROGNAME;
-             
-  	if (mkdir (_path.data(), 0755) != 0) {
-		// If directory	creation failed
-    	if (errno != EEXIST) {
-			_debug("Cannot create directory: %d\n", strerror(errno));
-			return -1;
-      	} 	
-  	} 
-
-	// Load user's config
-	_path = _path + "/" + PROGNAME + "rc";
-
-	exist = Config::tree()->populateFromFile(_path);
-	
-	if (exist == 0){
-		// If populateFromFile failed
-		return 0;
-	} else if (exist == 2) {
-		// If  file doesn't exist yet
-		return 2;
-	}
-	return exist;
-}
-
-void
-Manager::initConfigFile (void) 
-{
-	fill_config_fields_int(SIGNALISATION, VOIP_LINK_ID, DFT_VOIP_LINK); 	
-	fill_config_fields_str(SIGNALISATION, FULL_NAME, EMPTY_FIELD);
-	fill_config_fields_str(SIGNALISATION, USER_PART, EMPTY_FIELD); 
-	fill_config_fields_str(SIGNALISATION, AUTH_USER_NAME, EMPTY_FIELD); 
-	fill_config_fields_str(SIGNALISATION, PASSWORD, EMPTY_FIELD); 
-	fill_config_fields_str(SIGNALISATION, HOST_PART, EMPTY_FIELD); 
-	fill_config_fields_str(SIGNALISATION, PROXY, EMPTY_FIELD); 
-	fill_config_fields_int(SIGNALISATION, AUTO_REGISTER, YES);
-	fill_config_fields_int(SIGNALISATION, PLAY_TONES, YES); 
-	fill_config_fields_int(SIGNALISATION, PULSE_LENGTH, DFT_PULSE_LENGTH); 
-	fill_config_fields_int(SIGNALISATION, SEND_DTMF_AS, SIP_INFO); 
-	fill_config_fields_str(SIGNALISATION, STUN_SERVER, DFT_STUN_SERVER); 
-	fill_config_fields_int(SIGNALISATION, USE_STUN, NO); 
-
-	fill_config_fields_int(AUDIO, DRIVER_NAME, DFT_DRIVER); 
-	fill_config_fields_int(AUDIO, NB_CODEC, DFT_NB_CODEC); 
-	fill_config_fields_str(AUDIO, CODEC1, DFT_CODEC); 
-	fill_config_fields_str(AUDIO, CODEC2, DFT_CODEC); 
-	fill_config_fields_str(AUDIO, CODEC3, DFT_CODEC); 
-	fill_config_fields_str(AUDIO, CODEC4, DFT_CODEC); 
-	fill_config_fields_str(AUDIO, CODEC5, DFT_CODEC); 
-	fill_config_fields_str(AUDIO, RING_CHOICE, DFT_RINGTONE); 
-	fill_config_fields_int(AUDIO, VOLUME_SPKR_X, DFT_VOL_SPKR_X); 
-	fill_config_fields_int(AUDIO, VOLUME_SPKR_Y, DFT_VOL_SPKR_Y); 
-	fill_config_fields_int(AUDIO, VOLUME_MICRO_X, DFT_VOL_MICRO_X); 
-	fill_config_fields_int(AUDIO, VOLUME_MICRO_Y, DFT_VOL_MICRO_Y); 
-
-	fill_config_fields_str(PREFERENCES, SKIN_CHOICE, DFT_SKIN); 
-	fill_config_fields_int(PREFERENCES, CONFIRM_QUIT, YES); 
-	fill_config_fields_str(PREFERENCES, ZONE_TONE, DFT_ZONE); 
-	fill_config_fields_int(PREFERENCES, CHECKED_TRAY, NO); 
-	fill_config_fields_str(PREFERENCES, VOICEMAIL_NUM, DFT_VOICEMAIL); 
-}
-
-void
-Manager::initAudioCodec (void)
-{
-	_nCodecs = get_config_fields_int(AUDIO, NB_CODEC);
-	_codecDescVector = new CodecDescriptorVector();
-	
-	_codecDescVector->push_back(new CodecDescriptor(
-				get_config_fields_str(AUDIO, CODEC1)));
-
-	_codecDescVector->push_back(new CodecDescriptor(
-				get_config_fields_str(AUDIO, CODEC2)));
-	
-	_codecDescVector->push_back(new CodecDescriptor(
-				get_config_fields_str(AUDIO, CODEC3)));
-}
-
-void
-Manager::selectAudioDriver (void)
-{
-	
-#if defined(AUDIO_PORTAUDIO)
-	_audiodriverPA = new AudioLayer(this);
-	_audiodriverPA->openDevice(get_config_fields_int(AUDIO, DRIVER_NAME));
-#else
-# error You must define one AUDIO driver to use.
-#endif
-}
-
-// EOF
diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp
index af8cc18824..c7c3852a16 100644
--- a/src/sipvoiplink.cpp
+++ b/src/sipvoiplink.cpp
@@ -285,7 +285,7 @@ SipVoIPLink::answer (short id)
 int
 SipVoIPLink::hangup (short id) 
 {
-	int i = 1;
+	int i = 0;
 	if (!Manager::instance().getbCongestion()) {
 		_debug("Hang up call [id = %d, cid = %d, did = %d]\n", 
 				id, getSipCall(id)->getCid(), getSipCall(id)->getDid());	
@@ -306,7 +306,7 @@ SipVoIPLink::hangup (short id)
 int
 SipVoIPLink::cancel (short id) 
 {
-	int i = 1;
+	int i = 0;
 	if (!Manager::instance().getbCongestion()) {
 		_debug("Cancel call [id = %d, cid = %d]\n", id, getCid());
 		// Release SIP stack.
diff --git a/utilspp/lifetime_default.hpp b/utilspp/lifetime_default.hpp
new file mode 100644
index 0000000000..b0815c60ae
--- /dev/null
+++ b/utilspp/lifetime_default.hpp
@@ -0,0 +1,56 @@
+/*
+ *    Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre>
+ *    
+ *    Permission is hereby granted, free of charge, to any person obtaining
+ *    a copy of this software and associated documentation files 
+ *    (cURLpp), to deal in the Software without restriction, 
+ *    including without limitation the rights to use, copy, modify, merge,
+ *    publish, distribute, sublicense, and/or sell copies of the Software,
+ *    and to permit persons to whom the Software is furnished to do so, 
+ *    subject to the following conditions:
+ *    
+ *    The above copyright notice and this permission notice shall be included
+ *    in all copies or substantial portions of the Software.
+ *    
+ *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ *    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+ *    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+ *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+ *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIFETIME_DEFAULT_HPP
+#define LIFETIME_DEFAULT_HPP
+
+#include <stdexcept>
+#include <cstdlib>
+
+namespace utilspp
+{
+   template< typename T >
+   class lifetime_default
+   {
+      public:
+         static void schedule_destruction( T *obj, void (*func)() );
+         static void on_dead_reference();
+   };
+};
+
+template< typename T >
+void 
+utilspp::lifetime_default< T >::schedule_destruction( T *, void (*func)() )
+{
+   std::atexit(func);
+}
+
+template< typename T >
+void
+utilspp::lifetime_default< T >::on_dead_reference()
+{
+   throw std::logic_error( "Dead reference detected" );
+}
+
+#endif
+
diff --git a/utilspp/lifetime_with_longevity.hpp b/utilspp/lifetime_with_longevity.hpp
new file mode 100644
index 0000000000..eb75a87f42
--- /dev/null
+++ b/utilspp/lifetime_with_longevity.hpp
@@ -0,0 +1,59 @@
+/*
+ *    Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre>
+ *    
+ *    Permission is hereby granted, free of charge, to any person obtaining
+ *    a copy of this software and associated documentation files 
+ *    (cURLpp), to deal in the Software without restriction, 
+ *    including without limitation the rights to use, copy, modify, merge,
+ *    publish, distribute, sublicense, and/or sell copies of the Software,
+ *    and to permit persons to whom the Software is furnished to do so, 
+ *    subject to the following conditions:
+ *    
+ *    The above copyright notice and this permission notice shall be included
+ *    in all copies or substantial portions of the Software.
+ *    
+ *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ *    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+ *    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+ *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+ *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIFETIME_WITH_LONGEVITY_HPP
+#define LIFETIME_WITH_LONGEVITY_HPP
+
+#include <cassert>
+
+#include "private_members.hpp"
+
+namespace utilspp
+{
+   
+   template< typename T >
+   unsigned int get_longevity( T *p );
+
+   /**
+    * Assigns an object a longevity. Ensures ordered destructions of objects
+    * registered thusly during the exit sequence of the application.
+    */
+   template< typename T, typename T_destroyer >
+      void set_longevity( 
+            T *obj, 
+            unsigned int longevity, 
+            T_destroyer d = utilspp::private_members::deleter< T >::delete_object
+            );
+
+   template< typename T >
+      struct lifetime_with_longevity
+      {
+         static void schedule_destruction( T *obj, void (*func)() );
+         static void on_dead_reference();
+      };
+};
+
+#include "lifetime_with_longevity.inl"
+
+#endif
+
diff --git a/utilspp/lifetime_with_longevity.inl b/utilspp/lifetime_with_longevity.inl
new file mode 100644
index 0000000000..66e7817255
--- /dev/null
+++ b/utilspp/lifetime_with_longevity.inl
@@ -0,0 +1,67 @@
+template< typename T, typename T_destroyer >
+void
+utilspp::set_longevity( T *obj, unsigned int longevity, T_destroyer d )
+{
+   using namespace utilspp::private_members;
+
+   tracker_array new_array = static_cast< tracker_array >( 
+         std::realloc( 
+            m_tracker_array, 
+            m_nb_elements + 1
+            )
+         );
+   if( new_array == NULL )
+   {
+      throw std::bad_alloc();
+   }
+
+   lifetime_tracker *p = new concrete_lifetime_tracker< T, T_destroyer >( 
+         obj,
+         longevity,
+         d
+         );
+
+   m_tracker_array = new_array;
+
+   tracker_array pos = std::upper_bound( 
+         m_tracker_array, 
+         m_tracker_array + m_nb_elements,
+         p,
+         &lifetime_tracker::compare
+         );
+   std::copy_backward( 
+         pos, 
+         m_tracker_array + m_nb_elements, 
+         m_tracker_array + m_nb_elements + 1
+         );
+
+   *pos = p;
+   m_nb_elements++;
+   std::atexit( &at_exit_func );
+};
+
+template< typename T >
+void 
+utilspp::lifetime_with_longevity< T >::schedule_destruction( T *obj, void (*func)() )
+{
+   utilspp::private_members::adapter<T> adapter = { func };
+   utilspp::set_longevity( obj, get_longevity( obj ), adapter );
+}
+
+template< typename T >
+void 
+utilspp::lifetime_with_longevity< T >::on_dead_reference()
+{
+   throw std::logic_error("Dead reference detected");
+}
+
+template< typename T >
+unsigned int 
+utilspp::get_longevity( T * )
+{
+   return 1000;
+}
+
+
+
+
diff --git a/utilspp/null_type.hpp b/utilspp/null_type.hpp
new file mode 100644
index 0000000000..f294ef2426
--- /dev/null
+++ b/utilspp/null_type.hpp
@@ -0,0 +1,33 @@
+/*
+ *    Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre>
+ *    
+ *    Permission is hereby granted, free of charge, to any person obtaining
+ *    a copy of this software and associated documentation files 
+ *    (cURLpp), to deal in the Software without restriction, 
+ *    including without limitation the rights to use, copy, modify, merge,
+ *    publish, distribute, sublicense, and/or sell copies of the Software,
+ *    and to permit persons to whom the Software is furnished to do so, 
+ *    subject to the following conditions:
+ *    
+ *    The above copyright notice and this permission notice shall be included
+ *    in all copies or substantial portions of the Software.
+ *    
+ *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ *    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+ *    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+ *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+ *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef NULL_TYPE_HPP
+#define NULL_TYPE_HPP
+
+namespace utilspp
+{
+	class null_type;
+};
+
+#endif
+
diff --git a/utilspp/private_members.hpp b/utilspp/private_members.hpp
new file mode 100644
index 0000000000..192f090145
--- /dev/null
+++ b/utilspp/private_members.hpp
@@ -0,0 +1,98 @@
+/*
+ *    Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre>
+ *    
+ *    Permission is hereby granted, free of charge, to any person obtaining
+ *    a copy of this software and associated documentation files 
+ *    (cURLpp), to deal in the Software without restriction, 
+ *    including without limitation the rights to use, copy, modify, merge,
+ *    publish, distribute, sublicense, and/or sell copies of the Software,
+ *    and to permit persons to whom the Software is furnished to do so, 
+ *    subject to the following conditions:
+ *    
+ *    The above copyright notice and this permission notice shall be included
+ *    in all copies or substantial portions of the Software.
+ *    
+ *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ *    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+ *    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+ *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+ *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PRIVATE_MEMBERS_HPP
+#define PRIVATE_MEMBERS_HPP
+
+#include <cassert>
+
+namespace utilspp
+{
+   namespace private_members
+   {
+      /**
+       * Helper class for utils::set_longevity
+       */
+      class lifetime_tracker
+      {
+         public:
+            lifetime_tracker( unsigned int longevity );
+            virtual ~lifetime_tracker();
+            static bool compare( 
+                  const lifetime_tracker *l, 
+                  const lifetime_tracker *r
+                  );
+
+         private:
+            unsigned int m_longevity;
+      };
+
+      typedef lifetime_tracker** tracker_array;
+
+      extern tracker_array m_tracker_array;
+      extern int m_nb_elements;
+
+         /**
+          * Helper class for Destroyer
+          */
+         template< typename T >
+         struct deleter
+         {
+            void delete_object( T *obj );
+         };
+
+      /**
+       * Concrete lifetime tracker for objects of type T
+       */
+      template< typename T, typename T_destroyer >
+         class concrete_lifetime_tracker : public lifetime_tracker
+         {
+            public:
+               concrete_lifetime_tracker( 
+                     T *obj, 
+                     unsigned int longevity,
+                     T_destroyer d
+                     );
+
+               ~concrete_lifetime_tracker();
+
+            private:
+               T* m_tracked;
+               T_destroyer m_destroyer;
+         };
+
+      void at_exit_func();
+
+      template <class T>
+         struct adapter
+         {
+            void operator()(T*);
+            void (*m_func)();
+         };
+   };
+};
+
+#include "private_members.inl"
+
+#endif
+
diff --git a/utilspp/private_members.inl b/utilspp/private_members.inl
new file mode 100644
index 0000000000..d4c4539180
--- /dev/null
+++ b/utilspp/private_members.inl
@@ -0,0 +1,31 @@
+template< typename T >
+void
+utilspp::private_members::deleter< T >::delete_object( T *obj )
+{
+   delete obj;
+}
+
+template< typename T, typename T_destroyer >
+utilspp::private_members::concrete_lifetime_tracker< T, T_destroyer >::concrete_lifetime_tracker( 
+      T *obj,
+      unsigned int longevity,
+      T_destroyer d
+      ) 
+: lifetime_tracker( longevity )
+, m_tracked( obj )
+, m_destroyer( d )
+{}
+
+template< typename T, typename T_destroyer >
+utilspp::private_members::concrete_lifetime_tracker< T, T_destroyer >::~concrete_lifetime_tracker()
+{
+   m_destroyer( m_tracked );
+}
+
+
+template < typename T >
+void
+utilspp::private_members::adapter< T >::operator()(T*) 
+{ 
+   return (*m_func)(); 
+}
diff --git a/utilspp/singleton_holder.inl~ b/utilspp/singleton_holder.inl~
deleted file mode 100644
index 06d4a6460a..0000000000
--- a/utilspp/singleton_holder.inl~
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *    Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre>
- *    
- *    Permission is hereby granted, free of charge, to any person obtaining
- *    a copy of this software and associated documentation files 
- *    (cURLpp), to deal in the Software without restriction, 
- *    including without limitation the rights to use, copy, modify, merge,
- *    publish, distribute, sublicense, and/or sell copies of the Software,
- *    and to permit persons to whom the Software is furnished to do so, 
- *    subject to the following conditions:
- *    
- *    The above copyright notice and this permission notice shall be included
- *    in all copies or substantial portions of the Software.
- *    
- *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- *    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
- *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
- *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SINGLETON_HOLDER_INL
-#define SINGLETON_HOLDER_INL
-
-template
-<
-class T,
-template < class > class T_creation_policy,
-template < class > class T_lifetime_policy,
-template < class > class T_threading_model
->
-T&
-utilspp::singleton_holder
-<
-T,
-T_creation_policy,
-T_lifetime_policy,
-T_threading_model
->
-::instance()
-{
-    if ( m_instance == NULL )
-    {
-        make_instance();
-    }
-
-    return ( *m_instance );
-};
-
-template
-<
-class T,
-template < class > class T_creation_policy,
-template < class > class T_lifetime_policy,
-template < class > class T_threading_model
->
-void
-utilspp::singleton_holder
-<
-T,
-T_creation_policy,
-T_lifetime_policy,
-T_threading_model
->::make_instance()
-{
-    typename T_threading_model< T >::lock guard;
-(void)guard;
-
-    if ( m_instance == NULL )
-    {
-        if ( m_destroyed )
-        {
-            T_lifetime_policy< T >::on_dead_reference();
-            m_destroyed = false;
-        }
-
-        m_instance = T_creation_policy< T >::create();
-        T_lifetime_policy< T >::schedule_destruction( m_instance, &destroy_singleton );
-    }
-}
-
-template
-<
-class T,
-template < class > class T_creation_policy,
-template < class > class T_lifetime_policy,
-template < class > class T_threading_model
->
-void
-utilspp::singleton_holder
-<
-T,
-T_creation_policy,
-T_lifetime_policy,
-T_threading_model
->
-::destroy_singleton()
-{
-    assert( !m_destroyed );
-    T_creation_policy< T >::destroy( m_instance );
-    m_instance = NULL;
-    m_destroyed = true;
-}
-
-template < class T,
-template < class > class C,
-template < class > class L,
-template < class > class M
->
-typename utilspp::singleton_holder< T, C, L, M>::instance_type
-utilspp::singleton_holder< T, C, L, M >::m_instance;
-
-template
-<
-class T,
-template < class > class C,
-template < class > class L,
-template < class > class M
->
-bool utilspp::singleton_holder< T, C, L, M >::m_destroyed;
-
-#endif
diff --git a/utilspp/threading_single.hpp b/utilspp/threading_single.hpp
new file mode 100644
index 0000000000..1923bd1b8d
--- /dev/null
+++ b/utilspp/threading_single.hpp
@@ -0,0 +1,74 @@
+/*
+ *    Copyright (c) <2002-2004> <Jean-Philippe Barrette-LaPierre>
+ *    
+ *    Permission is hereby granted, free of charge, to any person obtaining
+ *    a copy of this software and associated documentation files 
+ *    (cURLpp), to deal in the Software without restriction, 
+ *    including without limitation the rights to use, copy, modify, merge,
+ *    publish, distribute, sublicense, and/or sell copies of the Software,
+ *    and to permit persons to whom the Software is furnished to do so, 
+ *    subject to the following conditions:
+ *    
+ *    The above copyright notice and this permission notice shall be included
+ *    in all copies or substantial portions of the Software.
+ *    
+ *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ *    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+ *    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+ *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+ *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SINGLE_THREADED_HPP
+#define SINGLE_THREADED_HPP
+
+#include "null_type.hpp"
+
+namespace utilspp
+{
+   template < typename T = utilspp::null_type >
+      struct threading_single
+      {
+         struct mutex
+         {
+            void lock();
+            void unlock();
+         };
+         
+         struct lock
+         {
+            lock();
+            lock( mutex &m );
+         };
+
+         typedef T volatile_type;
+      };
+};
+
+template< typename T >
+inline
+utilspp::threading_single< T >::lock::lock()
+{};
+
+template< typename T >
+inline
+utilspp::threading_single< T >::lock::lock( 
+      utilspp::threading_single< T >::mutex & )
+{}
+
+template< typename T >
+inline
+void
+utilspp::threading_single< T >::mutex::lock()
+{};
+
+template< typename T >
+inline
+void
+utilspp::threading_single< T >::mutex::unlock()
+{};
+
+#endif
+
-- 
GitLab