Существует ли способ получить потоковую вставку/извлечение без блокировки на basic_iostream в Windows?

Мои мнения о них:

1) нет, имена таблиц должны быть исключительными.

, В то время как это, кажется, имеет смысл для простого выбора (select * from Orders), это имеет меньше смысла для OO, эквивалентного (Orders x = new Orders).

таблица А в DB является действительно набором того объекта, это имеет больше смысла, как только Вы используете логику набора:

select Orders.*
from Orders inner join Products
    on Orders.Key = Products.Key

, Что последняя строка, фактическая логика соединения, выглядит сбивающей с толку со множественными именами таблиц.

я не уверен во всегда использовании псевдонима (как Matt предполагает), разрешает это.

2) Они должны быть исключительными, поскольку они только содержат 1 свойство

3), Никогда, если имя столбца неоднозначно (как выше, где у них обоих есть столбец под названием [Ключ]), название таблицы (или ее псевдоним) может отличить их достаточно хорошо. Вы хотите, чтобы запросы были быстры для ввода и простой - префиксы добавляют ненужную сложность.

4) Независимо от того, что Вы хотите, я предложил бы CapitalCase

, я не думаю, что существует один набор абсолютных инструкций по любому из них.

пока, независимо от того, что Вы выбираете, последовательно через приложение или DB, я не думаю, что это действительно имеет значение.

9
задан Adam Holmberg 16 July 2009 в 22:45
поделиться

4 ответа

Этот вопрос томился достаточно долго. Я собираюсь доложить, чем я закончил, даже если есть шанс, что меня высмеют.

Я уже определил, что проблема заключалась в том, что два потока заходили в тупик при попытке доступа к объекту iostream в отдельных операциях чтения и записи. Я мог видеть, что реализация операторов вставки и извлечения строкового потока в Visual Studio объявила Sentry, которая заблокировала буфер потока, связанный с обрабатываемым потоком.

Я знал, что для рассматриваемого потока для этого тупика реализация буфера потока была boost :: asio :: basic_socket_streambuf. Я проверил реализацию, чтобы увидеть, что операции чтения и записи (недополнение и переполнение) на самом деле работают с разными буферами (получение и размещение).

Проверив вышесказанное, я решил просто обойти блокировку для этого приложения. Для этого я использовал определения препроцессора для конкретного проекта, чтобы исключить код блокировки в реализации часового блокировки basic_istream:

    class _Sentry_base
        {   // stores thread lock and reference to input stream
    public:
        __CLR_OR_THIS_CALL _Sentry_base(_Myt& _Istr)
            : _Myistr(_Istr)
            {   // lock the stream buffer, if there
#ifndef MY_PROJECT
            if (_Myistr.rdbuf() != 0)
                _Myistr.rdbuf()->_Lock();
#endif
            }

        __CLR_OR_THIS_CALL ~_Sentry_base()
            {   // destroy after unlocking
#ifndef MY_PROJECT
            if (_Myistr.rdbuf() != 0)
                _Myistr.rdbuf()->_Unlock();
#endif
            }

Плюс:

  • Работает
  • Только мой проект (с соответствующими определениями) затронуто

Обратная сторона:

  • Кажется немного хакерским
  • Каждая платформа, на которой это построено, потребует этой модификации

Я планирую смягчить последний момент, громко задокументировав это в коде и документации проекта.

Я понимаю, что здесь может быть более элегантное решение, но в интересах целесообразности я выбрал прямое решение после должной осмотрительности, чтобы понять последствия.

Я использовал определения препроцессора для конкретного проекта, чтобы исключить код блокировки в реализации часового блокировки basic_istream:

    class _Sentry_base
        {   // stores thread lock and reference to input stream
    public:
        __CLR_OR_THIS_CALL _Sentry_base(_Myt& _Istr)
            : _Myistr(_Istr)
            {   // lock the stream buffer, if there
#ifndef MY_PROJECT
            if (_Myistr.rdbuf() != 0)
                _Myistr.rdbuf()->_Lock();
#endif
            }

        __CLR_OR_THIS_CALL ~_Sentry_base()
            {   // destroy after unlocking
#ifndef MY_PROJECT
            if (_Myistr.rdbuf() != 0)
                _Myistr.rdbuf()->_Unlock();
#endif
            }

Плюс:

  • Он работает
  • Затронут только мой проект (с соответствующими определениями)

Оборотная сторона:

  • Кажется немного хакерским
  • Каждая платформа, на которой это построено, потребует этой модификации

Я планирую смягчить последний момент, громко задокументировав это в коде и документации проекта.

Я понимаю, что здесь может быть более элегантное решение, но в интересах целесообразности я выбрал прямое решение после должной осмотрительности, чтобы понять последствия.

Я использовал определения препроцессора для конкретного проекта, чтобы исключить код блокировки в реализации часового блокировки basic_istream:

    class _Sentry_base
        {   // stores thread lock and reference to input stream
    public:
        __CLR_OR_THIS_CALL _Sentry_base(_Myt& _Istr)
            : _Myistr(_Istr)
            {   // lock the stream buffer, if there
#ifndef MY_PROJECT
            if (_Myistr.rdbuf() != 0)
                _Myistr.rdbuf()->_Lock();
#endif
            }

        __CLR_OR_THIS_CALL ~_Sentry_base()
            {   // destroy after unlocking
#ifndef MY_PROJECT
            if (_Myistr.rdbuf() != 0)
                _Myistr.rdbuf()->_Unlock();
#endif
            }

Плюс:

  • Он работает
  • Затронут только мой проект (с соответствующими определениями)

Оборотная сторона:

  • Кажется немного хакерским
  • Каждая платформа, на которой это построено, потребует этой модификации

Я планирую смягчить последний момент, громко задокументировав это в коде и документации проекта.

Я понимаю, что здесь может быть более элегантное решение, но в интересах целесообразности я выбрал прямое решение после должной осмотрительности, чтобы понять последствия.

  • Кажется немного хакерским
  • Каждая платформа, на которой это построено, будет нуждаться в этой модификации

Я планирую смягчить последний момент, громко задокументировав это в коде и документации проекта.

Я понимаю, что здесь может быть более элегантное решение, но в интересах целесообразности я выбрал прямое решение после должной осмотрительности, чтобы понять последствия.

  • Кажется немного хакерским
  • Каждая платформа, на которой это построено, будет нуждаться в этой модификации

Я планирую смягчить последний момент, громко задокументировав это в коде и документации проекта.

Я понимаю, что здесь может быть более элегантное решение, но в интересах целесообразности я выбрал прямое решение после должной осмотрительности, чтобы понять последствия.

1
ответ дан 5 December 2019 в 02:08
поделиться

Возможно, вы могли бы реализовать блокирующий слой самостоятельно? IE, имейте отдельные istream и ostream , которые вы сами блокируете при их вызове. Периодически проверяйте, разблокированы ли оба, а затем считывайте один в другой.

0
ответ дан 5 December 2019 в 02:08
поделиться

Вы явно очищали поток после записи в него? Это сообщение в блоге подразумевает, что ваши данные могут просто «застрять» в буфере. Если это правда, то, возможно, вы зашли в тупик, потому что еще нет ничего доступного для чтения. Добавьте stream << std :: flush в конец ваших операций отправки.

Альтернативное (хотя и менее эффективное) решение, предложенное в сообщении блога, - отключить буферизацию вывода потока:

stream.rdbuf()->pubsetbuf(0, 0);
0
ответ дан 5 December 2019 в 02:08
поделиться

Согласно документации boost [1] использование двух потоков, обращающихся к одному объект без мьютексов «небезопасен». Тот факт, что он работал на платформах Unix, не гарантирует, что он будет работать на платформе Windows.

Итак, ваши варианты:

  1. Перепишите свой код, чтобы ваши потоки не обращались к объекту одновременно.
  2. Исправьте ускорение библиотеку и отправьте изменения обратно
  3. Хорошо спросите Криса, внесет ли он изменения для платформы Windows

[1] http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/overview/ core / threads.html

1
ответ дан 5 December 2019 в 02:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: