Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Threading in QB64pe (again)
#1
Hello all,

I've been revisiting my earlier attempt at threading in QB64pe. You can look at the old thread at https://qb64forum.alephc.xyz/index.php?topic=3865.0 Thanks to guys that responded to that thread and helped me. 

I'm happy to say I made a bit of progress. I managed to get two separate free running threads to run concurrent with my main QB64 program. They don't do much, but they show its possible.

In order to get it working I had to cheat and use a c header file to make a wrapper for pthreads. This makes the declarations easier.

Code: (Select All)
// pthreadGFXTest.h
// Threading Header
#include "pthread.h"
// Only needed for the SIGTERM Constant
#include <signal.h>
// Initialize Threads
pthread_t thread0;
pthread_t thread1;
// Easy way to determine if a thread is running
bool threadRunning0 = false;
bool threadRunning1 = false;
// Setup Mutexes for each of the threads.
static pthread_mutex_t mutex0;
static pthread_mutex_t mutex1;
// QB's names for the threaded Subs
// You can locate these in your ''qb64pe/internal/temp'' folder.
// I found these in the 'main.txt'
void SUB_LINES();
void SUB_CIRCLES();
// wrap the subs so that you can easily get the void* for pthread
void* RunLines(void *arg){
    SUB_LINES();
}
void* RunCircles(void *arg){
    SUB_CIRCLES();
}
// These are the commands that are accessed by you program
void invokeLines(){
    if (!threadRunning0) {
        int iret = pthread_create( &thread0, NULL, RunLines, NULL);
        pthread_mutex_init(&mutex0, NULL);
        threadRunning0 = true;
    }
}
void invokeCircles(){
    if (!threadRunning1) {
        int iret = pthread_create( &thread1, NULL, RunCircles, NULL);
        pthread_mutex_init(&mutex1, NULL);
        threadRunning1 = true;
    }
}
void joinThread0(){
    pthread_join(thread0,NULL);
    threadRunning0 = false;
}
void joinThread1(){
    pthread_join(thread1,NULL);
    threadRunning1 = false;
}
void exitThread(){
    pthread_exit(NULL);
}
void killThread0(){
    if (threadRunning0) {
        int iret = pthread_kill(thread0, SIGTERM);
    }
}
void killThread1(){
    if (threadRunning1) {
        int iret = pthread_kill(thread1, SIGTERM);
    }
}
void lockThread0(){
    pthread_mutex_lock(&mutex0);
}
void unlockThread0(){
    pthread_mutex_unlock(&mutex0);
}
void lockThread1(){
    pthread_mutex_lock(&mutex1);
}
void unlockThread1(){
    pthread_mutex_unlock(&mutex1);
}

The test program draws lines in one thread and circles in another thread. You start and stop the threads by pressing '1' and '2' and 'ESC' quits.


Code: (Select All)
'***********************************************************************************
' Proof of concept threading in QB64pe.
' by justsomeguy
'***********************************************************************************

' Thread Library Declaration
DECLARE LIBRARY "./pthreadGFXTest"
  SUB invokeLines ' start Lines thread
  SUB invokeCircles ' start Circles thread
  SUB joinThread0 ' wait til thread is finished
  SUB joinThread1 ' wait til thread is finished
  SUB exitThread ' must be called as thread exits
  SUB killThread0 ' kill the thread
  SUB killThread1 ' kill the thread
  SUB lockThread0 ' mutex lock
  SUB unlockThread0 ' mutex unlock
  SUB lockThread1 ' mutex lock
  SUB unlockThread1 ' mutex unlock
END DECLARE

' Global variables
DIM SHARED AS INTEGER q0, q1 ' quit signals
DIM AS STRING ky

' Setup screen
_TITLE "Thread test"
SCREEN _NEWIMAGE(1024, 768, 32)
_FONT 8
CLS

' Fire up freerunning threads
invokeCircles
invokeLines

' Campout in an infinite loop
DO
  ky = INKEY$
  LOCATE 1, 1
  PRINT "Lines are drawn on one thread, Circles are drawn in a second thread."
  PRINT "Press '1' to toggle the Line drawing thread. "
  PRINT "Press '2' to toggle the Circle drawing thread."
  PRINT "Press 'ESC' to exit."

  IF ky = "1" THEN
    q0 = NOT q0
    IF q0 THEN
      joinThread0
    ELSE
      invokeLines
    END IF
  END IF

  IF ky = "2" THEN
    q1 = NOT q1
    IF q1 THEN
      joinThread1
    ELSE
      invokeCircles
    END IF
  END IF

  ' Quit the whole program
  IF ky = CHR$(27) THEN q0 = -1: q1 = -1: joinThread0: joinThread1: SYSTEM
LOOP


'***********************************************************************************
' Threaded
'***********************************************************************************

SUB lines ()
  ' Free running loop
  DO
    ' lock a mutex, just to be safe
    lockThread0
    ' Do something
    LINE (RND * _WIDTH, RND * _HEIGHT)-(RND * _WIDTH, RND * _HEIGHT), _RGB32(RND * 255, RND * 255, RND * 255)
    ' unlock mutex
    unlockThread0
    ' do I need to jump out?
  LOOP UNTIL q0 = -1
  ' Must call exitThread when leaving, so that joinThread works.
  exitThread
END SUB

SUB circles ()
  ' Free running loop
  DO
    ' lock a mutex, just to be safe
    lockThread1
    ' Do something
    CIRCLE (RND * _WIDTH, RND * _HEIGHT), RND * 50, _RGB32(RND * 255, RND * 255, RND * 255)
    ' unlock mutex
    unlockThread1
    ' do I need to jump out?
  LOOP UNTIL q1 = -1
  ' Must call exitThread when leaving, so that joinThread works.
  exitThread
END SUB


My goal, is to get my 2d physics engine to reside in a separate thread and have it free running computing collisions and motion while the main thread handles I/O and other logic.

I'm using QB64pe 3.11.0. I tested this on Linux Mint, MacOS and Windows 10. On windows I had to add '-pthread' to compiler settings and '--static' to the linker settings.

[Image: win-Comp-Setting.png]

To get this running on your computer, copy the header to your favorite text editor and save the file under 'pthreadGFXTest.h' Then copy the source to the same directory as the header and make sure your compiler and linker settings are correct. I'm not sure if its necessary, but I save my EXE to the source folder.

Beware that if you decide try playing around with the code, that it could crash in some wild ways. Error messages will not make sense, and it might run a bit and lockup for unknown reasons. QB64pe is not meant to be run like this, so there will not be much help if you try.
Reply


Messages In This Thread
Threading in QB64pe (again) - by justsomeguy - 05-27-2024, 12:58 AM
RE: Threading in QB64pe (again) - by DSMan195276 - 05-27-2024, 11:53 AM
RE: Threading in QB64pe (again) - by aurel - 05-27-2024, 12:26 PM
RE: Threading in QB64pe (again) - by justsomeguy - 05-27-2024, 02:32 PM
RE: Threading in QB64pe (again) - by DSMan195276 - 05-27-2024, 04:42 PM
RE: Threading in QB64pe (again) - by a740g - 05-27-2024, 06:26 PM
RE: Threading in QB64pe (again) - by DSMan195276 - 05-27-2024, 09:55 PM
RE: Threading in QB64pe (again) - by justsomeguy - 05-28-2024, 01:41 AM
RE: Threading in QB64pe (again) - by DSMan195276 - 05-28-2024, 01:31 PM
RE: Threading in QB64pe (again) - by justsomeguy - 05-28-2024, 04:03 PM
RE: Threading in QB64pe (again) - by Kernelpanic - 05-28-2024, 06:46 PM
RE: Threading in QB64pe (again) - by DSMan195276 - 05-28-2024, 11:14 PM
RE: Threading in QB64pe (again) - by justsomeguy - 05-29-2024, 03:33 PM
RE: Threading in QB64pe (again) - by DSMan195276 - 05-30-2024, 02:13 AM
RE: Threading in QB64pe (again) - by justsomeguy - 05-30-2024, 04:33 AM
RE: Threading in QB64pe (again) - by justsomeguy - 05-31-2024, 03:00 PM
RE: Threading in QB64pe (again) - by SMcNeill - 06-02-2024, 08:14 AM
RE: Threading in QB64pe (again) - by justsomeguy - 06-02-2024, 01:11 PM
RE: Threading in QB64pe (again) - by SMcNeill - 06-02-2024, 04:01 PM



Users browsing this thread: 21 Guest(s)