Создать копию очереди

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
NewUser
Старожил
Сообщения: 238
Зарегистрирован: 10 Ноябрь 2005, 23:07
Откуда: Краснодар
Благодарил (а): 6 раз

Создать копию очереди

Сообщение NewUser »

Здравствуйте, коллеги!
Впервые столкнулся с задачей клонирования очереди.
Имеется некая глобальная очередь, например, BasicQueue.
В отдельной процедуре нужна ее полная копия. Пользуясь документацией по языку сделал (в этой процедуре) следующее:
- в секции данных:
NewQueue &BasicQueue !запрототипировал
- в секции CODE:
NewQueue &= NEW(BasicQueue) !создал копию по образу и подобию
NewQueue &= BasicQueue !скопировал содержимое
Все ли правильно я сделал?
Если да, то почему:
- программа виснет при попытке освободить память оператором Dispose(NewQueue)
- при очистке BasicQueue очищается и NewQueue?
Если нет, то где мой затык в понимании работы с данным механизмом клонирования?
С6.3 ABC
kreator
✯ Ветеран ✯
Сообщения: 5190
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 11 раз
Поблагодарили: 26 раз

Создать копию очереди

Сообщение kreator »

NewUser писал(а):NewQueue &= BasicQueue !скопировал содержимое
Эта строчка - не копирование. Вы просто адреса совместили и всё, физически очередь осталась одна. Надо сделать честно, оно же тупо. Создать две очереди и в цикле по одной добавить во вторую. К сведению, есть оператор присвоения всей записи:

Код: Выделить всё

LOC:Queue2 :=: LOC:Queue1
Кажется, так. уточните. Но, опять же, копируется только одна запись, а не вся очередь.
We are hard at work… for you. :)
NewUser
Старожил
Сообщения: 238
Зарегистрирован: 10 Ноябрь 2005, 23:07
Откуда: Краснодар
Благодарил (а): 6 раз

Создать копию очереди

Сообщение NewUser »

kreator писал(а): Создать две очереди и в цикле по одной добавить во вторую
Я так всю свою кларионовскую жизнь и делал.
Но сейчас назревающая проблема в том, что таких очередей предвидеться много с одной стороны, и нет четкого понимания структуры исходной очереди - с другой.
Аватара пользователя
Admin
Администратор
Сообщения: 4011
Зарегистрирован: 05 Июль 2005, 15:59
Откуда: Хабаровск
Благодарил (а): 53 раза
Поблагодарили: 33 раза
Контактная информация:

Создать копию очереди

Сообщение Admin »

NewUser писал(а): Но сейчас назревающая проблема в том, что таких очередей предвидеться много с одной стороны, и нет четкого понимания структуры исходной очереди - с другой.
Задачу бы немного описали. Может народ что другое подскажет. Память тоже не резиновая :)
Рай совершает ошибки ничуть не реже чем ад. Просто у него хорошая пресса
NewUser
Старожил
Сообщения: 238
Зарегистрирован: 10 Ноябрь 2005, 23:07
Откуда: Краснодар
Благодарил (а): 6 раз

Создать копию очереди

Сообщение NewUser »

Во-первых, спасибо kreator за указание на ошибку!

И, в самом деле, может возможно решить задачу по-иному, нежели так, как это видеться в моей голове. :)
Имеется процедура, результатом которой является глобальная очередь выходных данных.
Также есть непредвиденное заранее количество процедур, которые обращаются к выше описанной процедуре и, после формирования очередной версии очереди выходных данных, используют эти данные в своих целях.
Кстати, вопрос: возможна ли при таком подходе конфликтная ситуация, возникающая при одновременном обращении к процедуре, формирующей исходную очередь данных?
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Создать копию очереди

Сообщение Yufil »

Если процедуры могут выполняться одновременно (в разных тредах), то да. Всякие манипуляции с глобальной очередью должны блокироваться через критические секции-мьютексы-семафоры...
NewUser
Старожил
Сообщения: 238
Зарегистрирован: 10 Ноябрь 2005, 23:07
Откуда: Краснодар
Благодарил (а): 6 раз

Создать копию очереди

Сообщение NewUser »

Так и есть. Вызываются из разных тредов.
А не могли бы прояснить как правильней/легче реализовать эту самую блокировку через "критические секции-мьютексы-семафоры..." средствами C6.3 ABC?
NewUser
Старожил
Сообщения: 238
Зарегистрирован: 10 Ноябрь 2005, 23:07
Откуда: Краснодар
Благодарил (а): 6 раз

Создать копию очереди

Сообщение NewUser »

Я бы сделал так.
Завел бы глобальную переменную-флаг, показывающую факт формирования глобальной очереди. Например, GLO:MakedQueue
В начале процедуры, формирующей эту очередь, присваивал бы ей GLO:MakedQueue = 1
После завершения: GLO:MakedQueue = 0
При обращении к данной процедуре проверял бы эту переменную в цикле.
Например:

Код: Выделить всё

Loop
   IF Not GLO:MakedQueue
      BasicQueueProcedure
      Break
   END    	  
End  
Или присвоение GLO:MakedQueue = 1 лучше сделать в вызывающей процедуре?
С учетом того, данные для формирования очереди рассчитываются практически мгновенно, это должно работать и работать быстро.
kreator
✯ Ветеран ✯
Сообщения: 5190
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 11 раз
Поблагодарили: 26 раз

Создать копию очереди

Сообщение kreator »

Не очень понял, конечно, задачу. Но зачем использовать глобальную очередь? А, во-вторых, можно поставить на неё флаг "Thread", что автоматически означает новую копию (???). Вообще, чем проще схема, тем лучше работает программа :) .
We are hard at work… for you. :)
NewUser
Старожил
Сообщения: 238
Зарегистрирован: 10 Ноябрь 2005, 23:07
Откуда: Краснодар
Благодарил (а): 6 раз

Создать копию очереди

Сообщение NewUser »

kreator писал(а): Вообще, чем проще схема, тем лучше работает программа
И я о том же!
Не очень понял, конечно, задачу.
А что именно не понятно? Несколькими постами ниже я, как мне кажется, её подробно описал. В том числе и зачем глобальная очередь. Она, по моему соображению, нужна для совместного её использования другими процедурами. Предлагаете перестроить архитектуру программы под другую реализацию описанного процесса? Тогда как?
И еще вопрос.
можно поставить на неё флаг "Thread", что автоматически означает новую копию
Исходя из того, что процедур, вызывающих процедуру, формирующую данную глобальную очередь, много, то как быть с разрастающимся количеством этих самых копий?
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Создать копию очереди

Сообщение Yufil »

NewUser писал(а): Я бы сделал так.
После завершения: GLO:MakedQueue = 0
При обращении к данной процедуре проверял бы эту переменную в цикле.
Например:

Код: Выделить всё

Loop
   IF Not GLO:MakedQueue
      BasicQueueProcedure
      Break
   END    	  
End  
Или присвоение GLO:MakedQueue = 1 лучше сделать в вызывающей процедуре?
С учетом того, данные для формирования очереди рассчитываются практически мгновенно, это должно работать и работать быстро.
Не прокатит. Другая задача может вклиниться между установкой флажка и чтением очереди

В качестве примера
- задача 1 установила флажок, чтобы читать очередь
- задача 2 закончила чтение и сбросила флажок
- задача 1 крутится в цикле, жрёт процессор и нифига не делает.
- задача 2 установила флажок
- очередь одновременно читается задачами 1 и 2

У меня в реальной программе (скорее всего, накрутил лишнего, но работает )

Код: Выделить всё

CloseQ:Q             QUEUE,PRE(CloseQ)
Npp                    LONG
Thread                 LONG
Type                   CSTRING(10)
Executable             CSTRING(260)
                     END

CloseQ:Mutex         &IMutex
                     .....                     
                     CloseQ:Mutex &= NewMutex()  ! Инициализация один раз в начале программы 
                     ..... 
!  Добавление записи в очередь 
            CloseQ:Mutex.Wait()
            CloseQ:PlanStep+=1
            CloseQ:Npp  = CloseQ:PlanStep
            CloseQ:Type = 'SCR'
            CloseQ:Thread = Thread# 
            Add(CloseQ:Q,1)
            CloseQ:Mutex.Release()

!  Удаление записи из очереди 
       CloseQ:Mutex.Wait()
       CloseQ:Thread = Thread()
       Get(CloseQ:Q, CloseQ:Thread)
       if ~ErrorCode()
         Delete(CloseQ:Q)
       End
       CloseQ:Mutex.Release()
                     
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3306
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 15 раз
Поблагодарили: 51 раз
Контактная информация:

Создать копию очереди

Сообщение Дед Пахом »

Проще заполнять не глобальную очередь, а очередь, переданную в процедуру в качестве параметра.
С уважением, ДП
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Создать копию очереди

Сообщение Yufil »

Всяко бывает. Например, в головном окне сидит планировщик, который создаёт список заданий. А другие треды эти задания исполняют.
kreator
✯ Ветеран ✯
Сообщения: 5190
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 11 раз
Поблагодарили: 26 раз

Создать копию очереди

Сообщение kreator »

NewUser писал(а):Кстати, вопрос: возможна ли при таком подходе конфликтная ситуация, возникающая при одновременном обращении к процедуре, формирующей исходную очередь данных?
Я не понимаю вот это. Если пользователь работает, то он не может одновременно работать в двух процедурах. Если есть какие-то процессы, которые выполняются одновременно, и ещё они могут передавать управление другим процессам, то да, наверно, возможно. Но что это за задача? В Кларионе тяжеловато (на мой взгляд) сделать независимые процессы с равным "приоритетом". Может я не прав, пусть народ поправит.
We are hard at work… for you. :)
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Создать копию очереди

Сообщение Yufil »

Хрен его знает, сейчас просмотрел приложение - а там аж четыре таких очереди.
Например, хотим запретить одновременное открытие одного документа в нескольких окнах
Создаём очередь - "код документа+тред" (список кодов открытых документов в разных тредах). Хочем мы открыть документ - ищем его код в очереди, если он уже открыт, достаточно окно вперёд вытащить. Закрываем окно - убираем документ из списка. Типичная ситуация - открываем новый документ и тут же закрываем старый. Вроде бы всё правильно, но что будет с этой очередью ? Вот...
Ответить