The standard approach on Windows (and no reason also for linux, FreeBSD) is to have per-process thread pools. E.g. each process in a .net app has a default thread pool. Windows also has an async IO api that requires a thread pool of threads to handle the IO (handled in the Win32 API, so built into the core OS).
A single thread can then wait for events that would require some processing (IO or timers being the most common) and then it passes that unit of work to the thread pool to be processed. Windows even takes pains to ensure that the last thread to process a unit of work, might then also be used to process the next item in the queue of work to eliminate costly context switching, and invalidation of data/instruction cache.
Thread pools allow the best use of threading by:
- limiting the number of threads a process creates/maintains. The thread pool itself can grow or shrink as demand changes.
- limiting the number of threads that are in a runnable state by queueing work to the pool. The pool itself will be sized according to number of CPU cores, e.g. 2 * CPU cores.
The main idea behind tread pools is that any thread that's not doing useful work is a waste of OS resources, so they make sure that they are either always fed with work, or get destroyed when idle for too long. From an overall machine efficiency perspective this makes total sense.
Having hundred or even thousands of threads created and idle is massively wasteful and bad design, the OS should not be burdened with such housekeeping.
Note that Apple's GCD also works on the same principle, as does libev/libuv.
Also choosing a base platform agnostic framework like SDL which has a lot of the OS interactions (keyboard & mouse) already abstracted away for you gets you pretty far on the cross-platform road.
>Apple’s garbage cables which fray and break after a few months of careful usage
We must be using them very differently then.
I still have charger cables for my original iPod (2007) which I use regularly that are not broken or frayed.
Also from older phones - which is one of the reasons I was happy that they stopped shipping all the chargers and headphones as I still already had them from previous purchases.
Cableitis is unfortunately a wasteful by-product of our current electronics culture.
As the proud owner of 3 plants in various stages of maturity I can say it's fun and rewarding (and fairly easy), but I'm under no illusions that I'll get edible fruit from them anytime. But they make a nice indoor plant.
Another way to germinate the seed is to store it in a plastic container (or zip bag) with a little bit of water, and leave it in a warm dark cupboard for a few weeks until the roots and stalk start to appear.
What might be nice instead is of Ukraine can buy a few French Exocet missiles and attack the Russian fleet in the Black sea. That might hit them where it hurts.
As I understand it, they have been attacking Russian ships. I guess there is some speculation that Russians have been using civilian shipping as cover, resulting in two non-Russian ships being damaged by fire meant for warships.
From what I can remember, UTF-8 consumes more CPU as it's more complex to process, has space savings for mostly ascii & European codepages, but can significantly bloat storage sizes for character sets that consistently require 3 or 4 bytes per character.
A single thread can then wait for events that would require some processing (IO or timers being the most common) and then it passes that unit of work to the thread pool to be processed. Windows even takes pains to ensure that the last thread to process a unit of work, might then also be used to process the next item in the queue of work to eliminate costly context switching, and invalidation of data/instruction cache.
Thread pools allow the best use of threading by: - limiting the number of threads a process creates/maintains. The thread pool itself can grow or shrink as demand changes. - limiting the number of threads that are in a runnable state by queueing work to the pool. The pool itself will be sized according to number of CPU cores, e.g. 2 * CPU cores.
The main idea behind tread pools is that any thread that's not doing useful work is a waste of OS resources, so they make sure that they are either always fed with work, or get destroyed when idle for too long. From an overall machine efficiency perspective this makes total sense.
Having hundred or even thousands of threads created and idle is massively wasteful and bad design, the OS should not be burdened with such housekeeping.
Note that Apple's GCD also works on the same principle, as does libev/libuv.