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

//: C11:GuardedEvenGenerator.cpp

// Simplifying mutexes with the Guard template.

//{L} ZThread

#include "EvenChecker.h"

#include "zthread/ThreadedExecutor.h"

#include "zthread/Mutex.h"

#include "zthread/Guard.h"

#include

using namespace ZThread;

using namespace std;

class GuardedEvenGenerator : public Generator {

  int currentEvenValue;

  Mutex lock;

public:

  GuardedEvenGenerator() { currentEvenValue = 0; }

  ~GuardedEvenGenerator() {

    cout << "~GuardedEvenGenerator" << endl;

  }

  int nextValue() {

    Guard g(lock);

    currentEvenValue++;

    Thread::yield();

    currentEvenValue++;

    return currentEvenValue;

  }

};

int main() {

  EvenChecker::test();

} ///:~

Note that the temporary return value is no longer necessary in nextValue( ). In general, there is less code to write, and the opportunity for user error is greatly reduced.

An interesting feature of the Guard template is that it can be used to manipulate other guards safely. For example, a second Guard can be used to temporarily unlock a guard:

//: C11:TemporaryUnlocking.cpp

// Temporarily unlocking another guard.

//{L} ZThread

#include "zthread/Thread.h"

#include "zthread/Mutex.h"

#include "zthread/Guard.h"

using namespace ZThread;

class TemporaryUnlocking {

  Mutex lock;

public:

  void f() {

    Guard g(lock);

    // lock is acquired

    // ...

    {

      Guard h(g);

      // lock is released

      // ...

      // lock is acquired

    }

    // ...

    // lock is released

  }

};

int main() {

  TemporaryUnlocking t;

  t.f();

} ///:~

A Guard can also be used to try to acquire a lock for a certain amount of time and then abort:

//: C11:TimedLocking.cpp

// Limited time locking.

//{L} ZThread

#include "zthread/Thread.h"

#include "zthread/Mutex.h"

#include "zthread/Guard.h"

using namespace ZThread;

class TimedLocking {

  Mutex lock;

public:

  void f() {

    Guard > g(lock);

    // ...

  }

};

int main() {

  TimedLocking t;

  t.f();

} ///:~

In this example, a Timeout_Exception will be thrown if the lock cannot be acquired within 500 milliseconds.

<p>Synchronizing entire classes</p>

The ZThread library also provides a GuardedClass template to automatically create a synchronized wrapper for an entire class. This means that every member function in the class will automatically be guarded:

//: C11:SynchronizedClass.cpp

//{L} ZThread

#include "zthread/GuardedClass.h"

using namespace ZThread;

class MyClass {

public:

  void func1() {}

  void func2() {}

};

int main() {

  MyClass a;

  a.func1(); // not synchronized

  a.func2(); // not synchronized

  GuardedClass b(new MyClass);

  // Synchronized calls, only one thread at a time allowed:

  b->func1();

  b->func2();

} ///:~

Object a is a not synchronized, so func1( ) and func2( ) can be called at any time by any number of threads. Object b is protected by the GuardedClass wrapper, so each member function is automatically synchronized and only one function per object can be called any time.

The wrapper locks at a class level of granularity, which may affect performance in some cases. If a class contains some unrelated functions, it may be better to synchronize those functions internally with two different locks. However, if you find yourself doing this, it means that one class contains groups of data that may not be strongly associated. Consider breaking the class into two classes.

Guarding all member functions of a class with a mutex does not automatically make that class thread-safe. You must carefully consider all threading issues in order to guarantee thread safety.

<p>Thread local storage</p>

A second way to eliminate the problem of tasks colliding over shared resources is to eliminate the sharing of variables, which can be done by creating different storage for the same variable, for each different thread that uses an object. Thus, if you have five threads using an object with a variable x, thread local storage automatically generates five different pieces of storage for x. Fortunately, the creation and management of thread local storage is taken care of automatically by ZThread’s ThreadLocal template, as seen here:

//: C11:ThreadLocalVariables.cpp

// Automatically giving each thread its own storage.

//{L} ZThread

#include "zthread/Thread.h"

#include "zthread/Mutex.h"

#include "zthread/Guard.h"

#include "zthread/ThreadedExecutor.h"

#include "zthread/Cancelable.h"

#include "zthread/ThreadLocal.h"

#include "zthread/CountedPtr.h"

#include

using namespace ZThread;

using namespace std;

class ThreadLocalVariables : public Cancelable {

  ThreadLocal value;

  bool canceled;

  Mutex lock;

public:

  ThreadLocalVariables() : canceled(false) {

    value.set(0);

  }

  void increment() { value.set(value.get() + 1); }

  int get() { return value.get(); }

  void cancel() {

    Guard g(lock);

    canceled = true;

  }

  bool isCanceled() {

    Guard g(lock);

    return canceled;

  }

};

class Accessor : public Runnable {

  int id;

  CountedPtr tlv;

public:

  Accessor(CountedPtr& tl, int idn)

  : id(idn), tlv(tl) {}

  void run() {

    while(!tlv->isCanceled()) {

      tlv->increment();

      cout << *this << endl;

    }

  }

  friend ostream&

    operator<<(ostream& os, Accessor& a) {

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

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

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

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

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

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

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

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

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