[Scummvm-cvs-logs] CVS: residual timer.cpp,NONE,1.1 timer.h,NONE,1.1 main.cpp,1.16,1.17 residual.vcproj,1.11,1.12 stdafx.h,1.2,1.3

Pawel Kolodziejski aquadran at users.sourceforge.net
Fri Dec 12 13:39:01 CET 2003


Update of /cvsroot/scummvm/residual
In directory sc8-pr-cvs1:/tmp/cvs-serv17288

Modified Files:
	main.cpp residual.vcproj stdafx.h 
Added Files:
	timer.cpp timer.h 
Log Message:
added timer code

--- NEW FILE: timer.cpp ---
// Residual - Virtual machine to run LucasArts' 3D adventure games
// Copyright (C) 2003 The ScummVM-Residual Team (www.scummvm.org)
//
//  This library 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 2.1 of the License, or (at your option) any later version.
//
//  This library 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 library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

#include "stdafx.h"
#include "bits.h"
#include "timer.h"
#include "debug.h"
#include <SDL.h>

Timer *g_timer = NULL;

Timer::Timer() :
	_mutex(0),
	_timerHandler(0),
	_lastTime(0) {

	create_mutex();

	g_timer = this;

	for (int i = 0; i < MAX_TIMERS; i++) {
		_timerSlots[i].procedure = NULL;
		_timerSlots[i].interval = 0;
		_timerSlots[i].counter = 0;
	}

	_thisTime = SDL_GetTicks();

	// Set the timer last, after everything has been initialised
	SDL_SetTimer(10, (SDL_TimerCallback) timer_handler);
}

Timer::~Timer() {
	SDL_SetTimer(0, NULL);

	{
		StackLock lock(_mutex);
		for (int i = 0; i < MAX_TIMERS; i++) {
			_timerSlots[i].procedure = NULL;
			_timerSlots[i].interval = 0;
			_timerSlots[i].counter = 0;
		}
	}


	// FIXME: There is still a potential race condition here, depending on how
	// the system backend implements set_timer: If timers are done using
	// threads, and if set_timer does *not* gurantee that after it terminates
	// that timer thread is not run anymore, we are fine. However, if the timer
	// is still running in parallel to this destructor, then it might be that
	// it is still waiting for the _mutex. So, again depending on the backend,
	// we might end up unlocking the mutex then immediately deleting it, while
	// the timer thread is about to lock it.
	delete_mutex(_mutex);
}

int Timer::timer_handler(int t) {
	if (g_timer)
		return g_timer->handler(t);
	return 0;
}

int Timer::handler(int t) {
	StackLock lock(_mutex);
	uint32 interval, l;

	_lastTime = _thisTime;
	_thisTime = SDL_GetTicks();
	interval = 1000 * (_thisTime - _lastTime);

	for (l = 0; l < MAX_TIMERS; l++) {
		if (_timerSlots[l].procedure && _timerSlots[l].interval > 0) {
			_timerSlots[l].counter -= interval;
			while (_timerSlots[l].counter <= 0) {
				// A small paranoia check which catches the case where
				// a timer removes itself (which it never should do).
				assert(_timerSlots[l].procedure && _timerSlots[l].interval > 0);
				_timerSlots[l].counter += _timerSlots[l].interval;
				_timerSlots[l].procedure(_timerSlots[l].refCon);
			}
		}
	}

	return t;
}

bool Timer::installTimerProc(TimerProc procedure, int32 interval, void *refCon) {
	assert(interval > 0);
	StackLock lock(_mutex);

	for (int l = 0; l < MAX_TIMERS; l++) {
		if (!_timerSlots[l].procedure) {
			_timerSlots[l].procedure = procedure;
			_timerSlots[l].interval = interval;
			_timerSlots[l].counter = interval;
			_timerSlots[l].refCon = refCon;
			return true;
		}
	}

	warning("Couldn't find free timer slot!");
	return false;
}

void Timer::removeTimerProc(TimerProc procedure) {
	StackLock lock(_mutex);

	for (int l = 0; l < MAX_TIMERS; l++) {
		if (_timerSlots[l].procedure == procedure) {
			_timerSlots[l].procedure = 0;
			_timerSlots[l].interval = 0;
			_timerSlots[l].counter = 0;
			_timerSlots[l].refCon = 0;
		}
	}
}

--- NEW FILE: timer.h ---
// Residual - Virtual machine to run LucasArts' 3D adventure games
// Copyright (C) 2003 The ScummVM-Residual Team (www.scummvm.org)
//
//  This library 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 2.1 of the License, or (at your option) any later version.
//
//  This library 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 library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

#ifndef COMMON_TIMER_H
#define COMMON_TIMER_H

#include "stdafx.h"
#include "bits.h"

#define MAX_TIMERS 3

typedef void (*TimerProc)(void *refCon);

class Timer {

private:
	MutexRef _mutex;
	void *_timerHandler;
	int32 _thisTime;
	int32 _lastTime;

	struct TimerSlots {
		TimerProc procedure;
		int32 interval;
		int32 counter;
		void *refCon;
	} _timerSlots[MAX_TIMERS];

public:
	Timer();
	~Timer();

	/**
	 * Install a new timer callback. It will from now be called every interval microseconds.
	 * The timer may be invoked from a separate thread. Hence any timer code should be
	 * written following the same safety guidelines as any other threaded code.
	 *
	 * @note Although the interval is specified in microseconds, the actual timer resolution
	 *       may be lower. In particular, with the SDL backend the timer resolution is 10ms.
	 * @param proc		the callback
	 * @param interval	the interval in which the timer shall be invoked (in microseconds)
	 * @param refCon	an arbitrary void pointer; will be passed to the timer callback
	 * @return	true if the timer was installed successfully, false otherwise
	 */
	bool installTimerProc(TimerProc proc, int32 interval, void *refCon);

	/**
	 * Remove the given timer callback. It will not be invoked anymore.
	 */
	void removeTimerProc(TimerProc proc);

protected:
	static int timer_handler(int t);
	int handler(int t);
};

extern Timer *g_timer;

#endif


Index: main.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/main.cpp,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- main.cpp	12 Dec 2003 21:17:31 -0000	1.16
+++ main.cpp	12 Dec 2003 21:38:10 -0000	1.17
@@ -26,6 +26,7 @@
 #include "registry.h"
 #include "engine.h"
 #include "sound.h"
+#include "timer.h"
 #include "mixer/mixer.h"
 #ifndef _MSC_VER
 #include <unistd.h>
@@ -54,6 +55,7 @@
 #endif
 
 extern SoundMixer *g_mixer;
+extern Timer *g_timer;
 
 int main(int argc, char *argv[]) {
   char 	GLDriver[1024];
@@ -106,6 +108,7 @@
   }
 
   g_mixer = new SoundMixer();
+  g_timer = new Timer();
   Mixer::instance()->start();
 
   lua_open();
@@ -158,7 +161,33 @@
   #endif
   Engine::instance()->mainLoop();
 
+  delete g_timer;
   delete g_mixer;
 
   return 0;
+}
+
+StackLock::StackLock(MutexRef mutex)
+	: _mutex(mutex) {
+	lock_mutex(_mutex);
+}
+
+StackLock::~StackLock() {
+	unlock_mutex(_mutex);
+}
+
+MutexRef create_mutex() {
+	return (MutexRef) SDL_CreateMutex();
+}
+
+void lock_mutex(MutexRef mutex) {
+	SDL_mutexP((SDL_mutex *) mutex);
+}
+
+void unlock_mutex(MutexRef mutex) {
+	SDL_mutexV((SDL_mutex *) mutex);
+}
+
+void delete_mutex(MutexRef mutex) {
+	SDL_DestroyMutex((SDL_mutex *) mutex);
 }

Index: residual.vcproj
===================================================================
RCS file: /cvsroot/scummvm/residual/residual.vcproj,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- residual.vcproj	12 Dec 2003 21:17:31 -0000	1.11
+++ residual.vcproj	12 Dec 2003 21:38:10 -0000	1.12
@@ -249,6 +249,12 @@
 				RelativePath="textsplit.h">

 			</File>

 			<File

+				RelativePath="timer.cpp">

+			</File>

+			<File

+				RelativePath="timer.h">

+			</File>

+			<File

 				RelativePath="vima.cpp">

 			</File>

 			<File


Index: stdafx.h
===================================================================
RCS file: /cvsroot/scummvm/residual/stdafx.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- stdafx.h	12 Dec 2003 08:39:07 -0000	1.2
+++ stdafx.h	12 Dec 2003 21:38:10 -0000	1.3
@@ -19,6 +19,20 @@
 #define _STDAFX_H
 
 
+typedef struct Mutex *MutexRef;
+
+class StackLock {
+	MutexRef _mutex;
+public:
+	StackLock(MutexRef mutex);
+	~StackLock();
+};
+
+MutexRef create_mutex();
+void lock_mutex(MutexRef mutex);
+void unlock_mutex(MutexRef mutex);
+void delete_mutex(MutexRef mutex);
+
 #if defined(WIN32)
 
 #ifdef _MSC_VER





More information about the Scummvm-git-logs mailing list