Biblioteka dll, dynamiczne wątki

0

Kilka tematów o wątkach już było ale nie znalazłem tam odpowiedzi, podobnie w sieci. Mam następujący problem/pytanie.
Jest napisany gotowy program obliczeniowy z silnikiem z formie biblioteki dll. Wszytko działa ok. Silnik jest trochę skomplikowany, pełno klas itd. Teraz ta biblioteka z silnikiem ma zostać wykorzystana przez inny program, a konkretnie ma zostać silnikiem w aplikacji serwerowej. Aplikacja ta ma wysyłać do biblioteki wiele zapytań na raz od różnych użytkowników, pobierać przesyłane od nich dane i wykonywać równocześnie obliczenia dla każdego zapytania. Obecnie ten silnik nie ma żadnych wątków, był pisany dla aplikacji jednostanowiskowej. Teraz trzeba go przerobić na wersję serwerową z wątkami które będą wykonywać obliczenia dla nowych użytkowników. Aplikacja do biblioteki nie jest pisana w delphi i nie zajmuje się nią, odpowiadam jedynie za bibliotekę. (Problem z połączeniem między nową aplikacją [w javie] a biblioteką delphi jest rozwiązany). Moje pytanie/problem brzmi: jak najprościej przerobić taką bibliotekę?
Zastanawiałem się nad stworzeniem jakiejś klasy od TThread z procedurami odpowiedzialnymi za pobieranie danych, wywoływanie obliczeń oraz pobieranie wyników. I w tych procedurach z wątku byłoby odwołanie do właściwych procedur obliczeniowych biblioteki. Procedury z wątku muszą zawierać identyfikatory (numerki dla poszczególnych użytkowników, aby rozróżnić poszczególne dane, obliczenia i wyniki). Czy takie przypisanie procedur i funkcji bez wątkowych do procedur i funkcji wątkowych pozwoli na bezkolizyjna pracę silnika? Chodzi o to że w silniku nie ma wątków i są jakieś zmienne wewnątrz poszczególnych klas. Czy jeśli za pomocą procedury z wątka wywołam procedurę bezwątkową, a następnie kolejny wątek wywoła tą samą procedurę, to czy da się rozróżnić dane w jednym i drugim wątki? przykład

procedure Pobierzdane(1); <- procedura z wątku 1
begin
  Wczytajdane;
end;
procedure Pobierzdane(2); <- procedura z wątku 2
begin
  Wczytajdane;
end;

(wątki będą tworzone jakoś dynamicznie z tymi numerami, chciałem tylko obrazowo pokazać o co mi chodzi)
i wywołanie potem w programie:

//(wywołanie wątku 1)
Pobierzdane(1);
//(wywołanie wątku 2)
Pobierzdane(2);

Czy w takim przypadku wartości w zmiennych z Wczytajdane dla Pobierzdane(1) oraz Pobierzdane(2) da się jakoś rozróżnić? Czy to będą te same wartości zmiennych? Wydaje mi się że będę miał te same dane ale dopiero zaczynam z wątkami.
Do głowy przychodzi mi także kompletna przebudowa całego silnika i stworzenie obecnych klas z pochodnych TThread ale to by była masakra. Jest tego zdecydowanie za dużo i pewnie coś bym po drodze jeszcze zepsuł. (ps. nie pisałem tej biblioteki z silnikiem, wiem co i jak tam działa ale to nie omja robota). Czy ktoś mógłby jakoś pomóc lub doradzić jak to wykonać?
Będę wdzięczny za każdą pomoc.

0

czesc,

taka uwaga na wstepie:
Nie robilem takich rzeczy i sam jestem ciekaw jak to sie sprawdzi, jednak jestem perzekonany ze ma to szanse zadzialac.
Traktujcie moja wypowiedz jako glos w dyskusji a nie zdanie wszystkowiedzacego:P
chetnie dowiem sie co myslicie o takim sposobie.

Jak dziala ten Twoj silnik?
czy (1) jest tak ze z glownego programu wywolujesz tylko jedna funkcje PoliczMiCosTam() i na koncu dostajesz wynik,
czy (2) silnik jest zbiorem funkcji i procedur ktore sa wywolywane z algorytmu wewnatrz glownego programu?

Jezeli (1) to sprobowalbym zrobic jakos tak:
wszystko co sie wykonywalo w ramach obliczen (zmienne globalne, procedury, funkcje i co tam jeszcze masz) zapakowalbym do jednej klasy. Wtedy calosc pracy Twojego silnika bedzie zamknieta wewnatrz jednego obiektu i nie bedzie sie gryzc z rownolegle tworzonymi obiektami.

w funkcji udostepnianej na zewnatrz zrobilbym utworzenie obiektu, przekazanie danych wejsciowych i na koniec zwrocienie wartosci i zwolnienie obiektu. nie dodawalbym watkow wewnatrz biblioteki.

a jesli masz wersje (2) to sprowadzilbym ja do postaci (1) :D

przyklad:

function FunkcjaUdostepnianaNaZewnatrz(DaneWejsciowe: TJakisTyp): TInnyTyp;
var MojObiekt: TMojaKlasa;
begin
  MojObiekt := TMojaKlasa.create;
  MojObiekt.Input := DaneWejsciowe;
  MojObiekt.WykonajObliczenia;
  result := MojObiekt.Wynik;
  MojObiekt.free;
end;
0

dzięki za odpowiedź.
niestety jest to raczej opcja (2). program będzie się odwoływał do biblioteki przez kilka funkcji i procedur (wczytywanie danych do obliczeń [kilka procedur na różne typy danych], inicjalizacja obliczeń, pobieranie wyników, procedura z możliwością przerwania obliczeń, pobieranie innych informacji po obliczeniach) - nie za bardzo da się to wpakować do jednego. poza tym jak pisałem sam program jest pisany w javie, biblioteka z delphi i wszystko łączy się przez JNI :( na razie było testowane połączenie przez JNI właśnie do wczytywania danych, wykonywania obliczeń itd. Ponieważ to działało teraz projekty idą niejako osobno, wszystko się połączy na koniec, więc nie ma dużej możliwości testowania rozwiązań (ja się javą nie zajmuję, chociaż coś tam do testów udało się skompilować).
a odnośnie tych wątków to chyba musi być na wątkach to robione. Jest jedna biblioteka i jedne procedury do obliczeń. Ponieważ do programu może przychodzić wiele równoczesnych połączeń, które trzeba obsłużyć od razu, obliczenia będą wykonywane równolegle. Wydaje mi się że tworząc jedynie oddzielne obiekty w nowej klasie to i tak przed wykonaniem kolejnego obliczenia będzie musiało zostać wykonane poprzednie, a wszystkie mają pracować niezależnie bez oczekiwania na swoją kolej - dobrze rozumiem ideę tej wspólnej klasy?

0

ja to rozumialem w taki sposob ze watek jest tworzony przez program nadrzedny (tu akurat pisany w Javie).
Nastepnie, kazdy watek dynamicznie laduje sobie bibklioteke.
(jesli zaladujesz biblioteke raz, przed uruchomieniem watkow to na pewno sie pogryza).
Natomiast sama biblioteka nie ma pojecia czy jest uruchamiana z kilku watkow rownolegle czy z jednego programu.

(tzn np serwer odbiera polaczenia, dla kazdego tworzy watek. watek laczy sie normalnie do biblioteki)

teraz pytanie czy do pamieci kazdego watku ladowana jest nowa instancja biblioteki
czy wszystkie uzywaja tej samej... tego nie wiem.
napisz prosty program w Delphi kozystajacy z Twojej dll i sprawdz.
(
dwa watki, w kazdym zaladuj biblioteke dynamicznie,
w jednym zapisz wartosc do zmiennej
a nastepnie w drugim odczytaj jej wartosc

  • jesli sie nie pogryza to nie musisz sie niczym przejmowac :-)
  • ale tak pieknie to tylko u jednego z operatorow ;-), ale warto sprawdzic.
    )

nie wyobrazam sobie pisania takiego programu bez mozliwosci robienia prob.

0
Johny_Morfina napisał(a)

dwa watki, w kazdym zaladuj biblioteke dynamicznie,T
w jednym zapisz wartosc do zmiennej
a nastepnie w drugim odczytaj jej wartosc

  • jesli sie nie pogryza to nie musisz sie niczym przejmowac :-)
  • ale tak pieknie to tylko u jednego z operatorow ;-), ale warto sprawdzic.
    )

próbowałem coś zrobić ale nie wychodzi to tam jak powinno. testowałem ze 2 wątki z procedurami w głównej formie bez biblioteki jeszcze i niestety nie tak to powinno działać. poza tym jeśli w jednym wątku wczytam daną to nie mogę jej odczytać w drugim, tzn. tak jak to teraz zrobiłem to właściwie mogłem ale chodzi o to że te wątki i dane w wątkach muszą być niezależne. nie mogę z jednego wątku odczytywać (mieć taką możliwość) wartości w drugim. każdy wątek ma się odnosić do nowego użytkownika który przesyła swoje dane i odbiera swoje wyniki. no i kwestia pamięci. załadowanie biblioteki dla nowych obliczeń zajmuje chyba więcej pamięci niż stworzenie nowego wątku (chyba). silnik jest trochę skomplikowany, składa się z kilkudziesięciu powiązanych ze sobą klas. nie tworzyłem go więc nie poruszam się po nim jeszcze swobodnie. dostałem gotowy program składający się z głównej aplikacji oraz silnika z bibliotece a teraz mam to dostosować do innego programu, z założeniem że teraz zamiast jednego użytkownika z biblioteki może korzystać nieznana liczba przez serwer.

postaram się jeszcze raz opisać jak to ma wyglądać. może ktoś miałby pomysł jak to zrobić.

jest biblioteka w delphi z silnikiem obliczeniowym. muszę przerobić tą bibliotekę aby móc uruchamiać wszystkie występujące tam funkcje/procedury dla poszczególnych użytkowników - dla każdego osobny zestaw, tak jak pisał Johny_Morfina w sensie że każdy użytkownik odpala sobie swoją kopię biblioteki. aby obliczenia się nie mieszały wątki zawierałyby jakiś znacznik typu integer, który odwoływałby się do konkretnego użytkownika. czyli np. user dostaje swój numer 25 i uruchamia procedurę do wczytania danych z numerem 25, funkcję obliczającą wszystko z numerem 25 i pobiera sobie wyniki z numerem 25. w tym samym czasie user o numerze 3 również wczytuje dane z nr.3, obliczenia nr.3 i pobiera swoje wyniki nr.3.

jak pisałem wcześniej stworzyłem sobie 2 niezależne wątki z których uruchomiłem procedury (procedury nie należą do klasy z wątkiem, procedury globalne, a w przypadku dll - należące do danych innych klas). no i uruchamiając taką procedurę w jednym wątku przez drugi wątek mam dostęp do danych wywołanych przez wątek 1. niby logiczne że tak będzie ponieważ odwołałem się do procedury globalnej ale w jaki sposób to przerobić aby działało tak jak ja chce? nie widzę możliwości stworzenia nowej klasy do której wpakuje wszystkie poprzednie klasy (hmm da się tak w ogóle?) aby wątki były niezależne. każdy wątek ma więc wykonywać te same zadania. pewnie trochę zagmatwałem ale nie wiem jak to inaczej wytłumaczyć.

ma ktoś pomysł jak to można rozwiązać?

//edit
właśnie patrzyłem że wszystkie zmienne wątkowe muszą zostać zadeklarowanie przy pomocy threadvar zamiast var właśnie po to aby wartość tej zmiennej była dla każdego wątku inna, przyjmowała indywidualna wartość. tylko że to się tyczy chyba tylko tych zmiennych które tworzone są w klasie wątku, a u mnie musi się to odnosić do innych klas bez wątkowych. w jaki sposób można teraz stworzyć nową klasę która by zawierała obiekty starej klasy? mam np. klasy

Tklasa1 = class(Tobject)
..
Tklasa2 = class(Tklasa1)
..
Tklasa3 = class(Tklasa2)

i żeby procedury i obiekt z klasy klasa3 mogły pracować w wątku to trzeba teraz zmienić klasę klasy Tklasa1 z Tobject na Tthread? tylko czy to tak działa?

0

sprobuje podrazyc ten temat.
na poczatek powiem jak to rozumiem - bo moze cos pokrecilem....

"jednoosobowy" program dziala tak:

start
cos_tam
wczytaj_biblioteke
x := jakas_funkcja z biblioteki
costam
y := inna_funkcj_zBiblioteki(x)
procedura_z_biblioteki
jakies_inne_rzeczy
koniec.

a serwer ma dzialac tak:

start
czeka_na_polaczenia
dla_kazdego_polaczenia_tworzy_watek
w_kazdym_watku(wykonaj_program_jednoosobowy)
...
koniec.

(zauwaz ze serwer nie wczytuje biblioteki - wszystko dzieje sie wewnatrz watku)
nie ma zadnych elementow globalnych.
minusem takiego rozwiazania moze byc duza ilosc pamieci zajmowanej
przez serwer - jesli biblioteka wymaga duzej ilosci zasobow.

jezeli biblioteka kozysta z plikow, sprzetu lub innych tego typu rzeczy,
lub chcesz aby jakies element programu byly wspolne dla wszystkich watkow
(np dla glownego i tych obliczeniowych (np zeby wyswietlac postep pracy w glownym programie))

wtedy niestety bedziesz musial pogrzebac wewnatrz biblioteki i zainteresowac sie sekcjami krytycznymi / mutexami (zob. TMultiReadExclusiveWriteSynchronizer i podobne). ale to juz powazna robota jest. ( a przeciez nie chemy sie przemeczac :D )

no i zastanow sie czy watki to jest to czego chcesz najbardziej :-)
dzieki watkom mozna poradzic sobie z sredniej wielkosci problemami
a do naprawde duzych watki sie nie nadaja bo nigdy nie bedziesz mial wystarczajacej ilosci procesorow zeby je wszystkie obsluzyc.

0

z tych wytycznych które dostałem to serwer ma działać chyba trochę inaczej. ponieważ wszystko ma się składać z klienta w javie(J) i biblioteki w delphi(D) to postaram się to podzielić:

start (J)
załadowanie biblioteki (J)
połączenie od usera 1 (J)
dynamiczne utworzenie wątku: (D)
np. watekobliczenowy( i : integer) - jakiś indentyfikator wątku
user 1 - utworzenie watku wątekobliczenowy(1) (D)
user 1 wywołuje obliczenia w wątku (1) [obliczenia(1)] (J)
połączenie od usera 2 (J)
dynamiczne tworzenie wątku: wątekobliczeniowy(2) (D)
user 1 - koniec obliczeń w wątku (1) [wyniki(1)], informacja(1) (D)
user 2 wywołanie obliczeń w wątku (2) [obliczenia(2)] (J)
user 1 - pobranie wyników z wątku (1) [wyniki(1)] (J)
user 2 - koniec obliczeń w wątku (2) [wyniki(2)], informacja(2) (D)
user 2 - pobranie wyników z wątku (2) [wyniki(2)] (J)
..
(usunięcie wątku po zakończeniu obliczeń i otrzymaniu takiego polecenia z javy)
końca chyba nie ma bo jeśli ma to być na serwerze to będzie pracowało cały czas.

mogłem gdzieś niewłaściwie przypisać (J) albo (D) ale mniej więcej tak to powinno działać. z javy wysyłana jest polecenie do utworzenia nowego wątku obliczeniowego, zwracany jest identyfikator tego wątku przez który wszystkie obliczenia, wyniki itd będą odwoływać się dla danego obiektu. ale to w bibliotece delphi ma być tworzony nowy wątek i nowe obliczenia a nie utworzenie wątku w javie i załadowanie do niego programu jednostanowiskowego. chociaż to rozwiązanie dla mnie byłoby wygodniejsze. a wątek i tak jest chyba jedynym rozwiązaniem jeśli dla kilku połączeń obliczenia mają się wykonywać od razu równolegle.
w każdym razie wielkie dzięki że odpowiedzi.

0

Trochę kombinowałem przy moim problemie ale potrzebuję pomocy bo kiepsko idzie. Zamiast jednej biblioteki z obliczeniami jest koncepcja dwóch. Jedna z modułem obliczeniowym zostaje tak jak była, natomiast dochodzi druga biblioteka która będzie obsługiwać tworzenie wątków i stanowić połączenie z javą. Próbowałem na prostym przykładzie pod delphi przetestować przetestować takie połączenie z dynamicznie tworzonymi wątkami które ładują sobie biblioteki. Wstawiłem 4 buttony: 2 do utworzenia 2 wątków (z załadowaniem do wątku biblioteki obliczeniowej) oraz 2 do wykonania obliczeń w tych wątkach i wyświetleniu jakiś obliczeń. Wszystko działa ok, jeśli załaduję bibliotekę do wątku 1 i potem chce wykonać obliczenia w wątku 2 (bez ładowania biblioteki) to wyrzuca błąd że nie znaleziono procedury z bibliotece (czyli nie korzysta z tej biblioteki dla wątku 1 - tak jak miało być). Mam jednak problem z identyfikacją wątków. W jaki sposób można "oznaczyć" wątki aby można się było do nich odwołać - do konkretnego wątku. Chodzi mi o dynamiczne wątki jak w temacie więc zmienne typu: watek1, watek2 itd nie wchodzą w grę. Nie jest znana liczba wątków, a po obliczeniach odpowiednie wątki trzeba usunąć. Myślałem żeby wywoływać wątki jako elementy tablicy z klasy Tthread ale: elementy są liczone od 0 i nie można nadać im indywidualnych numerów, przy kasowaniu danego elementu (wątku) z tablicy indeksy wszystkich pozostałych trzeba by pozmieniać i powysyłać te informacje do klientów (aby obliczenia się odnosiły do odpowiednich wątków). W jaki sposób przekazać ten identyfikator wątku? Jakoś przez właściwości? No i jak ogólnie to oznaczyć aby tworzyć te wątki dynamicznie jeśli nie przez tablice?

0

hmm a tworzyles kiedys jakies obiekty dynamicznie (np komponenty)?
najlepsze do tego sa listy.
robisz sobie np tak:

var ListaWatkow: TList;
    tmp: TWatek;
begin
  listaWatkow := TList.create;
  for i := 1 to n do begin
    tmp := TWatek.create;
    ListaWatkow.add(tmp);
  end;
end;

z <ort>usowaniem </ort>watkow to juz nie wiem jak zrobic (nie mam teraz pomyslu)
normalne obiekty sie <ort>usowa </ort>z listy tak:

  ListaWatkow.delete(x);  // x jest indeksem obiektu ktory chcesz usunac
lub
  ListaWatkow.remove(obiekt); //obiekt jest obiektem ktory chcesz usunac

ale w przypadku watkow trzeba jeszcze wiedziec kiedy go usunac...
moznaby sprobowac przekazac do watku (np przez parametr konstruktora)
liste na ktorej jest trzymany, a potem pod koniec procedury Execut (czy jak ona sie tam nazywa)
dodac takie cos:

  procedure TWatek.execute;
  begin
  freeonterminate := true;

  (...)

  // tu wypadaloby zablokowac jakas sekcje krytyczna bo ta lista jest w watku glownym i moga byc problemy 
  lista.remove(self);
  // a tu ja zwolnic
  end;

to tylko takie ogolne uwagi i jest szansa ze to nie zadzioala. pisze to z glowy, ale sam szukalbym w tym kierunku.

0

a moze wcale nie trzeba trzymac tych watkow?
moze wynik moznaby wyslac gdzies wprost z watku (np do pliku).

a w glownym programie tylko utworzyc watek i o nim zapomniec - sam sie zwolni jak sie skonczy

0

Kiedyś tworzyłem dynamicznie jakieś komponenty ale trochę czasu minęło. Problem z listą dalej polega na "parametrze/indeksie" wątku z listy. Załóżmy że na liście są 4 wątki, każdy user ma przyporządkowany numer wątku (indeks z listy). User 3 skończył obliczenia i jego wątek (element z listy) zostaje usunięty, czyli wylatuje 3 i 4 wchodzi na miejsce 3 (zmienia się oznaczenie/odwołanie do wątku o czym trzeba powiadomić usera)? Dobrze to rozumiem? Czy po 3 zostaje wolne miejsce i trzeba zmieniać rozmiar tablicy i tak za każdym razem po usunięciu elementu żeby lista się nie rozrosła? Z freeonterminate w wątku chyba nie przejdzie ponieważ założenie jest aby każda operacja była wykonywana oddzielnie (przesłanie danych do obliczeń, uruchomienie obliczeń, przerwanie obliczeń w razie potrzeby, pobranie wyników, zakończenie wątku/zwolnienie pamięci). Właśnie się zastanawiam nad wrzuceniem wszystkiego w jedną procedurę/funkcje która po otrzymaniu danych uruchomi obliczenia, zwróci wyniki oraz zwolni pamięć, tak jak wcześniej sugerowałeś. Chociaż to też nie wyeliminuje problemu z odwołaniem - musi być możliwość przerwania odpowiednich obliczeń :-/.

0

nie potrzebujesz 'parametru/indeksu'!
rozumiem ze chciales uzyc tego parametru zeby podac go klientowi aby ten wiedzial ktory watek go obsluguje, tak?
majac ten parametr klient pobieralby wskaznik do watku z tablicy.

zamiast tego mozesz klientowi od razu podac wskaznik do watku (wskaznik tez jest integerm).
w sumie nie musisz podawac wskaznika, mozesz podac sam watek:-) [dpisane: tzn obiekt watku]

//dopisane
a jak juz tak bardzo chcesz miec ten indeks to mozesz zrobic:

x := listaWatkow.indexOf(watek);
0

tak, wskaźnik przekazany by był klientowi żeby wiedział do którego wątku się odwołać, np. podczas przerwania obliczeń. przetestuję te rozwiązania i zobaczę jak to będzie działać.

0

pół roku minelo i trzeba wrócić do problemu bo nie został rozwiązany. nie zajmowałem się tym problemem jakiś czas i troche się zmieniło. sprawa wygląda tak.
mam stworzony obiektA klasy tthread zawierający inny obiektB mojej klasy który wykonuje obliczenia. w obiekcie A tworzone są obiekty B i tam się wszystko dzieje. tylko że obiekt B odwołuje się do biblioteki dll. każdy obiekt B łączy się niejako ze swoja kopią biblioteki dll. odwołanie do bibliteki wyglada następująco:

//zmienna w obiekcie B
var
  mojazmienna : TklasaC;

//zmienne w głownej procedurze wywolywanej do obliczen
var
  DLL         :THandle;
  MojaFunkcja : function( jakieś dane ) :TklasaC; stdcall;

begin
  DLL := LoadLibrary('biblioteka.dll');
  @MojaFunkcja := GetProcAddress(DLL, 'MojaFunkcja');
  mojazmienna := MojaFunkcja( jakieś dane );

  mojazmienna.procedura1; <- wywala błąd wewnątrz procedury dla > 1 wątków

  mojazmienna.procedura2;
end;

dla jednego wątku wszystko jest ok i nie ma problemów. ale już przy dwóch są błędy ponieważ np. operacje w procedurze1 po wczytaniu drugiego wątku jakby nadpisują dane danymi z wątku 2 a chcą wykonywac obliczenia dalej dla wątku 1 - to już nie te dane. no i wszystko sie wali. wcześniej probowałem robić obliczenia z deklaracją klasyA jako Tobject a nie tthread, ponieważ wielowątkowość jest zapewniona ze stronie aplikacji która łączy się z moim programem. tylko że tamta wielowątkowość jakby nie łądowała nowego obiektu tylko nadpisywała stary. siedze i kombinuje na rozne sposoby. znalazlem ze to cos jest nie tak z połączeniem z dll, chociaż połączeniem mam przez uchwyt zadeklarowany wewnątrz procedury, oddzielnie dla każdego obiektu i nie powinno to się gryźć. wcześniej juz znalazlem jeden błąd bo miałem zadeklarowana jedną zmienną globalną mojazmienna ,ktora nie byla z wazdnej klasie i wtedy odpalenie nowego watku powodowalo wymazanie starych danych i wykonanie calych obliczen na nowych. jakie moglem popelnić błedy, typy błędów? nawet te najprostrze i nagłupsze bo siedze nad tym juz nie wiem ile i nie mam nowych pomysłów. będę wdzięczny za kazda pomoc lub wskazówkę

//EDIT
własnie prześledziłem ładownaie biblioteki i wyszło ze oba wątki maja ten sam uchwyt... mam numer uchwytu po załadowaniu biblioteki dla pierwszego wątku i potem dla drugiego wątku ładuje się ten sam uchwyt, przerobiłem ładowanie biblioteki na 'tablice bibliotek' i dla tablicy [0,0] po załadowaniu pierwszej mam np. [5,0] a po załadowaniu drugiej [0,5].... kaszana
niby plik biblioteki jest jeden ale jak go załadować żeby każdy uchwyt miał własną kopie? kopiowanie pliku i usuwanie gdy juz sie wykorzysta jest bez sensu a to byla moja pierwsza i najprostrza mysl. wywalic uchwyt z procedury i wrzucic talibce globalną z ktorej bedzie pobierany? ale to tez uzyskam ten sam uchwyt. jakieś pomysły??

//EDIT2
zrobiłem 2 kopie biblioteki żeby każdy wątek załadował sobie swoją. ok- uchwyty inne i byłoby ok gdyby nie to że po załadowaniu drugiego uchwytu zniknął pierwszy, czyli prawie jak poprzednio [0,0], dla 1 [3,0]
po załadowaniu drugiego [0,7]. rozmiar tablicy mam zadeklarowany stały przy zmiennych. wywaliłem nawet deklaracje z procedury że niby drugi raz sie by ładowało i na nowo tworzyło tablice (chociaz procedury ładowane są dla osobnych obiektów wiec nie powinno miec to miejsca) i przeniosłem jako zmienna w klasie, dalej to samo. czy ja już za długo nad tym siedze? bo wiem ze to musi byc jakis banał

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