Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.03.03;
Скачать: [xml.tar.bz2];

Вниз

Создание динамической струскуры хранения данных.   Найти похожие ветки 

 
Erik   (2004-02-19 16:17) [0]

А решил отказатся от своих любимых динамических масивов. Но Переходить на TList нерешаюсь. Пока думаю воспользоватся следующей конструкцией.
TDynamicArray = class(TObject)
private
FData: Pointer;
FCount: Integer;
procedure SetCount(c: Integer)
protected
FItemSize: Integer;
procedure GetItem(i: Integer; var Result);
procedure SetItem(i: Integer; var value);
public
constructor Create; virtual;
destructor Destroy; override;
property ItemSize: Integer read FItemSize;
property Count: Integer read FCount write SetCount; // Write this to resize array.
property Data: Pointer read FData; // Read-only pointer to data.
end;

constructor TDynamicArray.Create;
begin
inherited Create;
// You have to set FItemSize in the constructor of your descendant classes!
FItemSize := 1;
// Start your array with room for a certain number of elements by setting Count.
Count := 0;
end;

destructor TDynamicArray.Destroy;
begin
// Dispose of the array data.
FreeMem(FData, FCount * FItemSize);
inherited Destroy;
end;

procedure TDynamicArray.SetCount(c: Integer);
begin
// Resize the array by reallocating FData.
FCount := c;
ReAllocMem(FData, FCount * FItemSize);
end;

procedure TDynamicArray.GetItem(i: Integer; var Result);
var
p: Pointer;
begin
if i >= Count then raise Exception.Create("Array index out of bounds.")
else begin
p := FData;
INC(Integer(p), i * FItemSize);
CopyMemory(@Result, p, FItemSize);
end;


 
Семен Сорокин   (2004-02-19 16:23) [1]

так чем TList то не нравится, там все это реализовано с гораздо-большими возможностями?


 
Erik   (2004-02-19 16:27) [2]

Будет многопользовательский доступ к данным, тоесть много читателей и много писателей. Еще хочется проверять эти данные их основного модуля и если появились изменения отображать(для отладки).
Есть множество возможностей для организации, какую лучше выбрать?
P.S.
В старом варианте переодически вылетал
Exception occured at $004069B4 (Module "System", Procedure "@DynArrayClear", Unit "", Line 0)
А структура была такая
IDStat = (idGive, idSave, idCancel, idFree);

RInd = record
User: Integer;
Id: Integer;
end;

THole = Record
Params: RTKParams;
Stat: IDStat;
end;
TArrHole = Array of THole;
PArrHole = ^TArrHole;
TCounter = Record
UserID: Cardinal;
Hole: TArrHole; //array one user of reservi aeg
end;

FList: Array of TCounter; - это исходная переменая
FLock: TMultiReadExclusiveWriteSynchronizer; - это для обеспечения раздельного доступа.


 
Amoeba   (2004-02-19 16:31) [3]

Изобретаем очередной велосипед?
Посмотри на http://home.earthlink.net/~akonshin/delphi_ru.htm


 
Владислав   (2004-02-19 16:32) [4]

Появится новый велосипед с квадратными колесами.


 
Тимохов   (2004-02-19 16:37) [5]


> Erik © (19.02.04 16:17)

Если записи содержат динамические массивы, строки или интерфейсы, то работать с их памятью напрямую можно только при определенных знаниях.
Если уж очень хочется, то почитай про методы initialize и finalize.

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

Согласен со многими тут - пользуйся TList, создавая элементы методом new и удаляя методом dispose. В этом случае дельфа сама на себя возьмет заботу о дин. массивах, строках и интерфейсах.


 
Тимохов   (2004-02-19 16:38) [6]

вот такая работа

> CopyMemory(@Result, p, FItemSize);

может привести при определенных условиях фиг знает к чему.


 
Тимохов   (2004-02-19 16:42) [7]


> Будет многопользовательский доступ к данным, тоесть много
> читателей и много писателей. Еще хочется проверять эти данные
> их основного модуля и если появились изменения отображать(для
> отладки).

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


 
Erik   (2004-02-19 17:01) [8]

Я заню про проблемы, поскольку проэкт уже реализован и кое как работает, иногда по 4 для подряд! :)
Я у себя Move и пр... использую но получилось ненадежно. :( Так вроде все отладил, но в многопользовательской среде появились проблемы. Причем несразу а через большой промежуток времени. Вот я и решил все радикально поменять. Можно и TList использовать, но все равно придется блок памяти самому распределять. Так какая разница где хранить указатели на эти блоки?


 
Курдль   (2004-02-19 17:06) [9]

TList - не панацея. Всего-навсего массив указателей.
Всегда лучше опираться на конструкции более высокого уровня.
Если Вы работаете с объектами - используйте для них TCollection.


 
Erik   (2004-02-19 17:23) [10]

To Курдль
Помоему я описал с чем я работаю, объектами у меня и непахнет.

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


 
Тимохов   (2004-02-19 17:26) [11]


> Можно и TList использовать, но все равно придется блок памяти
> самому распределять. Так какая разница где хранить указатели
> на эти блоки?

Почитайте кусочек 5 про new и dispose. И вообще не копируйте область памяти - делайте присвоение явно:

sourcerec.f1 := destinationrec.f1;
....
sourcerec.fn := destinationrec.fn;

Это куда надежней.

Если есть проблемы в многопользовательском режиме - надо использвать методы синхронизации - крит. секции, мьютексы или еще что.


 
jack128   (2004-02-19 17:39) [12]


> создавая элементы методом new и удаляя методом dispose.
> В этом случае дельфа сама на себя возьмет заботу о дин.
> массивах, строках и интерфейсах.
Это точно?
То есть такой код
var
p: PString;
begin
New(p);
p^ := StringOfChar("q", 10);
Dispose(p);
end; не приведет к утечке памяти??


 
Erik   (2004-02-19 17:42) [13]

To Тимохов
Количество параметров по пременое, занчить и разное количество памяти выделять надо. Зачить одним New необойдешся. Придется еще кусочик прикрепить.


 
Vuk   (2004-02-19 17:43) [14]

У меня есть реализация похожей структуры данных. В реализации разница в том, что при помещении данных в контейнер происходит копирование данных, а при получении возвращается указатель на хранящиеся в контейнере данные.

MaxArraySize = $1FFFFFFF;

PByteArray = ^TByteArray;
TByteArray = array [ 0..MaxArraySize ] of byte;

function TCLArray.Get( Index : integer ) : Pointer;
begin
{$ifdef ThreadSafe}
Lock;
{$endif}
CheckIndex( Index );
Result := @PByteArray( FItems )^[ Index * FItemSize ];
end;

procedure TCLArray.Put( Index : integer; Item : pointer );
begin
{$ifdef ThreadSafe}
Lock;
{$endif}
System.Move( Item^, PByteArray( FItems )^[ Index * FItemSize ], FItemSize );
end;



 
Игорь Шевченко   (2004-02-19 17:46) [15]


> проэкт уже реализован и кое как работает, иногда по 4 для
> подряд! :)


Замечательный критерий :))


 
Владислав   (2004-02-19 17:52) [16]

> jack128 © (19.02.04 17:39) [12]

А что? Должен?


 
Курдль   (2004-02-19 18:00) [17]


> To Курдль
> Помоему я описал с чем я работаю, объектами у меня и непахнет.
>
> Размышляю я, что и как лучше сделать. Вот и мнениями других
> специалистов поинтересовался.


Я, конечно, не специалист, но мне сдается, что Вы - засланный казачок из сей каких-нить. :)
Вы полностью подменяете обязанности компиллятора высокого уровня по заботе о выделении, размещении, освобождении памяти и т.п.
Если хотите, чтобы все супер-быстро работало - вернитесь за си и вперед! А если пишете на ЭТОМ - пользуйтесь ЕГО прелестями.
По существу. Вы предположили поработать с TList.
Я рекомендую TCollection. По сути своей это ничего не меняет - какие-то указатели, указатели на функции, указатели на указатели и т.п. Однако в design-time это даст огромные преимущетсва. Например, ссылки по индексам не только к объектам, но и к их свойствам; автоматическое добавление объектов вместе со всеми их причиндалами по Add, освобождение памяти по Free и т.п. Разве это плохо?


 
Юрий Зотов   (2004-02-19 18:01) [18]

> Erik © (19.02.04 16:27) [2]
> Будет многопользовательский доступ к данным, тоесть много
> читателей и много писателей

TThreadList. И все. Уже готовое. Без велосипедов.


 
Тимохов   (2004-02-19 18:04) [19]


> jack128 © (19.02.04 17:39) [12]
>
> var
> p: PString;
> begin
> New(p);
> p^ := StringOfChar("q", 10);
> Dispose(p);
> end; не приведет к утечке памяти??

Утечки не будет, т.к. pstring типизированный указатель.


 
Vuk   (2004-02-19 18:08) [20]

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


 
VLAD-MAL   (2004-02-19 18:10) [21]

Фундаментальные алгоритмы и структуры данных в Delphi
The Tomes of Delphi Algorithms and Data Structures
Джулиан Бакнелл

Цена: 278 руб.

На складе.
Вес: 510 грамм


Мягкая обложка, 560 стр., 2003 г.
Издательство: ДиаСофтЮП
ISBN 5-93772-087-3, 1-55622-736-1, Тираж: 3000 экз., Формат: 70x100/16

Афигенная книга!


 
jack128   (2004-02-19 18:13) [22]


> Владислав © (19.02.04 17:52) [16]
> > jack128 © (19.02.04 17:39) [12]
>
> А что? Должен?
Это зависит от того файнализирует ли Dispose строку. Вот
> Тимохов © говорит, что все ок.

> Тимохов © (19.02.04 18:04) [19]
А можно ссылку на хелп где это написано? ;-) Или ты это в asm коде высмотрел??


 
Тимохов   (2004-02-19 18:16) [23]


> jack128 © (19.02.04 18:13) [22]

Глянь finalize+f1


 
Юрий Зотов   (2004-02-19 18:16) [24]

> Vuk © (19.02.04 18:08) [20]

Разве защита внутри Add, Insert, Remove и пр. - это не защита на уровне методов?

Разве работа с указателями - это не работа с данными любого размера?

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


 
Тимохов   (2004-02-19 18:23) [25]


> Тимохов © (19.02.04 18:16) [23]

Я тут посмотрел сам куда Вас послал и был удивлен следующей фразой оттуда

Dynamic arrays can never be deallocated using the Dispose procedure, but can be freed by passing them to Finalize.

Не полнял я ее, что-то. В реальности dipose корректно освобождает и дин. массивы. О чем тут речь? Может вы лучше английский знаете?


 
Тимохов   (2004-02-19 18:24) [26]


> Юрий Зотов © (19.02.04 18:16) [24]

Вы, конечно, знаете, но все же замечу TThreadList не позволяет одновременное чтение.


 
Vuk   (2004-02-19 18:24) [27]

to Юрий Зотов:
>Разве защита внутри Add, Insert, Remove и пр. - это не защита на
>уровне методов?
"Недобросовестный" код может легко развалить защиту TThreadList. Достаточно вызвать LockList, запомнить ссылку, потом UnlockList. Все, с полученной ссылкой можно делать все что душе угодно невзирая на то, что происходит в других потоках.

>Разве работа с указателями - это не работа с данными любого
>размера?
4 байта. :o) А если мне нужен, например, список указателей на методы? Мне выделять вагон блоков по 8 байт в куче или лучше все-таки хранить их в некоем подобии динамического массива?


 
Владислав   (2004-02-19 18:24) [28]

> jack128 © (19.02.04 18:13) [22] & Тимохов © (19.02.04 18:16) [23]

Есть еще один способ :)

procedure TForm1.Button1Click(Sender: TObject);
var
p: PString;
i: Integer;
begin
for i := 1 to 100000 do
begin
New(p);
p^ := StringOfChar("q", 100000);
Dispose(p);
end
end;


 
Тимохов   (2004-02-19 18:26) [29]


> Владислав © (19.02.04 18:24) [28]
> > jack128 © (19.02.04 18:13) [22] & Тимохов ©

Способ чего?
Каков Ваш тезис?


 
Romkin   (2004-02-19 18:27) [30]

Есть велосипед покруче, TMultiReadExclusiveWriteSynchronizer
одно название чего стоит :)))
Это для тех, кто любит одновременное чтение :)


 
Serginio666   (2004-02-19 18:32) [31]

2 VLAD-MAL (19.02.04 18:10) [21]
Книга расчудеснейшая, только тираж маловат.


 
Владислав   (2004-02-19 18:32) [32]

> Vuk © (19.02.04 18:24) [27]

"4 байта. :o) А если мне нужен..."

Это точно...

А вообще-то, я в [4] имел ввиду несколько иное.
Написать "свой" TList или TThreadList под конкретный тип данных, чтобы оптимизировать обращение к ним... Полностью согласен, если овчинка выделки стоит... А вот писать такое обобщенное хранилище, ИМХО, только для общего развития. Где еще можно так "наколоться" или перечитать столько различной документации, чтобы хоть что то заработало?


 
Владислав   (2004-02-19 18:35) [33]

> Тимохов © (19.02.04 18:26) [29]

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

> Romkin © (19.02.04 18:27) [30]

Ну дык у этого "велосипеда" есть более короткое и более непонятное "название" ;)


 
Vuk   (2004-02-19 18:36) [34]

to Владислав:
>А вот писать такое обобщенное хранилище, ИМХО, только для общего
>развития.
Ну не знаю. В работе очень даже помогает. Пример со списком методов - из реальной жизни.


 
Владислав   (2004-02-19 18:41) [35]

> Vuk © (19.02.04 18:36) [34]

Как не крути, с типизированными "штуками" позже работать проще, а то, что помогает, ни сколько не спорю.


 
Vuk   (2004-02-19 18:43) [36]

to Владислав:
>с типизированными "штуками" позже работать проще
Кто бы спорил, только вот динамические массивы для этого не совсем удобны.


 
Владислав   (2004-02-19 18:48) [37]

> Vuk © (19.02.04 18:43) [36]

Почти сдаюсь :) В точку бьете ;) Хотя, в принципе, в [32] я об этом если не сказал, то обмолвился точно :)


 
Serginio666   (2004-02-19 18:58) [38]

2 Vuk ©
Реализация типизированного TList (StringList) на динамическом массиве это пара минут. Все что нужно это Count (капасити это Length), SetLength да правильно использовать Move , не забывая обниливать без вызова финализатора объеты поддерживающих подсчет ссылок.


 
Тимохов   (2004-02-19 18:58) [39]


> Владислав © (19.02.04 18:35) [33]
> > Тимохов © (19.02.04 18:26) [29]
>
> На моей конфигурации просто нет столько памяти, чтобы работа
> этой процедуры завершилась корректно ;)

Вы ошибаетесь - код выполнятется с нулевой утечкой памяти. Проверьте.


 
Vuk   (2004-02-19 19:01) [40]

Для примера. Вот код, который реализует список методов с минимальным сервисом (добавление/удаление/доступ к элементам) на основе того класса, фрагменты которого я приводил. Все вполне типизировано.


type
TMethodList = class(TObject)
private
FMethods: TCLArray;
function GetMethods(index: integer): TMethod;
procedure SetMethods(Index: integer; Value: TMethod);
function GetCount: integer;
public
constructor Create;
procedure Add(Handler : TMethod);
procedure Remove(Handler : TMethod);
procedure Delete(Index: integer);
property Count: integer read GetCount;
property Methods[index:integer]: TMethod read GetMethods write SetMethods;
end;

constructor TMethodList.Create;
begin
inherited Create;
FMethods := TCLArray.Create(10, 10, sizeof(TMethod));
end;

procedure TMethodList.Add(Handler : TMethod);
begin
FMethods.Add(@Handler);
end;

function TMethodList.GetMethods(index: integer): TMethod;
begin
Result := TMethod(FMethods.Items[index]^);
end;

procedure TMethodList.Remove(Handler : TMethod);
var
i : integer;
begin
i := FMethods.IndexOf(@TMethod(Handler));
if i <> -1 then
FMethods.Delete(i);
end;

procedure TMethodList.Delete(Index: integer);
begin
FMethods.Delete(Index);
end;

procedure TMethodList.SetMethods(Index: integer; Value: TMethod);
begin
FMethods.Items[index] := @Value;
end;

function TMethodList.GetCount: integer;
begin
Result := FMethods.Count;
end;


Для примера можете подумать, что нужно для реализации того же самого на динамических массивах. Особенно это касается удаления. :o)



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2004.03.03;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.006 c
1-6019
Максим
2004-02-19 11:59
2004.03.03
Текстовый файл


4-6267
LameFox
2003-12-26 16:38
2004.03.03
Оформление в Windows 2000 как в Windows XP


6-6176
Checist [root]
2003-12-27 03:04
2004.03.03
Проверка полной загрузки


14-6224
Rusta
2004-02-09 17:31
2004.03.03
Какой язык программирования выбрать для изучения?


1-6041
Miwa
2004-02-19 01:48
2004.03.03
Лог: как оптимально считать запись, состоящую из 2 строк...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский