Fibers
Note:
Fibers are of specialized interest. See the comment after the first bulleted item below to determine if you want to skip this section.A fiber, as the name implies, is a piece of a thread. More precisely, a fiber is a unit of execution within a thread that can be scheduled by the application rather than by the kernel. A thread can create numerous fibers, and the fibers themselves determine which of the thread's fibers will execute next. The fibers have independent stacks but otherwise run entirely in the context of the thread, having access, for example, to the thread's TLS and any mutexes[1] owned by the thread. Furthermore, fiber management occurs entirely in user space outside the kernel. Fibers can be thought of as lightweight threads, although there are numerous differences.
[1] A mutex, as explained in the next chapter, is a synchronization object that threads can own.
Fibers can be used for several purposes.
- Most importantly, many applications, especially some written for UNIX using proprietary thread implementations, now generally obsolete, are written to schedule their own threads. Fibers make it easier to port such applications to Windows. Most readers will not have such requirements and may want to skip this section.
- A thread does not need to block waiting for a file lock, mutex, named pipe input, or other resource. Rather, one fiber can poll the resource and, if the resource is not available, switch control to another specific fiber.
- Fibers operate within a thread and have access to thread and process resources. Unlike threads, fibers are not preemptively scheduled. The Windows executive, in fact, is not aware of fibers; fibers are managed within the fiber DLL entirely within user space.
- Fibers allow you to implement co-routines, whereby an application switches among several interrelated tasks. Threads do not allow this. The programmer has no direct control over which thread will be executed next.
- Major software vendors have used fibers and claim performance advantages. For example, Oracle Database 10g has an optional "fiber mode" (see http://download.oracle.com/owsf_2003/40171_colello.ppt ; this presentation also describes the threading model).
Six functions make up the fiber API. They are used in the following sequence and as shown in Figure 7-5.
- A thread must first enable fiber operation by calling ConvertThreadToFiber. The thread then consists of a single fiber, which can be considered the primary fiber. This call provides a pointer to fiber data, which can be used in much the same way that the thread argument was used to create unique data for a thread.
- Primary or other fibers create additional fibers using CreateFiber. Each fiber has a start address, a stack size, and a parameter. Each new fiber is identified by an address rather than by a handle.
- An individual fiber can obtain its data, as received from CreateFiber, by calling GetFiberData.
- Similarly, a fiber can obtain its identity with GetCurrentFiber.
- A running fiber yields control to another fiber by calling SwitchToFiber, indicating the address of the other fiber. Fibers must explicitly indicate the next fiber that is to run within the thread.
- The DeleteFiber function deletes an existing fiber and all its associated data.
- New functions, such as ConvertFiberToThread (which releases resources created by ConvertThreadToFiber), have been added to XP (NT 5.1), along with fiber local storage.
Figure 7-5. Control Flow among Fibers in a Thread
[View full size image]

- Master-slave scheduling.
One fiber, the primary fiber in this case, decides which fiber to run, and that fiber always yields control to the master fiber. Fiber 1 in Figure 7-5 behaves in this way. - Peer-to-peer scheduling.
A fiber determines the next fiber to run. The determination can be based on policies such as round-robin scheduling, priority scheduling based on a priority scheme, and so on. Co-routines would be implemented with peer-to-peer scheduling. In Figure 7-5, Fibers 0 and 2 switch control in this way.