Seite 1 von 2
aktuelles Element einer LinkedList()
Verfasst: 12.05.2014 11:53
von stab
Hallo,
lt. Hilfe gibt es ja mind. 2 Möglichkeiten, sich ein Element in einer LinkedList() merken zu wollen.
Code: Alles auswählen
*Old_Element = @mylist() ; Ermittelt die Adresse des aktuellen Elements
ChangeCurrentElement(mylist(), *Old_Element) ; Wiederherstellen des letzten aktuellen Elements (von vor der Suche)
und mittels
Code: Alles auswählen
PushListPosition(Numbers())
PopListPosition(Numbers())
Gibt es bei den Methoden entscheidende Vor- und Nachteile?
Danke, danke !!
Re: aktuelles Element einer LinkedList()
Verfasst: 12.05.2014 12:00
von Kiffi
hier noch die dritte:
Code: Alles auswählen
ListIndex = ListIndex(Numbers())
SelectElement(Numbers(), ListIndex)
zu Vor- und Nachteilen kann ich nichts sagen.
Grüße ... Kiffi
Re: aktuelles Element einer LinkedList()
Verfasst: 12.05.2014 14:40
von BSP
Hallo stab.
Ich arbeite gerade sehr stark mit Listen und kann vielleicht etwas dazu sagen:
Ich bastel gerad (mal wieder) an einem Steuerprg. für meine Modelbahn.
Früher habe ich das mit Arrays gemacht, nun benutze ich mal Listen.
Aber ich gestehe, das nächste mal mache ich das wieder mit Arrays.
Du kannst Dir immer nur den Zeiger oder die Nummer auf das Element merken, das gerade aktuell ist.
(Aber das ist bei Listen grundsätzlich so).
Mein_drittes_element = @Liste
Oder:
Mein_drittes_element = ListIndex(Liste())
Was aber, wenn gerade das 5te Element aktuell ist?
Zur Frage:
PushListPosition(Numbers())
PopListPosition(Numbers())
Diese Anweisungen arbeiten mit einem Stapel.
Das heisst:
Das zuletzt gemerkte wird als erstes wieder hergestellt.
Das zu verstehen ist wichtig.
Du kannst damit kein Element direkt anspringen und wiederherstellen.
Verzählst Du Dich beim wiederherstellen, landes Du in einem falschen Element und suchst Dich bei der Fehlerfindung tot.
Ich persönlich benutze das garnicht.
*Old_Element = @mylist() ; Ermittelt die Adresse des aktuellen Elements
ChangeCurrentElement(mylist(), *Old_Element) ; Wiederherstellen des letzten aktuellen Elements (von vor der Suche)
Diese Möglichkeit ist sehr schnell, da Du ein Element „direkt“ anspringen kannst.
Es arbeitet mit Zeigern auf den Speicherort im Pc, wo die Elemente sich befinden.
Diese Zeiger musst Du Dir ermitteln und merken. (*Old_Element = @mylist())
Du solltest sie z.B. nicht speichern, da die Zeiger in einem späteren Neustart des Prg wahrscheinlich nicht mehr stimmen.
Das Prg legt die Liste vielleicht an einem ander Ort im Speicher ab und dann stimmen die Zeiger nicht mehr.
Du musst die Adressen nach einem Prg- Start neu ermitteln und eventuell bei Bedarf in einer weiteren Liste (einem Array ?) speichern.
ChangeCurrentElement(mylist(), *Old_Element) konntroliert nicht, ob es das Element gibt.
Es geht ja auch „ChangeCurrentElement(mylist(), 0)
Dann kann es an anderen Stellen im Prg zum Absturz kommen, und dann heraus zu finden, wo Deine Zeiger falsch eingestellt wurden, kann sehr schwer werden.
Ich arbeite z.Z. mit mehreren Listen deren Elemente auch noch abhängigkeiten zueinander haben.
Daher finde ich es teilweise sehr unübersichtlich, jedesmal
ChangeCurrentElement(mylist(),Mein_xtes_element)
aufzurufen. Oder die gesuchten Elemente erst einmal zu ermitteln.
If SelectElement(Numbers(), ListIndex)
Hat den Vorteil, Du kannst damit direkt das xte Element anspringen. (So vorhanden).
Das dritte Element ist immer das Dritte, egal wo die Liste im Speicher ist.
Die Methode ist aber langsamer, weil die Liste intern jedesmal durchlaufen wird, bis das gewünschte Element erreicht ist.
Diese Nummern kannst Du aber speichern.
Gruß : Bernd
Re: aktuelles Element einer LinkedList()
Verfasst: 12.05.2014 15:01
von ts-soft
Eine weitere Möglichkeit, die aber nur bedingt passt, wäre das Beispiel aus der Hilfe:
Verwendung einer Map zur Indexierung einer verketteten Liste
zu finden im "Einsteiger-Kapitel".
Entspricht mehr oder weniger aber der SelectElement Variante, aber etwas komfortabler
Gruß
Thomas
Re: aktuelles Element einer LinkedList()
Verfasst: 13.05.2014 10:28
von stab
Danke für die Antworten. Mittels PUSH und POP sollte es dann funktionieren.
Meine Intention:
Ich fülle 3 Listen mit Dateiinformationen aus einem Netzwerk.
Dies können 1ne oder auch 1000 sein.
Danach werden Informationen aus den Listen nacheinander abgerufen.
Da Netzwerk = manchmal lansam dauert dieser Vorgang entsprechend.
Ich möchte diese Listen gerne im Thread füllen und gleichzeitig schon mit der Abarbeitung der Listen beginnen.
Dazu muss ich mir halt das jeweilige Element merken, um die Reihenfolge einzuhalten. Ich denke, das bekomme ich auch hin.
Ich habe es nur noch nicht geschafft, eine LinkedList() einer ThreadProzedur zu übergeben.
Ich kann es zwar auch anders lösen, fände es aber geschickter und würde auch gerne wissen, wie es geht.
Das sollte doch mittels einer Structure gehen. Einfache Beispiele finde ich aber nicht.
Kann mir jemand einen Link geben oder ganz einfach die Übergabe mal zeigen?
Danke!
Re: aktuelles Element einer LinkedList()
Verfasst: 13.05.2014 11:18
von ts-soft
stab hat geschrieben:Ich habe es nur noch nicht geschafft, eine LinkedList() einer ThreadProzedur zu übergeben.
Das macht ja auch nicht unbedingt Sinn. Da die Liste sowieso per Mutex gesichert werden muß, damit nur ein Thread
zur selben Zeit darauf zugreifen kann, spricht nichts dagegen, eine globale oder shared Liste zu nutzen.
Gruß
Thomas
Re: aktuelles Element einer LinkedList()
Verfasst: 13.05.2014 11:39
von Deluxe0321
Als bsp für eine queue (copy & pasta aus projekt - entschuldigt mögliche nicht abgefangene fehler):
Code: Alles auswählen
DeclareModule Processor
Enumeration ;CMD
#CMD_FIRST
#CMD_RUN
#CMD_LOAD
#CMD_BUILD
#CMD_GET
#CMD_POST
#CMD_END
#CMD_LAST
EndEnumeration
Enumeration ;TStatus
#STATUS_ON
#STATUS_OFF
EndEnumeration
Declare Init()
Declare PostCMD(Handle.i,CMD.i,*UserData = 0)
Declare Release(Handle.i,Wait.i = #True)
EndDeclareModule
Module Processor
;{ - internal
Structure List_MyList
CMD.i
*Data
EndStructure
Structure Processor
HSemaphore.i
HMutex.i
TStatus.i
TThreadID.i
List LElements.List_MyList() ;< -- liste
EndStructure
Macro IsHandle()
If Not Handle.i : ProcedureReturn #False : EndIf
EndMacro
Procedure Processor(*Processor.Processor)
Protected SElement.List_MyList
Protected HSemaphore.i, HMutex.i
If Not *Processor
ProcedureReturn #False
EndIf
LockMutex(*Processor\HMutex.i)
*Processor\TStatus.i = #STATUS_ON
UnlockMutex(*Processor\HMutex.i)
Debug "Processor starting.."
Repeat
Debug "<-- Waiting for CMD :)"
WaitSemaphore(*Processor\HSemaphore.i)
LockMutex(*Processor\HMutex.i)
ResetList(*Processor\LElements())
FirstElement(*Processor\LElements())
CopyStructure(@*Processor\LElements(),@SElement,List_MyList)
DeleteElement(*Processor\LElements())
UnlockMutex(*Processor\HMutex)
Select SElement\CMD.i
Case #CMD_RUN
Debug " --> #CMD_RUN"
;delay um etwas "workload" zu simulieren
Delay(2000)
Case #CMD_LOAD
Debug " --> #CMD_LOAD"
;delay um etwas "workload" zu simulieren
Delay(300)
Case #CMD_BUILD
Debug " --> #CMD_BUILD"
;delay um etwas "workload" zu simulieren
Delay(6000)
Case #CMD_END
Debug " --> #CMD_END --> ENDE!"
LockMutex(*Processor\HMutex.i)
*Processor\TStatus.i = #STATUS_OFF
UnlockMutex(*Processor\HMutex.i)
Debug "<-- ending now.."
Break
EndSelect
ForEver
EndProcedure
;} - internal
Procedure Init()
*Processor.Processor = AllocateMemory(SizeOf(Processor))
If Not *Processor : ProcedureReturn #False : EndIf
InitializeStructure(*Processor,Processor)
*Processor\HMutex = CreateMutex()
*Processor\HSemaphore = CreateSemaphore()
;start thread
*Processor\TThreadID.i = CreateThread(@Processor(),*Processor)
If Not *Processor\TThreadID.i
FreeMutex(*Processor\HMutex.i)
FreeSemaphore(*Processor\HSemaphore.i)
ClearStructure(*Processor,Processor)
FreeMemory(*Processor)
EndIf
ProcedureReturn *Processor
EndProcedure
Procedure PostCMD(Handle.i,CMD.i,*UserData = 0)
IsHandle()
If Not (CMD.i > #CMD_FIRST And CMD.i < #CMD_LAST)
ProcedureReturn #False
EndIf
Protected *Processor.Processor = Handle.i
LockMutex(*Processor\HMutex)
If AddElement(*Processor\LElements())
With *Processor\LElements()
\CMD.i = CMD.i
\Data = *UserData
EndWith
Else
UnlockMutex(*Processor\HMutex)
ProcedureReturn #False
EndIf
UnlockMutex(*Processor\HMutex)
SignalSemaphore(*Processor\HSemaphore.i)
ProcedureReturn #True
EndProcedure
Procedure Release(Handle.i,FinishQueue.i = #True)
IsHandle()
Protected *Processor.Processor = Handle.i
If Not Wait.i
LockMutex(*Processor\HMutex.i)
ClearList(*Processor\LElements())
UnlockMutex(*Processor\HMutex.i)
EndIf
;"ende" senden
PostCMD(*Processor,#CMD_END)
While IsThread(*Processor\TThreadID.i)
Delay(10)
Wend
FreeMutex(*Processor\HMutex.i)
FreeSemaphore(*Processor\HSemaphore.i)
ClearStructure(*Processor,Processor)
FreeMemory(*Processor)
Debug "release done!"
ProcedureReturn #True
EndProcedure
EndModule
Process = Processor::Init()
If Not Process : End : EndIf
OpenConsole("Queue Test")
Repeat
PrintN("CMD: (type them) --> run, load, build, end")
Line.s = Input()
Select LCase(Line.s)
Case "run"
Processor::PostCMD(Process,Processor::#CMD_RUN)
PrintN(" --> RUN send, check debug output..") : PrintN("")
Case "load"
Processor::PostCMD(Process,Processor::#CMD_LOAD)
PrintN(" --> LOAD send, check debug output..") : PrintN("")
Case "build"
Processor::PostCMD(Process,Processor::#CMD_BUILD)
PrintN(" --> BUILD send, check debug output..") : PrintN("")
Case "end"
PrintN(" --> END send, check debug output..")
If Processor::Release(Process)
Break
EndIf
Default
PrintN("kenne ich nicht =P")
EndSelect
ForEver
Grüße
Re: aktuelles Element einer LinkedList()
Verfasst: 13.05.2014 11:56
von NicTheQuick
Mit einer ConcurrentQueue kann ich auch dienen:
Video: [PB] HowTo: ConcurrentQueue. Und hier noch mal auf meiner Seite:
Wie schreibe ich eine ConcurrentQueue.
Re: aktuelles Element einer LinkedList()
Verfasst: 14.05.2014 17:33
von stab
Hallo,
danke noch mal für die Tipps.
Das Video von NicTheQuick hatte ich mir schon vorher mal angesehen und gestaunt, wie einfach doch programmieren sein kann.
Ich bekomme aber schon Stirnrunzeln, wenn ich die zwei "::" sehe, kann damit garnichts anfangen und weiß auch nicht, ob das in den Anfängerbereich gehört. Ich finde dazu auch nichts in der Hilfe. Suchen kann man danach jedenfalls nicht. Vielleicht zeigt mir jemand mal, wo das erklärt wird.
Warum nicht Listen in eine ThreadProzedur übergeben?
Ich finde, das macht schon Sinn. Wenn ich 10 Listen bearbeiten will, müsste ich ja 10 Prozeduren anlegen. Bei einer Programmänderung ganz schön aufwendig.
Also, was ich gesucht habe war ein simples Beispiel für Anfänger, nach langem probieren hat es dann geklappt:
Code: Alles auswählen
Structure mitlisten
List zahlen.l()
EndStructure
Procedure ListeImThread(*zeiger.mitlisten)
LastElement(*zeiger\zahlen())
AddElement(*zeiger\zahlen())
*zeiger\zahlen() = 1
EndProcedure
Define.mitlisten adresse
CreateThread(@ListeImThread(),@adresse)
; etc
Daraus gemacht habe ich folgendes:
Code: Alles auswählen
Structure mitlisten
List zahlen.l()
List namen$()
; usw
EndStructure
Global listposition = 0
Global MaxListgroesse = 20
Procedure ListeImThread(*zeiger.mitlisten)
For z = 0 To MaxListgroesse -1
d.l = Random(3,1)*1000
Delay (d)
LastElement(*zeiger\zahlen())
AddElement(*zeiger\zahlen())
*zeiger\zahlen() = d + z
Debug "neuer Wert nach: " + Str(d/1000) + " Sekunden: " + Str(d+z)
Next
; z.B noch weitere Listen bearbeiten
AddElement(*zeiger\namen$()) : *zeiger\namen$() = "Willi"
AddElement(*zeiger\namen$()) : *zeiger\namen$() = "Moritz"
EndProcedure
Define.mitlisten adresse
CreateThread(@ListeImThread(),@adresse)
Procedure leseListe(List z.l())
If ListIndex(z()) = MaxListgroesse -1
listposition = 0
EndIf
If ListSize(z()) > listposition
SelectElement(z(), listposition)
Debug "Juhu: " + Str(z())
listposition +1
Else
Debug "Mist! Nichts neues!"
EndIf
EndProcedure
Repeat
leseListe(adresse\zahlen())
Delay(1500)
ForEver
Die Liste wird im Hintergrund gefüllt. Mal schneller, mal langsamer.
Ich kann aber schon daraus lesen, sofern Elemente vorhanden sind.
Bisher hat es funktioniert.
Oder spricht irgendwas dagegen, das so umzusetzen?
vg stab
Re: aktuelles Element einer LinkedList()
Verfasst: 14.05.2014 17:35
von stab
Ich sehe gerade, habe Quote mit Code verwechselt.
Sorry.