OberonCore
https://forum.oberoncore.ru/

Бывают ли Viewer-ы не в динамической памяти
https://forum.oberoncore.ru/viewtopic.php?f=2&t=6143
Страница 1 из 1

Автор:  Rifat [ Суббота, 21 Октябрь, 2017 20:02 ]
Заголовок сообщения:  Бывают ли Viewer-ы не в динамической памяти

Читаю книгу "Object-oriented programming in Oberon-2" и там есть описание простой оконной системы, которая называется Oberon0 (не путать с простым компилятором Oberon-0, из книги "Compiler construction"). Так вот Frame-ы и Viewer-ы описываются следующим образом:
Код:
TYPE
  Frame* = POINTER TO FrameDesc;
  FrameDesc* = RECORD (OS.ObjectDesc)
    x*, y*: INTEGER; (*left bottom in pixels relative to left bot. of screen*)
    w*, h*: INTEGER (*width, height in pixels*)
  END;
  Viewer* = POINTER TO ViewerDesc;
  ViewerDesc* = RECORD (FrameDesc)
    menu-, cont-: Frame; (*menu frame, contents frame*)
    next-: Viewer;
  END;

То есть Viewer-ы организованы в список и у каждого Viewer-а есть указатель на следующий Viewer или на NIL. (Думаю, что и в BlackBox организация данных примерно такая же.)
А что, если бы модуль мог содержать не Viewer, а ViewerDesc и допустим можно было бы их так же организовывать в списки при необходимости. Тогда не нужно было бы вызывать NEW для создания объекта, а объекты создавались бы при загрузке модуля сразу в глобальной памяти. То есть был бы примерно такой код:
Код:
MODULE MainForm;
  IMPORT ...;

  VAR
    mainForm: ViewerDescr;
    someControl: ViewerControlDescr;
    ...

END MainForm.

Думаю, что в данном случае, были бы следующие преимущества:
1) Загружалось бы все быстрее, за счет того, что не нужно выделять память при помощи NEW.
2) Снижалась бы нагрузка на GC, и в принципе можно было бы создавать графические программы, которые вообще не обращаются к динамической памяти, а работают только с глобальной памятью и стеком программы.

Какие у данного метода могут быть недостатки?
Может быть данный метод уже где-то был реализован?

Автор:  Comdiv [ Суббота, 21 Октябрь, 2017 22:34 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Сколько Viewer-ов присутствует в типичной системе и насколько это большая нагрузка на динамическую память?

Автор:  Kemet [ Воскресенье, 22 Октябрь, 2017 07:50 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

а как из них список сделать?

Автор:  Trurl [ Воскресенье, 22 Октябрь, 2017 09:15 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

в статической памяти логичнее было бы массив.

Автор:  Kemet [ Воскресенье, 22 Октябрь, 2017 10:26 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

с вполне конкретным именем, чтобы можно было стандартно дергать

Автор:  Wlad [ Воскресенье, 22 Октябрь, 2017 10:29 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Rifat писал(а):
Читаю книгу "Object-oriented programming in Oberon-2" и там есть описание простой оконной системы, которая называется Oberon0 (не путать с простым компилятором Oberon-0, из книги "Compiler construction"). Так вот Frame-ы и Viewer-ы описываются следующим образом
...
А что, если ...
...
Какие у данного метода могут быть недостатки?
Может быть данный метод уже где-то был реализован?

Рифат, Ваш вопрос - несколько шире, чем конкретная реализация View.

В данном случае (как и во многих других), Вирт сделал методологическую и архитектурную ошибку, внеся знания о возможных отношениях, в которых может быть задействована и/или участвовать данная сущность в саму сущность.
Если таких отношений может быть всего одно ( как в случае со списком views ), - это кажется несущественным.
Но, исходя из общих подходов, лучше сделать общий класс List, оперирующий с элементами ЛЮБЫХ ссылочных/указательных типов.

Тогда бы и вопроса о том, каков способ создания и место нахождения экземпляра не имел бы значения.

Как только мы приходим к такому решению на уровне системы, моментально возникает задача (де)инициализации.
Эта задача также переходит на уровень общесистемной.
То есть, экземпляр может быть в куче или где-то статически. Инициализировать (экземпляр) нужно в любом случае.
Возникает инициализирующая часть. OurType_Init( OurTypePtr self, ...args...).
И - для размещения в куче, что-то "фабричное" - OurType OurType_Create( ...args... ), которое может вызывать ( может и - нет ) ***_Init.
Соответственно, можно организовать ***_DeInit & ****_Free (последний - для тэггированных типов).

Было принято неверное упрощённое решение, исходя из посыла простоты частного случая. Плюс отсутствие параметризации в языке.
Если есть желание, могу привести пример таких списков (но - на Си), которые я применяю в своих системах. Переделать подход для Оберона не составит труда, я думаю.

Автор:  Wlad [ Воскресенье, 22 Октябрь, 2017 10:54 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Добавлю.

Конечно, сборка мусора упрощает проектирования.
Но, она же, вносит и огромный пласт безответственности и невнимательности при проектировании.
В частности, люди совершенно упускают из виду:
- различия между местами хранения сущностей (статика/куча)
- роль конкретного списка (владелец элементов или "обозначатель" принадлежности сущности ко множеству/объединение сущностей с имеющимся признаком)
- необходимость уделять внимание дополнительным операциям при удалении элемента из данного списка

Методологически полезней изначально проектировать системы так, как будто сборки мусора нет. То есть, решать более общую задачу. Потом, части системы, отвечающие за очистку и удаление элементов - просто комментируются или удаляются из исходников.

Автор:  Info21 [ Воскресенье, 22 Октябрь, 2017 12:29 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Сборка мусора позволяет разделить (#2 DIVIDE ET IMPERA) разработку алгоритмов и оптимизацию в весьма чреватом аспекте управления памятью.

Автор:  Wlad [ Понедельник, 23 Октябрь, 2017 01:58 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Info21 писал(а):
Сборка мусора позволяет разделить (#2 DIVIDE ET IMPERA) разработку алгоритмов и оптимизацию в весьма чреватом аспекте управления памятью.

Разделить - нет.
Получить иллюзию - да.
Не всё так просто, как хотелось изначально.

Автор:  Rifat [ Понедельник, 23 Октябрь, 2017 10:15 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

В одной из старых тем было высказывание Федора Васильевича (и еще когда-то Илья Ермаков тоже высказывал похожую мысль):
Info21 писал(а):
Сформулирую главную мысль покороче, повторившись в 100000-й раз:

В отличие от всевозможных интерпретируемых языков (ФЯ и проч.)
автоматическое управление памятью в Обероне позволяет разделить (DIVIDE ET IMPERA) две важные и разные вещи:

фазу проектирования структур данных -- когда нужные структуры данных еще не известны -- и

фазу их оптимизации -- когда структуры данных в случае нужды (sic) отображаются на статическую память.

Получается, что в случае нужды с View, их не так то просто отобразить в статическую память. Как писал Wlad нужна инициализация, освобождение и так далее. Но в принципе, конечно, ничего невозможно нет. Можно и существующими средствами достичь того, что View будут хранится в статической памяти.

Автор:  Илья Ермаков [ Понедельник, 23 Октябрь, 2017 10:18 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Нужна конкретная постановка задачи.

Вам нужно использовать Viewer-ы в системе реального времени?

Подход Дагаева - выделили на старте нужное количество (или в пул с запасом) - и дальше используете, с уже выключенным NEW/GC.

Можно поиграть, если есть необходимость, и с другой стратегией выделения таких объектов - тупо линейной (как выделяются объекты в первом поколении в .NET), когда нарезается следующий кусок нужного размера под объект в линейной области памяти.

Автор:  Rifat [ Понедельник, 23 Октябрь, 2017 11:38 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

На самом деле нет никакой постановки задачи. Есть только когнитивный диссонанс :)
У меня всегда было представление, что когда точно известно сколько будет элементов, то лучше завести массив или список в статической памяти и уже с ним работать.
Динамическую память следует использовать тогда, когда точно не известно сколько будет элементов.
При проектировании GUI, чаще всего бывает известно, сколько контролов будет на форме и где они будут располагаться. То есть по идее, лучше бы их разместить статически, а не динамически.

Автор:  Илья Ермаков [ Понедельник, 23 Октябрь, 2017 16:11 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Угу, а потом получается, что если рассматривать существующие библиотеки GUI-виджетов как вариант для порта ББ, то часть из них пролетает в силу того, что у них состав элементов задаётся статически.

Автор:  Rifat [ Понедельник, 23 Октябрь, 2017 16:41 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

В принципе, конечно, можно реализовать вариант и со статическим размещением объектов в Обероне, но это будет выглядеть как "закат Солнца вручную".
Другое дело, перевешивают ли плюсы такого подхода минусы "заката Солнца вручную"?
То, есть что можно выиграть за счет того, что все будет размещаться статически?

Автор:  Wlad [ Понедельник, 23 Октябрь, 2017 17:19 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Rifat писал(а):
На самом деле нет никакой постановки задачи. Есть только когнитивный диссонанс :)
У меня всегда было представление, что когда точно известно сколько будет элементов, то лучше завести массив или список в статической памяти и уже с ним работать.
Динамическую память следует использовать тогда, когда точно не известно сколько будет элементов.
При проектировании GUI, чаще всего бывает известно, сколько контролов будет на форме и где они будут располагаться. То есть по идее, лучше бы их разместить статически, а не динамически.

Кстати, я использую "динамику" и в РВ системах. Но - как...
Например, для обобщённых списков.
Иногда я не знаю, сколько действительно элементов (например, "растянутая" по времени обрабатываемая команда) мне понадобится. Но я знаю, что элементы данного типа постоянно появляются и исчезают. Ввожу кэш/пул объектов в каждый такой тип. Дальше функция new/create "лезет" не к менеджеру памяти, а, сначала, в этот пул. Соответственно, освобождения памяти не происходит, а объект возвращается в пул объектов данного типа.
При старте программы, можно просто заранее заполнить пулы определённым количеством неинициализированных объектов.
Кстати и "сборка мусора" происходит путём "прочёсывания" списка всех пулов в системе. С конца списка. Потому, что в начало списка помещаются пулы, к которым происходит наиболее частое обращение.

Автор:  Wlad [ Понедельник, 23 Октябрь, 2017 17:38 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Ещё пар мыслей...
Кстати, работа со списками намного облегчается, если в списке хранятся не сами экземпляры объектов, а некие ссылочные элементы на объекты. Такое разделение позволяет легко реализовать дисциплину разделения "типов" хранимых объектов по месту создания/нахождения - в динамической и статической памяти. При внесении элемента в список, одним из аргументов можно передавать указатель на функцию-"деструктор" хранимого объекта. Тогда упрощается и операция копирования списка. Копируется/создаются "ссылки" вместе с самими объектами. Следовательно копируются и указатели на "деструкторы"/"деинициализаторы" соответствующих объектов.
Автоматом получается более правильное и чистое решение на счёт разделения "базового" функционала объектов и информации о том, в какие множества (списки) этот объект входит. Кроме того, мы автоматом получаем реализацию свойства "владения" списком своих элементов. Нет указателя на "деструктор" - нет и "владения" - элемент уничтожается где-то кем-то другим.

Ниже - заголовочный файл более "лёгкого" решения (ещё без внесения того, что описано выше в "ссылку"-элемент списка). Здесь дисциплина "владения" и освобождения объекта, при удалении списка или объекта из него "отдано на откуп" функциям, связанным с этими операциями.
Атрибут ICACHE_FLASH_ATTR означает размещение кода функции во флэш-памяти контроллера.
Код:
#ifndef __LISTS_H__
#define __LISTS_H__
//----------------------------------------------------------------------------
#include "lists_cfg.h"
#include "macros.h"
#include "typedefs.h"

typedef enum
{ List_Insert_Positions_Before
, List_Insert_Positions_After
} List_Insert_Positions_e;

typedef enum
{ LIST_ENTRY_MOVE_FIRST = (-2)
, LIST_ENTRY_MOVE_PREV  = (-1)
, LIST_ENTRY_MOVE_STAY  = 0
, LIST_ENTRY_MOVE_NEXT  = 1
, LIST_ENTRY_MOVE_LAST  = 2
} List_Entry_Move_Directions_e;

//----------------------------------------------------------------------------
struct _List_Entry;
#define List_Entry  struct _List_Entry*

struct _List;
#define List  struct _List*

typedef struct _List_Entry
{
   List        _list;
   List_Entry  _prev;
   List_Entry  _next;
   void* const _object;
} List_Entry_t;

//----------------------------------------------------------------------------
typedef struct _List
{
   List_Entry _first;
   List_Entry _last;
   int        _count;
} List_t;

//----------------------------------------------------------------------------
typedef void (*List_ObjectFunc     )(       List_Entry entry  ,       void* arg     );
typedef bool (*List_CheckObjectFunc)( const void*      object , const void* arg     );
typedef bool (*List_CmpObjectsFunc )( const void*      object1, const void* object2 ); //(*CmpFun)(object1,object2) must return TRUE if object1 "<=" object2
typedef void (*List_FreeObjectFunc )(       void*      object                       );

//----------------------------------------------------------------------------
List       ICACHE_FLASH_ATTR List_Create      ( void );
bool       ICACHE_FLASH_ATTR List_Init        (       List list );
bool       ICACHE_FLASH_ATTR List_DeInit      (       List list, List_FreeObjectFunc FreeObjectFunc );
bool       ICACHE_FLASH_ATTR List_Free        (       List list, List_FreeObjectFunc FreeObjectFunc );

// List_Clear just removes items all from the list (if FreeItemFunc == NULL) or frees them (if FreeItemFunc != NULL)
bool       ICACHE_FLASH_ATTR List_Clear       (       List list, List_FreeObjectFunc FreeObjectFunc );
bool       ICACHE_FLASH_ATTR List_IsEmpty     ( const List list );

List_Entry ICACHE_FLASH_ATTR List_Add         (       List list, const void* const object );
List_Entry ICACHE_FLASH_ATTR List_Insert      (       List list, const void* const object, List_Entry entry, List_Insert_Positions_e pos );
bool       ICACHE_FLASH_ATTR List_Remove      (       List list, List_Entry entry, List_FreeObjectFunc FreeObjectFunc );

bool       ICACHE_FLASH_ATTR List_Move        (       List list, List_Entry entry, List_Entry_Move_Directions_e direction );

List_Entry ICACHE_FLASH_ATTR List_First       ( const List list );
List_Entry ICACHE_FLASH_ATTR List_Prev        ( const List list, List_Entry entry );
List_Entry ICACHE_FLASH_ATTR List_Next        ( const List list, List_Entry entry );
List_Entry ICACHE_FLASH_ATTR List_Last        ( const List list );


void       ICACHE_FLASH_ATTR List_ForEach     ( const List list, List_ObjectFunc ObjectFunc, void* itemFuncArg );
//(*CmpFun)(object1,object2) must return TRUE if object1 "<=" object2
bool       ICACHE_FLASH_ATTR List_Sort        (       List list, List_CmpObjectsFunc CmpFunc );

List_Entry ICACHE_FLASH_ATTR List_Find        ( const List list, List_CheckObjectFunc CheckFunc, const void* checkFuncArg );
List_Entry ICACHE_FLASH_ATTR List_FindByObject( const List list, const void* object );

bool       ICACHE_FLASH_ATTR List_Assign      (       List list, const List src );

//----------------------------------------------------------------------------
   bool ICACHE_FLASH_ATTR Lists_Init( void );

#endif // #ifndef __LISTS_H__

Автор:  Илья Ермаков [ Понедельник, 23 Октябрь, 2017 18:03 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Предлагаю автору перемещение ветки в Системные вопросы.
Однозначно по тематике туда.

Если Rifat не против, то попросим модераторов перекинуть.

Автор:  Rifat [ Понедельник, 23 Октябрь, 2017 21:36 ]
Заголовок сообщения:  Re: Бывают ли Viewer-ы не в динамической памяти

Я не против)

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/