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

Вниз

Добавление в массив элемента   Найти похожие ветки 

 
@!!ex ©   (2008-03-26 06:53) [0]

Есть массив элементов.
Один поток перебирает элементы и обрабатывает их.
Второй, изредка дергает функцию добавления элементов в массив.
Вопрос в том, насколько корректно, что в массив добавляются элементы во время обработки массива другим потоком?
Смотрю, вроде никаких проблем не возникает. Ну добавились элементы, потом их просто игнорирует и обрабатывает при повторном проходе.
Но это первый взгляд. А на самом деле как?


 
MBo ©   (2008-03-26 07:05) [1]

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


 
@!!ex ©   (2008-03-26 07:13) [2]

Обработка:
procedure TObjectsControl.Update(dt: integer);
var
 Index:integer;
begin
 for Index:=0 to count-1 do
   Items[Index].Update(dt);
end;


Добавление:
procedure TObjectsControl.Assign(GameObject: TGameObject);
begin
 inc(Count);
 SetLength(Items,Count);
 Items[Count-1]:=GameObject;
 Items[Count-1].Enabled:=true;
end;


Если синхронизировать, то весь смысл использования потоков теряется, скорость один в 1, как на одном потоке.


 
@!!ex ©   (2008-03-26 07:19) [3]

Подумал сделать вот так:

Lock:TCriticalSection;

procedure TObjectsControl.Update(dt: integer);
var
 Index:integer;
 Obj:TGameObject;
begin
for Index:=0 to count-1 do begin
  Lock.Enter;
  Obj:=Items[Index];
  Lock.Leave;
  Obj.Update(dt);
end;
end;

procedure TObjectsControl.Assign(GameObject: TGameObject);
begin
Lock.Enter;
inc(Count);
SetLength(Items,Count);
Items[Count-1]:=GameObject;
Items[Count-1].Enabled:=true;
Lock.Leave;
end;

Это нормальный подход?


 
TUser ©   (2008-03-26 07:20) [4]

Пример неприятности.

Первый поток
while i<= length do
 something with A[i]
 inc (i);

Второй поток
SetLength (A, length + 1);
A[lenght-1] := anyshing.

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

Все, конечно, зависит от реализации потоков. Для этого примера возможное решение такое. Заведем флаг. И будем считать, что первый не может прерывать работу этих двух строцчек второго. Тогда второй д.б. таким

flag := false;
SetLength (A, length + 1);
A[lenght-1] := anyshing.
Flag := true;

а первый

while true do
 while not flag do begin end;
 do somthing with A[i];
 inc (i);
 if i > length then break;

Но вообще, не стоит оно того, - поставь критические секции. В общем случае, даже с применением такого флага могут быть проблемы.


 
TUser ©   (2008-03-26 07:21) [5]


> @!!ex ©   (26.03.08 07:13) [2]
>
>

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


 
MBo ©   (2008-03-26 07:24) [6]

>SetLength(Items,Count);

При этом Items располагается по новому адресу со всеми вытекающими....

Кстати, у тебя массив наращивается по одному элементу - это невыгодно, частые перераспределения памяти.


 
MBo ©   (2008-03-26 07:25) [7]

http://mbo88.narod.ru/ToC.html


 
TUser ©   (2008-03-26 07:27) [8]


> При этом Items располагается по новому адресу со всеми вытекающими.
> ...
>

Да, действительно. Мои рассуждения можно не читать.


 
MBo ©   (2008-03-26 07:28) [9]

Посмотри еще TThreadList в classes - там простейшая защита крит. секцией


 
@!!ex ©   (2008-03-26 07:31) [10]

> Но вообще, не стоит оно того, - поставь критические секции.
> В общем случае, даже с применением такого флага могут быть
> проблемы.

В [3] поставил критические секции. Правильно?


> >SetLength(Items,Count);
> При этом Items располагается по новому адресу со всеми вытекающими....

Да, я поэтому поставил критически секции. Правильно?


> Кстати, у тебя массив наращивается по одному элементу -
> это невыгодно, частые перераспределения памяти.

Количество элементов очень маленькое(в среднем 20, больше 50 редко). И меняется обычно не больше 1 раза в секунду, ну максимум 5.
Где массивы большие, там по другому реализовано. Выделение блоками, по 10, плюс удаление не уменьшает массив. Поэтому массив доходит до некоторого количества и замораживается, хотя элементы продолжают добавлятся и удалятся.


 
tesseract ©   (2008-03-26 10:22) [11]


> В [3] поставил критические секции. Правильно?


Обычно так и делаеться. Хотя есть варианты с потокобезопастным Tlist или очередью (не родным).


 
Паша 1   (2008-03-26 11:35) [12]


> MBo ©   (26.03.08 07:05) [1]

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


 
@!!ex ©   (2008-03-26 12:16) [13]

> ну откуда неприятности?

Realloc массива, перенос его в другой участок памяти


 
Паша 1   (2008-03-26 12:23) [14]

а! пардон, нумер [6] не увидел. а что, в другом потоке ссылка на массив "левая" остается? я с работой на низком уровне не сталкивался просто


 
tesseract ©   (2008-03-26 12:24) [15]


> зачем там критические секции с массивом? я не прав?


Они и не для массива нужны. Дабы значение переменной не напоминало функцию Random.


 
Mystic ©   (2008-03-26 13:27) [16]

> Количество элементов очень маленькое(в среднем 20, больше
> 50 редко).


А почему просто не сделать тогда массив длины MAX_LEN и отдельно переменную ArrayLength?


 
@!!ex ©   (2008-03-26 13:45) [17]

> [16] Mystic ©   (26.03.08 13:27)

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


 
Mystic ©   (2008-03-26 14:28) [18]

> Там где массив большой и часто обнеовляется, все работает
> немного по другому, а смысл оптимизировать то, что и так
> быстро работает?


Это не оптимизация, удо еще и удобство работы: не нужны вызовы SetLength. Это всегда так: в чем-то выигрываешь, в чем-то проигрываешь...

Ограничения же можно ввести, например
 (1) из условий задачи (например на шахматной доске 64 клетки)
 (2) из разумных пределов, превышение которого наверняка вызовет сбой в программе (например у нас есть N объектов, а затем в памяти строится все перестановки этих объектов. Таких перестановок N!, логично что число N можно ограничить, скажем, 1000. Ибо 1000! уже 4.0E2567, и навряд ли в ближайшем будущем быстродействие и память достигнет таких пределов, чтобы их можно было сгенерить.


 
Anatoly Podgoretsky ©   (2008-03-26 15:14) [19]

> @!!ex  (26.03.2008 6:53:00)  [0]

Ты про динамические массивы?
И не видишь проблем, они же перемещаются в памяти.


 
Anatoly Podgoretsky ©   (2008-03-26 15:17) [20]

> Mystic  (26.03.2008 13:27:16)  [16]

И последовательность, снача присвоение, а потом наращивание счетчика. Правда остается еще и удаление, где это не поможет.


 
@!!ex ©   (2008-03-26 15:32) [21]

> [19] Anatoly Podgoretsky ©   (26.03.08 15:14)

Так в [2] вынес в критическую секцию.


> [20] Anatoly Podgoretsky ©   (26.03.08 15:17)

ТАк вроде for в начале расчитывает условие выхода и потом его не трогает?

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


 
GEN++ ©   (2008-03-26 16:30) [22]

IMXO:
При заданных условиях по кол-ву элементов массива [10]
конечно нужно использовать статиеский массив конечной разумной
длины.В структуру элtмента можно добавить поле индекса элемента в
массиве (или м.б. номер его поступления), индексу 0 соответствует
невалидный элемент, тогда легко будет удалять элементы присваивая им
индекс=0. Естественно поле индекса должно заполняться последним.



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

Форум: "Прочее";
Текущий архив: 2008.05.11;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.009 c
2-1208032052
voe
2008-04-13 00:27
2008.05.11
Непонятное поведение Application.ProcessMessages


4-1188820743
Че
2007-09-03 15:59
2008.05.11
Служба


2-1208152850
lewka-serdceed
2008-04-14 10:00
2008.05.11
ComboBox в ячейке StringGrid


2-1207909029
savyhinst
2008-04-11 14:17
2008.05.11
Как вызвать диалог выбора папки???


15-1206724373
tesseract
2008-03-28 20:12
2008.05.11
Быстрый tiling





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский