Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > поставщики-клиенты


Автор: zss 23.3.2006, 11:05
Хочу создать очередб с ожиданиями и с отказами, но что-то слетает smile

есть циклический буфер
Код
template <typename T>
class CyclicBuffer {
private :
    std::deque<T> container_;
    size_t maxSize_;

protected :
    virtual void OnOverflow (unsigned value) const {
        DebugMessage ("Debug", "Переполнение буфера");
    }

public :
    typedef typename std::deque<T>::value_type value_type;
    typedef typename std::deque<T>::size_type  size_type;

    explicit CyclicBuffer (unsigned size) : maxSize_ (size) {
        assert (size);
        if (!maxSize_) {
            throw std::range_error ("Циклический буфер не может быть равен 0");
        }
    }
    virtual ~CyclicBuffer () {;}
    void push (const value_type& value) {
        if (container_.size() == maxSize_) {
            OnOverflow (value->size());
            container_.pop_front();
        }
        container_.push_back (value);
    }
    void pop (void) { container_.pop_front (); }
    const value_type& get (void) const { return container_.front(); }
    void clear (void) { container_.clear(); }
    size_type size (void) const { return container_.size(); }
    size_type max_size (void) const { return maxSize_; }
    bool empty (void) const { return container_.empty(); }


на его основе хочу создать очередь (поставщики-клиенты)

Код
template <typename T>
class Queue {
private :
    CyclicBuffer<T> queue_;
    CRITICAL_SECTION section_
    HANDLE semaphore_;

    bool Lock (void) const {

        DWORD result = WaitForSingleObject (semaphore_, 100);
        return (result == WAIT_OBJECT_0);
    }
    bool Unlock (void) const {
        return ReleaseSemaphore (semaphore_, 1, NULL)){
    }


public :
    typedef typename CyclicBuffer<T>::value_type value_type;

    explicit Queue (unsigned size)
        : queue_ (size){

        InitializeCriticalSection (&section_);
        semaphore_ = CreateSemaphore (NULL, 0, size, NULL);
    }
    virtual ~Queue () {
        CloseHandle (semaphore_);
        DeleteCriticalSection (&section_);
    }

    void push (const value_type& value) {

        // если очередь заполнена, то ждем 100 мс.
        // если не дождались, то входим в критическую секцию и потеря данных
        if (!Unlock()) Lock ();
        EnterCriticalSection (&section_);
        queue_.push (value);
        Unlock();
        LeaveCriticalSection (&section_);
    }
    bool pop (value_type& value) {
        // если очередь пуста, то ждем 100 мс
        // если не дождались, то выходим (flase)
        if (!Lock()) return false;
        EnterCriticalSection (&section_);
        value = queue_.get();
        queue_.pop();
        LeaveCriticalSection (&section_);
        return true;
    }
    void reset (void) {
        // входим в критическую секцию
        // числим очередь и сбрасываем семафор
        EnterCriticalSection (&section_);
        for (int i = 0; i < queue_.size(); i++){
           Lock();
        }
        queue_.clear();
        LeaveCriticalSection (&section_);
    }
    unsigned max_size (void) const { return queue_.max_size(); }
};


так вот получается, что, например, если я вхожу в критическую секцию reset() и сбрасываю
семафор, то поток, который проверяет pop() пройдет условие и будет ждать входа в критическую секцию

как только я выйду из reset, поток в pop войдет, но очередь пуста !!!

Также и в push

Тоесть мне нужно как-то умудрится подождать очередь в pop и push, войти в критическую секцию и сделать свое дело smile

Автор: threef 23.3.2006, 15:37
Критично ли использование семафора ? ИМХО это системный и довольно медленный ресурс, скорее нужен для межпроцессного общения - раз. Тщательнее было бы использовать функции
Interlocked... и статическую переменную класса.

А у тебя получается смена очередности Semaphore - CriticalSexion, сначала закрой CS, а затем начинай мудрить с семафорами.

Автор: sdeniss 23.3.2006, 19:04
Цитата(zss @ 23.3.2006, 11:05 Найти цитируемый пост)
for (int i = 0; i < queue_.size(); i++){
          Lock();
        }

-- зачем???smile)) мож надо было Unlock(), хоть какое то логика была быsmile))
Но ты вроде всегда освобождаешь семафор так, что тоже непонятно зачем

Автор: threef 23.3.2006, 20:25
sdeniss
Это таким образом идет очистка очереди. Wait -функции очищают семафор до 0. Потом при помощи Unlock добавляются элементы в очередь.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)