10.3.3. Ceder el paso

Si sabe que ha logrado realizar lo que necesita durante una pasada a través de un bucle en su función run() (la mayoría de las funciones run() suponen un periodo largo de tiempo de ejecución), puede darle un toque al mecanismo de planificación de hilos, decirle que ya ha hecho suficiente y que algún otro hilo puede tener la CPU. Este toque (y es un toque - no hay garantía de que su implementación vaya a escucharlo) adopta la forma de la función yield().

Podemos construir una versión modificada de los ejemplos de LiftOff cediendo el paso después de cada bucle:

//: C11:YieldingTask.cpp
// Suggesting when to switch threads with yield().
//{L} ZThread
#include <iostream>
#include "zthread/Thread.h"
#include "zthread/ThreadedExecutor.h"
using namespace ZThread;
using namespace std;

class YieldingTask : public Runnable {
  int countDown;
  int id;
public:
  YieldingTask(int ident = 0) : countDown(5), id(ident) {}
  ~YieldingTask() {
    cout << id << " completed" << endl;
  }
  friend ostream&
  operator<<(ostream& os, const YieldingTask& yt) {
    return os << "#" << yt.id << ": " << yt.countDown;
  }
  void run() {
    while(true) {
      cout << *this << endl;
      if(--countDown == 0) return;
      Thread::yield();
    }
  }
};

int main() {
  try {
    ThreadedExecutor executor;
    for(int i = 0; i < 5; i++)
      executor.execute(new YieldingTask(i));
  } catch(Synchronization_Exception& e) {
    cerr << e.what() << endl;
  }
} ///:~

Listado 10.11. C11/YieldingTask.cpp


Puede ver que la tarea del método run() es en un bucle infinito en su totalidad. Utilizando yield(), la salida se equilibra bastante que en el caso en el que no se cede el paso. Pruebe a comentar la llamada a Thread::yield() para ver la diferencia. Sin embargo, en general, yield() es útil en raras ocasiones, y no puede contar con ella para realizar un afinamiento serio sobre su aplicación.