I found the SDL tutorial on threads to be a bit confusing and it didn’t mention things like making an autorelease pool for every sdl thread. I made a test program to demonstrate the way I think you’re supposed to do things.
Here is the Xcode project:http://lackeyccg.com/code/ThreadTest.zip
or for just the 1 source file:http://lackeyccg.com/code/MainThreadTest.mmI documented my code to explain why I was doing things. If anyone wants to take a look at it, please let me know if you have any suggestions or if you think I did something wrong.
Code:
/*
The purpose of this test program is to show how to use threads with SDL in an objective c environment.
This program has one main process which is in an endless loop. If there is not currently a worker thread,
the main process creates one. The worker thread should perform its tasks without making the main process
hang, which is the main reason for using a thread in the first place. When the worker thread process has
completed, the next time the main process checks if the worker is done, it will then see that it is and
launch another worker thread, and so on.
*/
#include <CoreFoundation/CFURL.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFString.h>
#include <Cocoa/Cocoa.h>
#include <SDL.h>
#include
using namespace std;
static SDL_threadID gMainThreadId;
static NSAutoreleasePool * gAutoReleasePool=NULL;
static SDL_Thread *gWorkerThread=NULL;
static SDL_mutex *gMutex = NULL;
static bool gIsWorkerThreadFinished = true;
void SetUpPool()
{
if(gAutoReleasePool)
[gAutoReleasePool release];
gAutoReleasePool = [[NSAutoreleasePool alloc] init];
}
void FreePool()
{
if(gAutoReleasePool)
[gAutoReleasePool release];
gAutoReleasePool=NULL;
}
void Quit()
{
if(gMutex)
SDL_DestroyMutex(gMutex);
FreePool();
}
void SomeFunctionThatUsesAutoReleasePool()
{// This function just retrieves the contents of a URL.
/// This function is run from the worker thread and uses the autorelease pool to test that it’s freed from the thread.
NSString urlString=@“http://lackeyccg.com/code/test.txt”;
NSError error = nil;
NSString* text = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];
if( text )
NSLog(@“Text=%@”, text);
else
NSLog(@“Error = %@”, error);
}
int SDLCALL ThreadWorkerFunction(void *data)
{
// Gotta make a autorelease pool for each thread if you explicitly or implicitly use things that use the pool.
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
if(!autoreleasepool)
exit(1);
Uint32 StartTime=SDL_GetTicks();
SomeFunctionThatUsesAutoReleasePool();//Run a function that uses autorelease pool, to test that it's freed.
SDL_Delay(10000);// This 10 second delay is put in here to simulate a lot of work being done.
while(1)
{
if(gMutex)
{
if (SDL_LockMutex(gMutex) == 0)//Make this only readable while locked. If you can't lock it, try until you can.
{
gIsWorkerThreadFinished=true; //This is a flag that the main thread will look for.
cout << "\tWorker thread " << SDL_ThreadID() << " is done after " << SDL_GetTicks()-StartTime << " milliseconds." << endl;
int Result=SDL_UnlockMutex(gMutex);
if(Result!=0)// if you just successfully locked it, you should be able to unlock it
exit(1);
break;
}
else
SDL_Delay(100);
}
}
[autoreleasepool release];// Gotta free the pool at the end of your thread.
return 0;
}
int main(int argc, char *argv[])
{
SetUpPool();// Set up the autorelease pool for the main process.
if (SDL_Init(0) < 0) // Load the SDL library
exit(1);
gMainThreadId=SDL_ThreadID();
cout << "gMainThreadId:" << gMainThreadId << endl;
gMutex = SDL_CreateMutex();
if(!gMutex)
exit(1);
gIsWorkerThreadFinished = true;//Set this true to start the first worker thread.
Uint32 ThreadStartTime=0;
int TotalNumThreadsEverMade=0;
int done = 0;
while(!done)
{
if(gMutex)
{
if (SDL_LockMutex(gMutex) == 0)//Make this only readable while locked. If you can't lock it, try next loop.
{
if(gIsWorkerThreadFinished)
{
int ThreadReturnValue=0;
if(gWorkerThread)
{
SDL_WaitThread(gWorkerThread, &ThreadReturnValue);//If there is currently a worker thread, wait for it to finish.
cout << "Main process notes the worker thread completed with return value of " << ThreadReturnValue << endl;
}
ThreadStartTime=SDL_GetTicks();
gIsWorkerThreadFinished=false;
gWorkerThread=SDL_CreateThread(ThreadWorkerFunction, NULL, NULL);// make a new worker thread if old one is finished.
TotalNumThreadsEverMade++;
cout << "Main process made a worker thread. Total threads ever made:" << TotalNumThreadsEverMade << endl;
if(!gWorkerThread)
exit(1);
}
else
{
cout << "Main process has been waiting for worker thread for " << SDL_GetTicks()-ThreadStartTime << " MS." << endl;
}
int Result=SDL_UnlockMutex(gMutex);
if(Result!=0)// if you just successfully locked it, you should be able to unlock it
exit(1);
}
else
cout << "main thread can't unlock mutex" << endl;
}
SDL_Delay(1000);//This simulates the main process performing work.
}
Quit();
return 0;
}
/*
// SAMPLE OUTPUT:----------------------------------------
gMainThreadId:2897558056
Main process made a worker thread. Total threads ever made:1
2013-10-05 06:56:11.569 threadtest[11801:1203] Text=This is a test.
Main process has been waiting for worker thread for 1001 MS.
Main process has been waiting for worker thread for 2002 MS.
Main process has been waiting for worker thread for 3002 MS.
Main process has been waiting for worker thread for 4003 MS.
Main process has been waiting for worker thread for 5004 MS.
Main process has been waiting for worker thread for 6004 MS.
Main process has been waiting for worker thread for 7005 MS.
Main process has been waiting for worker thread for 8006 MS.
Main process has been waiting for worker thread for 9007 MS.
Main process has been waiting for worker thread for 10009 MS.
Worker thread 2953318400 is done after 10108 milliseconds.
Main process notes the worker thread completed with return value of 0
Main process made a worker thread. Total threads ever made:2
2013-10-05 06:56:22.475 threadtest[11801:1207] Text=This is a test.
Main process has been waiting for worker thread for 1001 MS.
Main process has been waiting for worker thread for 2002 MS.
Main process has been waiting for worker thread for 3003 MS.
Main process has been waiting for worker thread for 4004 MS.
Main process has been waiting for worker thread for 5005 MS.
Main process has been waiting for worker thread for 6007 MS.
Main process has been waiting for worker thread for 7008 MS.
Main process has been waiting for worker thread for 8009 MS.
Main process has been waiting for worker thread for 9010 MS.
Worker thread 2953318400 is done after 10002 milliseconds.
Main process notes the worker thread completed with return value of 0
Main process made a worker thread. Total threads ever made:3
2013-10-05 06:56:32.485 threadtest[11801:120b] Text=This is a test.
Main process has been waiting for worker thread for 1001 MS.
Main process has been waiting for worker thread for 2002 MS.
*/