Читаем Thinking In C++. Volume 2: Practical Programming полностью

  void run() {

    try {

      while(!Thread::interrupted()) {

        // Blocks until job is offered/accepted:

        cradle->offerEngineBotServices();

        cout << "Installing engine" << endl;

        (*cradle)->addEngine();

        cradle->taskFinished();

      }

    } catch(Interrupted_Exception&) { /* Exit */ }

    cout << "EngineRobot off" << endl;

  }

};

class DriveTrainRobot : public Runnable {

  CradlePtr cradle;

public:

  DriveTrainRobot(CradlePtr cr) : cradle(cr) {}

  void run() {

    try {

      while(!Thread::interrupted()) {

        // Blocks until job is offered/accepted:

        cradle->offerDriveTrainBotServices();

        cout << "Installing DriveTrain" << endl;

        (*cradle)->addDriveTrain();

        cradle->taskFinished();

      }

    } catch(Interrupted_Exception&) { /* Exit */ }

    cout << "DriveTrainRobot off" << endl;

  }

};

class WheelRobot : public Runnable {

  CradlePtr cradle;

public:

  WheelRobot(CradlePtr cr) : cradle(cr) {}

  void run() {

    try {

      while(!Thread::interrupted()) {

        // Blocks until job is offered/accepted:

        cradle->offerWheelBotServices();

        cout << "Installing Wheels" << endl;

        (*cradle)->addWheels();

        cradle->taskFinished();

      }

    } catch(Interrupted_Exception&) { /* Exit */ }

    cout << "WheelRobot off" << endl;

  }

};

class Reporter : public Runnable {

  CarQueue carQueue;

public:

  Reporter(CarQueue& cq) : carQueue(cq) {}

  void run() {

    try {

      while(!Thread::interrupted()) {

        cout << carQueue->get() << endl;

      }

    } catch(Interrupted_Exception&) { /* Exit */ }

    cout << "Reporter off" << endl;

  }

};

int main() {

  cout << "Press to quit" << endl;

  try {

    CarQueue chassisQueue(new TQueue),

             finishingQueue(new TQueue);

    CradlePtr cradle(new Cradle);

    ThreadedExecutor assemblyLine;

    assemblyLine.execute(new EngineRobot(cradle));

    assemblyLine.execute(new DriveTrainRobot(cradle));

    assemblyLine.execute(new WheelRobot(cradle));

    assemblyLine.execute(

      new Director(chassisQueue, finishingQueue, cradle));

    assemblyLine.execute(new Reporter(finishingQueue));

    // Start everything running by producing chassis:

    assemblyLine.execute(new ChassisBuilder(chassisQueue));

    cin.get();

    assemblyLine.interrupt();

  } catch(Synchronization_Exception& e) {

    cerr << e.what() << endl;

  }

} ///:~

You’ll notice that Car takes a shortcut: it assumes that bool operations are atomic, which, as previously discussed, is generally a safe assumption but one to consider carefully. Each Car begins as an unadorned chassis, and different robots will attach different parts to it, calling the appropriate "add" function when they do.

A ChassisBuilder simply creates a new Car every second and places it into the chassisQueue. A Director manages the build process by taking the next Car off the chassisQueue, putting it into the Cradle, telling all the robots to startWork( ), and suspending itself by calling waitUntilWorkFinished( ). When the work is done, the Director takes the Car out of the Cradle and puts in into the finishingQueue.

The Cradle is the crux of the signaling operations. A Mutex and a Condition object control both the working of the robots and indicate whether all the operations are finished. A particular type of robot can offer its services to the Cradle by calling the "offer" function appropriate to its type. At this point, that robot thread is suspended until the Director calls startWork( ), which changes the hiring flags and calls broadcast( ) to tell all the robots to show up for work. Although this system allows any number of robots to offer their services, each one of those robots has its thread suspended by doing so. You could imagine a more sophisticated system in which the robots register themselves with many different Cradles without being suspended by that registration process and then reside in a pool waiting for the first Cradle that needs a task completed.

After each robot finishes its task (changing the state of the Car in the process), it calls taskFinished( ), which sends a signal( ) to the readyCondition, which is what the Director is waiting on in waitUntilWorkFinished( ). Each time the director thread awakens, the state of the Car is checked, and if it still isn’t finished, that thread is suspended again.

When the Director inserts a Car into the Cradle, you can perform operations on that Car via the operator->( ). To prevent multiple extractions of the same car, a flag causes an error report to be generated. (Exceptions don’t propagate across threads in the ZThread library.)

In main( ), all the necessary objects are created and the tasks are initialized, with the ChassisBuilder begun last to start the process. (However, because of the behavior of the TQueue, it wouldn’t matter if it were started first.) Note that this program follows all the guidelines regarding object and task lifetime presented in this chapter, and so the shutdown process is safe.

<p>Deadlock</p>
Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных