Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Pipes  (Прочитано 17610 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 07-04-2009 17:13 » 

Хочу применить именованные пайпы для скидывания сообщений в дочерние процессы. До практики ещё не дошёл, читаю мсдн. Но сильно не понравилась фраза

Цитата
When a process uses WriteFile to write to an anonymous pipe, the write operation is not completed until all bytes are written. If the pipe buffer is full before all bytes are written, WriteFile does not return until another process or thread uses ReadFile to make more buffer space available

вопрос: как узнать, сколько данных можно ещё записать в трубу, чтобы не вызвать такой ситуации с затыканием ? Среди функций для работы с трубами не нашёл ничего такого, или, может, невнимательно смотрел...
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 07-04-2009 17:49 » 

леш, то значит, что если ты сказал "записать 100 кБ в трубу", то пока эти 100 кБ не прочтут на другой стороне, твой процесс будет заблокирован в ядре. Это нормально. Ведь так с любым хендлом происходит. Возможно асинхронное IO поможет.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 08-04-2009 03:04 » 

нет, я так понял из фразы, что если с другого конца не прочитали, а я тут пытаюсь сверх буфера затолкать данные, тогда произойдёт блокировка, а пока влазит - блокировки не будет. Дело в том, что основной процесс вешать ни в коем случае нельзя, лучше пусть дочерний потеряет данные, чем основной зависнет

Цитата
Возможно асинхронное IO поможет.

есть мысль связать сокетом  , а так же WM_COPYDATA (с последним, так понимаю, нужно окно-приёмник создать) .

Щас начну с WM_COPYDATA пробовать )
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 08-04-2009 03:17 » 

Леш, пофиг, чем ты их свяжешь - в любом случае есть буфера, превысив которые ты заблокируешься.

Значит у тебя есть три решения:
1. Неблокируемый IO
2. Ассинхронный IO
3. Отдельный поток для IO
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 08-04-2009 03:22 » new

так я с асинхронным сокетом попробую также ) Он ничего не заблокирует.
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 08-04-2009 03:27 » 

Главное понимать, что при любом способе передачи, запихнуть в хендл больше размера буфера не удастся Ага
Надо иметь свой собственный буфер, достаточный, чтобы пережить наибольшее время блокировки принимающей стороны.
Мне тут видится связанный список буферов (для небольшого превышения) и сброс во временный файл.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 08-04-2009 09:58 » 

а почему WM_COPYDATA  не удаётся послать через PostMessage , разрешает только SendMessage ?
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 08-04-2009 12:52 » 

Алексей1153++, Улыбаюсь Так чтобы заблокировать процесс... Природу не обманешь!
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 08-04-2009 15:13 » 

гацтво ))

Ну я уже вышел из положения - в приёмнике засовываю данную в FIFO и выхожу. А в отдельном потоке вытаскиваю из стека и обрабатываю. Главное, что тут блокировки неожиданной не будет Улыбаюсь

Ну я то думал сначала, что WM_COPYDATA именно копирует данные, а она только указатель передаёт
« Последнее редактирование: 08-04-2009 15:23 от Алексей1153++ » Записан

zubr
Гость
« Ответ #9 : 08-04-2009 16:36 » 

Ну, если все так сложно, то как вариант сбрасывай данные в файл или файлмаппинг, а с помощью пайпов, майлслотов, сокетов, сообщений или событий просто дашь сигнал на чтение буфера.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 08-04-2009 16:48 » 

нет, с файлом возиться не хочется. С сообщенитем неплохо получилось
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 08-04-2009 18:45 » 

Алексей1153++, с файлом надежнее всего Да-да
Не все может поместиться в памяти и не не все там следует хранить - не резиновая.

При любой межпроцессовой коммуникации (не важно - на одной машине, или нет) есть вероятность блокировки передающего процесса. Все потому, что надо кому-то блокироваться в ожидании события (иной способ - опрос очереди событий, но это системно зависимо и вообще - см. доки). В случае асинхронного IO блокироваться будет другой поток. Тоже самое будет, если ты передашь (любым способом) данные в другой поток, а тот тупо сделает блокируемую запись.
« Последнее редактирование: 08-04-2009 18:49 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 08-04-2009 19:01 » 

с файлом мне не очень удобно, а передаётся данных за один раз немного - максимум 100-200 байт. Пока оставлю так, там увидим )
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 08-04-2009 19:06 » 

а в STL есть реализация FIFO стека ? Я вот свой написал, но может там уже есть готовое
Код:
#pragma once

#include <afxmt.h>

//для класса T должен быть определён оператор присваивания =
template <class T>
class CStackFIFO
{
struct s_soul
{
DWORD m_dwdCountMax;
DWORD m_dwdCountCur;
T* m_pBegin;//первый положенный элемент
T* m_pEmpty;//первый свободный элемент
T* m_pArray;
const T* m_pArrayEnd_p1;
}m_soul;
CCriticalSection m_crit;

public:
CStackFIFO()
{
::memset(&m_soul,0,sizeof(m_soul));
}

CStackFIFO(DWORD dwdLen_in)
{
::memset(&m_soul,0,sizeof(m_soul));
Create(dwdLen_in);
}

void ClearContent()
{
m_crit.Lock();
{
if(m_soul.m_pArray)
{
m_soul.m_dwdCountCur=0;
m_soul.m_pBegin=m_soul.m_pArray;
m_soul.m_pEmpty=m_soul.m_pArray;
}
}
m_crit.Unlock();

}

bool IsCreated()
{
bool bResult=false;

m_crit.Lock();
{
for(;;)
{
if(!m_soul.m_pArray)break;
if(!m_soul.m_dwdCountMax)break;
bResult=true;
break;
}
}
m_crit.Unlock();

return bResult;
}

~CStackFIFO()
{
Destroy();
}

void Destroy()
{
m_crit.Lock();
{
if(m_soul.m_pArray)
{
delete [] m_soul.m_pArray;
m_soul.m_pArray=0;
}
::memset(&m_soul,0,sizeof(m_soul));
}
m_crit.Unlock();
}

bool Create(DWORD dwdLen_in, bool RedimIfAlreadyCreated=false)
{
bool bResult=false;

m_crit.Lock();
{
for(;;)
{
if(m_soul.m_pArray)
{
if(RedimIfAlreadyCreated)
{
CStackFIFO tmpSt;
T t;

if(!tmpSt.Create(dwdLen_in))break;

//копируем первые элементы (начиная с m_pBegin)


while(Pop(t))
{
if(!tmpSt.Push(t))break;
}

//мочим
Destroy();

//переселение душ
::memmove(&m_soul,&tmpSt.m_soul,sizeof(m_soul));
::memset(&tmpSt.m_soul,0,sizeof(tmpSt.m_soul));
//теперь tmpSt - пуст, в его деструкторе ничего не удалится

bResult=true;
}
}
else
{
if(dwdLen_in)
{
m_soul.m_pArray=new T[dwdLen_in];
if(m_soul.m_pArray)
{
m_soul.m_dwdCountMax=dwdLen_in;
m_soul.m_dwdCountCur=0;
m_soul.m_pBegin=m_soul.m_pArray;
m_soul.m_pEmpty=m_soul.m_pArray;
m_soul.m_pArrayEnd_p1=m_soul.m_pArray+m_soul.m_dwdCountMax;
bResult=true;
}
}

}

break;
}


}
m_crit.Unlock();

return bResult;
}

bool Push(const T& PushT)
{
return Push(&PushT);
}

bool Push(const T* pPushT)
{
bool bResult=false;

m_crit.Lock();
{
if(m_soul.m_pArray)
{
if(m_soul.m_dwdCountCur<m_soul.m_dwdCountMax)
{
if(m_soul.m_pEmpty>=m_soul.m_pArrayEnd_p1) throw;//на всяк пож

*m_soul.m_pEmpty=*pPushT;
m_soul.m_dwdCountCur++;

if(m_soul.m_pEmpty==m_soul.m_pArrayEnd_p1-1)
{
//кольцо замкнулось, переходим в начало массива
m_soul.m_pEmpty=m_soul.m_pArray;
}
else
{
m_soul.m_pEmpty++;
}
bResult=true;
}
}
}
m_crit.Unlock();

return bResult;
}

bool Pop(T& PopT)
{
bool bResult=false;

m_crit.Lock();
{
if(m_soul.m_pArray)
{
if(m_soul.m_dwdCountCur)
{
if(m_soul.m_pBegin>=m_soul.m_pArrayEnd_p1) throw;//на всяк пож

PopT=*m_soul.m_pBegin;
m_soul.m_dwdCountCur--;

if(m_soul.m_pBegin==m_soul.m_pArrayEnd_p1-1)
{
//кольцо замкнулось, переходим в начало массива
m_soul.m_pBegin=m_soul.m_pArray;
}
else
{
m_soul.m_pBegin++;
}
bResult=true;
}
}
}
m_crit.Unlock();

return bResult;
}
};

тест
Код:
	CString txt;

CStackFIFO<CString> myFIFO(30);
if(myFIFO.IsCreated())
{
myFIFO.Destroy();
}

myFIFO.Create(20);
if(myFIFO.IsCreated())
{
myFIFO.Destroy();
}

myFIFO.Create(15);
if(myFIFO.IsCreated())
{
myFIFO.Create(10);

myFIFO.Create(10,true);

myFIFO.Create(15,true);

myFIFO.Create(5,true);

myFIFO.Destroy();
}

myFIFO.Create(15);
if(myFIFO.IsCreated())
{
myFIFO.Create(5,true);

txt="1";myFIFO.Push(txt);
txt="2";myFIFO.Push(txt);
txt="3";myFIFO.Push(txt);
txt="4";myFIFO.Push(txt);
txt="5";myFIFO.Push(txt);
txt="6";myFIFO.Push(txt);

myFIFO.Create(10,true);

myFIFO.Create(3,true);

myFIFO.Destroy();
}

myFIFO.Create(15);
if(myFIFO.IsCreated())
{
myFIFO.Create(5,true);

txt="1";myFIFO.Push(txt);
txt="2";myFIFO.Push(txt);
txt="3";myFIFO.Push(txt);
txt="4";myFIFO.Push(txt);
txt="5";myFIFO.Push(txt);
txt="6";myFIFO.Push(txt);

myFIFO.Pop(txt);
myFIFO.Pop(txt);
myFIFO.Pop(txt);
txt="7";myFIFO.Push(txt);
txt="8";myFIFO.Push(txt);
txt="9";myFIFO.Push(txt);
txt="10";myFIFO.Push(txt);

myFIFO.Pop(txt);
myFIFO.Pop(txt);
myFIFO.Pop(txt);
myFIFO.Pop(txt);
myFIFO.Pop(txt);
myFIFO.Pop(txt);

myFIFO.Create(10,true);

myFIFO.Create(3,true);

myFIFO.Destroy();
}

int iii=1;


« Последнее редактирование: 08-04-2009 20:13 от Алексей1153++ » Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 08-04-2009 20:23 » 

std::queue
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 08-04-2009 20:35 » 

спасибо

Код:
template <
   class Type,
   class Container = deque<Type>
>
class queue

только я не понял назначение параметра "class Container = deque<Type>"
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 09-04-2009 04:10 » 

Алексей1153++, и не забудь мутекс.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 09-04-2009 04:26 » 

Ром, я критическую секцию применил, у меня всё в одном процессе происходит
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #18 : 09-04-2009 06:28 » 

Цитата
только я не понял назначение параметра "class Container = deque<Type>"
Это какой класс-контейнер ты хочеш использовать. По умолчанию deque, Основное отличие от vector, то что можно вставлять и удалять не только концовку массива, но и  начало массива.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 09-04-2009 06:36 » 

Это какой класс-контейнер ты хочеш использовать. По умолчанию deque, Основное отличие от vector, то что можно вставлять и удалять не только концовку массива, но и  начало массива.
В связи с возможностью вставки в начало deque имеет ещё одно ключевое отличие: у вектора все объекты помещаются в один непрерывный массив, который по мере необходимости автоматически увеличивается (обычно вдвое) и переразмещается; deque же работает с набором блоков, и при необходимости выделяет ещё один. Поэтому deque экономнее по памяти и не копирует всю начинку при необходимости увеличить размер массива. Но зато random-access уже не гарантируется никакого (в смысле, не получится использовать, как порой используют вектор: получить указатель на начальный элемент и работать с буфером напрямую).
Для queue - в самый раз, т.к. deque обычно рекомендуют использовать вместо vector в случаях, когда требуется частая вставка в начало и конец, и удаление оттуда, и не требуется произвольный доступ.
« Последнее редактирование: 09-04-2009 06:38 от Вад » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines