Алекс Jenter - Программирование на Visual C++. Архив рассылки

Здесь есть возможность читать онлайн «Алекс Jenter - Программирование на Visual C++. Архив рассылки» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Жанр: Программирование, на русском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Программирование на Visual C++. Архив рассылки: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Программирование на Visual C++. Архив рассылки»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ
, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.

Программирование на Visual C++. Архив рассылки — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Программирование на Visual C++. Архив рассылки», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Ну, а какие у нас альтернативы? Да, пожалуй, только одна. Не использоватьAPI для работы с критическими секциями. Вместо них написать свои собственные. Пусть даже не такие обточенные напильником, как в WindowsNT. Не страшно. Нам это понадобится только в debug-конфигурациях. В release'ах мы будем продолжать использовать оригинальный API от Майкрософт. Для этого напишем несколько функций полностью совместимых по типам и количеству аргументов с "настоящим" API и добавим #defineкак у MFC для переопределения оператора newв debug-конфигурациях.

Листинг 14. Собственная реализация критических секций

#if defined(_DEBUG) && !defined(_NO_DEADLOCK_TRACE)

#define DEADLOCK_TIMEOUT 30000

#define CS_DEBUG 1

// Создаем на лету событие для операций ожидания,

// но никогда его не освобождаем. Так удобней для отладки

static inline HANDLE _CriticalSectionGetEvent(LPCRITICAL_SECTION pcs) {

HANDLE ret = pcs->LockSemaphore;

if (!ret) {

HANDLE sem = ::CreateEvent(NULL, false, false, NULL);

ATLASSERT(sem);

if (!(ret = (HANDLE)::InterlockedCompareExchangePointer(

&pcs->LockSemaphore, sem, NULL))) ret = sem;

else ::CloseHandle(sem); // Кто-то успел раньше

}

return ret;

}

// Ждем, пока критическая секция не освободится либо время ожидания

// будет превышено

static inline VOID _WaitForCriticalSectionDbg(LPCRITICAL_SECTION pcs) {

HANDLE sem = _CriticalSectionGetEvent(pcs);

DWORD dwWait;

do {

dwWait = ::WaitForSingleObject(sem, DEADLOCK_TIMEOUT);

if (WAIT_TIMEOUT == dwWait) {

ATLTRACE("Critical section timeout (%u msec):"

" tid 0x%04X owner tid 0x%04X\n", DEADLOCK_TIMEOUT,

::GetCurrentThreadId(), pcs->OwningThread);

}

} while(WAIT_TIMEOUT == dwWait);

ATLASSERT(WAIT_OBJECT_0 == dwWait);

}

// Выставляем событие в активное состояние

static inline VOID _UnWaitCriticalSectionDbg(LPCRITICAL_SECTION pcs) {

HANDLE sem = _CriticalSectionGetEvent(pcs);

BOOL b = ::SetEvent(sem);

ATLASSERT(b);

}

// Заполучем критическую секцию в свое пользование

inline VOID EnterCriticalSectionDbg(LPCRITICAL_SECTION pcs) {

if (::InterlockedIncrement(&pcs->LockCount)) {

// LockCount стал больше нуля.

// Проверяем идентификатор нити

if (pcs->OwningThread == (HANDLE)::GetCurrentThreadId()) {

// Нить та же самая. Критическая секция наша.

pcs->RecursionCount++;

return;

}

// Критическая секция занята другой нитью.

// Придется подождать

_WaitForCriticalSectionDbg(pcs);

}

// Либо критическая секция была "свободна",

// либо мы дождались. Сохраняем идентификатор текущей нити.

pcs->OwningThread = (HANDLE)::GetCurrentThreadId();

pcs->RecursionCount = 1;

}

// Заполучаем критическую секцию если она никем не занята

inline BOOL TryEnterCriticalSectionDbg(LPCRITICAL_SECTION pcs) {

if (-1L == ::InterlockedCompareExchange(&pcs->LockCount, 0, -1)) {

// Это первое обращение к критической секции

pcs->OwningThread = (HANDLE)::GetCurrentThreadId();

pcs->RecursionCount = 1;

} else if (pcs->OwningThread == (HANDLE)::GetCurrentThreadId()) {

// Это не первое обращение, но из той же нити

::InterlockedIncrement(&pcs->LockCount);

pcs->RecursionCount++;

} else return FALSE; // Критическая секция занята другой нитью

return TRUE;

}

// Освобождаем критическую секцию

inline VOID LeaveCriticalSectionDbg(LPCRITICAL_SECTION pcs) {

// Проверяем, чтобы идентификатор текущей нити совпадал

// с идентификатор нити-влядельца.

// Если это не так, скорее всего мы имеем дело с ошибкой

ATLASSERT(pcs->OwningThread == (HANDLE)::GetCurrentThreadId());

if (--pcs->RecursionCount) {

// Не последний вызов из этой нити.

// Уменьшаем значение поля LockCount

::InterlockedDecrement(&pcs->LockCount);

} else {

// Последний вызов. Нужно "разбудить" какую-либо

// из ожидающих ниток, если таковые имеются

ATLASSERT(NULL != pcs->OwningThread);

pcs->OwningThread = NULL;

if (::InterlockedDecrement(&pcs->LockCount) >= 0) {

// Имеется, как минимум, одна ожидающая нить

_UnWaitCriticalSectionDbg(pcs);

}

}

}

// Удостоверяемся, что ::EnterCriticalSection() была вызвана

// до вызова этого метода

inline BOOL CheckCriticalSection(LPCRITICAL_SECTION pcs) {

return pcs->LockCount >= 0

&& pcs->OwningThread == (HANDLE)::GetCurrentThreadId();

}

// Переопределяем все функции для работы с критическими секциями.

// Определение класса CLock должно быть после этих строк

#define EnterCriticalSection EnterCriticalSectionDbg

#define TryEnterCriticalSection TryEnterCriticalSectionDbg

#define LeaveCriticalSection LeaveCriticalSectionDbg

#endif

Ну и заодно добавим еще один метод в наш класс CLock

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Программирование на Visual C++. Архив рассылки»

Представляем Вашему вниманию похожие книги на «Программирование на Visual C++. Архив рассылки» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Алексей Макеев - Смертельный архив
Алексей Макеев
libcat.ru: книга без обложки
Алексей Апухтин
Отзывы о книге «Программирование на Visual C++. Архив рассылки»

Обсуждение, отзывы о книге «Программирование на Visual C++. Архив рассылки» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x