im not experienced with multithreading programing (though i learned a
bit of it 20 years ago i decided it is not nice for me enough to do it)
i only tend to do things that seem reasonable to me and i have some doubts
hovever in my small view on things i may say that
I.
-asleep() function
(who puts cpu core on sleep given miliseconds (or microseconds)
(by put on sleep i also thing it just chnges the context of execution
to anuther thread for given time eventually) I FIND REASONABLE
(i see no problem with that)
II.
async call of function (it is a call to some function that spawns a
thread, so main thread continues but the second spawned on that function executes also until it find some of async end when its job is done
I ALSO FIND reasoneble (no problem with that)
III.
there is a third thing...i name it acquire ..it is some kind os assembly instruction or pair of assembly instustions with some guarantees
i mean acquire(x) should work if(x==0) x=TID (thread id or something
like that) so its like conditional move-a-a mov eax, tid; movz x, eax;
(where movz would mean here mov if x is 0 if not set a cpu flag)
and this should be proof of core crashes on this acces i mean only one
can acquire (im not sure if present cpu have it - that probably should
have - becouse it makes such operation very cheap then)
NOTE im meybe even less sura about this acquire becouse theoretically probably such acquireless (and maybe even mostly sleepless) programming
is possible but im not sure if it wouldnt be handy too
THOSE 3 "PRIMITIVES" imo are quite A SET to make multithreaded
programming "by hand".i also think it should be most lightweight,
i mean async call should be very light probbly (and probbaly it is its a metter of line of assembly or two i hope)...same with sleep (as in fact sleep and async call are close things
so i would hope that should be just maybe a set of few assebly opcodes
(if i not mislooked and something heavvier is needed)
conclusion is what i already said it seem that those 3 thing
(primitives) allows to do a lot of multithreading without bloated
libraries i hope
eventually correct me if im wrong
(also not to say they are best way of doing multithreading but if they
are lightweight it is at least minimally reasonable in some way it seems)
There are stackless coroutine libraries for C that work entirely from
the pre-processor, with similar limitations to the C++ coroutines (like
not being able to yield from normal functions called from the
coroutine).-a There are also stackful coroutine libraries, which are more flexible but have higher overhead.
C coroutine solutions require more manual coding than C++ for tracking
local variables that must be preserved between calls/yields, but on the other hand they don't require the dog's breakfast of boilerplate classes
and code that C++ coroutines need.
It is still an astoundingly ignorant claim.-a If you had said C had not changed much since 1999, it would be reasonable - though C23 has quite a number of new features.-a And even then it would only be in reference to
the C standards - the C ecosystem has changed enormously.
On Wed, 10 Jun 2026 13:53:59 +0200, fir wrote:
im not experienced with multithreading programing ...
It does tend to be error-prone.
ThatrCOs why it is best reserved for CPU-intensive tasks that can
benefit from running a bunch of cores at once.
For cases where the bottleneck is in the I/O or the network connection
(which is a lot of them), threading is typically unnecessary. Instead,
the popular approach nowadays is to use coroutines.
<https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Async_JS/Introducing>
<https://docs.python.org/3/library/asyncio.html>
On Thu, 11 Jun 2026 09:21:13 +0200, Bonita Montero wrote:
C hasn't been improved much since 1973. You still stick with the
same lowlevel view.
Actually, just as you can use threading APIs with C, you can use
stackful coroutine libraries as well.
Stackless ones are another matter.
Bonita Montero pisze:
Am 11.06.2026 um 09:52 schrieb David Brown:
There are no coroutines in the C standard.-a There are a wide variety
of coroutine implementations in C, with different mixtures of
features, limitations, efficiencies, portability and requirements.-a...
Real coroutines aren't possible with C since with native coroutines you
need functions that can be suspended and resumed.
c lasks some low lewel core management imo -it is more visible in
multicore times..but even in old times there was something like
interrupts - who allowed theoretically but probably also practically
freeze a branch and resume it - so somemechanics of multthreading
was even on 1core machines - i remember it was in 8-bit c64 really
C hasn't been improved much since 1973.
What an astoundingly ignorant claim.
Compared to C++ that's true.
On 6/10/2026 9:40 PM, Lawrence DrCOOliveiro wrote:--- Synchronet 3.22a-Linux NewsLink 1.2
For cases where the bottleneck is in the I/O or the network
connection (which is a lot of them), threading is typically
unnecessary. Instead, the popular approach nowadays is to use
coroutines.
Not sure why you say that.
It does tend to be error-prone.
ThatrCOs why it is best reserved for CPU-intensive tasks that can
benefit from running a bunch of cores at once.
Coroutines are the most elegant way to handle finite state machines.
They need explicit language support and can't be handled exclsuively
with libraries.
Real coroutines aren't possible with C since with native coroutines
you need functions that can be suspended and resumed.
Coroutines have nothing to do with multithreaded programming, but
they can be used to have sth. more lightweight than threading.
... per fibers on threads is a, well, kind of a different story.
On Thu, 11 Jun 2026 16:01:47 -0700, Chris M. Thomasson wrote:
... per fibers on threads is a, well, kind of a different story.
Are these rCLfibrerCY things just some kind of runtime abstraction built
on top of OS threads?
On Thu, 11 Jun 2026 14:18:09 -0700, Chris M. Thomasson wrote:
On 6/10/2026 9:40 PM, Lawrence DrCOOliveiro wrote:
For cases where the bottleneck is in the I/O or the network
connection (which is a lot of them), threading is typically
unnecessary. Instead, the popular approach nowadays is to use
coroutines.
Not sure why you say that.
It does tend to be error-prone.
ThatrCOs why it is best reserved for CPU-intensive tasks that can
benefit from running a bunch of cores at once.
C coroutine solutions require more manual coding than C++ for tracking[...]
local variables that must be preserved between calls/yields, but on the other hand they don't require the dog's breakfast of boilerplate classes
and code that C++ coroutines need.
On Thu, 11 Jun 2026 10:28:55 +0200, Bonita Montero wrote:
Real coroutines aren't possible with C since with native coroutines
you need functions that can be suspended and resumed.
Just think of them as non-preemptive threads.
I donrCOt know whatrCOs rCLheavyweightrCY about threading, beyond the stack allocations. ...
Am 12.06.2026 um 03:32 schrieb Lawrence DrCOOliveiro:
I donrCOt know whatrCOs rCLheavyweightrCY about threading, beyond the stack >> allocations. ...
Yes, the allocation of the stack is very expensive. And the
context-switch between threads is a magnitudes more expensive
than switching between two coroutine conexts.
The fibers float along the threads... ;^)
Am 12.06.2026 um 03:32 schrieb Lawrence DrCOOliveiro:
I donrCOt know whatrCOs rCLheavyweightrCY about threading, beyond the stack >> allocations. ...
Yes, the allocation of the stack is very expensive. And the
context-switch between threads is a magnitudes more expensive than
switching between two coroutine conexts.
On 6/11/2026 6:33 PM, Lawrence DrCOOliveiro wrote: > > Are these
rCLfibrerCY things just some kind of runtime abstraction > built on top
of OS threads? Basically. You need to make your own scheduler for the
fiber on the threads.
FWIW, check this shit out. Coroutines can be emulated even in BASIC.
This is a recursive stack here. Its all manual... :^)
[code omitted]
On Fri, 12 Jun 2026 06:16:42 +0200, Bonita Montero wrote:
Yes, the allocation of the stack is very expensive. And the
context-switch between threads is a magnitudes more expensive than
switching between two coroutine conexts.
Why should that be? What extra overhead is there in context-switching
between preemptive threads, versus non-preemptive ones?
Am 13.06.2026 um 01:52 schrieb Lawrence DrCOOliveiro:
On Fri, 12 Jun 2026 06:16:42 +0200, Bonita Montero wrote:
Yes, the allocation of the stack is very expensive. And the
context-switch between threads is a magnitudes more expensive than
switching between two coroutine conexts.
Why should that be? What extra overhead is there in context-switching
between preemptive threads, versus non-preemptive ones?
Because with threading the context-switch happens inside the kernel.
On Thu, 11 Jun 2026 21:11:13 -0700, Chris M. Thomasson wrote:
FWIW, check this shit out. Coroutines can be emulated even in BASIC.
This is a recursive stack here. Its all manual... :^)
[code omitted]
I see a lot of rCLGOSUB 8000rCY within the subroutine starting at line
8000, so thatrCOs a lot of recursion, not coroutines. Plus yourCOve got
the explicit RS array stack for assembling the components of the
curve. Normally you would either have either recursion or an explicit
stack, since each one subsumes the functions of the other, so there shouldnrCOt be a need for both.
In other words, I think yourCOve got the worst of both worlds? Recursion
that isnrCOt enough to solve the problem purely recursively, plus an
explicit stack that isnrCOt enough to keep track of the entire stack
state?
Its a recursive koch fractal using AppleSoft basic.
Am 13.06.2026 um 01:52 schrieb Lawrence DrCOOliveiro:
On Fri, 12 Jun 2026 06:16:42 +0200, Bonita Montero wrote:
Yes, the allocation of the stack is very expensive. And the
context-switch between threads is a magnitudes more expensive than
switching between two coroutine conexts.
Why should that be? What extra overhead is there in
context-switching between preemptive threads, versus non-preemptive
ones?
Because with threading the context-switch happens inside the kernel.
On Sat, 13 Jun 2026 05:05:23 +0200, Bonita Montero wrote:
Am 13.06.2026 um 01:52 schrieb Lawrence DrCOOliveiro:
On Fri, 12 Jun 2026 06:16:42 +0200, Bonita Montero wrote:
Yes, the allocation of the stack is very expensive. And the
context-switch between threads is a magnitudes more expensive than
switching between two coroutine conexts.
Why should that be? What extra overhead is there in
context-switching between preemptive threads, versus non-preemptive
ones?
Because with threading the context-switch happens inside the kernel.
Microsoft Windows problems again?
On Sat, 13 Jun 2026 13:46:55 -0700, Chris M. Thomasson wrote:
Its a recursive koch fractal using AppleSoft basic.
Yes, that was pretty clear. As was the fact that you were able to get
it working, not *because of* your choice of BASIC to write it in, but
*in spite of* that.
On 6/11/2026 5:12 PM, Lawrence DrCOOliveiro wrote:
On Thu, 11 Jun 2026 14:18:09 -0700, Chris M. Thomasson wrote:
On 6/10/2026 9:40 PM, Lawrence DrCOOliveiro wrote:
For cases where the bottleneck is in the I/O or the network
connection (which is a lot of them), threading is typically
unnecessary. Instead, the popular approach nowadays is to use
coroutines.
Not sure why you say that.
It does tend to be error-prone.
Well, shit happens. :^)
ThatrCOs why it is best reserved for CPU-intensive tasks that can
benefit from running a bunch of cores at once.
On 6/13/2026 5:32 PM, Lawrence DrCOOliveiro wrote:
On Sat, 13 Jun 2026 13:46:55 -0700, Chris M. Thomasson wrote:
Its a recursive koch fractal using AppleSoft basic.
Yes, that was pretty clear. As was the fact that you were able to
get it working, not *because of* your choice of BASIC to write it
in, but *in spite of* that.
It has current stack space.
So, with a little work it should be workable for continuations.
Microsoft Windows problems? What do you mean? preemptive threads say
POSIX threads are going to have the same issues. Right?
On Tue, 16 Jun 2026 12:22:24 -0700, Chris M. Thomasson wrote:
Microsoft Windows problems? What do you mean? preemptive threads say
POSIX threads are going to have the same issues. Right?
Well, when talking to a Windows programmer, and they say something you
know doesnrCOt sound right, it seems reasonable to conclude that it
comes from their Windows-specific experience.
On 6/16/2026 8:09 PM, Lawrence DrCOOliveiro wrote:
On Tue, 16 Jun 2026 12:22:24 -0700, Chris M. Thomasson wrote:
Microsoft Windows problems? What do you mean? preemptive threads say
POSIX threads are going to have the same issues. Right?
Well, when talking to a Windows programmer, and they say something you
know doesnrCOt sound right, it seems reasonable to conclude that it
comes from their Windows-specific experience.
POSIX threads are preemptive and subject to the same scheduling
concerns... Right?
On 6/16/2026 8:09 PM, Lawrence DrCOOliveiro wrote:
On Tue, 16 Jun 2026 12:22:24 -0700, Chris M. Thomasson wrote:
Microsoft Windows problems? What do you mean? preemptive threads
say POSIX threads are going to have the same issues. Right?
Well, when talking to a Windows programmer, and they say something
you know doesnrCOt sound right, it seems reasonable to conclude that
it comes from their Windows-specific experience.
POSIX threads are preemptive and subject to the same scheduling
concerns... Right?
On Wed, 17 Jun 2026 20:29:23 -0700, Chris M. Thomasson wrote:
On 6/16/2026 8:09 PM, Lawrence DrCOOliveiro wrote:They are lighter-weight than processes. But then, processes on *nix
On Tue, 16 Jun 2026 12:22:24 -0700, Chris M. Thomasson wrote:POSIX threads are preemptive and subject to the same scheduling
Microsoft Windows problems? What do you mean? preemptive threadsWell, when talking to a Windows programmer, and they say something
say POSIX threads are going to have the same issues. Right?
you know doesnrCOt sound right, it seems reasonable to conclude that
it comes from their Windows-specific experience.
concerns... Right?
systems are cheaper to create on *nix systems than on Dave-Cutler-type systems, we know that already.
IrCOm talking about preemption semantics, which are the same on POSIX
and Windows.
They are lighter-weight than processes. But then, processes on *nix
systems are cheaper to create on *nix systems than on Dave-Cutler-type systems, we know that already.
Am 18.06.2026 um 06:11 schrieb Lawrence DrCOOliveiro:
They are lighter-weight than processes. But then, processes on *nix
systems are cheaper to create on *nix systems than on Dave-Cutler-type
systems, we know that already.
Yes, they are, but if performance is your concern better use thread pools.
On Tue, 16 Jun 2026 12:23:32 -0700, Chris M. Thomasson wrote:
On 6/13/2026 5:32 PM, Lawrence DrCOOliveiro wrote:
On Sat, 13 Jun 2026 13:46:55 -0700, Chris M. Thomasson wrote:
Its a recursive koch fractal using AppleSoft basic.
Yes, that was pretty clear. As was the fact that you were able to
get it working, not *because of* your choice of BASIC to write it
in, but *in spite of* that.
It has current stack space.
But being BASIC, it only has fixed-length arrays to use as the stack, doesnrCOt it?
So, with a little work it should be workable for continuations.
I added continuations to my toy PostScript-revival language. I soon discovered that having a dedicated stack area was a bad idea. So what
happens is call frames are allocated on the heap, and chained together
in various ways: for transferring control for a return, exit, yield or
stop. An instance of the Continuation class keeps a copy of the
CallFrame object that was current when it was created, and simply
makes that current again when it is invoked.
On 6/16/2026 8:07 PM, Lawrence DrCOOliveiro wrote:
On Tue, 16 Jun 2026 12:23:32 -0700, Chris M. Thomasson wrote:
On 6/13/2026 5:32 PM, Lawrence DrCOOliveiro wrote:
On Sat, 13 Jun 2026 13:46:55 -0700, Chris M. Thomasson wrote:
Its a recursive koch fractal using AppleSoft basic.
Yes, that was pretty clear. As was the fact that you were able to
get it working, not *because of* your choice of BASIC to write it
in, but *in spite of* that.
It has current stack space.
But being BASIC, it only has fixed-length arrays to use as the stack,
doesnrCOt it?
Well yeah. So you create a buffer.
So, with a little work it should be workable for continuations.
I added continuations to my toy PostScript-revival language. I soon
discovered that having a dedicated stack area was a bad idea. So what
happens is call frames are allocated on the heap, and chained together
in various ways: for transferring control for a return, exit, yield or
stop. An instance of the Continuation class keeps a copy of the
CallFrame object that was current when it was created, and simply
makes that current again when it is invoked.
Am 18.06.2026 um 06:11 schrieb Lawrence DrCOOliveiro:
They are lighter-weight than processes. But then, processes on *nix
systems are cheaper to create on *nix systems than on
Dave-Cutler-type systems, we know that already.
Yes, they are, but if performance is your concern better use thread
pools.
On Thu, 18 Jun 2026 18:23:28 +0200, Bonita Montero wrote:
Am 18.06.2026 um 06:11 schrieb Lawrence DrCOOliveiro:
They are lighter-weight than processes. But then, processes on *nix
systems are cheaper to create on *nix systems than on
Dave-Cutler-type systems, we know that already.
Yes, they are, but if performance is your concern better use thread
pools.
All that does is save the initial creation overhead, not the
(supposed) context-switching overhead. Which is what you were
complaining about, wasnrCOt it?
Not exactly sure what you mean here. Windows and POSIX have basically
the same overhead with preemptive threads. ...
This measures the overhead of a preempted context switch:
[code omitted]
On Sat, 20 Jun 2026 11:47:44 +0200, Bonita Montero wrote:
This measures the overhead of a preempted context switch:
[code omitted]
ldo@theon:c++_try> g++ --std=c++26 context_switch_overhead.cpp
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccGEPNJM.o: in function `std::__atomic_ref<main::id_tsc, false, false>::load(std::memory_order) const':
context_switch_overhead.cpp:(.text+0x547): undefined reference to `__atomic_load_16'
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccGEPNJM.o: in function `std::__atomic_ref<main::id_tsc, false, false>::compare_exchange_strong(main::id_tsc&, main::id_tsc, std::memory_order, std::memory_order) const':
context_switch_overhead.cpp:(.text+0x671): undefined reference to `__atomic_compare_exchange_16'
collect2: error: ld returned 1 exit status
Got more errors when I didnrCOt specify a newer C++ --std option, but
donrCOt know how to get rid of these ...
to `__atomic_load_16'On Sat, 20 Jun 2026 11:47:44 +0200, Bonita Montero wrote:
This measures the overhead of a preempted context switch:
[code omitted]
ldo@theon:c++_try> g++ --std=c++26 context_switch_overhead.cpp
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccGEPNJM.o: in function `std::__atomic_ref<main::id_tsc, false, false>::load(std::memory_order) const':
context_switch_overhead.cpp:(.text+0x547): undefined reference
to `__atomic_compare_exchange_16'/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccGEPNJM.o: in function `std::__atomic_ref<main::id_tsc, false, false>::compare_exchange_strong(main::id_tsc&, main::id_tsc, std::memory_order, std::memory_order) const':
context_switch_overhead.cpp:(.text+0x671): undefined reference
-latomiccollect2: error: ld returned 1 exit status
Got more errors when I didnrCOt specify a newer C++ --std option, but
donrCOt know how to get rid of these ...
Got it!
ldo@theon:c++_try> g++ --std=c++23 context_switch_overhead.cpp
ldo@theon:c++_try> ./a.out-latomic
17858.5
ldo@theon:c++_try> g++ --std=c++26 context_switch_overhead.cpp
ldo@theon:c++_try> ./a.outI've improved the code. Now it measures the time for a preempted context
18899.2
So what do the numbers mean?
I've improved the code. Now it measures the time for a preempted
context switch in microseconds:
And this code measures the time for a voluntary context switch
(yield) in microseconds:
On Sat, 20 Jun 2026 22:41:39 -0000 (UTC), I wrote:
On Sat, 20 Jun 2026 11:47:44 +0200, Bonita Montero wrote:
This measures the overhead of a preempted context switch:
[code omitted]
ldo@theon:c++_try> g++ --std=c++26 context_switch_overhead.cpp
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccGEPNJM.o: in function `std::__atomic_ref<main::id_tsc, false, false>::load(std::memory_order) const':
context_switch_overhead.cpp:(.text+0x547): undefined reference to `__atomic_load_16'
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccGEPNJM.o: in function `std::__atomic_ref<main::id_tsc, false, false>::compare_exchange_strong(main::id_tsc&, main::id_tsc, std::memory_order, std::memory_order) const':
context_switch_overhead.cpp:(.text+0x671): undefined reference to `__atomic_compare_exchange_16'
collect2: error: ld returned 1 exit status
Got more errors when I didnrCOt specify a newer C++ --std option, but
donrCOt know how to get rid of these ...
Got it!
ldo@theon:c++_try> g++ --std=c++23 context_switch_overhead.cpp -latomic
ldo@theon:c++_try> ./a.out
17858.5
ldo@theon:c++_try> g++ --std=c++26 context_switch_overhead.cpp -latomic
ldo@theon:c++_try> ./a.out
18899.2
So what do the numbers mean?
When you are compiling without optimisation enabled?-a Probably nothing, unless the time taken is only due to code in libraries that you did not compile.
Am 12.06.2026 um 06:19 schrieb Chris M. Thomasson:
The fibers float along the threads... ;^)
If you have as many fibres as you otherwise would have coroutines
and the number is lage you waste a lot of memory.
The only difference is that with fibers you can switch the context
from any function.
On Thu, 18 Jun 2026 00:18:18 -0700, Chris M. Thomasson wrote:
IrCOm talking about preemption semantics, which are the same on POSIX
and Windows.
But for some reason the previous poster thinks that doing thread
preemption in the kernel is somehow more resource-heavy than doing the
exact same thing in userspace.
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 70 |
| Nodes: | 6 (0 / 6) |
| Uptime: | 37:38:06 |
| Calls: | 948 |
| Calls today: | 2 |
| Files: | 1,325 |
| Messages: | 280,462 |