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

    return os << "#" << a.id << ": " << a.tlv->get();

  }

};

int main() {

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

  try {

    CountedPtr

      tlv(new ThreadLocalVariables);

    const int sz = 5;

    ThreadedExecutor executor;

    for(int i = 0; i < sz; i++)

      executor.execute(new Accessor(tlv, i));

    cin.get();

    tlv->cancel(); // All Accessors will quit

  } catch(Synchronization_Exception& e) {

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

  }

} ///:~

When you create a ThreadLocal object by instantiating the template, you are only able to access the contents of the object using the get( ) and set( ) functions. The get( ) function returns a copy of the object that is associated with that thread, and set( ) inserts its argument into the object stored for that thread, returning the old object that was in storage. You can see this is use in increment( ) and get( ) in ThreadLocalVariables.

Since tlv is shared by multiple Accessor objects, it is written as Cancelable so that the Accessors can be signaled when we want to shut the system down.

When you run this program, you’ll see evidence that the individual threads are each allocated their own storage.

<p>Terminating tasks</p>

In previous examples, we have seen the use of a "quit flag" or the Cancelable interface in order to terminate a task. This is a reasonable approach to the problem. However, in some situations the task must be terminated more abruptly. In this section, you’ll learn about the issues and problems of such termination.

First, let’s look at an example that not only demonstrates the termination problem but is also an additional example of resource sharing. To present this example, we’ll first need to solve the problem of iostream collision

<p>Preventing iostream collision</p>

You may have noticed in previous examples that the output is sometimes garbled. The problem is that C++ iostreams were not created with threading in mind, and so there’s nothing to keep one thread’s output from interfering with another thread’s output.

To solve the problem, we need to create the entire output packet first and then explicitly decide when to try to send it to the console. One simple solution is to write the information to an ostringstream and then use a single object with a mutex as the point of output among all threads, to prevent more than one thread from writing at the same time:

//: C11:Display.h

// Prevents ostream collisions

#ifndef DISPLAY_H

#define DISPLAY_H

#include "zthread/Mutex.h"

#include "zthread/Guard.h"

#include

#include

class Display { // Share one of these among all threads

  ZThread::Mutex iolock;

public:

  void output(std::ostringstream& os) {

    ZThread::Guard g(iolock);

    std::cout << os.str();

  }

};

#endif // DISPLAY_H ///:~

This way, all of the standard operator<<( ) functions are predefined for us and the object can be built in memory using familiar ostream operators. When a task wants to display output, it creates a temporary ostringstream object that it uses to build up the desired output message. When it calls output( ), the mutex prevents multiple threads from writing to this Display object. (You must use only one Display object in your program, as you’ll see in the following examples.)

This just shows the basic idea, but if necessary, you can build a more elaborate framework. For example, you could enforce the requirement that there be only one Display object in a program by making it a Singleton. (The ZThread library has a Singleton template to support Singletons.)

<p>The ornamental garden</p>

In this simulation, the garden committee would like to know how many people enter the garden each day though its multiple gates. Each gate has a turnstile or some other kind of counter, and after the turnstile count is incremented, a shared count is incremented that represents the total number of people in the garden.

//: C11:OrnamentalGarden.cpp

//{L} ZThread

#include "Display.h"

#include "zthread/Thread.h"

#include "zthread/FastMutex.h"

#include "zthread/Guard.h"

#include "zthread/ThreadedExecutor.h"

#include "zthread/CountedPtr.h"

#include

#include

#include

using namespace ZThread;

using namespace std;

class Count : public Cancelable {

  FastMutex lock;

  int count;

  bool paused, canceled;

public:

  Count() : count (0), paused(false), canceled(false) {

    srand(time(0)); // Seed the random number generator

  }

  int increment() {

    // Comment the following line to see counting fail:

    Guard g(lock);

    int temp = count ;

    if(rand() < RAND_MAX/2) // Yield half the time

      Thread::yield();

    return (count  = ++temp);

  }

  int value() {

    Guard g(lock);

    return count;

  }

  void cancel() {

    Guard g(lock);

    canceled = true;

  }

  bool isCanceled() {

    Guard g(lock);

    return canceled;

  }

  bool pause() {

    Guard g(lock);

    paused = true;

  }

  bool isPaused() {

    Guard g(lock);

    return paused;

  }

};

class Entrance : public Runnable {

  CountedPtr count;

  CountedPtr display;

  int number;

  int id;

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

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

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

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

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

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

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

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

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