whoops, the released version won't resize until AFTER you've switched images,

due to forgetting to initialize a variable in the entry path after a refactoring
This commit is contained in:
nothings.org 2007-06-25 19:13:13 +00:00
parent b4e8c222ea
commit 8fd269ecd4
4 changed files with 58 additions and 28 deletions

29
imv.c
View File

@ -155,8 +155,8 @@ typedef struct
int lru; int lru;
} ImageFile; } ImageFile;
stb_semaphore cache_mutex; stb_mutex cache_mutex, decode_mutex;
stb_semaphore decode_queue, decode_mutex; stb_semaphore decode_queue;
stb_semaphore disk_command_queue; stb_semaphore disk_command_queue;
typedef struct typedef struct
@ -186,13 +186,13 @@ o("READ: Waiting for disk request.\n");
stb_sem_waitfor(disk_command_queue); stb_sem_waitfor(disk_command_queue);
// grab the command; don't let the command or the cache change while we do it // grab the command; don't let the command or the cache change while we do it
stb_sem_waitfor(cache_mutex); stb_mutex_begin(cache_mutex);
{ {
dc = dc_shared; dc = dc_shared;
for (i=0; i < dc.num_files; ++i) for (i=0; i < dc.num_files; ++i)
dc.files[i]->status = LOAD_reading; dc.files[i]->status = LOAD_reading;
} }
stb_sem_release(cache_mutex); stb_mutex_end(cache_mutex);
o("READ: Got disk request, %d items.\n", dc.num_files); o("READ: Got disk request, %d items.\n", dc.num_files);
for (i=0; i < dc.num_files; ++i) { for (i=0; i < dc.num_files; ++i) {
@ -256,12 +256,12 @@ start:
} }
if (best) { if (best) {
int retry = FALSE; int retry = FALSE;
stb_sem_waitfor(cache_mutex); stb_mutex_begin(cache_mutex);
if (best->status == LOAD_reading_done) if (best->status == LOAD_reading_done)
best->status = LOAD_decoding; best->status = LOAD_decoding;
else else
retry = TRUE; retry = TRUE;
stb_sem_release(cache_mutex); stb_mutex_end(cache_mutex);
if (retry) goto start; if (retry) goto start;
} }
return best; return best;
@ -620,7 +620,7 @@ void flush_cache(int locked)
limit = MAX_CACHED_IMAGES - MIN_CACHE; limit = MAX_CACHED_IMAGES - MIN_CACHE;
if (total > max_cache_bytes || occupied_slots > limit) { if (total > max_cache_bytes || occupied_slots > limit) {
qsort((void *) list, n, sizeof(*list), ImageFilePtrCompare); qsort((void *) list, n, sizeof(*list), ImageFilePtrCompare);
if (!locked) stb_sem_waitfor(cache_mutex); if (!locked) stb_mutex_begin(cache_mutex);
for (i=0; i < n && occupied_slots > MIN_CACHE && (occupied_slots > limit || total > max_cache_bytes); ++i) { for (i=0; i < n && occupied_slots > MIN_CACHE && (occupied_slots > limit || total > max_cache_bytes); ++i) {
ImageFile p; ImageFile p;
/* @TODO: this is totally squirrely and probably buggy. we need to /* @TODO: this is totally squirrely and probably buggy. we need to
@ -641,7 +641,7 @@ void flush_cache(int locked)
} }
} }
if (MAIN_OWNS(&p) && p.status != LOAD_unused) { if (MAIN_OWNS(&p) && p.status != LOAD_unused) {
if (!locked) stb_sem_release(cache_mutex); if (!locked) stb_mutex_end(cache_mutex);
o("MAIN: freeing cache: %s\n", p.filename); o("MAIN: freeing cache: %s\n", p.filename);
stb_sdict_remove(file_cache, p.filename, NULL); stb_sdict_remove(file_cache, p.filename, NULL);
--occupied_slots; // occupied slots --occupied_slots; // occupied slots
@ -653,10 +653,10 @@ o("MAIN: freeing cache: %s\n", p.filename);
if (p.filedata) free(p.filedata); if (p.filedata) free(p.filedata);
if (p.image) imfree(p.image); if (p.image) imfree(p.image);
if (p.error) free(p.error); if (p.error) free(p.error);
if (!locked) stb_sem_waitfor(cache_mutex); if (!locked) stb_mutex_begin(cache_mutex);
} }
} }
if (!locked) stb_sem_release(cache_mutex); if (!locked) stb_mutex_end(cache_mutex);
o("Reduced to %d megabytes\n", total >> 20); o("Reduced to %d megabytes\n", total >> 20);
} }
} }
@ -742,7 +742,7 @@ void advance(int dir)
fileinfo[cur_loc].lru = ++lru_stamp; fileinfo[cur_loc].lru = ++lru_stamp;
// need to grab the cache // need to grab the cache
stb_sem_waitfor(cache_mutex); stb_mutex_begin(cache_mutex);
dc.num_files = 0; dc.num_files = 0;
queue_disk_command(&dc, cur_loc, 1); // first thing to load: this file queue_disk_command(&dc, cur_loc, 1); // first thing to load: this file
queue_disk_command(&dc, wrap(cur_loc+dir), 0); // second thing to load: the next file (preload) queue_disk_command(&dc, wrap(cur_loc+dir), 0); // second thing to load: the next file (preload)
@ -752,7 +752,7 @@ void advance(int dir)
dc_shared = dc; dc_shared = dc;
stb_sem_release(disk_command_queue); stb_sem_release(disk_command_queue);
} }
stb_sem_release(cache_mutex); stb_mutex_end(cache_mutex);
// tell loader not to bother with old data // tell loader not to bother with old data
for (i=0; i < MAX_CACHED_IMAGES; ++i) for (i=0; i < MAX_CACHED_IMAGES; ++i)
if (cache[i].lru < lru_stamp-1) if (cache[i].lru < lru_stamp-1)
@ -1147,10 +1147,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
if (argc < 1) { MessageBox(NULL, "Specify an image file to view", "imv(stb)", MB_OK); exit(0); } if (argc < 1) { MessageBox(NULL, "Specify an image file to view", "imv(stb)", MB_OK); exit(0); }
resize_workers = stb_workq_new(resize_threads, resize_threads * 4); resize_workers = stb_workq_new(resize_threads, resize_threads * 4);
cache_mutex = stb_sem_new(1,0); cache_mutex = stb_mutex_new();
disk_command_queue = stb_sem_new(1,1); disk_command_queue = stb_sem_new(1,1);
decode_queue = stb_sem_new(1,1); decode_queue = stb_sem_new(1,1);
decode_mutex = stb_sem_new(1,0); decode_mutex = stb_mutex_new();
image_data = stbi_load(argv[0], &image_x, &image_y, &image_n, BPP); image_data = stbi_load(argv[0], &image_x, &image_y, &image_n, BPP);
if (image_data == NULL) { if (image_data == NULL) {
@ -1173,6 +1173,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
cache[0].filename = strdup(filename); cache[0].filename = strdup(filename);
file_cache = stb_sdict_new(1); file_cache = stb_sdict_new(1);
stb_sdict_add(file_cache, filename, (void *) &cache[0]); stb_sdict_add(file_cache, filename, (void *) &cache[0]);
source_c = (ImageFile *) &cache[0];
{ {

5
readme.txt Normal file
View File

@ -0,0 +1,5 @@
COMPILING
There is a workspace/project file for VC6 (VC98) in the "vc6" subdirectory.
Or you can just directly compile imv.c, with multithreaded runtime.

29
stb.h
View File

@ -1,4 +1,4 @@
/* stb-1.88 -- Sean's Tool Box -- public domain -- http://nothings.org/stb.h /* stb-1.89 -- Sean's Tool Box -- public domain -- http://nothings.org/stb.h
no warranty is offered or implied; use this code at your own risk no warranty is offered or implied; use this code at your own risk
This is a single header file with a bunch of useful utilities This is a single header file with a bunch of useful utilities
@ -118,6 +118,8 @@ Bug reports, feature requests, etc. can be mailed to 'sean' at the above site.
3. Version History 3. Version History
1.89 support ';' in constant-string wildcards; stb_mutex wrapper (can implement
with EnterCriticalRegion eventually)
1.88 portable threading API (only for win32 so far); worker thread queueing 1.88 portable threading API (only for win32 so far); worker thread queueing
1.87 fix wildcard handling in stb_readdir_recursive 1.87 fix wildcard handling in stb_readdir_recursive
1.86 support ';' in wildcards 1.86 support ';' in wildcards
@ -10579,10 +10581,17 @@ void stb_compress_stream_end(int close)
// Threads // Threads
// //
typedef void *stb_thread;
typedef void * (*stb_thread_func)(void *); typedef void * (*stb_thread_func)(void *);
// do not rely on these types, this is an implementation detail.
// compare against STB_THREAD_NULL and ST_SEMAPHORE_NULL
typedef void *stb_thread;
typedef void *stb_semaphore; typedef void *stb_semaphore;
typedef void *stb_mutex;
#define STB_SEMAPHORE_NULL NULL #define STB_SEMAPHORE_NULL NULL
#define STB_THREAD_NULL NULL
#define STB_MUTEX_NULL NULL
// get the number of processors (limited to those in the affinity mask for this process). // get the number of processors (limited to those in the affinity mask for this process).
STB_EXTERN int stb_processor_count(void); STB_EXTERN int stb_processor_count(void);
@ -10623,6 +10632,10 @@ STB_EXTERN void stb_sem_delete (stb_semaphore s);
STB_EXTERN void stb_sem_waitfor(stb_semaphore s); STB_EXTERN void stb_sem_waitfor(stb_semaphore s);
STB_EXTERN void stb_sem_release(stb_semaphore s); STB_EXTERN void stb_sem_release(stb_semaphore s);
STB_EXTERN stb_mutex stb_mutex_new(void);
STB_EXTERN void stb_mutex_delete(stb_mutex m);
STB_EXTERN void stb_mutex_begin(stb_mutex m);
STB_EXTERN void stb_mutex_end(stb_mutex m);
#ifdef STB_DEFINE #ifdef STB_DEFINE
@ -10671,6 +10684,10 @@ static void stb__thread_run(void *t)
static stb_thread stb_create_thread_raw(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel) static stb_thread stb_create_thread_raw(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
{ {
#ifdef _MT #ifdef _MT
#if defined(STB_FASTMALLOC) && !defined(STB_FASTMALLOC_ITS_OKAY_I_ONLY_MALLOC_IN_ONE_THREAD)
stb_fatal("Error! Cannot use STB_FASTMALLOC with threads.\n");
return STB_THREAD_NULL;
#else
unsigned long id; unsigned long id;
stb__thread *data = (stb__thread *) malloc(sizeof(*data)); stb__thread *data = (stb__thread *) malloc(sizeof(*data));
if (!data) return NULL; if (!data) return NULL;
@ -10683,6 +10700,7 @@ static stb_thread stb_create_thread_raw(stb_thread_func f, void *d, volatile voi
id = _beginthread(stb__thread_run, 0, data); id = _beginthread(stb__thread_run, 0, data);
if (id == -1) return NULL; if (id == -1) return NULL;
return (void *) id; return (void *) id;
#endif
#else #else
stb_fatal("Must compile mult-threaded to use stb_thread/stb_work."); stb_fatal("Must compile mult-threaded to use stb_thread/stb_work.");
return NULL; return NULL;
@ -10721,6 +10739,13 @@ stb_thread stb_create_thread(stb_thread_func f, void *d)
return stb_create_thread2(f,d,NULL,STB_SEMAPHORE_NULL); return stb_create_thread2(f,d,NULL,STB_SEMAPHORE_NULL);
} }
// mutex implemented by wrapping semaphore
stb_mutex stb_mutex_new(void) { return stb_sem_new(1,0); }
void stb_mutex_delete(stb_mutex m) { stb_sem_delete (m); }
void stb_mutex_begin(stb_mutex m) { stb_sem_waitfor(m); }
void stb_mutex_end(stb_mutex m) { stb_sem_release(m); }
static int stb__work_maxitems = 64; static int stb__work_maxitems = 64;
typedef struct typedef struct

View File

@ -42,7 +42,8 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release" # PROP Intermediate_Dir "Release"
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /G6 /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD BASE RSC /l 0x409 /d "NDEBUG"
@ -65,9 +66,11 @@ LINK32=link.exe
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug" # PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug" # PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD BASE RSC /l 0x409 /d "_DEBUG"
@ -85,17 +88,13 @@ LINK32=link.exe
# Name "stb_imv - Win32 Release" # Name "stb_imv - Win32 Release"
# Name "stb_imv - Win32 Debug" # Name "stb_imv - Win32 Debug"
# Begin Group "Source Files" # Begin Source File
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" SOURCE=..\imv.c
# End Group # End Source File
# Begin Group "Header Files" # Begin Source File
# PROP Default_Filter "h;hpp;hxx;hm;inl" SOURCE=..\stb.h
# End Group # End Source File
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target # End Target
# End Project # End Project