What happens to the fibers which ran on a thread when the thread exits?


What happens to the fibers which ran on a thread when the thread exits? Are all the fibers destroyed?

No, only the currently-executing fiber is destroyed. Fibers running on other threads and fibers which are not running on any thread at all are not affected.

Fibers do not have thread affinity (when not running), and they do not remember what threads they have been run on. Indeed, one of the features of fibers is that you can switch away from a fiber on one thread, then switch to that same fiber on another thread, and that fiber will resume execution on the new thread. Fibers are the social butterflies of scheduling: They will hang out on any thread that invites them to run. Once one thread deschedules a fiber, the fiber loses any affinity for the thread and is perfectly happy to hang out on any other thread. Or on the original thread, if the original thread comes crawling back begging for another chance.

You can run a fiber on any thread you want, provided you don't run it on two threads at once. (Well, and of course, you have to have prepared the thread for fiber execution by calling ConvertThreadToFiber.)

Next time, some additional musing about fibers.

Comments (15)
  1. Ken says:

    Do fibers play nicely with CoInitialize then…?  

  2. Anon says:

    Only if windows supported cloning a Fiber – we would have full blown continuations then. Well, maybe in a future versions of windows.

  3. David Walker says:

    When a fiber is not running, what information does it have?  I thought a fiber was a unit of execution (or so MSDN says), not a bunch of associated storage.

  4. Aaron says:

    @Ken

    I am not an expert on Win32 fibers, but I would say that the rules for CoInitialize are likely fiber-agnostic.  That is to say, the normal rules for threading apply (to threads).  

    Since fibers are just kernel objects and do not have physical counterparts inside the CPU, what matters is the thread that runs CoInitializeEx, and what it passes for a concurrency model.  Fibers are unrelated, except in so much that they may happen to execute on different threads at different times, so you should code your application and pick your concurrency model with that in mind.

  5. A. Skrobov says:

    Anon: you can clone a fiber on your own; pFiber is exactly the pointer to the fiber data. I’ve tried, and it works just fine.

    David: a fiber has a stack, a copy of all CPU registers, and a SEH chain. That’s about all.

    [And then it will stop working once the internal format of fibers changes. Like it has once already. -Raymond]
  6. A. Skrobov says:

    Aaron: fibers are no kernel objects.

    They live entirely in user-land.

    That’s their most apparent benefit: switching between contexts of execution without the transition to kernel-mode and back.

  7. Crescens2k says:

    David:

    If you look at it that way, when it isn’t running a thread is just a bunch of associated storage too.

    It may be inaccurate but fibers should just be seen as manually scheduled threads.

    Logically the fiber itself needs to keep its full state. If it didn’t then it would cause major problems. For example, without it’s own stack then it would require thread affinity, and the hosting thread couldn’t run itself while the fiber is running. It would need to keep the register state otherwise it would lose everything that it has been working on.

    An analogy I just thought of is think about your internet access. You are checking your email at home, notice the time and realise you are late for work. So you shut everything down, and then go to work. Once you get there you continue checking your emails (since they are available on the internet too).

    It doesn’t matter that you were doing it through your own computer or your work computer. You were still able to check your email.

    Ken:

    It is questionable whether using COM in a fiber is a good idea, especially if you initialise it and create it as a apartment threaded object.

    Whats more, if a fiber is scheduled how do you know if the thread it is running on has actually had CoInitialize called on it.

    The only way that threads could ever play nice is if you initialise every thread in your application with CoInitializeEx and set all of them to multi threaded.

  8. Aaron says:

    A. Skrobov: Yes, sorry, that was a dumb mistake on my part.  For some reason I was thinking that fibers were represented by HANDLEs like threads.  

  9. It would be nice, if there will be some kind of debugger support for fibers….

    This is currently a very bad situation… there is no list of fibers nor other fiber-support like Callstacks in minidumps…

    Is there hope, that this will be added to the next OS

  10. Dan says:

    Fibers? What?  The only thing I know about fiber is my breakfast is high in it.  And it is good for digestion.

    I clearly missed this when I was learning Windows threading…

  11. David Walker says:

    That all makes sense, thanks.

  12. Leif Strand says:

    "you can switch away from a fiber on one thread, then switch to that same fiber on another thread"

    Cool!  I did not know this.  I suppose one could use this feature to implement a thread pool?  I.e., have a bunch of fibers that are brought to life by some smaller number of threads?  Hmmm…

  13. W says:

    Since my original post seems to have been lost:

    Anon:

    While writing cloneable fibers should

    be doable, I don’t think it would work well.

    You would have to clone all the data on the stack. And since you don’t know which programming language the functions higher in the call stacks are written in you’d memcopy their local variables. Once the control passes up to them again all hell breaks lose.

    For example they might call the destructors their local variables. Now image these being handles, or auto/smart-pointers and you get stuff freed twice.

    Your thread and process will crash and burn oh so beautifully.

    So you need a more tightly controlled environment than Win32. It might be possible to tac it on to .net, since all managed value-types are memcopyable there. But probably you’ll still end up disposing stuff twice.

    So I guess continuation support on code which has sideeffects/is not purely functional is not possible.

    [You also have problems with pointers to the stack (which now point to somebody else’s stack after you memcpy it), and the fact that multiple invocations of a continuation do not share variables. I thought it was interesting that, instead of breaking down a problem into the easy part and the impossible part, Anon broke it down into three impossible parts (presumably all to be accomplished before breakfast.) -Raymond]

    David Walker:

    Obviously it has a stack, and the state of the CPU stored somewhere. Potentially it has a TLS too, but I’m too lazy to check if the TLS is per thread or per fiber.

  14. Crescens2k says:

    W:

    TLS is done using the identity of the thread. So what the fiber sees is what the data the thread that it is running on sees. (I thought the name "Thread Local Storage" was obvious enough for people to not to get confused).

    There is something called Fiber Local Storage. It works like TLS but it is for fibers. So if you wanted an application which uses fibers to have a per fiber set of data, then you would use FLS.

  15. Jilted says:

    "Or on the original thread, if the original thread comes crawling back begging for another chance."

    Please, please let me host your execution!  I promise I won’t get pre-empted again!  Look, I am affined to core 0!  Your favorite L1 cache is just a lookup away!

Comments are closed.