Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #27876 > unrolled thread

C++ threads versus PThreads for embedded Linux on ARM micro

Started by"gp.kiwi@gmail.com" <graeme.prentice@gmail.com>
First post2018-07-20 04:01 -0700
Last post2018-08-01 12:28 -0700
Articles 20 on this page of 50 — 15 participants

Back to article view | Back to comp.arch.embedded


Contents

  C++ threads versus PThreads for embedded Linux on ARM micro "gp.kiwi@gmail.com" <graeme.prentice@gmail.com> - 2018-07-20 04:01 -0700
    Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-07-20 20:19 +0200
      Re: C++ threads versus PThreads for embedded Linux on ARM micro graeme.prentice@gmail.com - 2018-07-20 15:54 -0700
        Re: C++ threads versus PThreads for embedded Linux on ARM micro Paul Rubin <no.email@nospam.invalid> - 2018-07-20 18:27 -0700
          Re: C++ threads versus PThreads for embedded Linux on ARM micro graeme.prentice@gmail.com - 2018-07-20 23:58 -0700
            Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-07-21 14:32 +0200
              Re: C++ threads versus PThreads for embedded Linux on ARM micro mac <acolvin@efunct.com> - 2018-07-26 19:37 +0000
            Re: C++ threads versus PThreads for embedded Linux on ARM micro Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2018-07-21 21:48 +0300
            Re: C++ threads versus PThreads for embedded Linux on ARM micro Rob Gaddi <rgaddi@highlandtechnology.invalid> - 2018-07-23 09:58 -0700
    Re: C++ threads versus PThreads for embedded Linux on ARM micro Les Cargill <lcargill99@comcast.com> - 2018-07-22 13:15 -0500
    Re: C++ threads versus PThreads for embedded Linux on ARM micro StateMachineCOM <statemachineguru@gmail.com> - 2018-07-27 08:51 -0700
      Re: C++ threads versus PThreads for embedded Linux on ARM micro "gp.kiwi@gmail.com" <graeme.prentice@gmail.com> - 2018-07-27 14:53 -0700
        Re: C++ threads versus PThreads for embedded Linux on ARM micro Paul Rubin <no.email@nospam.invalid> - 2018-07-27 15:23 -0700
        Re: C++ threads versus PThreads for embedded Linux on ARM micro StateMachineCOM <statemachineguru@gmail.com> - 2018-07-30 09:08 -0700
        Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-07-31 09:21 +0200
      Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-07-31 09:13 +0200
        Re: C++ threads versus PThreads for embedded Linux on ARM micro StateMachineCOM <statemachineguru@gmail.com> - 2018-07-31 15:16 -0700
          Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-01 07:53 +0200
          Re: C++ threads versus PThreads for embedded Linux on ARM micro pozz <pozzugno@gmail.com> - 2018-08-01 15:49 +0200
          Re: C++ threads versus PThreads for embedded Linux on ARM micro upsidedown@downunder.com - 2018-08-01 21:47 +0300
            Re: C++ threads versus PThreads for embedded Linux on ARM micro StateMachineCOM <statemachineguru@gmail.com> - 2018-08-01 12:11 -0700
              Re: C++ threads versus PThreads for embedded Linux on ARM micro Tom Gardner <spamjunk@blueyonder.co.uk> - 2018-08-01 20:23 +0100
              Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-02 12:24 +0200
                Re: C++ threads versus PThreads for embedded Linux on ARM micro upsidedown@downunder.com - 2018-08-02 16:14 +0300
                  Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-02 16:43 +0200
                    Re: C++ threads versus PThreads for embedded Linux on ARM micro StateMachineCOM <statemachineguru@gmail.com> - 2018-08-02 09:12 -0700
                      Re: C++ threads versus PThreads for embedded Linux on ARM micro Tom Gardner <spamjunk@blueyonder.co.uk> - 2018-08-02 18:13 +0100
                      Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-02 23:05 +0200
                        Re: C++ threads versus PThreads for embedded Linux on ARM micro StateMachineCOM <statemachineguru@gmail.com> - 2018-08-02 14:22 -0700
                          Re: C++ threads versus PThreads for embedded Linux on ARM micro Niklas Holsti <niklas.holsti@tidorum.invalid> - 2018-08-03 10:14 +0300
                          Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-03 10:22 +0200
                      Re: C++ threads versus PThreads for embedded Linux on ARM micro Tom Gardner <spamjunk@blueyonder.co.uk> - 2018-08-02 23:48 +0100
                    Re: C++ threads versus PThreads for embedded Linux on ARM micro upsidedown@downunder.com - 2018-08-02 19:56 +0300
                      Re: C++ threads versus PThreads for embedded Linux on ARM micro Tom Gardner <spamjunk@blueyonder.co.uk> - 2018-08-02 18:14 +0100
                        Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-02 23:12 +0200
                          Re: C++ threads versus PThreads for embedded Linux on ARM micro Tom Gardner <spamjunk@blueyonder.co.uk> - 2018-08-02 23:52 +0100
                            Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-03 10:28 +0200
                              Re: C++ threads versus PThreads for embedded Linux on ARM micro Tom Gardner <spamjunk@blueyonder.co.uk> - 2018-08-03 11:21 +0100
                                Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-03 13:51 +0200
                          Re: C++ threads versus PThreads for embedded Linux on ARM micro upsidedown@downunder.com - 2018-08-03 09:11 +0300
                        Re: C++ threads versus PThreads for embedded Linux on ARM micro George Neuner <gneuner2@comcast.net> - 2018-08-04 03:00 -0400
                  Re: C++ threads versus PThreads for embedded Linux on ARM micro Robert Wessel <robertwessel2@yahoo.com> - 2018-08-02 12:23 -0500
                    Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-02 23:13 +0200
                      Re: C++ threads versus PThreads for embedded Linux on ARM micro George Neuner <gneuner2@comcast.net> - 2018-08-04 03:08 -0400
                Re: C++ threads versus PThreads for embedded Linux on ARM micro Robert Wessel <robertwessel2@yahoo.com> - 2018-08-02 12:23 -0500
                Re: C++ threads versus PThreads for embedded Linux on ARM micro George Neuner <gneuner2@comcast.net> - 2018-08-02 14:15 -0400
                  Re: C++ threads versus PThreads for embedded Linux on ARM micro Tom Gardner <spamjunk@blueyonder.co.uk> - 2018-08-02 19:21 +0100
                    Re: C++ threads versus PThreads for embedded Linux on ARM micro David Brown <david.brown@hesbynett.no> - 2018-08-02 23:18 +0200
                      Re: C++ threads versus PThreads for embedded Linux on ARM micro Tom Gardner <spamjunk@blueyonder.co.uk> - 2018-08-03 00:02 +0100
            Re: C++ threads versus PThreads for embedded Linux on ARM micro StateMachineCOM <statemachineguru@gmail.com> - 2018-08-01 12:28 -0700

Page 1 of 3  [1] 2 3  Next page →


#27876 — C++ threads versus PThreads for embedded Linux on ARM micro

From"gp.kiwi@gmail.com" <graeme.prentice@gmail.com>
Date2018-07-20 04:01 -0700
SubjectC++ threads versus PThreads for embedded Linux on ARM micro
Message-ID<ddc2da65-65a3-4307-b93b-5ad1cc62a418@googlegroups.com>
We're starting an embedded Linux C++ project with an ARM micro and using GCC V7.  Can anyone suggest pros and cons of using C++ Threads versus PThreads (Posix threads).

[toc] | [next] | [standalone]


#27877

FromDavid Brown <david.brown@hesbynett.no>
Date2018-07-20 20:19 +0200
Message-ID<pit93d$dtv$1@dont-email.me>
In reply to#27876
On 20/07/18 13:01, gp.kiwi@gmail.com wrote:
> We're starting an embedded Linux C++ project with an ARM micro and using GCC V7.  Can anyone suggest pros and cons of using C++ Threads versus PThreads (Posix threads).
> 

C++ threads are always a wrapper around an underlying library.  So if 
you are using C++ on Linux, the C++ threads /are/ pthreads.  These are 
the points I can think of for preferring C++ threads:

+ You have a nice class/template library with C++ threads, instead of a 
C function interface.

+ You have have RAII classes for locks and other synchronisation objects.

+ You have consistency with other C++ thread systems.

+ Your compiler may understand that your code is threaded.

- You need at least C++11 (but that has huge advantages anyway, compared 
to older C++).

- It is marginally more fiddly if you need the underlying thread details 
for features not supported by the C++ thread library.

[toc] | [prev] | [next] | [standalone]


#27878

Fromgraeme.prentice@gmail.com
Date2018-07-20 15:54 -0700
Message-ID<62f86a9d-b0fe-4368-9de7-f0b71ffc203d@googlegroups.com>
In reply to#27877
On Saturday, July 21, 2018 at 6:19:31 AM UTC+12, David Brown wrote:
> On 20/07/18 13:01, gp...@gmail.com wrote:
> > We're starting an embedded Linux C++ project with an ARM micro and using GCC V7.  Can anyone suggest pros and cons of using C++ Threads versus PThreads (Posix threads).
> > 
> 
> C++ threads are always a wrapper around an underlying library.  So if 
> you are using C++ on Linux, the C++ threads /are/ pthreads.  These are 
> the points I can think of for preferring C++ threads:
> 
> + You have a nice class/template library with C++ threads, instead of a 
> C function interface.
> 
> + You have have RAII classes for locks and other synchronisation objects.
> 
> + You have consistency with other C++ thread systems.
> 
> + Your compiler may understand that your code is threaded.
> 
> - You need at least C++11 (but that has huge advantages anyway, compared 
> to older C++).
> 
> - It is marginally more fiddly if you need the underlying thread details 
> for features not supported by the C++ thread library.

That's great, thanks.

[toc] | [prev] | [next] | [standalone]


#27879

FromPaul Rubin <no.email@nospam.invalid>
Date2018-07-20 18:27 -0700
Message-ID<877elpgyxt.fsf@nightsong.com>
In reply to#27878
graeme.prentice@gmail.com writes:
> That's great, thanks.

Also, ask yourself if you really need threads in the first place.
Depending on what you're doing, you may be better off with multiple
processes.  That gets rid of a lot of lock and race hazards, and if the
processes can communicate through sockets, that improves scalability by
making it easier for you to distribute your program across multiple
machines if you run out of cpu cores on your original machine.

[toc] | [prev] | [next] | [standalone]


#27880

Fromgraeme.prentice@gmail.com
Date2018-07-20 23:58 -0700
Message-ID<734190e1-1761-4ee8-9774-b7a09903fa9b@googlegroups.com>
In reply to#27879
On Saturday, July 21, 2018 at 1:28:02 PM UTC+12, Paul Rubin wrote:
> 
> Also, ask yourself if you really need threads in the first place.
> Depending on what you're doing, you may be better off with multiple
> processes.  That gets rid of a lot of lock and race hazards, and if the
> processes can communicate through sockets, that improves scalability by
> making it easier for you to distribute your program across multiple
> machines if you run out of cpu cores on your original machine.

Thanks for the suggestion.  The micro is an ARM9 LPC3250 SOM (we're forced to use this at the moment) which I believe is single core (it's hard to find out for some reason) but it could easily change in future.  Based on a previous project, race conditions and deadlocks are a major headache so I'm hoping the core data will be written to by one thread only, maybe with lock-free queues.  The CPU data cache is 32KB and it's probably "write through".  We would have to do some performance tests to see if multi-processes and sockets is viable.   

[toc] | [prev] | [next] | [standalone]


#27881

FromDavid Brown <david.brown@hesbynett.no>
Date2018-07-21 14:32 +0200
Message-ID<piv95r$je2$1@dont-email.me>
In reply to#27880
On 21/07/18 08:58, graeme.prentice@gmail.com wrote:
> On Saturday, July 21, 2018 at 1:28:02 PM UTC+12, Paul Rubin wrote:
>>
>> Also, ask yourself if you really need threads in the first place.
>> Depending on what you're doing, you may be better off with multiple
>> processes.  

There are certainly tasks that are better handled as multiple processes 
rather than multiple threads.  (But note that it is not an either/or 
choice - often the best solution uses both.)

>> That gets rid of a lot of lock and race hazards, 

No, it does not - it merely changes them.  If your separate threads of 
execution need to synchronise, communicate, or agree about shared 
resources, then there is no theoretical difference about the types of 
hazards, races, or other such problems if you use multiple threads or 
multiple processes.  The details change, and the types of 
synchronisation objects use can change, but they do no not go away. 
Some may be handled by the OS rather than the application, however - for 
example, a pipe between processes will let you communicate without worry 
about locks for the underlying shared data structure, at the cost of 
being a lot less efficient than shared memory in threads.

Multiple processes have higher resource costs, and they make it a lot 
harder to use tools such as "-fsanitize=thread" to find problems.  On 
the other hand, they make it easier to break the problem down into 
separate tasks that are handled independently and tested independently. 
That helps if you have different developers - or even different 
programming languages.

>> and if the
>> processes can communicate through sockets, that improves scalability by
>> making it easier for you to distribute your program across multiple
>> machines if you run out of cpu cores on your original machine.

True.

This can also be useful during development when you might have some of 
the bits running on your target system, and other bits running on your 
host computer (perhaps under a debugger).

> 
> Thanks for the suggestion. The micro is an ARM9 LPC3250 SOM (we're
> forced to use this at the moment) which I believe is single core (it's
> hard to find out for some reason) but it could easily change in future.


That doesn't matter for the choice of threads, processes or both.

> Based on a previous project, race conditions and deadlocks are a major
> headache so I'm hoping the core data will be written to by one thread
> only, maybe with lock-free queues. The CPU data cache is 32KB and it's
> probably "write through". We would have to do some performance tests to
> see if multi-processes and sockets is viable.

Multiple processes are slower than multiple threads, and sockets are 
much slower than in-process queues.  But the sockets are more flexible. 
You might find you want an abstraction that can use either method as a 
backend, and change during different stages of development.


[toc] | [prev] | [next] | [standalone]


#27894

Frommac <acolvin@efunct.com>
Date2018-07-26 19:37 +0000
Message-ID<1188747523.554326005.017098.acolvin-efunct.com@news.eternal-september.org>
In reply to#27881
You can also communicate among processes through shared memory (e.g. mmap).

To look at a other way, processes require explicit sharing, threads share
implicitly.

On an embedded system, the heavier cost of process switching may be
important.

[toc] | [prev] | [next] | [standalone]


#27882

FromTauno Voipio <tauno.voipio@notused.fi.invalid>
Date2018-07-21 21:48 +0300
Message-ID<pivv5q$una$1@dont-email.me>
In reply to#27880
On 21.7.18 09:58, graeme.prentice@gmail.com wrote:
> Thanks for the suggestion.  The micro is an ARM9 LPC3250 SOM (we're forced to use this at the moment) which I believe is single core (it's hard to find out for some reason) but it could easily change in future.  Based on a previous project, race conditions and deadlocks are a major headache so I'm hoping the core data will be written to by one thread only, maybe with lock-free queues.  The CPU data cache is 32KB and it's probably "write through".  We would have to do some performance tests to see if multi-processes and sockets is viable.



For number of cores on your system, if you have Linux running on the
target, have a look at /proc/cpuinfo:

tauno@pi2:~ $ cat /proc/cpuinfo
processor	: 0
model name	: ARMv7 Processor rev 5 (v7l)
BogoMIPS	: 38.40
Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt 
vfpd32 lpae evtstrm
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xc07
CPU revision	: 5

processor	: 1
model name	: ARMv7 Processor rev 5 (v7l)
BogoMIPS	: 38.40
Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt 
vfpd32 lpae evtstrm
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xc07
CPU revision	: 5

processor	: 2
model name	: ARMv7 Processor rev 5 (v7l)
BogoMIPS	: 38.40
Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt 
vfpd32 lpae evtstrm
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xc07
CPU revision	: 5

processor	: 3
model name	: ARMv7 Processor rev 5 (v7l)
BogoMIPS	: 38.40
Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt 
vfpd32 lpae evtstrm
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xc07
CPU revision	: 5

Hardware	: BCM2835
Revision	: a01041
Serial		: 0000000064d34ba1

---

The above is from a Raspberry Pi 2.

-- 

-TV

[toc] | [prev] | [next] | [standalone]


#27888

FromRob Gaddi <rgaddi@highlandtechnology.invalid>
Date2018-07-23 09:58 -0700
Message-ID<pj51f6$r1k$1@dont-email.me>
In reply to#27880
On 07/20/2018 11:58 PM, graeme.prentice@gmail.com wrote:
> On Saturday, July 21, 2018 at 1:28:02 PM UTC+12, Paul Rubin wrote:
>>
>> Also, ask yourself if you really need threads in the first place.
>> Depending on what you're doing, you may be better off with multiple
>> processes.  That gets rid of a lot of lock and race hazards, and if the
>> processes can communicate through sockets, that improves scalability by
>> making it easier for you to distribute your program across multiple
>> machines if you run out of cpu cores on your original machine.
> 
> Thanks for the suggestion.  The micro is an ARM9 LPC3250 SOM (we're forced to use this at the moment) which I believe is single core (it's hard to find out for some reason) but it could easily change in future.  Based on a previous project, race conditions and deadlocks are a major headache so I'm hoping the core data will be written to by one thread only, maybe with lock-free queues.  The CPU data cache is 32KB and it's probably "write through".  We would have to do some performance tests to see if multi-processes and sockets is viable.
> 

3250 is single-core.  Happens to be a part we use a lot around here, 
although we always go bare-metal rather than running Linux.  Cache is 
programmable through the page-table as to whether it's write-through or not.

The reason you're having trouble determining much of this information is 
that NXP bought large chunks of that chip wholesale from ARM without 
anyone there actually understanding it.  So the NXP documentation is 
spotty and occasionally wrong (let me tell you of our I2C-based woes).

There's a document available directly from ARM, ARM DDI 0198E, that is 
specifically the ARM926EJ-S Technical Reference Manual.  Getting into 
the details on the 3250 is nearly impossible without it.

-- 
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order.  See above to fix.

[toc] | [prev] | [next] | [standalone]


#27885

FromLes Cargill <lcargill99@comcast.com>
Date2018-07-22 13:15 -0500
Message-ID<pj2hc7$5hr$1@dont-email.me>
In reply to#27876
gp.kiwi@gmail.com wrote:
> We're starting an embedded Linux C++ project with an ARM micro and
> using GCC V7.  Can anyone suggest pros and cons of using C++ Threads
> versus PThreads (Posix threads).
> 

I'd suggest thinking about a design for how you'd measure which works
in context for you. If I run pthreads on a big Linux machine it'll be 
different from running them in a VM. Similarly, it'll be different on
a RasPi 3 sized ARM computer.

-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#27895

FromStateMachineCOM <statemachineguru@gmail.com>
Date2018-07-27 08:51 -0700
Message-ID<b28cf52f-2a9e-4e6a-9f3f-8b9921c3a0c1@googlegroups.com>
In reply to#27876
Traditional threads, whichever way you package them (as C++ threads, p-threads or any other thread library), typically correspond to the "shared-state concurrency and blocking" approach. This approach is known to be problematic, and many experts in concurrent programming recommend to drastically limit both sharing and blocking according to the following three best practices:

1. Keep data isolated and bound to threads. Threads should hide (encapsulate) their private data and other resources, and not share them with the rest of the system.

2. Communicate among threads asynchronously via messages (event objects). Using asynchronous events keeps the threads running truly independently, without any further blocking on each other.

3. Threads should spend their lifetime responding to incoming events, so their mainline should consist of an event-loop that handles events one at a time (to completion), thus avoiding any concurrency hazards within a thread itself.

The set of these best practices are collectively known as the Active Object design pattern (a.k.a. Actor). While this pattern can be applied manually on top of a traditional threads, a better way is to use an Active Object framework.

The main difference is that when you use "naked" threads, you write the main body of the application (such as the thread routines for all your tasks) and you call various thread-library services (e.g., a semaphore or a time delay). When you use a framework, you reuse the overall architecture and write the code that it calls. This leads to inversion of control, which allows the framework to automatically enforce the best practices of concurrent programming. In contrast, a "naked" threads let you do anything and offer no help or automation for the best practices.

[toc] | [prev] | [next] | [standalone]


#27896

From"gp.kiwi@gmail.com" <graeme.prentice@gmail.com>
Date2018-07-27 14:53 -0700
Message-ID<8490b5e0-bf86-413c-866e-8a10a3d87466@googlegroups.com>
In reply to#27895
Thanks.  What is an "event object"?  What is the best way to pass data asynchronously using a queue, on Linux?  I've read that lock-free data structures are easy to get wrong and best avoided and that the C++ thread library doesn't have any lock free data structures - mainly because there's too many variations to have a generalized data structure.

Can we use the "libcds" library and be confident that it will work correctly?

https://github.com/khizmax/libcds


On Saturday, July 28, 2018 at 3:52:02 AM UTC+12, StateMachineCOM wrote:
> Traditional threads, whichever way you package them (as C++ threads, p-threads or any other thread library), typically correspond to the "shared-state concurrency and blocking" approach. This approach is known to be problematic, and many experts in concurrent programming recommend to drastically limit both sharing and blocking according to the following three best practices:
[snip]

[toc] | [prev] | [next] | [standalone]


#27897

FromPaul Rubin <no.email@nospam.invalid>
Date2018-07-27 15:23 -0700
Message-ID<877elge2t0.fsf@nightsong.com>
In reply to#27896
"gp.kiwi@gmail.com" <graeme.prentice@gmail.com> writes:
> Thanks.  What is an "event object"?

Just a message that you pass from one thread to another.

> What is the best way to pass data asynchronously using a queue, on
> Linux?

I'd probably just use std::deque with a lock.  

You might look at seastar-project.org for some inspiration.

[toc] | [prev] | [next] | [standalone]


#27898

FromStateMachineCOM <statemachineguru@gmail.com>
Date2018-07-30 09:08 -0700
Message-ID<d68320e5-08d8-4e2b-9a00-21fdde1dd9de@googlegroups.com>
In reply to#27896
On Friday, July 27, 2018 at 5:53:28 PM UTC-4, gp....@gmail.com wrote:
> What is an "event object"? What is the best way to pass data asynchronously using a queue, on Linux?

I can tell you how this is done in the QP/C++ framework, which I've designed and refined for almost two decades now. But before I can get to the technical, I need to make full disclosure that QP is a dual-licensed (open-source/commercial) product of my company (see https://www.state-machine.com), so I do have a commercial interest in promoting it.

So, now going back to your question, "event objects" are messages that threads send to each other via event queues. But a naive implementation of copying messages to and from the queues is expensive and hurts real-time performance. So, in the QP framework, the events are allocated from fixed-size pools and only pointers to events are kept in the event queues. The framework maintains the copy-by-value semantics as much as possible, while event objects are really shared under the hood. The framework also automatically recycles events that are processed.

Specifically to the POSIX port of QP/C++, which has been available for over 15 years now, each active object runs in its own p-thread. These threads are organized as an event-loop (according to the best practice I listed in my previous thread), so they block only in one place--when the event queue is empty. The queue uses internally a p-thread mutex and a condition variable to implement blocking on an event queue and signaling the queue. But the application programmer does not need to know any of it, because the main point is that the framework does the heavy lifting of thread-safe asynchronous event exchange. The application threads (active objects) only process the events one at a time (to completion), but they don't need to worry about any low-level mechanisms like mutexs or condition variables.

The design also allows you to avoid sharing of anything (except events) among the threads, which is another best-practice of concurrent programming. This means that you don't need to use any synchronization objects. In this sense, the RAII benefits of synchronization mechanisms in the C++ threads don't matter.

There is of course much more to active object framework like QP/C++ to capture here. For example, the framework supports Hierarchical State Machines to implement the internal behavior of active objects. There is also a free modeling tool (QM), with which you can design your HSMs graphically and generate production-code automatically. But all of this requires a paradigm shift from the traditional sequential-programming with blocking to event-driven programming without blocking or sharing. To learn more, you might read about the key concepts here:

https://www.state-machine.com/doc/concepts

Miro Samek
state-machine.com

[toc] | [prev] | [next] | [standalone]


#27900

FromDavid Brown <david.brown@hesbynett.no>
Date2018-07-31 09:21 +0200
Message-ID<pjp2l1$4c7$1@dont-email.me>
In reply to#27896
On 27/07/18 23:53, gp.kiwi@gmail.com wrote:
> Thanks.  What is an "event object"?  What is the best way to pass
> data asynchronously using a queue, on Linux?  I've read that
> lock-free data structures are easy to get wrong and best avoided and
> that the C++ thread library doesn't have any lock free data
> structures - mainly because there's too many variations to have a
> generalized data structure.


Lock-free data structures can range from very simple to very difficult,
and there can be huge differences depending on the details of the
structure.  A single-writer, single-reader fixed size queue is /easy/ -
it's just two atomic counters for "head" and "tail" and an array, with a
little care about memory ordering.  For single core embedded processors,
it's usually sufficient to just use "volatile" - for bigger systems,
C++11 or C11 atomics handle the details.

On the other hand, a queue that can have variable size, and more than
one reader or writer, quickly gets really complicated to handle
lock-free, and often it is much simpler, safer and cheaper to use a
lock.  On the third hand, if you have multiple cores you might want
lock-free again for scalability.

There is no simple answer here, and much depends on the details of
exactly what you are wanting.  As long as you ask general questions,
you'll only get general answers.

> 
> Can we use the "libcds" library and be confident that it will work
> correctly?
> 
> https://github.com/khizmax/libcds
> 
> 
> On Saturday, July 28, 2018 at 3:52:02 AM UTC+12, StateMachineCOM
> wrote:
>> Traditional threads, whichever way you package them (as C++
>> threads, p-threads or any other thread library), typically
>> correspond to the "shared-state concurrency and blocking" approach.
>> This approach is known to be problematic, and many experts in
>> concurrent programming recommend to drastically limit both sharing
>> and blocking according to the following three best practices:
> [snip]
> 

[toc] | [prev] | [next] | [standalone]


#27899

FromDavid Brown <david.brown@hesbynett.no>
Date2018-07-31 09:13 +0200
Message-ID<pjp272$1uc$1@dont-email.me>
In reply to#27895
On 27/07/18 17:51, StateMachineCOM wrote:
> Traditional threads, whichever way you package them (as C++ threads,
> p-threads or any other thread library), typically correspond to the
> "shared-state concurrency and blocking" approach. This approach is
> known to be problematic, and many experts in concurrent programming
> recommend to drastically limit both sharing and blocking according to
> the following three best practices:
> 
> 1. Keep data isolated and bound to threads. Threads should hide
> (encapsulate) their private data and other resources, and not share
> them with the rest of the system.

Encapsulation is always a good principle, but don't take it too far.  If
two parts of the system need to share data of significant size, then you
want shared data, not "messages" or other synchronisation mechanisms.
(You use the messages or other synchronisation to communicate metadata -
such as who owns the real data space at any given time - but not the
data itself.)

> 
> 2. Communicate among threads asynchronously via messages (event
> objects). Using asynchronous events keeps the threads running truly
> independently, without any further blocking on each other.
> 

Blocking is fine with threads.  If you have a single core cpu - or more
threads than cores - then blocking is often more efficient than
attempting to continue.  After all, if thread A is asking thread B to do
something (via a message, actor call, or whatever) then thread B can't
get started in doing the work A wants until A has taken a break.  It's
cheaper to have a voluntary break (yield, or blocking call) than to wait
for a scheduling change.

So use blocking calls whenever they fit naturally in the progression of
the code - and non-blocking calls whenever /that/ is the more natural
fit.  Don't make the mistake of thinking that one is inherently "better"
or necessarily more efficient - /measure/ the /real/ effects if
efficiency is vital.

> 3. Threads should spend their lifetime responding to incoming events,
> so their mainline should consist of an event-loop that handles events
> one at a time (to completion), thus avoiding any concurrency hazards
> within a thread itself.
> 
> The set of these best practices are collectively known as the Active
> Object design pattern (a.k.a. Actor). While this pattern can be
> applied manually on top of a traditional threads, a better way is to
> use an Active Object framework.

Actor designs can certainly have their advantages - equally certainly,
they are not the best design for all uses.  Whenever someone says "this
is the best way to do it", it's unlikely to be that simple - and
whenever they say so without knowing exact details of the problem at
hand, they are almost certainly wrong.

> 
> The main difference is that when you use "naked" threads, you write
> the main body of the application (such as the thread routines for all
> your tasks) and you call various thread-library services (e.g., a
> semaphore or a time delay). When you use a framework, you reuse the
> overall architecture and write the code that it calls. This leads to
> inversion of control, which allows the framework to automatically
> enforce the best practices of concurrent programming. In contrast, a
> "naked" threads let you do anything and offer no help or automation
> for the best practices.
> 

[toc] | [prev] | [next] | [standalone]


#27901

FromStateMachineCOM <statemachineguru@gmail.com>
Date2018-07-31 15:16 -0700
Message-ID<4c2a996d-d88f-4954-a2af-e4e4663c6b35@googlegroups.com>
In reply to#27899
@David Brown: Absolutely, if you stick to the traditional sequential programming paradigm with shared-state concurrency and blocking threads, the three best practices I listed in my previous post can all be questioned, relaxed, and ultimately dismissed.

That's because they represent a different, event-driven ("reactive") programming paradigm. The distinction is important, because the two programming paradigms do NOT mix well, certainly not inside the same thread. So it is important to always realize which paradigm you are using in which thread, to avoid confusion and mixing the two.

To back up this point, I'd like to recommend the article "Managing Concurrency in Complex Embedded Systems" by David Cummings (http://www.kellytechnologygroup.com/main/concurrent-embedded-systems-website.pdf ). The author presents general guiding principles of structuring threads, which he found particularly useful and which he applied in the NASA Mars rovers and other mission-critical systems. The paper starts with the description of the general thread structure, which can be immediately recognized as the event-loop. The bulk of the paper then focuses on discussing several scenarios in which designers might be tempted to apply thread BLOCKING, followed by explanations why blocking is always a BAD idea. Again, I repeat, that this conclusion applies to the "event-driven" thread structure, which the author started with.

[toc] | [prev] | [next] | [standalone]


#27902

FromDavid Brown <david.brown@hesbynett.no>
Date2018-08-01 07:53 +0200
Message-ID<pjrhrv$ac1$1@dont-email.me>
In reply to#27901
On 01/08/18 00:16, StateMachineCOM wrote:
> @David Brown: Absolutely, if you stick to the traditional sequential programming paradigm with shared-state concurrency and blocking threads, the three best practices I listed in my previous post can all be questioned, relaxed, and ultimately dismissed.
> 
> That's because they represent a different, event-driven ("reactive") programming paradigm. The distinction is important, because the two programming paradigms do NOT mix well, certainly not inside the same thread. So it is important to always realize which paradigm you are using in which thread, to avoid confusion and mixing the two.
> 
> To back up this point, I'd like to recommend the article "Managing Concurrency in Complex Embedded Systems" by David Cummings (http://www.kellytechnologygroup.com/main/concurrent-embedded-systems-website.pdf ). The author presents general guiding principles of structuring threads, which he found particularly useful and which he applied in the NASA Mars rovers and other mission-critical systems. The paper starts with the description of the general thread structure, which can be immediately recognized as the event-loop. The bulk of the paper then focuses on discussing several scenarios in which designers might be tempted to apply thread BLOCKING, followed by explanations why blocking is always a BAD idea. Again, I repeat, that this conclusion applies to the "event-driven" thread structure, which the author started with.
> 

I haven't read the link yet (I will do so), but I do agree that blocking 
is a very bad idea in an event-driven thread.

[toc] | [prev] | [next] | [standalone]


#27903

Frompozz <pozzugno@gmail.com>
Date2018-08-01 15:49 +0200
Message-ID<pjsdpk$c17$1@dont-email.me>
In reply to#27901
Il 01/08/2018 00:16, StateMachineCOM ha scritto:
> @David Brown: Absolutely, if you stick to the traditional sequential programming paradigm with shared-state concurrency and blocking threads, the three best practices I listed in my previous post can all be questioned, relaxed, and ultimately dismissed.
> 
> That's because they represent a different, event-driven ("reactive") programming paradigm. The distinction is important, because the two programming paradigms do NOT mix well, certainly not inside the same thread. So it is important to always realize which paradigm you are using in which thread, to avoid confusion and mixing the two.
> 
> To back up this point, I'd like to recommend the article "Managing Concurrency in Complex Embedded Systems" by David Cummings (http://www.kellytechnologygroup.com/main/concurrent-embedded-systems-website.pdf ). 

Thanks for this reference... it is a very *very* instructive material.

[toc] | [prev] | [next] | [standalone]


#27904

Fromupsidedown@downunder.com
Date2018-08-01 21:47 +0300
Message-ID<3kv3md9lvenno2jabfamrccu2glr6j877h@4ax.com>
In reply to#27901
On Tue, 31 Jul 2018 15:16:07 -0700 (PDT), StateMachineCOM
<statemachineguru@gmail.com> wrote:

>@David Brown: Absolutely, if you stick to the traditional sequential programming paradigm with shared-state concurrency and blocking threads, the three best practices I listed in my previous post can all be questioned, relaxed, and ultimately dismissed.
>
>That's because they represent a different, event-driven ("reactive") programming paradigm. The distinction is important, because the two programming paradigms do NOT mix well, certainly not inside the same thread. So it is important to always realize which paradigm you are using in which thread, to avoid confusion and mixing the two.
>
>To back up this point, I'd like to recommend the article "Managing Concurrency in Complex Embedded Systems" by David Cummings (http://www.kellytechnologygroup.com/main/concurrent-embedded-systems-website.pdf ). The author presents general guiding principles of structuring threads, which he found particularly useful and which he applied in the NASA Mars rovers and other mission-critical systems. The paper starts with the description of the general thread structure, which can be immediately recognized as the event-loop. The bulk of the paper then focuses on discussing several scenarios in which designers might be tempted to apply thread BLOCKING, followed by explanations why blocking is always a BAD idea. Again, I repeat, that this conclusion applies to the "event-driven" thread structure, which the author started with.

It seems Cummings has reinvented the wheel :-). 

Those principles were used already in the 1970's to implement real
time systems under RSX-11 on PDP-11. Later on these principles were
also used on real time systems under RMX-80 for 8080 and similar
kernels.

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | comp.arch.embedded


csiph-web