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

int main(int argc, char* argv[]) {

  try {

    Thread t(new Blocked);

    if(argc > 1)

      Thread::sleep(1100);

    t.interrupt();

  } catch(Synchronization_Exception& e) {

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

  }

} ///:~

You can see that run( ) contains two points where blocking can occur: the call to Thread::sleep(1000) and the call to cin.get( ). By giving the program any command-line argument, you tell main( ) to sleep long enough that the task will finish its sleep( ) and move into the cin.get( ). If you don’t give the program an argument, the sleep( ) in main( ) is skipped. In this case, the call to interrupt( ) will occur while the task is sleeping, and you’ll see that this will cause Interrupted_Exception to be thrown. If you give the program a command-line argument, you’ll discover that a task cannot be interrupted if it is blocked on IO. That is, you can interrupt out of any blocking operation except IO.

This is a little disconcerting if you’re creating a thread that performs IO, because it means that I/O has the potential of locking your multithreaded program. The problem is that, again, C++ was not designed with threading in mind; quite the opposite, it effectively pretends that threading doesn’t exist. Thus, the iostream library is not thread-friendly. If the new C++ standard decides to add thread support, the iostream library may need to be reconsidered in the process.

<p>Blocked by a mutex</p>

In the previous list of ways to become blocked, the last one happens when you’re trying to call a function whose mutex has already been acquired. In this situation, the calling task will be suspended until the mutex becomes available. The following example tests whether this kind of blocking is interruptible:

//: C11:Interrupting2.cpp

// Interrupting a thread blocked

// with a synchronization guard.

//{L} ZThread

#include "zthread/Thread.h"

#include "zthread/Mutex.h"

#include "zthread/Guard.h"

#include

using namespace ZThread;

using namespace std;

class BlockedMutex {

  Mutex lock;

public:

  BlockedMutex() {

    lock.acquire();

  }

  void f() {

    Guard g(lock);

    // This will never be available

  }

};

class Blocked2 : public Runnable {

  BlockedMutex blocked;

public:

  void run() {

    try {

      cout << "Waiting for f() in BlockedMutex" << endl;

      blocked.f();

    } catch(Interrupted_Exception& e) {

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

      // Exit the task

    }

  }

};

int main(int argc, char* argv[]) {

  try {

    Thread t(new Blocked2);

    t.interrupt();

  } catch(Synchronization_Exception& e) {

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

  }

} ///:~

The class BlockedMutex has a constructor that acquires the object’s own Mutex and never releases it. For that reason, if you try to call f( ), you will always be blocked because the Mutex cannot be acquired. In Blocked2, the run( ) function will therefore be stopped at the call to blocked.f( ). When you run the program you’ll see that, unlike the iostream call, interrupt( ) can break out of a call that’s blocked by a mutex.

<p>Checking for an interrupt</p>

Note that when you call interrupt( ) on a thread, the only time that the interrupt occurs is when the task enters, or is already inside, a blocking operation (except, as you’ve seen, in the case of IO, where you’re just stuck). But what if you’ve written code that may or may not make such a blocking call, depending on the conditions in which it is run? If you can only exit by throwing an exception on a blocking call, you won’t always be able to leave the run( ) loop. Thus, if you call interrupt( ) to stop a task, your task needs a second opportunity to exit in the event that your run( ) loop doesn’t happen to be making any blocking calls.

This opportunity is presented by the interrupted status, which is set by the call to interrupt( ). You check for the interrupted status by calling interrupted( ). This not only tells you whether interrupt( ) has been called, it also clears the interrupted status. Clearing the interrupted status ensures that the framework will not notify you twice about a task being interrupted. You will be notified via either a single Interrupted_Exception, or a single successful Thread::interrupted( ) test. If you want to check again to see whether you were interrupted, you can store the result when you call Thread::interrupted( ).

The following example shows the typical idiom that you should use in your run( ) function to handle both blocked and non-blocked possibilities when the interrupted status is set:

//: C11:Interrupting3.cpp

// General idiom for interrupting a task.

//{L} ZThread

#include "zthread/Thread.h"

#include

#include

#include

using namespace ZThread;

using namespace std;

class NeedsCleanup {

  int id;

public:

  NeedsCleanup(int ident) : id(ident) {

    cout << "NeedsCleanup " << id << endl;

  }

  ~NeedsCleanup() {

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

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

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

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

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

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

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

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

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