BlitzThreads (Windows only)

Miscellaneous Forums/Blitz Showcase/BlitzThreads (Windows only)

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Urban legends aside, I've got too much going on project wise to try and implement any sort of multi-platform.
So here's the bmax/C++ source used, public domain so hopefully someone else can finish it off for us.(this won't be a commercial product from me. ever.)

anyway, enough rambling, here's the juice. (This is the latest version btw, I'd nab it if you're using the above.
You can now pass a pointer to a thread. (Edit-fixed a bug.)
Strict

Module PUB.Thread

ModuleInfo "Version: 1.00"
ModuleInfo "Author:Antony Wells"
ModuleInfo "License:Public Domain"
ModuleInfo "Copyright: Public Domain"
ModuleInfo "Modserver: BRL" '(if they want). I doubt it!.

'Note only win32 link is working(Source code below) so this'll crash out on mac/linux atm..if that.
?win32
Import "ThreadLayer.c"
?macOS 
'Import "MacThread.c"
?linux
'Import "LinuxThread.c"
?

Import BRL.LinkedList
Import BRL.Stream
Import BRL.Bank

Type TResource

	Method New()
		
		Mutex = makeMutex()
		
	End Method
	
	Method Delete()
		
		cleanMutex( mutex )
		closeObject( mutex )
		
	End Method
	
	Method Lock()
		
		waitForObject( mutex,0)
		Return 1
			
	End Method
	
	Method Unlock()
	
		cleanMutex( mutex )	
	
	End Method
	
	Method GetInt:Int()
		Return dInt[0]
	End Method
	
	Method getFloat:Float()
		Return dFloat[0]
	End Method
	
	Method getDouble:Double()
		Return dDouble[0]
	End Method
	
	Method getStream:TStream()
		Return dStream
	End Method
	
	Method getBank:TBank()
		Return dBank
	End Method
		
	Method getType:Object()
		Return dObject
	End Method
					
	Field dInt:Int Ptr
	Field dFloat:Float Ptr
	Field dDouble:Double Ptr
	Field dBank:TBank
	Field dObject:Object
	Field dStream:TStream
	Field Mutex:Int

End Type


Type TThread
	
	Function Init()
		
		Threads = CreateList()
		SharedData = CreateList()
	
		
	End Function 
	
	Method New()
		FlagLock = CreateLock()
	End Method
	
	Method Delete()
		
		If handle<>0
			cleanThread(handle)
			closeObject(Handle)
			handle = 0
		End If
		
		
	End Method	
	
	Function ProtectInt:TResource( Resource:Int Var )
	
		Local TRes:TResource = New TResource
		TRes.dInt =Varptr Resource
		Return TRes
	
	End Function
	
	Function ProtectFloat:TResource( Resource:Float Var)
	
		Local TRes:TResource = New TResource
		TRes.dFloat = Varptr Resource
		Return TRes

	End Function
	
	Function ProtectBank:TResource( Resource:TBank )

		Local TRes:TResource = New TResource
		TRes.dBank = Resource
		Return TRes

	End Function
	
	Function ProtectType:TResource( Resource:Object )
		
		Local TRes:TResource = New TResource
		TRes.dObject = Resource
		Return TRes
		
	End Function
	
	Function ProtectStream:TResource( Resource:TStream )
	
		Local TRes:TResource = New TResource
		TRes.dStream = Resource
		Return TRes
		
	End Function	
	
	
	Function Create:TThread( bb_func:Int(tp:Byte Ptr),value:Int=0 )
		
		Local Spawn:TThread = New TThread
		'Spawn.Handle = makeThread( bb_func )
		Spawn.bbfunc = bb_func
		ListAddLast Threads,Spawn
		Spawn.PassValue = New Int[1]
		Spawn.passValue[0] = Value
		Return Spawn
				
	End Function
	
	Method SetParInt(value:Int)
		PassValue[0]=Value
		PassMode = 0
	End Method
	
	
	
	Function RunAll()
		
		For Local Thread:TThread = EachIn Threads
		
			Thread.Pause()
						
		Next
		
	End Function 
	
	
	Function PauseAll()
		
		For Local Thread:TThread = EachIn Threads
		
			If Thread.Handle<>0
				Thread.Pause()
			EndIf 
				
		Next
		
	End Function

	Method Active:Byte()
	'	RequestLock( flagLock )
		Return ActiveFlag	
	'	ReleaseLock( flagLock )
	End Method
	
	Function ResumeAll()
	
		For Local Thread:TThread = EachIn Threads
			
			If Thread.Handle<>0
				Thread.Resume()
			End If
		
		Next
			
	End Function
		
	Method Run()
		
		Handled = makeThreadValue( bbFunc,PassValue)
		
	End Method
	
	Method Pause()
		
		haltThread( Handle )
		
	End Method
	
	Method Resume()
		
		restartThread( Handle )
		
	End Method
			
	Method Stop()
		
		cleanThread( Handle )
		closeObject( Handle )
		Handle = Null
		
	End Method

	Method SetPriority( nPriority:Int )
	
		Assert handle,"Thread not running"
		AlterThreadPriority( handle,nPriority)
	
	End Method
	
	
	
	'Waits for a thread to finish, maxwait defines how long to wait for. 0 = as long as it takes.
	Method Wait(MaxWait:Int=0)
		waitForObject( Handle,MaxWait )		
	End Method
	
	
	Field Handle:Int
	Field ActiveFlag:Byte
	Global Threads:TList
	Global Master:TThread
	Global SharedData:TList
	Field bbfunc:Int(tp:Byte Ptr)
	Field passValue:Int Ptr,PassMode:Short
	Field CapsuleThread:Int,flagLock:Int
End Type

TThread.Init()

Public
?win32
Extern 

	Function makeThread:Int(bb_func:Int(tp:Byte Ptr))
	Function waitForObject( threadHandle:Int,MaxWait:Int )
	Function makeMutex:Int()
	Function cleanMutex(mutex:Int)
	Function closeObject(handle:Int)
	Function cleanThread(handle:Int)
	Function AlterThreadPriority( handle:Int,priority:Int)
	Function haltThread(handle:Int)
	Function restartThread(handle:Int)
	Function makeThreadValue:Int(bb_func:Int(tp:Byte Ptr),value:Int Ptr) 

End Extern
?mac
Throw "DreamSpace - BlitzThreads is not yet supported on Mac. Sorry."
?linux
Throw "DreamSpace - BlitzThreads is not yet Supported on Linux. Sorry."
?

Function CreateThread:TThread( bb_func:Int(tp:Byte Ptr))
	
	Return TThread.Create( bb_func )
	
End Function


Function WaitThread( In:TThread,WaitUntil:Int=0 )

	In.Wait( WaitUntil )

End Function

'Returns immediately
Function RunThread( In:TThread )

	In.Run()	

End Function

Function PauseThread( In:TThread )

	In.Pause()

End Function

Function ResumeThread( In:TThread )
	
	In.Resume()
	
End Function

Function StopThread( In:TThread ) 

	In.Stop()

End Function 

Global ActiveThread:TThread
Global ActiveFunction:Int(BB_Func:Byte Ptr)
Global ActiveMutex = CreateLock()

Function CreateLock:Int()
	Return makeMutex()
End Function 

Function RequestLock:Int(LockID:Int)
	Return waitForObject( LockId,0 )
End Function 

Function ReleaseLock(LockId:Int)
	cleanMutex( lockId   )
End Function



'TheadLayer.c
#include <windows.h>



// Thread spawner for 
HANDLE makeThreadValue( int (*function),LPVOID *value){
HANDLE threadHandle;
	threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)function,value, 0, NULL);
	return threadHandle;
};

HANDLE makeThread(int (*function)){
	HANDLE threadHandle;
	threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)function,NULL, 0, NULL);
	return threadHandle;
};

void AlterThreadPriority( HANDLE threadHandle,int priority){
	switch(priority){
	case 1:
		priority = THREAD_PRIORITY_IDLE;
		break;
	case 2:
		priority = THREAD_PRIORITY_LOWEST;
		break;
	case 3:
		priority = THREAD_PRIORITY_BELOW_NORMAL;
		break;
	case 4:
		priority = THREAD_PRIORITY_NORMAL;
		break;
	case 5:
		priority = THREAD_PRIORITY_ABOVE_NORMAL;
	case 6:
		priority = THREAD_PRIORITY_HIGHEST;
		break;
	case 7:
		priority = THREAD_PRIORITY_TIME_CRITICAL;
		break;
	}
	SetThreadPriority( threadHandle,priority);
}

void haltThread( HANDLE threadHandle ){
	SuspendThread( threadHandle );
}

void restartThread(HANDLE threadHandle){
	ResumeThread( threadHandle);
}


void waitForObject(HANDLE threadHandle,int wait){
	if(wait>0){
	WaitForSingleObject( threadHandle,wait);
	}else{
	WaitForSingleObject( threadHandle,INFINITE);
	}
}

void closeObject( HANDLE in){
	CloseHandle( in );
};

void cleanThread( HANDLE threadHandle ){
	TerminateThread( threadHandle ,0 );
}

void threadActive( HANDLE threadHandle ){
	
}

HANDLE makeMutex(){
	return CreateMutex(NULL, 0, NULL);
}

void cleanMutex( mutexHandle){
	ReleaseMutex( mutexHandle );
}


Freel free to upload any improvements to this thread..or your own.