Friday, March 15, 2019

Digest for comp.lang.c++@googlegroups.com - 22 updates in 5 topics

Louis Krupp <lkrupp@nospam.pssw.com.invalid>: Mar 14 05:45PM -0600

On Thu, 14 Mar 2019 18:15:02 -0500, Peabody
 
> return error;
> };
>};
 
I haven't got a clue, but you might want to look at these:
 
https://www.boost.org/doc/libs/1_69_0/boost/asio/serial_port_base.hpp
 
https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_dcb
 
You might want to search the code for "fDtrControl".
 
Louis
Paavo Helde <myfirstname@osa.pri.ee>: Mar 15 07:55AM +0200

On 15.03.2019 1:15, Peabody wrote:
> I believe is ENABLED, so I think that means initState is zero. But I don't
> know where that comes from. Also, I don't know what calls all this stuff.
 
> Any clarifications will be appreciated.
 
This code just saves and reads a single integer, it does not do anything
substantial.
 
'initState' is the name of a local parameter, it's natural it does not
show up elsewhere.
 
If TESTControl doesn't either, then it's possible it is just some mockup
class used only for testing purposes and is not a part of the real program.
David Brown <david.brown@hesbynett.no>: Mar 15 01:03PM +0100

On 15/03/2019 00:15, Peabody wrote:
> lines low when it runs. I would like to at least get it to leave DTR high,
> or if possible actually generate the pattern itself so a generic USB-to-
> Serial adapter can be used as the hardware interface.
 
Let's take a step back, and ask what you are actually trying to achieve.
If you are trying to program msp430 microcontrollers using the BSL,
then fiddling with this C++ code when you don't know any C++ is almost
certainly the most difficult way to do it. There are several existing
solutions for working with the BSL - in particular, there are libraries
and programs in Python for the job. If you don't know Python, and you
don't know C++, then you'll get further faster by starting with the
Python code than with the C++ code.
Peabody <waybackNO584SPAM44@yahoo.com>: Mar 15 10:50AM -0500

David Brown says...
 
> for the job. If you don't know Python, and you don't
> know C++, then you'll get further faster by starting
> with the Python code than with the C++ code.
 
That's a fair point, and I may be approaching this wrong.
But the idea is to have a way to flash firmware updates in
the field, so that people who don't know anything about
electronics, and don't have Python installed on their
computers, can update firmware with a USB cable and a cheap
USB adapter, or possibly just the cable since the adapter
can be embedded on the project's board as in Arduinos.
 
I've modified the BSLDEMO program used to flash older MSP430
parts so they can now be flashed with a generic adapter, and
I just wanted to do the same for the newer parts that use
BSL-Scripter. Of course TI should be doing this, and I've
suggested as much to them, but to no avail so far.
 
The benefit of modifying Scripter is that the ultimate user
only needs one file to do the updates, in addition to
installing the adapter's VCP driver if it's not already
included in their OS. I'm just not sure a Python solution
works as well for the general public.
Peabody <waybackNO584SPAM44@yahoo.com>: Mar 15 11:29AM -0500

Paavo Helde says...
 
> This code just saves and reads a single integer, it does
> not do anything substantial.
 
I found this thread going back to 2010. The third post
contains code that looks very similar to what I'm working
with, and the author says it works fine. So while I don't
understand it, it appears that this code lets you change the
state of the RTS line. And similarly for DTR.
 
http://boost.2283326.n4.nabble.com/get-set-RTS-on-serial-port-td2598718.html
 
 
> If TESTControl doesn't either, then it's possible it is
> just some mockup class used only for testing purposes
> and is not a part of the real program.
 
I understand now about initState. But if TESTControl isn't
called from anywhere in the source, then something else is
causing DTR and RTS to be brought low. Perhaps that's just
the way Boost opens serial ports if FlowControl is None.
 
In any case, it also seems that my changes could simply call
TESTControl and RESETControl with the appropriate argument
to change the state of these lines.
James Moe <jimoeDESPAM@sohnen-moe.com>: Mar 15 12:50PM -0700

On 14/03/2019 4.15 PM, Peabody wrote:
 
> I don't know anything about BOOST. It appears that something called
> "initState" is key to what's going on here, [...]
 
Not really.
"TESTControl(uint16_t initState)" offers a way to initialize the
internal variable "state" when an instance of TESTControl is created. I
note there is no default constructor; "state" would then be undefined.
Since you cannot find an instance of TESTControl, I would assume it is
unused.
 
--
James Moe
jmm-list at sohnen-moe dot com
Think.
Paavo Helde <myfirstname@osa.pri.ee>: Mar 14 08:48PM +0200


>> That's why you check for the flag also *before* the waiting.
 
> I don't think this will work. It still does not guarantee that the child
> thread will arrive at wait() before the main thread has called notify_one().
 
That's true, but this guarantee is not needed for anything. If the flag
is already raised when the thread first comes around to lock the mutex,
then it will know it has been already notified, and will not call wait()
at all.
 
Maybe you are thinking that thread synchronizations can be done by
notify() and wait() only. Nope, for reliable synchronization you need
the share a data state and communicate the data state (a single bit flag
in this simple example). Mutexes, notifications and waits are just
helpers for making this data sharing fast and reliable.
johnbenny@nowhere.co.uk: Mar 15 09:58AM

On Thu, 14 Mar 2019 20:48:35 +0200
>the share a data state and communicate the data state (a single bit flag
>in this simple example). Mutexes, notifications and waits are just
>helpers for making this data sharing fast and reliable.
 
Fair enough, but given that you can reliably synchronise seperate processes
using signals and/or IPC only it seems a pity the same can't be done with
threads just using system calls instead of having to rely on polling flags
too.
Sam <sam@email-scan.com>: Mar 15 07:09AM -0400

> using signals and/or IPC only it seems a pity the same can't be done with
> threads just using system calls instead of having to rely on polling flags
> too.
 
Signals are not thread safe. Apples and oranges. And you'll be surprised to
learn that IPC works in exactly the same way: use an internal shared state
variable, and the same mutexes and condition variables to coordinate the
activity between the threads.
 
If you really wish to call a single function to notify a thread, and another
function to wait for a notification, there is no law that says you can't.
Your first function simply has to a lock the mutex, increment a counter
variable, signal a condition variable, and return (and unlock the mutex).
Your second function has to lock the mutex, check if the shared counter is
0, and if so wait for the condition variable and go back to the previous
step; and when the shared counter is not 0, reset it back to 0 and return
the number of times it's been signaled (also after unlocking the mutex).
 
Abra-cadabra! Presenting: a single function for notifying a thread, and a
single function to reliably wait for the notification, if it hasn't been
already, and if the thread's already been notified, it returns the number of
times it's been notified. Now, you can feel free to pretend that's how
threads get notified in your entire application.
"Öö Tiib" <ootiib@hot.ee>: Mar 15 05:44AM -0700

> using signals and/or IPC only it seems a pity the same can't be done with
> threads just using system calls instead of having to rely on polling flags
> too.
 
What you mean by IPC? It usually means things like message queues, sockets
and/or pipes. These work great with threads as well.
 
Basically it is possible that such (thread safe) message queues (pipe can
be viewed as one to one message queue and socket as two pipes in
opposite directions) to be the only way to transfer data between threads.
No data has to be shared otherwise. It simplifies lot of things and we can
use condition variable for building such thread safe message queues but
it is not working like message queue on its own (like your OP code seemed
to expect).
Paavo Helde <myfirstname@osa.pri.ee>: Mar 15 03:09PM +0200

>> helpers for making this data sharing fast and reliable.
 
> Fair enough, but given that you can reliably synchronise seperate processes
> using signals and/or IPC only
 
I'm not so familiar with signals, but isn't it so that in a
single-threaded app a typical (non-fatal) signal handler sets a *flag*
which is periodically *polled* by the main app?
 
Also, when starting up a new process, how do you know how long you have
to wait for it to set up the signal handlers, before you can send
signals to it? Seems a harder problem to me with processes than with
threads.
 
> it seems a pity the same can't be done with
> threads just using system calls instead of having to rely on polling flags
> too.
 
Wait+notify is usually not called polling; instead, it is a mechanism to
avoid polling. It's also important what it is not: it is not a mechanism
for encoding the program state, the program state is still best encoded
by data variables. So when one receives a notification one has to go and
study the program state to decide what to do next.
 
For example, you complained that std::condition_variable notifications
are not queued. Queuing a notification would not be so useful as there
may be several different notifications in general and one would not know
which notifications exactly are in the queue, not to speak about
spurious wake-ups which would look like ghost notifications.
 
Instead, in C++ you can easily build your own inter-thread queue,
holding custom notification aka event objects, potentially containing
tons of attached data. Such a queue can be built e.g. by using a
std::deque object, a mutex and a condition variable. The deque would
constitute the shared data state which I'm talking about all the time.
 
As usual, the C++ core language gives you the tools to build things, not
ready-made solutions. The notify mechanism is intentionally minimal
(notifications can be lost or appear from a thin air, no data attached
to the notifications, etc.) in order to not get in the way of
implementing solutions on top of it.
"Öö Tiib" <ootiib@hot.ee>: Mar 15 06:34AM -0700

On Friday, 15 March 2019 15:10:12 UTC+2, Paavo Helde wrote:
 
> I'm not so familiar with signals, but isn't it so that in a
> single-threaded app a typical (non-fatal) signal handler sets a *flag*
> which is periodically *polled* by the main app?
 
From https://en.wikipedia.org/wiki/Signal_(IPC)
"When a signal is sent, the operating system interrupts the target process'
normal flow of execution to deliver the signal. Execution can be
interrupted during any non-atomic instruction. If the process has previously
registered a signal handler, that routine is executed. Otherwise, the
default signal handler is executed."
Bonita Montero <Bonita.Montero@gmail.com>: Mar 15 02:35PM +0100

> using signals and/or IPC only it seems a pity the same can't be done with
> threads just using system calls instead of having to rely on polling flags
> too.
 
Thread-synchronization with condition-variables in the manner you've
been presented here is usually magnitudes more efficient than relying
only on kernel-facilities.
The downside of the usual condition-variables in this way is just
that there might be spurious or stolen wakeups; but this happens
not very often.
scott@slp53.sl.home (Scott Lurndal): Mar 15 01:36PM

>using signals and/or IPC only it seems a pity the same can't be done with
>threads just using system calls instead of having to rely on polling flags
>too.
 
Perhaps you should instead investigate using sem_post(2)/sem_wait(2)?
scott@slp53.sl.home (Scott Lurndal): Mar 15 02:32PM

> interrupted during any non-atomic instruction. If the process has previously
> registered a signal handler, that routine is executed. Otherwise, the
> default signal handler is executed."
 
And "deliver the signal" means run the registered (signal(2) or sigaction(2))
handler. Which often sets a flag that is polled by the app main loop.
johnbenny@nowhere.co.uk: Mar 15 04:17PM

On Fri, 15 Mar 2019 05:44:01 -0700 (PDT)
>> too.
 
>What you mean by IPC? It usually means things like message queues, sockets
>and/or pipes. These work great with threads as well.
 
They do, but using them means you get the extra complexity of their API
without the safety that seperate processes provide.
johnbenny@nowhere.co.uk: Mar 15 04:24PM

On Fri, 15 Mar 2019 07:09:03 -0400
>learn that IPC works in exactly the same way: use an internal shared state
>variable, and the same mutexes and condition variables to coordinate the
>activity between the threads.
 
How a subsystem works internally is irrelevant , its what the application
programmer has to do that matters.
 
>If you really wish to call a single function to notify a thread, and another
>function to wait for a notification, there is no law that says you can't.
 
Sure, but should I have to? If I write data to a pipe or a message queue or a
socket it doesn't vanish into a black hole if the receiver doesn't immediately
read from it. It stays there until a read occurs so avoiding data loss and race
conditions. I don't see why the thread notify can't be the same.
 
>already, and if the thread's already been notified, it returns the number of
>times it's been notified. Now, you can feel free to pretend that's how
>threads get notified in your entire application.
 
Meanwhile with socket & pipe based IPC I can just sit in a select(). No faffing
about with control variables and mutexes. When data arrives the function exits
whether that data was written before it was entered or after.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Mar 15 06:36PM

On Thu, 14 Mar 2019 12:45:51 +0000 (UTC)
> variable is subject to race conditions and so is calling sleep() unless you
> set it to sleep for 10 seconds or something to be absolutely sure the thread
> has reached wait()?

You have received a number of answers about how to correct your code
with a while loop and a flag. However, you might care to note that C++11
comes with a convenience overload for std::condition_variable::wait()
which takes a predicate and so avoids the need to code your own while
loop, namely:
 
void wait(std::unique_lock<std::mutex>& lock, Predicate pred);
 
This:
 
wait(lock, pred)
 
is equivalent to:
 
while (!pred()) {
wait(lock);
}
 
Condition variables are called "condition" variables for a reason,
which is that they require a predicate. Your code failed to provide one.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 14 11:37PM

>I don't know anything about BOOST. It appears that something called
>"initState" is key to what's going on here, but I don't find that in any
>other source code file, or any occurrence of "TESTControl" either.
 
"initState" is a parameter whose scope is just the above
constructor body.
 
Often, one cannot "just quickly" understand and modify a
C++ program without having properly learned C++.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 15 11:45AM

>>other source code file, or any occurrence of "TESTControl" either.
>"initState" is a parameter whose scope is just the above
>constructor body.
 
Of course, such an initialization in the body might give away
that the author has not received special C++ education because
otherwise he would have used a member initialization list!
Marcel Mueller <news.5.maazl@spamgourmet.org>: Mar 15 08:28AM +0100

Am 10.03.19 um 09:17 schrieb Jorgen Grahn:
>> I'm interested in is firstly: how did you learn to program a binary
>> tree in C++? Specifically, what implementation were you taught?
 
> I never did.
 
Same here. I took a short look at the concept and decided that overhead
of /binary/ trees is by far too high and probably never used them
anymore. This applies to all kinds ob binary trees like R-B trees or AVL.
 
I prefer B-Trees, or for certain applications maybe a Trie.
 
 
> In C++ I've never needed anything that the standard containers
> couldn't give me, e.g. the features of a search tree exposed by
> std::map, or the std::make_heap stuff if that counts.
 
From my point of view a B-Tree is missing in C++ (and many other
languages). I closed this gap at least in C++, Java and C# projects.
 
 
Marcel
Nikki Locke <nikki@trumphurst.com>: Mar 14 11:23PM

Available C++ Libraries FAQ
 
URL: http://www.trumphurst.com/cpplibs/
 
This is a searchable list of libraries and utilities (both free
and commercial) available to C++ programmers.
 
If you know of a library which is not in the list, why not fill
in the form at http://www.trumphurst.com/cpplibs/cppsub.php
 
Maintainer: Nikki Locke - if you wish to contact me, please use the form on the website.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: