Problem z wątkami

Odpowiedz Nowy wątek
2011-07-10 20:34
0

Tym razem nie chodzi o niedziałający kod. Mój kod działa, nawet nieźle. Więc w czym problem? Zacznijmy od początku.

Jak pewnie (nie) wiecie piszę EasyScript który jest interpreterem mojego języka ES. Działa on bez zarzutu, nawet coś czasami go rozwijam, ale chodzi tutaj o podstawę jego działania, a mianowicie o sposób wykonywania procedury jak IF,SET,ADD czy cokolwiek.
Mianowicie, mam ustalony wzór procedury która może być wykonywana przez ES, gdzieś mam też do niej wskaźnik. Wszystko śmiga.

Stosuje ES międzyinnymi w jednym z moich większych projektów PRNDWN. Jest to bot internetowy, który skacze po stronach i pobiera jakieśtam pliki - definicję jak ma to zrobić są właśnie w ES. PRNDWN jest wielowątkowy. I tu zaczynają się schody, bo:
Mam pare interpreterów ES (w obiektach). Jeden na główny wątek i po jednym na każdy wątek poszukiwacza. Problem polega na tym, że większość dodanych (na potrzeby PRNDWN) procedur ES musi się odwołać do obiektu wątku, którego nie osiągniemy od tak. Dlatego zrobiłem zmienną globalną, i gdy któryś wątek wykonuje ES to przypisuje pod tą zmienną referencję do siebie.

I tu jest problem:
Jest szansa, że gdy jeden wątek będzie wykonywać polecenia, drugi wątek zmieni referencję, i stanie się coś nieciekawego. Albo (tutaj akurat nie jestem pewien) dwa interpretery ES wykonają naraz tą samą procedurę - też problem.

Myślałem już nad zrobiniem sekcji krytycznej, ale spowodowałoby to zdecydowanie zmniejszenie wydajności ES i co za tym idzie całego programu.
Macie może jakieś pomysły jak to rozwiązać?
Jeszcze taka mała podpowiedź: ES jest teoretycznie obiektowy a w praktyce to spora część jego kodu niskiego poziomu jest w procedurach.


Nie pisz do mnie PM o czymś co nie dotyczy bezpośrednio mnie. | Nie rozmawiaj ze mną jeśli brak Ci kultury (wystarczy że mi brakuje) | Nie jestem zły, jestem po prostu zły.

Pozostało 580 znaków

2011-07-10 23:14
0

napisać porządnie aby się nie gryzły wątki między sobą i każdy miał swoją kopię danych na których będzie operował


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij

Pozostało 580 znaków

2011-07-11 00:07
0
Misiekd napisał(a)

napisać porządnie aby się nie gryzły wątki między sobą i każdy miał swoją kopię danych na których będzie operował

A jak mam coś takiego zrobić z procedurami?
Jeśli procedura będzie w obiekcie to procedura w innym obiekcie będzie 'inna'? Bo nad tym głównie rozmyślałem.
Dane już w 99% przypadków są threadsafe (sekcje krytyczne)/skopiowane dla wątków.


Nie pisz do mnie PM o czymś co nie dotyczy bezpośrednio mnie. | Nie rozmawiaj ze mną jeśli brak Ci kultury (wystarczy że mi brakuje) | Nie jestem zły, jestem po prostu zły.
edytowany 1x, ostatnio: payl, 2011-07-11 00:10

Pozostało 580 znaków

2011-07-11 00:26
0
payl napisał(a)

Jeśli procedura będzie w obiekcie to procedura w innym obiekcie będzie 'inna'? Bo nad tym głównie rozmyślałem.

a po polsku


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij

Pozostało 580 znaków

2011-07-11 01:41
0
Misiekd napisał(a)

a po polsku

Tak myślałem że nie skumasz.

Tłumacząc działanie ES jeszcze raz:
Mam sobię tablicę z nazwą procedury, typami które przyjmuje oraz wskaźnik na realną procedurę, którą potem wykonuję. Jak według Ciebie miałoby to wyglądać w wersji obiektowej?

Tutaj masz kod:

type
GoProc=Function(pESint:pointer;var_ls:TES_Pvrlst;org_s:tes_string):integer stdcall;
 
TES_Proc=record
        naz:string;
        addr:pointer;//Wskaźnik na procedurę
        lvr:TES_Lvrlst;
        accept_any_vars:boolean;
        wer:word;
        end;
 
[...]
function ES_SYS_VER_MAJ(pESint:pointer;var_ls:TES_Pvrlst;org_s:tes_string):integer stdcall;
begin
  [...]
end;
 
[...]
    proc.naz:='VER_MAJ';
    setlength(proc.lvr,1);
    proc.lvr[0].typ:=es_nmb;
    proc.addr:=@ES_SYS_VER_MAJ;
    proc.accept_any_vars:=FALSE;
    addproc(proc);
[...]
 
Wykonanie:
 
go_procedure:=goproc(go_lst[PolID].addr);
result:=go_procedure(@tes_int(self),pvr,s);
res.typ:=es_anything;

I jak to zrobić obiektowo :P.


Nie pisz do mnie PM o czymś co nie dotyczy bezpośrednio mnie. | Nie rozmawiaj ze mną jeśli brak Ci kultury (wystarczy że mi brakuje) | Nie jestem zły, jestem po prostu zły.
edytowany 1x, ostatnio: payl, 2011-07-11 01:41

Pozostało 580 znaków

2011-07-11 10:37
0

ale po co mi ten kod? Co sobie mam z nim zrobić? Jak od początku masz pisany kod nieobiektowo i nie thread-safe to teraz dwoma machnięciami się tego nie zmieni. Przypuszczam, że masz różne procedury z takimi samymi parametrami ale robiące różne rzeczy. Takie cudo to się przez dziedziczenie bardzo ładnie i prosto załatwia


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij

Pozostało 580 znaków

2011-07-11 15:06
0
Misiekd napisał(a)

Takie cudo to się przez dziedziczenie bardzo ładnie i prosto załatwia

Może jakiś przykład albo jaśniej? :P Bo póki co nie wiem jak miałoby to wyglądać.


Nie pisz do mnie PM o czymś co nie dotyczy bezpośrednio mnie. | Nie rozmawiaj ze mną jeśli brak Ci kultury (wystarczy że mi brakuje) | Nie jestem zły, jestem po prostu zły.

Pozostało 580 znaków

2011-07-11 15:31
type
  TZwierz = class
  public 
    function DajGlos: string; virtual; abstract;
  end;
 
  TKot = class(TZwierz)
  public 
    function DajGlos: string; override;
  end;
 
  TPies = class(TZwierz)
  public 
    function DajGlos: string; override;
  end;
 
implementation
 
function TKot.DajGlos: string; 
begin
  Result := 'miau';
end;
 
function TPies.DajGlos: string; 
begin
  Result := 'hau';
end;
 
//i gdzieś tam daleko
var
  zwierza: array [0..1] of TZwierz;
  i: Integer;
begin
  zwierza[0] := TKot.Create;
  zwierza[1] := TPies.Create;
  for i := 0 to 1 do
    WriteLn(zwierza[i].DajGlos);
 
  for i := 0 to 1 do
    zwierza[i].Free;
end;

i na takiej zasadzie w go_lst miał byś po prostu obiekty różnych typów ale dziedziczące po tym samym przodku


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij

Pozostało 580 znaków

2011-07-11 17:05
0
Misiekd napisał(a)

i na takiej zasadzie w go_lst miał byś po prostu obiekty różnych typów ale dziedziczące po tym samym przodku

Ooo genialne. Dzięki, misiekd :P


Nie pisz do mnie PM o czymś co nie dotyczy bezpośrednio mnie. | Nie rozmawiaj ze mną jeśli brak Ci kultury (wystarczy że mi brakuje) | Nie jestem zły, jestem po prostu zły.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0