Страница 1 из 3

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

Добавлено: 31 Март 2016, 9:16
NewUser
Здравствуйте, коллеги!
Впервые столкнулся с задачей клонирования очереди.
Имеется некая глобальная очередь, например, BasicQueue.
В отдельной процедуре нужна ее полная копия. Пользуясь документацией по языку сделал (в этой процедуре) следующее:
- в секции данных:
NewQueue &BasicQueue !запрототипировал
- в секции CODE:
NewQueue &= NEW(BasicQueue) !создал копию по образу и подобию
NewQueue &= BasicQueue !скопировал содержимое
Все ли правильно я сделал?
Если да, то почему:
- программа виснет при попытке освободить память оператором Dispose(NewQueue)
- при очистке BasicQueue очищается и NewQueue?
Если нет, то где мой затык в понимании работы с данным механизмом клонирования?
С6.3 ABC

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

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

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

LOC:Queue2 :=: LOC:Queue1
Кажется, так. уточните. Но, опять же, копируется только одна запись, а не вся очередь.

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

Добавлено: 31 Март 2016, 10:03
NewUser
kreator писал(а): Создать две очереди и в цикле по одной добавить во вторую
Я так всю свою кларионовскую жизнь и делал.
Но сейчас назревающая проблема в том, что таких очередей предвидеться много с одной стороны, и нет четкого понимания структуры исходной очереди - с другой.

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

Добавлено: 31 Март 2016, 10:05
Admin
NewUser писал(а): Но сейчас назревающая проблема в том, что таких очередей предвидеться много с одной стороны, и нет четкого понимания структуры исходной очереди - с другой.
Задачу бы немного описали. Может народ что другое подскажет. Память тоже не резиновая :)

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

Добавлено: 31 Март 2016, 10:16
NewUser
Во-первых, спасибо kreator за указание на ошибку!

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

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

Добавлено: 31 Март 2016, 10:52
Yufil
Если процедуры могут выполняться одновременно (в разных тредах), то да. Всякие манипуляции с глобальной очередью должны блокироваться через критические секции-мьютексы-семафоры...

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

Добавлено: 31 Март 2016, 11:14
NewUser
Так и есть. Вызываются из разных тредов.
А не могли бы прояснить как правильней/легче реализовать эту самую блокировку через "критические секции-мьютексы-семафоры..." средствами C6.3 ABC?

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

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

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

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

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

Добавлено: 31 Март 2016, 11:45
kreator
Не очень понял, конечно, задачу. Но зачем использовать глобальную очередь? А, во-вторых, можно поставить на неё флаг "Thread", что автоматически означает новую копию (???). Вообще, чем проще схема, тем лучше работает программа :) .

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

Добавлено: 31 Март 2016, 11:57
NewUser
kreator писал(а): Вообще, чем проще схема, тем лучше работает программа
И я о том же!
Не очень понял, конечно, задачу.
А что именно не понятно? Несколькими постами ниже я, как мне кажется, её подробно описал. В том числе и зачем глобальная очередь. Она, по моему соображению, нужна для совместного её использования другими процедурами. Предлагаете перестроить архитектуру программы под другую реализацию описанного процесса? Тогда как?
И еще вопрос.
можно поставить на неё флаг "Thread", что автоматически означает новую копию
Исходя из того, что процедур, вызывающих процедуру, формирующую данную глобальную очередь, много, то как быть с разрастающимся количеством этих самых копий?

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

Добавлено: 31 Март 2016, 12:09
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()
                     

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

Добавлено: 31 Март 2016, 12:10
Дед Пахом
Проще заполнять не глобальную очередь, а очередь, переданную в процедуру в качестве параметра.

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

Добавлено: 31 Март 2016, 12:22
Yufil
Всяко бывает. Например, в головном окне сидит планировщик, который создаёт список заданий. А другие треды эти задания исполняют.

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

Добавлено: 31 Март 2016, 12:29
kreator
NewUser писал(а):Кстати, вопрос: возможна ли при таком подходе конфликтная ситуация, возникающая при одновременном обращении к процедуре, формирующей исходную очередь данных?
Я не понимаю вот это. Если пользователь работает, то он не может одновременно работать в двух процедурах. Если есть какие-то процессы, которые выполняются одновременно, и ещё они могут передавать управление другим процессам, то да, наверно, возможно. Но что это за задача? В Кларионе тяжеловато (на мой взгляд) сделать независимые процессы с равным "приоритетом". Может я не прав, пусть народ поправит.

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

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