-/* xscreensaver, Copyright (c) 2006, 2007 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2010 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#import "xlockmoreI.h"
#import "jwxyz-timers.h"
+/* Garbage collection only exists if we are being compiled against the
+ 10.6 SDK or newer, not if we are building against the 10.4 SDK.
+ */
+#ifndef MAC_OS_X_VERSION_10_6
+# define MAC_OS_X_VERSION_10_6 1060 /* undefined in 10.4 SDK, grr */
+#endif
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 /* 10.6 SDK */
+# import <objc/objc-auto.h>
+# define DO_GC_HACKERY
+#endif
+
extern struct xscreensaver_function_table *xscreensaver_function_table;
/* Global variables used by the screen savers
perror ("putenv");
abort();
}
-// free (npath); // Oops, don't free this! putenv() does not copy it!
+
+ /* Don't free (npath) -- MacOS's putenv() does not copy it. */
}
perror ("putenv");
abort();
}
- free (env);
+ /* Don't free (env) -- MacOS's putenv() does not copy it. */
}
};
static const char *default_defaults [] = {
".doFPS: False",
+ ".doubleBuffer: True", // for most OpenGL hacks
".textMode: date",
// ".textLiteral: ",
// ".textFile: ",
gettimeofday (&tv, 0);
now = tv.tv_sec + (tv.tv_usec / 1000000.0);
next_frame_time = now + (delay / 1000000.0);
+
+
+# ifdef DO_GC_HACKERY
+ /* Current theory is that the 10.6 garbage collector sucks in the
+ following way:
+
+ It only does a collection when a threshold of outstanding
+ collectable allocations has been surpassed. However, CoreGraphics
+ creates lots of small collectable allocations that contain pointers
+ to very large non-collectable allocations: a small CG object that's
+ collectable referencing large malloc'd allocations (non-collectable)
+ containing bitmap data. So the large allocation doesn't get freed
+ until GC collects the small allocation, which triggers its finalizer
+ to run which frees the large allocation. So GC is deciding that it
+ doesn't really need to run, even though the process has gotten
+ enormous. GC eventually runs once pageouts have happened, but by
+ then it's too late, and the machine's resident set has been
+ sodomized.
+
+ So, we force an exhaustive garbage collection in this process
+ approximately every 5 seconds whether the system thinks it needs
+ one or not.
+ */
+ {
+ static int tick = 0;
+ if (++tick > 5*30) {
+ tick = 0;
+ objc_collect (OBJC_EXHAUSTIVE_COLLECTION);
+ }
+ }
+# endif // DO_GC_HACKERY
}