Best way to pass Queue Records to Another Queue From another thread?

What’s the best way to do passing records of a queue to other queue in another thread?

I have a background monitoring window that will take care of all the data processing to produce outputs that is needed from my dashboard window so that it will not block the dashboard user inputs.

I use notify() and notification() to pass simple data output such as total item record, etc. that only needs single value. but have no idea how to pass record from background monitoring queue to my dashboard queue. Otherwise I really need to define that queue globally :sweat_smile:

If you have stringtheory and Jfiles, you could use a couple of quick statement to convert the queue to json text and pass it as a simple string, reverse the procedure to load.

I think it’s something simple like json.save(Queue) to save and json.load to load. But docs would be a good idea

Also check the serialize methods in StringTheory, particularly SerializeQueue which basically iterates SerializeGroup over each queue entry. Default is CSV format but you can override the boundaries/separators if desired.

Or did you mean passing the queue using some pointer? Obviously you would need a global queue type and a critical section so that only one thread could access it at a time. Thinking about it if you were going down that route you may as well just have the whole queue global and synchronise access. You might be better using the inmemory driver? Or perhaps Capesoft’s MaxQueue.

You can pass arbitrarily complex structures between threads
The general concept is

In the calling Thread:

  1. NEW memory in the calling thread
  2. copy the data into the NEW’d structure
  3. pass the ADDRESS (or INSTANCE) to the receiving thread

In the receiving thread:

  1. interpret the address as a reference to the expected structure
  2. use the complex structure
  3. DISPOSE the reference

Note: ADDRESS(Queue) points the queue buffer, whereas INSTANCE( Queue, THREAD() ) points to the entire queue

Calling thread:

  CODE
  ToPassQ &= NEW QueueTypeYada
  DO FillPassQ_FromActualData
  NOTIFY( Notify:QueueTypeYada, ReceivingThread, INSTANCE( ToPassQ, THREAD() ) )

Receiving Thread:

   INCLUDE('QueueTypeYada.inc'),ONCE

ThisWindow         CLASS(WindowManager)
YadaQ                 &QueueTypeYada
TakeNotify             PROCEDURE()
TakeNotify:QueueTypeYada   PROCEDURE( SIGNED xThread, LONG xParam)
YadaQ:Dispose          PROCEDURE()
YadaQ:Free             PROCEDURE
TakeEvent              PROCEDURE,DERIVED,BYTE,PROC
Kill                   PROCEDURE,PROC,BYTE,DERIVED    ! Level:Notify means dead already
                    END 

   CODE
   !....

ThisWindow.TakeEvent PROCEDURE()
   CODE
   CASE EVENT() 
       OF EVENT:NOTIFY;  SELF.TakeNotifiy()
   END
   RETURN Parent.TakeEvent()


ThisWindow.TakeNotifiy PROCEDURE()
NotifyCode      UNSIGNED
NotifyThread    SIGNED
NotifyParameter LONG
  CODE
  IF          NOTIFICATION(NotifyCode,NotifyThread,NotifyParameter)
    CASE NotifyCode
        OF Notify:QueueTypeYada; SELF.YadaQ:Dispose()
                                 ThisWindow.YadaQ  &= 0 + NotifyParameter

        ! handle other notifications here
   END 
  END

YadaQ:Dispose          PROCEDURE()
   CODE 
  IF NOT ThisWindow.YadaQ &=  NULL
      SELF.YadaQ:Free()  ! knows about nested references and handles them too
      DISPOSE( ThisWindow.YadaQ )  
   END 
      
ThisWindow.Kill PROCEUDRE()
    CODE 
    SELF.YadaQ:Dispose()
    PARENT.Kill()

Note: I (nearly?) always wrap my queues in a class dervied from my ctQueue
which simplifies the copying, freeing and disposing among other things

Also I use a derived window manager which has a .TakeNotifiy already added

If you just want to pass One Queue record that can be put in a STRING. Both threads need to know the QUEUE Declaration. The easy way is to define a TYPE then inherit that.

QRecStrRef  &STRING
 ...
  !Send Record to another thread
  GET(SomeQ,X)
  QRecStrRef &= NEW( STRING( SIZE(SomeQ) ))
  QRecStrRef = SomeQ   !Q record in string
  NOTIFY( Xxxxx, TargetThreadNo, ADDRESS(QRecStrRef) )
  !Do the DISPOSE(QRecStrRef) in Target amd NOT here

In the Target Thread turn that address into a STRING and put that in a local Queue or Group with the same structure.

QRecStrRef  &STRING
QRecStrAddr LONG
 ...
  NOTIFICATION( NCode, FromThreadNo, QRecStrAddr) 
  IF NCode=Xxxxx AND QRecStrAddr <> 0 THEN 
      QRecStrRef &= (QRecStrAddr)   !Now we have a STRING
      Local_SomeQ = QRecStrRef
    ! Now you have a Queue or Group here 
      DISPOSE(QRecStrRef)   !Else Leak
  END 

I think this is what I needed, I will try this and let you guys know, btw both my procedure threads are in different dll’s so I will try if this works. Thanks.

I haven’t exactly copy the code here but this really works. Using INSTANCE() really helps