crummy new-fangled threads... well, fork() is rock-solid

This commit is contained in:
Albert Cahalan 2005-01-19 05:01:48 +00:00
parent 9fd801a159
commit d20829d5ab
2 changed files with 281 additions and 8 deletions

View file

@ -14,9 +14,8 @@ http://www.newbreedsoftware.com/tuxpaint/
----------------------- -----------------------
* Splash screen appears earlier, along with the version info and cursor. * Splash screen appears earlier, along with the version info and cursor.
* Normal start-up time reduced by 11.4 seconds by splitting out font * Normal start-up time greatly reduced by splitting out font loading
loading into a separate thread. You only wait if you want the text tool. into a separate process. You only wait if you want the text tool.
(450 MHz Mac G4, 7200 RPM ATA disk, about 200 font files)
* added eat_startup_events in an attempt to make early escape possible * added eat_startup_events in an attempt to make early escape possible
(perhaps the user started Tux Paint by mistake, or the system is (perhaps the user started Tux Paint by mistake, or the system is

View file

@ -39,9 +39,8 @@
// plan to rip this out as soon as it is considered stable // plan to rip this out as soon as it is considered stable
#ifndef NO_THREADS //#define THREADED_FONTS
#define THREADED_FONTS #define FORKED_FONTS
#endif
/* Method for printing images: */ /* Method for printing images: */
@ -322,6 +321,9 @@ extern char* g_win32_getlocale(void);
static SDL_Thread *font_thread; static SDL_Thread *font_thread;
static volatile long font_thread_done; static volatile long font_thread_done;
static void run_font_scanner(void);
static int font_scanner_pid;
static int font_socket_fd;
#include "tools.h" #include "tools.h"
#include "titles.h" #include "titles.h"
@ -1544,6 +1546,8 @@ static style_info **user_font_styles;
static int num_font_styles; static int num_font_styles;
static int num_font_styles_max; static int num_font_styles_max;
static void receive_some_font_info(void);
static TTF_Font *getfonthandle(int desire) static TTF_Font *getfonthandle(int desire)
{ {
family_info *fi = user_font_families[desire]; family_info *fi = user_font_families[desire];
@ -2407,6 +2411,10 @@ static void eat_startup_events(void)
int main(int argc, char * argv[]) int main(int argc, char * argv[])
{ {
#ifdef FORKED_FONTS
run_font_scanner();
#endif
/* Set up locale support */ /* Set up locale support */
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
@ -2998,6 +3006,9 @@ static void mainloop(void)
update_screen_rect(&r_toolopt); update_screen_rect(&r_toolopt);
update_screen_rect(&r_ttoolopt); update_screen_rect(&r_ttoolopt);
draw_tux_text(TUX_WAIT, "This is a slow computer with lots of fonts...", 1); draw_tux_text(TUX_WAIT, "This is a slow computer with lots of fonts...", 1);
#ifdef FORKED_FONTS
receive_some_font_info();
#else
while(!font_thread_done) while(!font_thread_done)
{ {
// FIXME: should respond to quit events // FIXME: should respond to quit events
@ -3007,6 +3018,7 @@ static void mainloop(void)
} }
// FIXME: should kill this in any case // FIXME: should kill this in any case
SDL_WaitThread(font_thread, NULL); SDL_WaitThread(font_thread, NULL);
#endif
} }
draw_tux_text(tool_tux[cur_tool], tool_tips[cur_tool], 1); draw_tux_text(tool_tux[cur_tool], tool_tips[cur_tool], 1);
cur_thing = cur_font; cur_thing = cur_font;
@ -6513,7 +6525,7 @@ static void tp_ftw(char *restrict const dir, unsigned dirlen, int rsrc,
} }
closedir(d); closedir(d);
#if 1 #if 0
#ifndef THREADED_FONTS #ifndef THREADED_FONTS
show_progress_bar(); show_progress_bar();
eat_startup_events(); eat_startup_events();
@ -6555,7 +6567,7 @@ static void loadfont_callback(const char *restrict const dir, unsigned dirlen, t
{ {
while(i--) while(i--)
{ {
#if 1 #if 0
#ifndef THREADED_FONTS #ifndef THREADED_FONTS
show_progress_bar(); show_progress_bar();
eat_startup_events(); eat_startup_events();
@ -6904,6 +6916,260 @@ static int load_user_fonts(void *vp)
return 0; // useless, wanted by threading library return 0; // useless, wanted by threading library
} }
#ifdef FORKED_FONTS
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <sys/wait.h>
static void reliable_write(int fd, const void *buf, size_t count)
{
do
{
ssize_t rc = write(fd,buf,count);
if(rc==-1)
{
switch(errno)
{
default:
return;
case EAGAIN:
case ENOSPC:
; // satisfy a C syntax abomination
struct pollfd p = (struct pollfd){fd, POLLOUT, 0};
poll(&p, 1, -1); // try not to burn CPU time
// FALL THROUGH
case EINTR:
continue;
}
}
buf += rc;
count -= rc;
} while(count);
}
static void reliable_read(int fd, void *buf, size_t count)
{
do
{
ssize_t rc = read(fd,buf,count);
if(rc==-1)
{
switch(errno)
{
default:
return;
case EAGAIN:
; // satisfy a C syntax abomination
struct pollfd p = (struct pollfd){fd, POLLIN, 0};
poll(&p, 1, -1); // try not to burn CPU time
// FALL THROUGH
case EINTR:
continue;
}
}
if(rc==0)
break; // EOF. Better not happen before the end!
buf += rc;
count -= rc;
} while(count);
}
static void run_font_scanner(void)
{
int sv[2];
if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
exit(42);
font_scanner_pid = fork();
if(font_scanner_pid)
{
// parent (or error -- but we're screwed in that case)
font_socket_fd = sv[0];
close(sv[1]);
return;
}
font_socket_fd = sv[1];
close(sv[0]);
reliable_read(font_socket_fd, &no_system_fonts, sizeof no_system_fonts);
SDL_Init(SDL_INIT_NOPARACHUTE);
TTF_Init();
load_user_fonts(NULL);
int size = 0;
int i = num_font_families;
while(i--)
{
char *s;
s = user_font_families[i]->directory;
if(s) size += strlen(s);
s = user_font_families[i]->family;
if(s) size += strlen(s);
s = user_font_families[i]->filename[0];
if(s) size += strlen(s);
s = user_font_families[i]->filename[1];
if(s) size += strlen(s);
s = user_font_families[i]->filename[2];
if(s) size += strlen(s);
s = user_font_families[i]->filename[3];
if(s) size += strlen(s);
size += 6; // for '\0' on each of the above
}
size += 2; // for 2-byte font count
char *buf = malloc(size);
char *walk = buf;
// printf("Sending %u bytes with %u families.\n", size, num_font_families);
*walk++ = num_font_families & 0xff;
*walk++ = num_font_families >> 8;
i = num_font_families;
while(i--)
{
int len;
char *s;
s = user_font_families[i]->directory;
if(s)
{
len = strlen(s);
memcpy(walk, s, len);
walk += len;
}
*walk++ = '\0';
s = user_font_families[i]->family;
if(s)
{
len = strlen(s);
memcpy(walk, s, len);
walk += len;
}
*walk++ = '\0';
s = user_font_families[i]->filename[0];
if(s)
{
len = strlen(s);
memcpy(walk, s, len);
walk += len;
}
*walk++ = '\0';
s = user_font_families[i]->filename[1];
if(s)
{
len = strlen(s);
memcpy(walk, s, len);
walk += len;
}
*walk++ = '\0';
s = user_font_families[i]->filename[2];
if(s)
{
len = strlen(s);
memcpy(walk, s, len);
walk += len;
}
*walk++ = '\0';
s = user_font_families[i]->filename[3];
if(s)
{
len = strlen(s);
memcpy(walk, s, len);
walk += len;
}
*walk++ = '\0';
}
reliable_write(font_socket_fd, buf, size);
exit(0);
}
static void receive_some_font_info(void)
{
char *buf = NULL;
unsigned buf_size = 0;
unsigned buf_fill = 0;
fcntl(font_socket_fd, F_SETFL, O_NONBLOCK);
for(;;)
{
if(buf_size <= buf_fill*9/8+128)
{
buf_size = buf_size*5/4+256;
buf = realloc(buf, buf_size);
}
ssize_t rc = read(font_socket_fd, buf+buf_fill, buf_size-buf_fill);
//printf("read: fd=%d buf_fill=%u buf_size=%u rc=%ld\n", font_socket_fd, buf_fill, buf_size, rc);
if(rc==-1)
{
switch(errno)
{
default:
return;
case EAGAIN:
; // satisfy a C syntax abomination
struct pollfd p = (struct pollfd){font_socket_fd, POLLIN, 0};
show_progress_bar();
poll(&p, 1, 29); // try not to burn CPU time
continue;
case EINTR:
continue;
}
}
buf_fill += rc;
if(!rc)
break;
}
close(font_socket_fd);
show_progress_bar();
unsigned char *walk = buf;
num_font_families = *walk++;
num_font_families += *walk++ << 8;
// printf("Got %u bytes with %u families.\n", buf_fill, num_font_families);
user_font_families = malloc(num_font_families * sizeof *user_font_families);
family_info *fip = malloc(num_font_families * sizeof **user_font_families);
unsigned i = num_font_families;
while(i--)
{
user_font_families[i] = fip+i;
unsigned len;
len = strlen(walk);
user_font_families[i]->directory = len ? walk : NULL;
walk += len + 1;
len = strlen(walk);
user_font_families[i]->family = len ? walk : NULL;
walk += len + 1;
len = strlen(walk);
user_font_families[i]->filename[0] = len ? walk : NULL;
walk += len + 1;
len = strlen(walk);
user_font_families[i]->filename[1] = len ? walk : NULL;
walk += len + 1;
len = strlen(walk);
user_font_families[i]->filename[2] = len ? walk : NULL;
walk += len + 1;
len = strlen(walk);
user_font_families[i]->filename[3] = len ? walk : NULL;
walk += len + 1;
user_font_families[i]->handle = NULL;
// score left uninitialized
}
waitpid(font_scanner_pid,NULL,0);
font_thread_done = 1;
}
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/* Setup: */ /* Setup: */
@ -7682,7 +7948,11 @@ static void setup(int argc, char * argv[])
do_setcursor(cursor_watch); do_setcursor(cursor_watch);
eat_startup_events(); eat_startup_events();
#ifdef FORKED_FONTS
reliable_write(font_socket_fd, &no_system_fonts, sizeof no_system_fonts);
#else
font_thread = SDL_CreateThread(load_user_fonts, NULL); font_thread = SDL_CreateThread(load_user_fonts, NULL);
#endif
// continuing on with the rest of the cursors... // continuing on with the rest of the cursors...
@ -11871,6 +12141,9 @@ static void cleanup(void)
large_font = NULL; large_font = NULL;
} }
#ifdef FORKED_FONTS
free(user_font_families); // we'll leak the bodies... oh well
#else
for (i = 0; i < num_font_families; i++) for (i = 0; i < num_font_families; i++)
{ {
if (user_font_families[i]) if (user_font_families[i])
@ -11892,6 +12165,7 @@ static void cleanup(void)
user_font_families[i] = NULL; user_font_families[i] = NULL;
} }
} }
#endif
#ifndef NOSOUND #ifndef NOSOUND
if (use_sound) if (use_sound)