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

I have another test program that uses threads. This time it creates from 1 to 8 worker threads and they draw colored squares across the screen.

As before it needs a header file to setup threading. Its name is 'workers.h'

Code: (Select All)
// workers.h
// Threading Header
#include "pthread.h"
// Only needed for the SIGTERM Constant
#include <signal.h>
#include <unistd.h>
#include <time.h>

#define RETRYCOUNT 5
// Initialize Threads
static pthread_t thread[9];

typedef struct thread_data {
   int id;
} thread_data;

// Easy was to determine if a thread is running
bool threadRunning[] = {false,false,false,false,false,false,false,false,false,false};

// Setup Mutexes.
static pthread_mutex_t mutex[9];

// 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_WORKERTHREAD(int32*_SUB_WORKERTHREAD_LONG_ID);

// wrap the subs so that you can easily get the void* for pthread
void* RunWorker(void *arg){
    thread_data *tdata=(thread_data *)arg;
    int a = tdata->id;
    SUB_WORKERTHREAD((int32*)&a);
}

// These are the commands that are accessed by you program
void invokeWorker(int id){
    thread_data tdata;
    tdata.id = id;
    int icount = 0;
    if (!threadRunning[id]) {
        while(pthread_create( &thread[id], NULL, RunWorker, (void *)&tdata))
        {
            icount++;
            if (icount > RETRYCOUNT){
                return;
            }
            sleep(1);
        };
        pthread_mutex_init(&mutex[id], NULL);
        threadRunning[id] = true;
    }
    sleep(1);
}

void joinThread(int id){
    pthread_join(thread[id],NULL);
    threadRunning[id] = false;
}

void exitThread(){
    pthread_exit(NULL);
}

void killThread(int id){
    if (threadRunning[id]) {
        int iret = pthread_kill(thread[id], SIGTERM);
    }
}

void lockThread(int id){
    pthread_mutex_lock(&mutex[id]);
}

void unlockThread(int id){
    pthread_mutex_unlock(&mutex[id]);
}
And the QB side is as follows. Its name is whatever you like.
Code: (Select All)
DECLARE LIBRARY "./workers"
  SUB invokeWorker (BYVAL id AS LONG) ' start Lines thread
  SUB joinThread (BYVAL id AS LONG) ' wait til thread is finished
  SUB exitThread ' must be called as thread exits
  SUB killThread (BYVAL id AS LONG) ' kill the thread
  SUB lockThread (BYVAL id AS LONG) ' mutex lock
  SUB unlockThread (BYVAL id AS LONG) ' mutex unlock
END DECLARE

TYPE tWorker
  xstart AS LONG
  ystart AS LONG
  xsize AS LONG
  ysize AS LONG
  xdir AS _BYTE
  x AS LONG
  y AS LONG
  colour AS LONG
  command AS LONG
  sc AS LONG
  img AS _MEM
  offset AS _OFFSET
  dly AS _BYTE
END TYPE

DIM indx AS LONG
DIM ky AS STRING
DIM AS INTEGER tc

_TITLE "Worker Thread Test"

SCREEN _NEWIMAGE(800, 600, 32)
DO
  CLS
  PRINT "How many worker threads? Low spec machines should start less than 4."
  INPUT "(1 - 8, 0 to quit):"; tc
  IF tc = 0 THEN SYSTEM
LOOP UNTIL tc >= 1 AND tc <= 8
tc = tc - 1
CLS

DIM SHARED AS tWorker worker(tc)

FOR indx = 0 TO tc
  resetWorker indx
  worker(indx).sc = _NEWIMAGE(worker(indx).xsize + 1, worker(indx).ysize + 1, 32)
  worker(indx).img = _MEMIMAGE(worker(indx).sc)
NEXT
LOCATE 1
FOR indx = 0 TO tc
  PRINT "Starting thread:"; indx
  invokeWorker indx
NEXT
CLS
DO
  ky = INKEY$
  IF ky = "d" THEN
    FOR indx = 0 TO tc
      worker(indx).dly = NOT worker(indx).dly
    NEXT
  END IF

  IF ky = "s" THEN
    CLS
    FOR indx = 0 TO tc
      worker(indx).command = NOT worker(indx).command
      IF worker(indx).command THEN
        joinThread indx
      ELSE
        PRINT "Restarting thread:"; indx
        _DISPLAY
        invokeWorker indx
      END IF
    NEXT
    CLS
  END IF

  IF ky = CHR$(27) THEN
    FOR indx = 0 TO tc
      worker(indx).command = -1
      joinThread indx
      SYSTEM
    NEXT
  END IF

  FOR indx = 0 TO tc
    _PRINTSTRING (indx * 100 + 10, 220), "Worker:" + STR$(indx)
    _PUTIMAGE (indx * 100, 250), worker(indx).sc
  NEXT

  _PRINTSTRING (10, 380), "Press 'd' toggle thread slowdown. Press 's' to start/stop threads. Press 'ESC' to exit."
  _LIMIT 60
  _DISPLAY
LOOP

SUB resetWorker (id AS LONG)
  worker(id).xsize = 100
  worker(id).ysize = 100
  worker(id).xstart = 0
  worker(id).ystart = 0
  worker(id).x = worker(id).xstart
  worker(id).y = worker(id).ystart
  worker(id).xsize = 100
  worker(id).ysize = 100
  worker(id).xdir = 1
  worker(id).colour = _RGB32(RND * 255, RND * 255, RND * 255)
END SUB

SUB workerThread (id AS LONG)
  DIM AS INTEGER dly

  DO
    lockThread id
    IF worker(id).x + worker(id).xdir > worker(id).xstart + worker(id).xsize OR worker(id).x + worker(id).xdir < worker(id).xstart THEN
      worker(id).xdir = -worker(id).xdir
      IF worker(id).y + 1 > worker(id).ysize THEN
        resetWorker id
      ELSE
        worker(id).y = worker(id).y + 1
      END IF
    ELSE
      worker(id).x = worker(id).x + worker(id).xdir
    END IF

    worker(id).offset = worker(id).img.OFFSET + (worker(id).x * 4) + (worker(id).y * worker(id).xsize * 4)
    _MEMPUT worker(id).img, worker(id).offset + 0, _BLUE32(worker(id).colour) AS _UNSIGNED _BYTE
    _MEMPUT worker(id).img, worker(id).offset + 1, _GREEN32(worker(id).colour) AS _UNSIGNED _BYTE
    _MEMPUT worker(id).img, worker(id).offset + 2, _RED32(worker(id).colour) AS _UNSIGNED _BYTE
    _MEMPUT worker(id).img, worker(id).offset + 3, 255 AS _UNSIGNED _BYTE

    IF NOT worker(id).dly THEN dly = 0: DO: dly = dly + 1: LOOP UNTIL dly < 0
    unlockThread id

  LOOP WHILE worker(id).command = 0
  exitThread
END SUB
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: 3 Guest(s)