BlitzThreads Part Duex.

Miscellaneous Forums/Blitz Showcase/BlitzThreads Part Duex.

http://www.excess.eclipse.co.uk/dreamspace.mod.zip

Well it's the DVD repacking of Part...Un..Une...One...

Posted it about 8 months ago, or 5 months ago..depending on my ability to read a date correctly.
Would be GREEEAT if someone with a mac/linux added Calls for the mac linux.

You can use the ?mac ?linux ?x86 compiler directives to add this into the same lib.

It's a module in this form, but it's part C++, so it'll be straight forward. I just have no mac/linux set up to do it.

You'll all need this come BlitzMaxPs3...:)

From the original Thread. Just checked the rar and there were no docs/source, just the mod `mam.


It's object driven, although there are function wrappers for those used to that.

Classes are(There's no docs)

TThread.

Global functions(Contained within TThread. I.e TThread.

Create() )
Create( BlitzFunction ) Create a thread and return a TThread object.
RunAll() 'Runs all threads
PauseAll() 'Pauses all threads
StopAll() 'Stops all threads

Local functions specific to each thread instance,

Run() 'Runs the function provided when creating the thread, in another thread.

Priority( Value:Int) 'Set the threads priority, value ranges from 1 to 7. (default = 3, pre-set)

Pause() 'Pause the thread

Resume() 'Resume the thread,
-
Global functions within TThread to allow async data access,
All return a TResource object/integer handle.

ProtectInt( x variable )
ProtectFloat( x variable )
ProtectBank( Bank:TBank )
ProtectStream( Stream:TStream )
-

With the tResource object returned, you can lock access rights to it within your thread,

Wrapper functions are,

ThreadHandle =CreateThread( Function )
PauseThread( ThreadHandle )
ThreadPriority( ThreadHandle,Priority )
PauseThread(Threadhandle)
ResumeThread(ThreadHandle)
StopThread(ThreadHandle)
RunThread(ThreadHandle)

There's also a manual locking system, in addition to protected storage.

Lock = CreateLock()

RequestLock(Lock)
ReleaseLock(lock)

which allows you to restrict threads of the same locking patterns to one run at a time.(Prevent deadlocks..if you're lucky :) )

TestApp

Simple mode


Update = CreateThread( UpdateVal )
NetWork = CreateThread( PrintVal )
RunThread(Update)
RunThread(NetWork)


Global ourVal

Function updateVal:Int(bb_func:Byte Ptr)

repeat
ourVal:+1
forever

End function

Function printVal:Int (bb_func:Byte Ptr)

repeat
Print "Val:"+OurVal
Delay 1000
forever

End Function

Print "Thread Handle>"+Res

repeat
Delay 5000
Print "Master thread!"
Forever



Advanced Mode



Update:TThread = TThread.Create( UpdateVal )
NetWork:TThread = TThread.Create( PrintVal )
Update.Run()
Network.Run()


Global ourVal

Function updateVal:Int(bb_func:Byte Ptr)

repeat
ourVal:+1
forever

End function

Function printVal:Int (bb_func:Byte Ptr)

repeat
Print "Val:"+OurVal
Delay 1000
forever

End Function

Print "Thread Handle>"+Res

repeat
Delay 5000
Print "Master thread!"
Forever




Install


To install, copy dreamspace.mod folder into your bmax mod folder(Windows only atm) and you're done.



Source BMX

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 - <span style="background-color: #ffff66; color: #000000; font-weight: bold;">BlitzThreads</span> is not yet supported on Mac. Sorry."
?linux
Throw "DreamSpace - <span style="background-color: #ffff66; color: #000000; font-weight: bold;">BlitzThreads</span> 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




C++ (imported by the bmx code, you don't need VC or anything.]

Call it ThreadLayer.C (Well you don't have it. You do if you want it to work but you don't have to.)
#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 );
}



Max2D and input handling o not really like this module ...
unhandled memory exception error all over without any real reason *at least to me*
:-(

Yeah, it's more for custom code then max's in built stuff.

Your game logic, etc. AI.. BlitzThreads(Whoever's versions.) Should be made official, and blitz made 100% thread safe. Even home pc cpus are multi-core now.

even if not multicore, networking singlethread is useless.

For the rest I'm using "faked" threading (using a own event system with function references etc. results in 1 Million mainloop passes at 60 FPS rendered)

But for some aspecs an own thread is needed ...
Networking is one thing, dynamic media loading another for example ...

Hopefully it will be added ... because I don't think that a next gen 3D engine can be called as such if it runs single threaded, no mather how many cores. There are things that have to run parallel ... like terrains, physics ...

even if not multicore, networking singlethread is quite pointless.

For the rest I'm using "faked" threading (using a own event system with function references etc. results in 1 Million mainloop passes at 60 FPS rendered)

But for some aspects an own thread is needed ...
Networking is one thing, dynamic media loading another for example ...

Hopefully it will be added ... because I don't think that a next gen 3D engine can be called as such if it runs single threaded, no mather how many cores. There are things that have to run parallel ... like terrains, physics ...