Thread overview
D threading and shared variables
Apr 07, 2019
Archie Allison
Apr 07, 2019
Doc Andrew
Apr 07, 2019
Archie Allison
Apr 07, 2019
Mike Wey
Apr 07, 2019
Archie Allison
Apr 08, 2019
Kagamin
Apr 07, 2019
Johan Engelen
Apr 09, 2019
Archie Allison
Apr 11, 2019
Kagamin
April 07, 2019
I have written an industrial control program which uses serial ports to communicate with hardware but am having problems, perhaps with shared memory, on Windows.

The SerialPort class calls C object-file functions. Transmits are on one thread and receives on another (all within a class derived from Thread), with a signal(created from a mutex) notifying the transmit thread when a packet has arrived.

This generally works OK when tied to a Console but when link options are changed to be SUBSYSTEM:WINDOWS and ENTRY:mainCRTStartup it rarely does.

Compiling with -vtls shows the serial port is in thread local storage. As a hardware resource, I wasn't sure if this matters. I've tried casting to a shared object so it no longer appears in the -vtls list, with no difference.

Does anyone have ideas about where I may have misunderstood the threading and shared-memory design of D or what I can look at?

April 07, 2019
On Sunday, 7 April 2019 at 14:08:07 UTC, Archie Allison wrote:
> I have written an industrial control program which uses serial ports to communicate with hardware but am having problems, perhaps with shared memory, on Windows.
>
> The SerialPort class calls C object-file functions. Transmits are on one thread and receives on another (all within a class derived from Thread), with a signal(created from a mutex) notifying the transmit thread when a packet has arrived.
>
> This generally works OK when tied to a Console but when link options are changed to be SUBSYSTEM:WINDOWS and ENTRY:mainCRTStartup it rarely does.
>
> Compiling with -vtls shows the serial port is in thread local storage. As a hardware resource, I wasn't sure if this matters. I've tried casting to a shared object so it no longer appears in the -vtls list, with no difference.
>
> Does anyone have ideas about where I may have misunderstood the threading and shared-memory design of D or what I can look at?

When you say it "rarely works" when run as a GUI app (vs console), it makes me think that there's probably a race condition going on, and the extra context switching that takes place in GUI mode makes it more likely. I haven't tried it in D, but you may be able use Application Verifier with your app to add checks for lock contention. Without more information about the way your threads are synchronized it's hard to say for sure though.
April 07, 2019
On Sunday, 7 April 2019 at 14:35:24 UTC, Doc Andrew wrote:

> When you say it "rarely works" when run as a GUI app (vs console), it makes me think that there's probably a race condition going on, and the extra context switching that takes place in GUI mode makes it more likely. I haven't tried it in D, but you may be able use Application Verifier with your app to add checks for lock contention. Without more information about the way your threads are synchronized it's hard to say for sure though.

The codebase is a reasonable size so too big (and proprietary) to share.

It's always run with a GUI (GTKD), it's just the difference in linking so launching (a)GUI + attached console for stdout.writeln vs. (b)just the GUI window. There's nothing I'd expect to cause races or deadlocks.

April 07, 2019
On 07-04-2019 16:49, Archie Allison wrote:
> The codebase is a reasonable size so too big (and proprietary) to share.
> 
> It's always run with a GUI (GTKD), it's just the difference in linking so launching (a)GUI + attached console for stdout.writeln vs. (b)just the GUI window. There's nothing I'd expect to cause races or deadlocks.
> 

How are you using the GUI, GTK is not thread safe, all gui function calls should be made from the GUI thread.

Last time i checked threadsEnter and threadsLeave didn't work properly on windows.

-- 
Mike Wey
April 07, 2019
On Sunday, 7 April 2019 at 17:52:40 UTC, Mike Wey wrote:
>> 
>
> How are you using the GUI, GTK is not thread safe, all gui function calls should be made from the GUI thread.
>
> Last time i checked threadsEnter and threadsLeave didn't work properly on windows.

All GUI updates are sent from a worker thread to the GUI thread using the D message passing system and immutable object arguments. I'm pretty satisfied it's not a problem.

The general principle of the classes doing the comms are:

class name :Thread
{
  Mutex m;
  Condition sig;
  shared char[] shared_buffer;
  CommunicationClass comm;

  this()
  {
    m = new Mutex;
    sig = new Condition(m);
    comm = new CommunicationClass;
    super(&receive_thread);
    start();
  }

  //the main routine being called
  void packet_transaction()
  {
    comm.send_data();
    synchronized(m)
    {
      if (sig.wait(dur!("seconds")(1)) == true)
        do_something();
      else
        do_timeout();
    }
  }

  void receive_thread()
  {
    local_buffer;
    while(true)
    {
      local_buffer += comm.get_data();
      if (some condition)
      {
        synchronized(m)
        {
          copy local_buffer to shared_buffer;
          sig.notify();
        }
      }
    }
  }
};
April 07, 2019
On Sunday, 7 April 2019 at 14:08:07 UTC, Archie Allison wrote:
>
> This generally works OK when tied to a Console but when link options are changed to be SUBSYSTEM:WINDOWS and ENTRY:mainCRTStartup it rarely does.

Manually setting the entry point sounds problematic if no other precautions are taken. Are you sure that druntime is initialized? See [1].

- Johan

[1] https://wiki.dlang.org/D_for_Win32
April 08, 2019
On Sunday, 7 April 2019 at 14:49:20 UTC, Archie Allison wrote:
> The codebase is a reasonable size so too big (and proprietary) to share.

You can reduce it to a minimal example that doesn't work. Static variables are thread local by default in D unless they are marked as shared or __gshared.
April 09, 2019
On Sunday, 7 April 2019 at 22:18:56 UTC, Johan Engelen wrote:
> On Sunday, 7 April 2019 at 14:08:07 UTC, Archie Allison wrote:
>>
>> This generally works OK when tied to a Console but when link options are changed to be SUBSYSTEM:WINDOWS and ENTRY:mainCRTStartup it rarely does.
>
> Manually setting the entry point sounds problematic if no other precautions are taken. Are you sure that druntime is initialized? See [1].
>
> - Johan
>
> [1] https://wiki.dlang.org/D_for_Win32

I changed the main code as described in the article but the effect seems to be the same as just using the link options. Is there anything obviously wrong with the variable declarations in the code sample? It looks like having a console output window in addition to just the GUI is having some sort of effect on threading, sharing or timing.

April 11, 2019
Well, if the code is too complex to debug, the usual solution is to try simpler code and see if it works.