Thread overview
June 14

Over time it has increasingly become clear that stackless coroutines have won over stackfull coroutines (fibers), due to a number of reasons.

This proposal does not introduce a new type of coroutine, but provides a migration path for existing fiber users to be able to replace their eventloop implementation to using a more powerful functionality (such as IOCP which is considered the gold standard for its problem domain and is getting to be available everywhere in some form) without breaking their entire codebase.

Critically fibers must migrate between threads, the implementation isn't the problem, the problem is the language does not guarantee that this can occur safely, this was understood 12 years ago.
Unfortunately it is not possible for the compiler to understand where yields take place like with stackless coroutines, so we have to apply a very broad transitive guarantee that the unsafe things do not happen at this level.

Everything unsafe takes place with anything thread local. Thread local storage is the biggie, but also locks may not appreciate being unlocked in another thread and to make matters worse they are quite often (if not usually) reentrant upon the same thread.

The proposal for in the language is one new attribute @notl to disable thread local access, it is transitive.

The proposal for in core.attributes is two new attributes @notlwhitelist and @notlblacklist. These will only ever be recognized on the type, not on a variable.
I am not sold on the names, feel free to suggest others!

The reason why they only work on the type is to prevent working around this limitation for a type that genuinely isn't safe to do so.

The reason we need the white list is to make TaskLocal from vibe.d work, and the blacklist is to prevent __gshared or shared which are not safe (like a mutex) from working here either.

I understand that people may be nervous at the prospect, that the intention here is to break all current fiber users code, but that isn't the case.
This is for migration purposes only, on the Fiber type an overload would be added that accepts the function with @notl on it. If it is supplied a flag is set that allows moving between threads that can be checked.

Do you need to be concerned about this? Unless you're working with eventloops and wanting to both be safe and to migrate away from a polling solution (which is limited in the number of handles each thread can take) probably not. But having (a) solution would be valuable to those that need it.

Walter asked me to do an ideas thread on this so here it is.

Destroy!

June 14

On Friday, 14 June 2024 at 17:30:27 UTC, Richard (Rikki) Andrew Cattermole wrote:

>

Destroy!

Instead of introducing 3 new attributes I think its a lot better to make TLS @system instead.

TLS should be used sparingly anyway, so making its usage more difficult is a lot cheaper than extra attributes than make everything else harder.

June 15
On 15/06/2024 8:50 AM, Sebastiaan Koppe wrote:
> On Friday, 14 June 2024 at 17:30:27 UTC, Richard (Rikki) Andrew Cattermole wrote:
>>
>> Destroy!
> 
> Instead of introducing 3 new attributes I think its a lot better to make TLS @system instead.
> 
> TLS should be used sparingly anyway, so making its usage more difficult is a lot cheaper than extra attributes than make everything else harder.

That doesn't help ``TaskLocal`` which is a fiber-local wrapper in vibe.d, it should be stored in TLS.

You end up needing a whitelist solution.
June 15
On Saturday, 15 June 2024 at 08:43:12 UTC, Richard (Rikki) Andrew Cattermole wrote:
> On 15/06/2024 8:50 AM, Sebastiaan Koppe wrote:
>> On Friday, 14 June 2024 at 17:30:27 UTC, Richard (Rikki) Andrew Cattermole wrote:
>>>
>>> Destroy!
>> 
>> Instead of introducing 3 new attributes I think its a lot better to make TLS @system instead.
>> 
>> TLS should be used sparingly anyway, so making its usage more difficult is a lot cheaper than extra attributes than make everything else harder.
>
> That doesn't help ``TaskLocal`` which is a fiber-local wrapper in vibe.d, it should be stored in TLS.
>
> You end up needing a whitelist solution.

In your opening post you say fibers lost, which I agree with, but then proceed to propose 3 new attributes for a fiber library feature which is  essentially mimicking globals. Why would we want to make it easier to do the wrong thing?

Any use of global, thread or task local variable should raise eyebrows. Typically they are needed only in core libraries or runtimes.
June 16
On 16/06/2024 1:07 AM, Sebastiaan Koppe wrote:
> In your opening post you say fibers lost, which I agree with, but then proceed to propose 3 new attributes for a fiber library feature which is  essentially mimicking globals. Why would we want to make it easier to do the wrong thing?

1. Migration to better event loops without forcing everyone to rewrite the world and in turn lowering the cost of adoption.
2. It'll map into stackless, we'll need a solution there to prevent escaping for things like locks between states. So it isn't a waste of effort.

June 17
On Saturday, 15 June 2024 at 13:12:12 UTC, Richard (Rikki) Andrew Cattermole wrote:
> On 16/06/2024 1:07 AM, Sebastiaan Koppe wrote:
>> In your opening post you say fibers lost, which I agree with, but then proceed to propose 3 new attributes for a fiber library feature which is  essentially mimicking globals. Why would we want to make it easier to do the wrong thing?
>
> 1. Migration to better event loops without forcing everyone to rewrite the world and in turn lowering the cost of adoption.

I'll like to see those event loops before proposing to change the language.

Also, I am skeptical of not having to rewrite things. As much as I want to avoid it, I just don't see it happening.

> 2. It'll map into stackless, we'll need a solution there to prevent escaping for things like locks between states. So it isn't a waste of effort.

Holding synchronous locks across suspension points isn't recommended. You'll want to avoid it by switching to async locks or use lock-free algorithms.
June 18
On 18/06/2024 4:19 AM, Sebastiaan Koppe wrote:
> On Saturday, 15 June 2024 at 13:12:12 UTC, Richard (Rikki) Andrew Cattermole wrote:
>> On 16/06/2024 1:07 AM, Sebastiaan Koppe wrote:
>>> In your opening post you say fibers lost, which I agree with, but then proceed to propose 3 new attributes for a fiber library feature which is  essentially mimicking globals. Why would we want to make it easier to do the wrong thing?
>>
>> 1. Migration to better event loops without forcing everyone to rewrite the world and in turn lowering the cost of adoption.
> 
> I'll like to see those event loops before proposing to change the language.
> 
> Also, I am skeptical of not having to rewrite things. As much as I want to avoid it, I just don't see it happening.

Have you looked at vibe.d eventcore implementation?

Its not IOCP. It is polling everywhere.

Either it gets adapted to IOCP or its stuck with polling and bad performance.

Might as well kick start the eventloop rewrite before we get stackless coroutines.

But that means fibers need to be made "safe" to move between threads.

>> 2. It'll map into stackless, we'll need a solution there to prevent escaping for things like locks between states. So it isn't a waste of effort.
> 
> Holding synchronous locks across suspension points isn't recommended. You'll want to avoid it by switching to async locks or use lock-free algorithms.

Yes, the language shouldn't be allowing that.

It could never be right. It needs more information on library types to prevent it.
June 19
On Monday, 17 June 2024 at 16:37:54 UTC, Richard (Rikki) Andrew Cattermole wrote:
>
> On 18/06/2024 4:19 AM, Sebastiaan Koppe wrote:
>> On Saturday, 15 June 2024 at 13:12:12 UTC, Richard (Rikki) Andrew Cattermole wrote:
> Have you looked at vibe.d eventcore implementation?
>
> Its not IOCP. It is polling everywhere.
>
> Either it gets adapted to IOCP or its stuck with polling and bad performance.

My biggest gripe with it is that its not enabling structured concurrency.

> Might as well kick start the eventloop rewrite before we get stackless coroutines.
>
> But that means fibers need to be made "safe" to move between threads.

I don't think the problem is with fibers per se. They can move between threads just fine, and TLS variables continue to function as designed, that is, they point to the thread local data of the thread the fiber happens to be executing on.

Rather, I believe the problem is with assumptions code makes when (mis)using TLS data. To that end, can you give me an example of code ran on fibers that needs to be made "safe"?

Also, could it be you are trying to do too many things at once? Salvaging eventcore, doing an eventloop, fibers _and_ stackless coroutines? I see no reason why any of them need to be as coupled as suggested.
June 20
On 20/06/2024 7:11 AM, Sebastiaan Koppe wrote:
>     Might as well kick start the eventloop rewrite before we get
>     stackless coroutines.
> 
>     But that means fibers need to be made "safe" to move between threads.
> 
> I don't think the problem is with fibers per se. They can move between threads just fine, and TLS variables continue to function as designed, that is, they point to the thread local data of the thread the fiber happens to be executing on.

With a fiber you have the unknown yield locations so the compiler cannot make guarantees regarding safety. But yes I noted that there is nothing stopping them from a technical perspective in my opening post.

> Rather, I believe the problem is with assumptions code makes when (mis)using TLS data. To that end, can you give me an example of code ran on fibers that needs to be made "safe"?

Yes its the assumption that is the problem, and those assumptions are very easy to make even for experienced developers (i.e. calling into a library that wasn't designed to be used from a stack(less) coroutine that can move between threads.

> Also, could it be you are trying to do too many things at once? Salvaging eventcore, doing an eventloop, fibers /and/ stackless coroutines? I see no reason why any of them need to be as coupled as suggested.

I'm not sure what you mean by coupling here.

There is no point in improving vibe.d's eventloop support if nothing can take advantage of it.

I remember vibe.d was designed 12 years ago with the knowledge that fibers couldn't move between threads safely. This was a design constraint and this proposal alleviates it.

As for doing too much, I'm not comfortable with writing the DIP at the present point in time for stack less coroutines. The slicing and dicing of it and what it would take in compiler has unknown restrictions. Now if Walter were to tell me that it's too important to care about the complexity of implementation and I can do whatever and we'll figure it out eventually that would be a good thing to know.