summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortruelight <truelight@openttd.org>2007-02-08 23:46:25 +0000
committertruelight <truelight@openttd.org>2007-02-08 23:46:25 +0000
commit7cd68b5a072ce788e3a9fad0767b2015d397ee73 (patch)
treebda0f305d17d31d1e4b13d4d3937b315b0ed0037
parent424001168d89da0c58e426e808f175598bc15eb9 (diff)
downloadopenttd-7cd68b5a072ce788e3a9fad0767b2015d397ee73.tar.xz
(svn r8647) -Codechange: add a general way to handle platforms who can only have a limited amount of file-descripters open at any given time.
The Fios keeps track how many times a file is opened, and tries to close up files which aren't used often. The first platform using this is PSP. Patch based on the work of Turulo.
-rw-r--r--src/fileio.cpp66
-rw-r--r--src/stdafx.h7
2 files changed, 70 insertions, 3 deletions
diff --git a/src/fileio.cpp b/src/fileio.cpp
index 2a09916ea..e7e95453f 100644
--- a/src/fileio.cpp
+++ b/src/fileio.cpp
@@ -7,19 +7,26 @@
#include "string.h"
#include "macros.h"
#include "variables.h"
+#include "debug.h"
/*************************************************/
/* FILE IO ROUTINES ******************************/
/*************************************************/
#define FIO_BUFFER_SIZE 512
+#define MAX_HANDLES 64
typedef struct {
byte *buffer, *buffer_end; ///< position pointer in local buffer and last valid byte of buffer
uint32 pos; ///< current (system) position in file
FILE *cur_fh; ///< current file handle
- FILE *handles[64]; ///< array of file handles we can have open
+ FILE *handles[MAX_HANDLES]; ///< array of file handles we can have open
byte buffer_start[FIO_BUFFER_SIZE]; ///< local buffer when read from file
+#if defined(LIMITED_FDS)
+ uint open_handles; ///< current amount of open handles
+ const char *filename[MAX_HANDLES]; ///< array of filenames we (should) have open
+ uint usage_count[MAX_HANDLES]; ///< count how many times this file has been opened
+#endif /* LIMITED_FDS */
} Fio;
static Fio _fio;
@@ -38,10 +45,27 @@ void FioSeekTo(uint32 pos, int mode)
fseek(_fio.cur_fh, _fio.pos, SEEK_SET);
}
+#if defined(LIMITED_FDS)
+static void FioRestoreFile(int slot)
+{
+ /* Do we still have the file open, or should we reopen it? */
+ if (_fio.handles[slot] == NULL) {
+ DEBUG(misc, 6, "Restoring file '%s' in slot '%d' from disk", _fio.filename[slot], slot);
+ FioOpenFile(slot, _fio.filename[slot]);
+ }
+ _fio.usage_count[slot]++;
+}
+#endif /* LIMITED_FDS */
+
// Seek to a file and a position
void FioSeekToFile(uint32 pos)
{
- FILE *f = _fio.handles[pos >> 24];
+ FILE *f;
+#if defined(LIMITED_FDS)
+ /* Make sure we have this file open */
+ FioRestoreFile(pos >> 24);
+#endif /* LIMITED_FDS */
+ f = _fio.handles[pos >> 24];
assert(f != NULL);
_fio.cur_fh = f;
FioSeekTo(GB(pos, 0, 24), SEEK_SET);
@@ -92,6 +116,9 @@ static inline void FioCloseFile(int slot)
if (_fio.handles[slot] != NULL) {
fclose(_fio.handles[slot]);
_fio.handles[slot] = NULL;
+#if defined(LIMITED_FDS)
+ _fio.open_handles--;
+#endif /* LIMITED_FDS */
}
}
@@ -112,6 +139,30 @@ bool FioCheckFileExists(const char *filename)
return true;
}
+#if defined(LIMITED_FDS)
+static void FioFreeHandle()
+{
+ /* If we are about to open a file that will exceed the limit, close a file */
+ if (_fio.open_handles + 1 == LIMITED_FDS) {
+ uint i, count;
+ int slot;
+
+ count = UINT_MAX;
+ slot = -1;
+ /* Find the file that is used the least */
+ for (i = 0; i < lengthof(_fio.handles); i++) {
+ if (_fio.handles[i] != NULL && _fio.usage_count[i] < count) {
+ count = _fio.usage_count[i];
+ slot = i;
+ }
+ }
+ assert(slot != -1);
+ DEBUG(misc, 6, "Closing filehandler '%s' in slot '%d' because of fd-limit", _fio.filename[slot], slot);
+ FioCloseFile(slot);
+ }
+}
+#endif /* LIMITED_FDS */
+
FILE *FioFOpenFile(const char *filename)
{
FILE *f;
@@ -141,11 +192,20 @@ FILE *FioFOpenFile(const char *filename)
void FioOpenFile(int slot, const char *filename)
{
- FILE *f = FioFOpenFile(filename);
+ FILE *f;
+#if defined(LIMITED_FDS)
+ FioFreeHandle();
+#endif /* LIMITED_FDS */
+ f = FioFOpenFile(filename);
if (f == NULL) error("Cannot open file '%s%s'", _paths.data_dir, filename);
FioCloseFile(slot); // if file was opened before, close it
_fio.handles[slot] = f;
+#if defined(LIMITED_FDS)
+ _fio.filename[slot] = filename;
+ _fio.usage_count[slot] = 0;
+ _fio.open_handles++;
+#endif /* LIMITED_FDS */
FioSeekToFile(slot << 24);
}
diff --git a/src/stdafx.h b/src/stdafx.h
index d2d57d1d9..29f32c3ce 100644
--- a/src/stdafx.h
+++ b/src/stdafx.h
@@ -77,6 +77,13 @@
# define BSWAP16(x) ((x) >> 8 | (x) << 8)
#endif /* __APPLE__ */
+#if defined(PSP)
+/* PSP can only have 10 file-descriptors open at any given time, but this
+ * switch only limits reads via the Fio system. So keep 2 fds free for things
+ * like saving a game. */
+#define LIMITED_FDS 8
+#endif /* PSP */
+
/* by default we use [] var arrays */
#define VARARRAY_SIZE