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

As an example that brings together many of the concepts in this chapter, consider a hypothetical robotic assembly line for automobiles. Each Car will be built in several stages, and in this example we’ll look at a single stage: after the chassis has been created, at the time when the engine, drive train, and wheels are attached. The Cars are transported from one place to another via a CarQueue, which is a type of TQueue. A Director takes each Car (as a raw chassis) from the incoming CarQueue and places it in a Cradle, which is where all the work is done. At this point, the Director tells all the waiting robots (using broadcast( )) that the Car is in the Cradle ready for the robots to work on it. The three types of robots go to work, sending a message to the Cradle when they finish their tasks. The Director waits until all the tasks are complete and then puts the Car onto the outgoing CarQueue to be transported to the next operation. In this case, the consumer of the outgoing CarQueue is a Reporter object, which just prints the Car to show that the tasks have been properly completed.

//: C11:CarBuilder.cpp

// How broadcast() works.

//{L} ZThread

#include "zthread/Thread.h"

#include "zthread/Mutex.h"

#include "zthread/Guard.h"

#include "zthread/Condition.h"

#include "zthread/ThreadedExecutor.h"

#include "TQueue.h"

#include

#include

using namespace ZThread;

using namespace std;

class Car {

  bool engine, driveTrain, wheels;

  int id;

public:

  Car(int idn) : id(idn), engine(false),

  driveTrain(false), wheels(false) {}

  // Empty Car object:

  Car() : id(-1), engine(false),

  driveTrain(false), wheels(false) {}

  // Unsynchronized -- assumes atomic bool operations:

  int getId() { return id; }

  void addEngine() { engine = true; }

  bool engineInstalled() { return engine; }

  void addDriveTrain() { driveTrain = true; }

  bool driveTrainInstalled() { return driveTrain; }

  void addWheels() { wheels = true; }

  bool wheelsInstalled() { return wheels; }

  friend ostream& operator<<(ostream& os, const Car& c) {

    return os << "Car " << c.id << " ["

      << " engine: " << c.engine

      << " driveTrain: " << c.driveTrain

      << " wheels: " << c.wheels << " ]";

  }

};

typedef CountedPtr< TQueue > CarQueue;

class ChassisBuilder : public Runnable {

  CarQueue carQueue;

  int counter;

public:

  ChassisBuilder(CarQueue& cq) : carQueue(cq), counter(0){}

  void run() {

    try {

      while(!Thread::interrupted()) {

        Thread::sleep(1000);

        // Make chassis:

        Car c(counter++);

        cout << c << endl;

        // Insert into queue

        carQueue->put(c);

      }

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

    cout << "ChassisBuilder off" << endl;

  }

};

class Cradle {

  Car c; // Holds current car being worked on

  bool occupied;

  Mutex workLock, readyLock;

  Condition workCondition, readyCondition;

  bool engineBotHired, wheelBotHired, driveTrainBotHired;

public:

  Cradle()

  : workCondition(workLock), readyCondition(readyLock) {

    occupied = false;

    engineBotHired = true;

    wheelBotHired = true;

    driveTrainBotHired = true;

  }

  void insertCar(Car chassis) {

    c = chassis;

    occupied = true;

  }

  Car getCar() { // Can only extract car once

    if(!occupied) {

      cerr << "No Car in Cradle for getCar()" << endl;

      return Car(); // "Null" Car object

    }

    occupied = false;

    return c;

  }

  // Access car while in cradle:

  Car* operator->() { return &c }

  // Allow robots to offer services to this cradle:

  void offerEngineBotServices() {

    Guard g(workLock);

    while(engineBotHired)

      workCondition.wait();

    engineBotHired = true; // Accept the job

  }

  void offerWheelBotServices() {

    Guard g(workLock);

    while(wheelBotHired)

      workCondition.wait();

    wheelBotHired = true; // Accept the job

  }

  void offerDriveTrainBotServices() {

    Guard g(workLock);

    while(driveTrainBotHired)

      workCondition.wait();

    driveTrainBotHired = true; // Accept the job

  }

  // Tell waiting robots that work is ready:

  void startWork() {

    Guard g(workLock);

    engineBotHired = false;

    wheelBotHired = false;

    driveTrainBotHired = false;

    workCondition.broadcast();

  }

  // Each robot reports when their job is done:

  void taskFinished() {

    Guard g(readyLock);

    readyCondition.signal();

  }

  // Director waits until all jobs are done:

  void waitUntilWorkFinished() {

    Guard g(readyLock);

    while(!(c.engineInstalled() && c.driveTrainInstalled()

            && c.wheelsInstalled()))

      readyCondition.wait();

  }

};

typedef CountedPtr CradlePtr;

class Director : public Runnable {

  CarQueue chassisQueue, finishingQueue;

  CradlePtr cradle;

public:

  Director(CarQueue& cq, CarQueue& fq, CradlePtr cr)

  : chassisQueue(cq), finishingQueue(fq), cradle(cr) {}

  void run() {

    try {

      while(!Thread::interrupted()) {

        // Blocks until chassis is available:

        cradle->insertCar(chassisQueue->get());

        // Notify robots car is ready for work

        cradle->startWork();

        // Wait until work completes

        cradle->waitUntilWorkFinished();

        // Put car into queue for further work

        finishingQueue->put(cradle->getCar());

      }

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

    cout << "Director off" << endl;

  }

};

class EngineRobot : public Runnable {

  CradlePtr cradle;

public:

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

Перейти на страницу:

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

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

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

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

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

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

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

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