Вверх ↑
Этот топик читают: Гость
Ответов: 9906
Рейтинг: 351
#16: 2008-07-05 10:59:44 ЛС | профиль | цитата
nesco писал(а):
Тут вопрос другого плана, как синхронизировать приложения при изменении данных

Нет этого вопроса.
Как обычно, для разных потоков работающими одними и теми же данными.
На то метод и низкоуровневый, что работа с данными - отдельно, синхронизация, если надо - отдельно, послать сигнал, если надо - отдельно.
Послать сигнал, это Events.doSet, дождаться сигнала - WaitObject.doWait
Про синхронизацию - уже говорил... Только нарисовать его могу еще: code_9388.txt
Конечно мьютекс для этого надо дорабатывать, под его штатное использование

И не надо строить самому высокоуровневое средство из низкоуровневых (очередной процессор, грубо говоря)
Низкоуровневые средства и нужны для того, что бы пользователь сам построил то, что в его конкретной задаче удобнее (ты этого никогда не узнаешь) и быстрее.

Или выбрал виндячее высокоуровневое
карма: 9

0
файлы: 1code_9388.txt [4.6KB] [469]
Разработчик
Ответов: 26170
Рейтинг: 2127
#17: 2008-07-05 11:42:03 ЛС | профиль | цитата
Galkov писал(а):
Послать сигнал, это Events.doSet, дождаться сигнала - WaitObject.doWait

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

------------ Дoбавленo:


Galkov писал(а):
как обычно, для разных потоков работающими одними и теми же данными

В том и ценность этого метода, что не надо синхорнизировать потоки. Открывая файл, делается еще одна копия данных. Не нужны там никакие мьютексы, система сама синхронизирует доступ к файлу.
карма: 22

0
Ответов: 2125
Рейтинг: 159
#18: 2008-07-05 11:52:57 ЛС | профиль | цитата
nesco, назови компонент SharedMemory (или даже SharedStream), и опционально - сохранение этого дела в файле, т.е. чтобы содержимое не потерялось от запуска к запуску. Имя этого SharedStream в системе - тоже опционально, и если оно есть, то сначала попытаться открыть отображение с таким именем (получится, либо работаем с существующим файлом, даже не зная его имени, либо с виртуальным файлом, если имя файла не задано).
------------ Дoбавленo:

nesco писал(а):
А как будет отрабатываться это безобразие в сервисах, ведь там нет отработки сообщений

Мютексы никаким боком не стоят вместе с обработкой сообщений. Это, грубо говоря - глобальная переменная, чтение/запись которой будет делать грантированно только один процесс/поток.

nesco писал(а):
Не нужны там никакие мьютексы, система сама синхронизирует доступ к файлу.

А вот это не факт. Ты можешь обрабатывать разные участки файла, и если не заблокировать доступ, ты можешь обработать старые данные в одной области и новые в другой, а это не всегда правильно. Тут надо транзакциями работать, т.е. после начала транзакции ты имеешь либо данные до начала транзакции, либо тобой записанные, и вмешательства извне исключены.
карма: 1

0
Разработчик
Ответов: 26170
Рейтинг: 2127
#19: 2008-07-05 14:30:46 ЛС | профиль | цитата
tsdima писал(а):
опционально - сохранение этого дела в файле, т.е. чтобы содержимое не потерялось от запуска к запуску

Содержимое не теряется от запуска к запуску, пока не закрою проекцию файла, хоть тыщу раз запускай.

tsdima писал(а):
Мютексы никаким боком не стоят вместе с обработкой сообщений

А где это ты видел, что бы я это писал
Вопрос был задан вот на это
Galkov писал(а):
Послать сигнал, это Events.doSet, дождаться сигнала - WaitObject.doWait


tsdima писал(а):
Тут надо транзакциями работать, т.е. после начала транзакции ты имеешь либо данные до начала транзакции, либо тобой записанные, и вмешательства извне исключены

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

------------ Дoбавленo:


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

------------ Дoбавленo:


tsdima писал(а):
либо с виртуальным файлом, если имя файла не задано

Ему все равно имя и класс нужно присвоить и к нему обращаться по его имени или классу

------------ Дoбавленo:


Все хорошо, но вот зачем нам это нужно для файлов, я не понимаю, особенно для больших -- никакой выгоды не получается. Читаем Рихтера (пример одного алгоритма)

Рихтер писал(а):
Этот алгоритм проецирует представления по 64 Кб (в соответствии с гранулярностью выделения памяти) или менее. Кроме того, функция MapViewOfFile требует, чтобы передаваемое ей смещение в файле тоже было кратно гранулярности выделения памяти. Подпрограмма проецирует на адресное пространство сначала одно представление, подсчитывает в нем количество нулей, затем переходит к другому представлению, и все повторяется. Спроецировав и просмотрев все 64-килобайтовые блоки, подпрограмма закрывает объект "проекция файла".


и перед самим примером

Рихтер писал(а):
Я обещал рассказать, как спроецировать на небольшое адресное просранство файл длиной 16 экзабайтов. Так вот, этого сделать нельзя. Вам придется проецировать не весь файл, а его представление, содержащее лишь некую часть данных. Вы начнете с того, что спроецируете представление самого начала файла. Закончив обработку данных в этом представлении, Вы отключите его и спроецируете представление следующей части файла — и так до тех пор, пока не будет обработан весь файл. Конечно, это делает работу с большими файлами, проецируемыми в память, не слишком удобной, но утешимся тем, что длина большинства файлов достаточно мала


Какую от всего этого мы получим выгоду Я хотел использовать эту фичу для обмена данными между приложениями, блоками по размеру меньше гранулярности (до 64 кб), и совершенно не для физических файлов, те именно создать простой сервер/клиент по типу PIPE, но гораздо проще и не зависящий от передачи оконных сообщений

------------ Дoбавленo:


Вот, что я хотел сделать применительно к HiAsm'y

Рихтер писал(а):
Эта программа, "17 MMFShare.exe" (см. листинг на рис. 17-3), демонстрирует, как происходит обмен данными между двумя и более процессами с помощью файлов, проецируемых в память. Файлы исходного кода и ресурсов этой программы находятся в каталоге 17-MMFShare на компакт-диске, прилагаемом к книге.

Чтобы понаблюдать за происходящим, нужно запустить минимум две копии MMFShare. Каждый экземпляр программы создаст свое диалоговое окно.

Чтобы переслать данные из одной копии MMFShare в другую, наберите какой нибудь текст в поле Data. Затем щелкните кнопку Create Mapping Of Data. Программа вызовет функцию CreateFileMapping, чтобы создать объект "проекция файла" размером 4 Кб и присвоить ему имя MMFSharedData (ресурсы выделяются объекту из страничного файла). Увидев, что объект с таким именем уже существует, программа выдаст сообщение, что не может создать объект. А если такого объекта нет, программа создаст объект, спроецирует представление файла на адресное пространство процесса и скопирует данные из поля Data в проецируемый файл.

Далее MMFShare прекратит проецировать представление файла, отключит кнопку Create Mapping Of Data и активизирует кнопку Close Mapping Of Data. На этот момент проецируемый в память файл с именем MMFSharedData будет просто "сидеть" где-то в системе. Никакие процессы пока не проецируют представление на данные, содержащиеся в файле.

Если Вы теперь перейдете в другую копию MMFShare и щелкнете там кнопку Open Mapping And Get Data, программа попытается найти объект "проекция файла" с именем MMFSharedData через функцию OpenFileMapping, Если ей не удастся найти объект с таким именем, программа выдаст соответствующее сообщение. В ином случае она спроецирует представление объекта на адресное пространство своего процесса и скопирует данные из проецируемого файла в поле Data. Вот и все! Вы переслали данные из одного процесса в другой

Кнопка Close Mapping Of Data служит для закрытия объекта "проекция файла", что высвобождает физическую память, занимаемую им в страничном файле. Если же объект "проекция файла" не существует, никакой другой экземпляр программы MMFShare не сможет открыть зтот объект и получить от него данные. Кроме того, если один экземпляр программы создал объект "проекция файла", то остальным повторить его создание и тем самым перезаписать данные, содержащиеся в файле, уже не удастся.

карма: 22

0
Ответов: 9906
Рейтинг: 351
#20: 2008-07-05 14:33:11 ЛС | профиль | цитата
nesco, мы читали
карма: 9

0
Разработчик
Ответов: 26170
Рейтинг: 2127
#21: 2008-07-11 10:39:18 ЛС | профиль | цитата
Galkov писал(а):
мы читали

То, что ты читал, я не сомневаюсь, но другие может и не читали, пусть почитают

------------ Дoбавленo:


Вот, соорудил -- ver 1.00

Проверил на своем комплексе -- работает устойчиво, мало весит и прост в применении. Данные передавались от одного приложения другому.
Сервисы еще не сооружал, но хочу попробовать, должен работать.
Максимальный размер передаваемых данных за одну сессию -- 4 байта размер данных + 65532 байтов данных
карма: 22

0
файлы: 1project_mmf_1_00.zip [8.3KB] [320]
Администрация
Ответов: 15295
Рейтинг: 1519
#22: 2008-07-14 13:52:10 ЛС | профиль | цитата
с учетом того, что в данном случае физически сервер ничем по функциональности не отличается от клиента дествительно стоило делать один элемент.
карма: 27
0
Ответов: 9906
Рейтинг: 351
#23: 2008-07-14 13:55:58 ЛС | профиль | цитата
Dilma, он ведь еще и третий в голове держит - для файлов

карма: 9

0
Разработчик
Ответов: 26170
Рейтинг: 2127
#24: 2008-07-14 14:09:31 ЛС | профиль | цитата
Galkov, вообще-то я его по аналогии с Mail делал, он такого же принципа, да и бета версия это, чисто для предложений.
Ты бы мне лучше другое сказал, какого черта в сервере Move жрет ресурс, как списанный, и никакими коврижками не удается его стабилизировать, складывается впечатление, что каждое обращение к FileMap'y создает новую копию

------------ Дoбавленo:


Galkov писал(а):
возможно, пользоваться

До этого еще очень далеко

------------ Дoбавленo:


Galkov писал(а):
Size:integer

А почему integer, это же только 4 Гб, лучше, наверное -- целочисленное Real c внутренним преобразованием в int64

------------ Дoбавленo:


Galkov писал(а):
Имеет левые точки
1) doOpen
2) doClose

А команду на чтение или запись, разве не надо
------------ Дoбавленo:

Galkov писал(а):
Дайте мне поручение, а уж особым -- я его и сам как-нибудь сделаю


Вот тут надо, я сам навязался, и никто мне ничего не давал
карма: 22

0
Ответов: 9906
Рейтинг: 351
#25: 2008-07-14 15:01:32 ЛС | профиль | цитата
nesco писал(а):
вообще-то я его по аналогии с Mail делал

Вообще-то, надо было по аналогии с MemoryStream и FileStream делать.
Если уж оно на той же вкладке расположено.
FilleStream - для "коротких" файлов
MemoryStream - блок памяти
Это - либо кадр "длинного" файла, либо блок памяти, но, глобально видимый

Вообще-то, ЛЮБОЙ блок памяти, это тоже файл, просто он показывает в pagefile.sys.
При указании имени конкретного файла - просто экономится место в нем (в pagefile.sys), вот и вся великая разница.


nesco писал(а):
А почему integer, это же только 4 Гб, лучше, наверное -- целочисленное Real c внутренним преобразованием в int64

Буквари-то читать внимательней надо...
1) Вообще-то 2Г - винда верхние 2Г для своих нужд использует, и тебе их никогда не даст
2) Какой размер у dwNumberOfBytesToMap (последний аргумент в MapViewOfFile), по твоему


nesco писал(а):
А команду на чтение или запись, разве не надо

А как по твоему без этих команд обходятся MemoryStream и FileStream


nesco писал(а):
и никто мне ничего не давал

Это, между прочим, была цитата.
Фраза господина Мерзляева (или Мерзяева) в исполнении Олега Бассилашвили



Вон, оказывается тебе коллега tsdima, все уже сто раз растолковал, да и я уже по третьему кругу иду, кажется...
И имя ему, соответствующее функциональности, уже придумано:
tsdima писал(а):
nesco, назови компонент SharedMemory (или даже SharedStream)

карма: 9

0
Разработчик
Ответов: 26170
Рейтинг: 2127
#26: 2008-07-14 15:23:03 ЛС | профиль | цитата
Galkov писал(а):
Буквари-то читать внимательней надо...

Между прочим, в Рихтере вот что написано

Рихтер писал(а):
Остальные три параметра относятся к резервированию региона адресного пространства и к отображению на него физической памяти. При этом необязательно проецировать на адресное пространство весь файл сразу. Напротив, можно спроецировать лишь малую его часть, которая в таком случае называется представлением (view) — теперь-то Вам, наверное, понятно, откуда произошло название функции MapViewOfFile

Проецируя на адресное пространство процесса представление файла, нужно сделать две вещи. Во-первых, сообщить системе, какой байт файла данных считать в представлении первым. Для этого предназначены параметры dwFileOffsetHigh и dwFileOffsetLow. Поскольку Windows поддерживает файлы длиной до 16 экзабайтов, приходится определять смещение в файле как 64 разрядное число старшие 32 бита передаются в параметре dwFileOffsetHigh, а младшие 32 бита — в параметре dwFileOffsetLow. Заметьте, что смещение в файле должно быть кратно гранулярности выделения памяти в данной системе. (В настоящее время во всех реализациях Windows она составляет 64 Кб.)

------------ Дoбавленo:

Тут надо определится с тем, что мы хотим делать, если иметь просто файл в памяти, то это одни параметры, а если проекцию внешнего файла, то совершенно другие
карма: 22

0
Ответов: 9906
Рейтинг: 351
#27: 2008-07-14 16:05:21 ЛС | профиль | цитата
nesco писал(а):
Тут надо определится с тем, что мы хотим делать, если иметь просто файл в памяти, то это одни параметры, а если проекцию внешнего файла, то совершенно другие

Начинай читать все заново, блин

"Просто файл в памяти", и "проекция внешнего файла" - ЭТО ОДНО И ТОЖЕ

Мне, лично, все просто и понятно
И, у меня лично, эта определенность есть давно.
Судя по написанному tsdima - не только у меня.

Нужен элемент, по имени SharedStream, который пользователь видит в <Палитре Элементов> рядом с MemoryStream и FileStream, и пользуется ими совершенно одинаково - с помощью элемента DataToFile (а я еще и DataToFileEx)
Даже точки и св-ва этого элемента - в основном перечислены
Galkov писал(а):

  • Имеет св-ва 1) FileName:sting
    2) CoreName:string
    3) Offset:real
    4) Size:integer
  • Имеет левые точки 1) doOpen
    2) doClose
  • Имеет верхние точки в соответствии со св-ми по желанию
  • Имеет нижнюю точку Stream ((ну может +еще и Memory - аля в MemoryStream))
    И все

  • С чем еще надо определяться - не пойму
    Все просто как электровеник

    ------------ Дoбавленo:

    Вот же ж блин, свой пост затер....
    ------------ Дoбавленo:

    Кстати, говоря, Stream - это один из тех самых "хэндлов", по которые Dilma втолковывал тебе, что они совершенно не обязаны иметь отношение к виндячему окну, и который позволяет не ходить вокруг элемента "целыми пачками связей"

    карма: 9

    0
    Разработчик
    Ответов: 26170
    Рейтинг: 2127
    #28: 2008-07-14 16:18:58 ЛС | профиль | цитата
    Galkov писал(а):
    Мне, лично, все просто и понятно

    Что совсем не означает, что понятно другим
    Galkov писал(а):
    И, у меня лично, эта определенность есть давно.

    Ну, с чем тебя и поздравляю

    Galkov писал(а):
    Нужен элемент, по имени SharedStream

    Еще раз, для тех, кто в бронепоезде -- типа, нужна общая проекция какого либо файла, присоединенного или созданного в памяти (последний фиг может быть больше 64 кб, сколько ни пытался, не дает создать больше), к котрому можно без линков обращаться как к общему ресурсу по имени CoreName, так я понял, или не так
    карма: 22

    0
    Ответов: 9906
    Рейтинг: 351
    #29: 2008-07-14 17:56:55 ЛС | профиль | цитата
    nesco писал(а):
    Ну, с чем тебя и поздравляю

    Ты забыл привести еще несколько цитат.
    Galkov писал(а):
    Судя по написанному tsdima - не только у меня.

    Galkov писал(а):
    Вон, оказывается тебе коллега tsdima, все уже сто раз растолковал, да и я уже по третьему кругу иду, кажется...
    И имя ему, соответствующее функциональности, уже придумано:
    tsdima писал(а):
    nesco, назови компонент SharedMemory (или даже SharedStream)

    Ну это так, на всякий случай, чтобы иронией не захлебнуться....


    nesco писал(а):
    последний фиг может быть больше 64 кб, сколько ни пытался, не дает создать больше

    
    #sha
    Add(MainForm,11176470,49,49)
    {
    Left=20
    Top=105
    Width=527
    link(onCreate,2797906:doLoad,[])
    }
    Add(RichEdit,2797906,168,42)
    {
    Left=10
    Top=35
    Width=495
    Height=225
    Align=5
    FileName=".\compiler\Fpc\kol.pas"
    ScrollBars=3
    }
    Add(InlineCode,2371655,224,105)
    {
    WorkPoints=#7:doWrite|6:doRead|
    EventPoints=#6:onRead|
    Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses windows,kol,Share,Debug;|0:|4:type|28: THiAsmClass = class(TDebug)|10: private|18: hMMF:THandle;|16: Data:PChar;|9: public|22: onRead:THI_Event;|24: constructor Create;|33: destructor Destroy;override;|47: procedure doWrite(var _D:TData; idx:word);|46: procedure doRead(var _D:TData; idx:word);|5: end;|0:|14:implementation|0:|31:constructor THiAsmClass.Create;|5:begin|104: hMMF := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, 10000000, 'MySuperPuperName');|62: Data := MapViewOfFile(hMMF, FILE_MAP_WRITE, 0, 0, 10000000);|4:end;|0:|31:destructor THiAsmClass.Destroy;|5:begin|24: UnmapViewOfFile(Data);|20: CloseHandle(hMMF);|4:end;|0:|30:procedure THiAsmClass.doWrite;|24:var s:string; i:integer;|5:begin|21: s := ToString(_D); |17: i := length(s);|20: Move(i,Data[0],4);|23: Move(s[1],Data[4],i);|4:end;|0:|29:procedure THiAsmClass.doRead;|24:var s:string; i:integer;|5:begin|20: Move(Data[0],i,4);|17: SetLength(s,i);|23: Move(Data[4],s[1],i);|32: _hi_CreateEvent(_D,@onRead,s);|4:end;|0:|0:|0:|4:end.|
    link(onRead,2797906:doText,[(268,111)(268,90)(156,90)(156,62)])
    }
    Add(Menu,9436858,49,98)
    {
    Menu=#5:Write|4:Read|
    Point(onSelectNum)
    link(onSelectNum,12401350:doEvent,[])
    }
    Add(IndexToChanel,12401350,112,105)
    {
    link(onEvent1,2298906:doData,[])
    link(onEvent2,2371655:doRead,[])
    }
    Add(DoData,2298906,168,105)
    {
    link(onEventData,2371655:doWrite,[])
    link(Data,2797906:Text,[])
    }
    1) Делаю запуск схемы - получаю полный KOL
    2) Делаю запуск второй копии - получаю тоже полный KOL
    3) Во второй делаю Read - получаю пустой текст
    4) В первой делаю Write
    5) Во второй снова делаю Read - и снова получаю полный KOL

    Вроде он побольше, чем 64К будет.
    Вывод: не морочь людям голову про 64К
    И кстати, для для тех кто в бронепоезде: размер аллокации квантуется по 4К

    nesco писал(а):
    типа, нужна общая проекция какого либо файла, присоединенного или созданного в памяти (

    Вообще-то, типа нужен элемент, воспринимаемый пользователем так же как и MemoryStream/FileStream, но обладающий небольшими фишками:
    1) Глобальной видимостью из других процессов
    2) Возможностью (не обязательной) связать его с куском терабайтного файла

    Один такой элемент, и все.
    Не надо больше ничего.
    Уже даже точки и св-ва ему написали....
    И не надо сочинять за меня какие-то "протоколы обмена"

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


    карма: 9

    0
    Разработчик
    Ответов: 26170
    Рейтинг: 2127
    #30: 2008-07-14 19:02:56 ЛС | профиль | цитата
    Galkov писал(а):
    Все, на самом деле, гораздо проще и понятней, чем оно у тебя в голове есть.

    Ну, может оно так и есть, все пытаюсь себе задачу усложнить.

    ------------ Дoбавленo:


    Galkov писал(а):
    1) Глобальной видимостью из других процессов
    2) Возможностью (необязательной) связать его с куском терабайтного файла

    Ну вот, дошли и до того, что конкретно надо.

    А какого размера буфер предусматривать, фиксированный ( у тебя в примере, вроде 10000000) или переменный, или выбирать его из списка


    карма: 22

    0
    Сообщение
    ...
    Прикрепленные файлы
    (файлы не залиты)