Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Bisonte
Beiträge: 2468 Registriert: 01.04.2007 20:18
Beitrag
von Bisonte » 22.08.2019 08:33
Hallo.
Hier hab ich mal das Ticket Beispiel aus dem PB-SDK (ObjectManagement) annähernd nach PB übersetzt.
Ich habe hierzu auch mal das "Pseudo OOP Konzept" benutzt um mehrere TicketObjekte ohne Mehraufwand haben zu können.
Ich hoffe auf Fragen, Verbesserungen und Kritik
Code: Alles auswählen
DeclareModule Ticket
EnableExplicit
Interface iTicket
CreateTicket(Ticket) ; Erstellt eine ID (#PB_Any ist möglich)
IsTicket(Ticket) ; Gibt eine TicketID zurück oder False
TicketID(Ticket) ;
GetTicket(TicketID)
FreeTicket(Ticket)
DestroyTicket()
EndInterface
Declare.i CreateTicketObject(StructureSize)
EndDeclareModule
Module Ticket
Structure obj
vTable.i
StructureSize.q
Map Object.i()
EndStructure
Procedure.i IsTicket(*this.obj, Ticket)
Protected Result = #Null
If FindMapElement(*this\Object(), Str(Ticket))
Result = *this\Object()
EndIf
ProcedureReturn Result
EndProcedure
Procedure.i FreeTicket(*this.obj, Ticket)
Protected *Mem = IsTicket(*this, Ticket)
If *Mem
FreeMemory(*Mem)
DeleteMapElement(*this\Object(), Str(Ticket))
EndIf
EndProcedure
Procedure.i CreateTicket(*this.obj, Ticket)
Protected Result = Ticket, *Mem = #Null
If *this\StructureSize > 0
*Mem = AllocateMemory(*this\StructureSize)
If *Mem
If Ticket = #PB_Any
Result = *Mem
Else
FreeTicket(*this, Ticket)
EndIf
If AddMapElement(*this\Object(), Str(Result))
*this\Object() = *Mem
EndIf
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure.i TicketID(*this.obj, Ticket)
Protected Result = IsTicket(*this, Ticket)
ProcedureReturn Result
EndProcedure
Procedure.i GetTicket(*this.obj, TicketID)
Protected Result = #Null
ForEach *this\Object()
If *this\Object() = TicketID
Result = Val(MapKey(*this\Object()))
Break
EndIf
Next
ProcedureReturn Result
EndProcedure
Procedure.i DestroyTicket(*this.obj)
ForEach *this\Object()
If *this\Object()
FreeMemory(*This\Object())
EndIf
Next
FreeStructure(*this) : *this = #Null
ProcedureReturn *this
EndProcedure
Procedure.i CreateTicketObject(StructureSize)
Protected *this.obj = AllocateStructure(obj)
If *this
*this\vTable = ?vTable_iTicket
*this\StructureSize = StructureSize
ClearMap(*this\Object())
EndIf
ProcedureReturn *this
EndProcedure
DataSection
vTable_iTicket:
Data.i @CreateTicket()
Data.i @IsTicket()
Data.i @TicketID()
Data.i @GetTicket()
Data.i @FreeTicket()
Data.i @DestroyTicket()
EndDataSection
EndModule
UseModule Ticket
Structure myTicket
Value.i
EndStructure
myGadgets.iTicket = CreateTicketObject(SizeOf(myTicket))
myGadget = myGadgets\CreateTicket(5)
myGadgetID = myGadgets\TicketID(myGadget)
If myGadgetID
InitializeStructure(myGadgetID, myTicket)
EndIf
Debug myGadget
Debug myGadgetID
Debug myGadgets\IsTicket(myGadget)
P ureB asic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom
Mijikai
Beiträge: 754 Registriert: 25.09.2016 01:42
Beitrag
von Mijikai » 22.08.2019 12:45
Sieht gut aus ich vermute aber das eine normale Liste anstelle der Map nochmal schneller wäre.
Bisonte
Beiträge: 2468 Registriert: 01.04.2007 20:18
Beitrag
von Bisonte » 22.08.2019 16:56
Mijikai hat geschrieben: Sieht gut aus ich vermute aber das eine normale Liste anstelle der Map nochmal schneller wäre.
Map hab ich genommen, wegen dem direkten Zugriff. Bei einer Liste müsste man ja immer durchiterieren.
Fällt bei kleinen Sachen nicht auf, aber bei sehr vielen "Tickets" bestimmt...
P ureB asic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom
mk-soft
Beiträge: 3853 Registriert: 24.11.2004 13:12
Wohnort: Germany
Beitrag
von mk-soft » 22.08.2019 17:04
Maps sind schneller. Gerade wenn man viele angelegt hat. Auch wenn man vorher ein Key erstellen muss.
Hatte ich schon mal getestet.
Mijikai
Beiträge: 754 Registriert: 25.09.2016 01:42
Beitrag
von Mijikai » 22.08.2019 18:28
Bisonte hat geschrieben: Bei einer Liste müsste man ja immer durchiterieren.
Fällt bei kleinen Sachen nicht auf, aber bei sehr vielen "Tickets" bestimmt...
Geht ohne wie bei einer Map.
Mijikai
Beiträge: 754 Registriert: 25.09.2016 01:42
Beitrag
von Mijikai » 22.08.2019 18:32
mk-soft hat geschrieben: Maps sind schneller. Gerade wenn man viele angelegt hat. Auch wenn man vorher ein Key erstellen muss.
Hatte ich schon mal getestet.
Ich habe bisher immer Listen für schneller gehalten.
Mijikai
Beiträge: 754 Registriert: 25.09.2016 01:42
Beitrag
von Mijikai » 22.08.2019 20:29
Hab mal ne Listen Variante geschrieben und nen Speed Test gemacht.
Die Liste war ca 7x schneller be 100k Tickets.
Hier der Code zum Testen:
Code: Alles auswählen
EnableExplicit
DeclareModule Ticket
;TicketSystem
;Author Bisonte
EnableExplicit
Interface iTicket
CreateTicket(Ticket) ; Erstellt eine ID (#PB_Any ist möglich)
IsTicket(Ticket) ; Gibt eine TicketID zurück oder False
TicketID(Ticket) ;
GetTicket(TicketID)
FreeTicket(Ticket)
DestroyTicket()
EndInterface
Declare.i CreateTicketObject(StructureSize)
EndDeclareModule
Module Ticket
Structure obj
vTable.i
StructureSize.q
Map Object.i()
EndStructure
Procedure.i IsTicket(*this.obj, Ticket)
Protected Result = #Null
If FindMapElement(*this\Object(), Str(Ticket))
Result = *this\Object()
EndIf
ProcedureReturn Result
EndProcedure
Procedure.i FreeTicket(*this.obj, Ticket)
Protected *Mem = IsTicket(*this, Ticket)
If *Mem
FreeMemory(*Mem)
DeleteMapElement(*this\Object(), Str(Ticket))
EndIf
EndProcedure
Procedure.i CreateTicket(*this.obj, Ticket)
Protected Result = Ticket, *Mem = #Null
If *this\StructureSize > 0
*Mem = AllocateMemory(*this\StructureSize)
If *Mem
If Ticket = #PB_Any
Result = *Mem
Else
FreeTicket(*this, Ticket)
EndIf
If AddMapElement(*this\Object(), Str(Result))
*this\Object() = *Mem
EndIf
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure.i TicketID(*this.obj, Ticket)
Protected Result = IsTicket(*this, Ticket)
ProcedureReturn Result
EndProcedure
Procedure.i GetTicket(*this.obj, TicketID)
Protected Result = #Null
ForEach *this\Object()
If *this\Object() = TicketID
Result = Val(MapKey(*this\Object()))
Break
EndIf
Next
ProcedureReturn Result
EndProcedure
Procedure.i DestroyTicket(*this.obj)
ForEach *this\Object()
If *this\Object()
FreeMemory(*This\Object())
EndIf
Next
FreeStructure(*this) : *this = #Null
ProcedureReturn *this
EndProcedure
Procedure.i CreateTicketObject(StructureSize)
Protected *this.obj = AllocateStructure(obj)
If *this
*this\vTable = ?vTable_iTicket
*this\StructureSize = StructureSize
ClearMap(*this\Object())
EndIf
ProcedureReturn *this
EndProcedure
DataSection
vTable_iTicket:
Data.i @CreateTicket()
Data.i @IsTicket()
Data.i @TicketID()
Data.i @GetTicket()
Data.i @FreeTicket()
Data.i @DestroyTicket()
EndDataSection
EndModule
DeclareModule TICKET2
;TicketSystem
;Author Mijikai
Interface TICKET_INTERFACE
Id.i()
Validate.i()
Info.i()
Size.i()
Release.i()
EndInterface
Interface MANAGER_INTERFACE
TicketCreate.i(TickedId.i = #PB_Any)
TicketCount.i()
TicketInvalidate.i(Ticket.i)
Release.i()
EndInterface
Declare.i Manager(TicketSize.i)
EndDeclareModule
Module TICKET2
EnableExplicit
Structure SLOT_STRUCT
*vtable
*id.TICKET_STRUCT
*manager.MANAGER_STRUCT
*buffer
EndStructure
Structure TICKET_STRUCT
*vtable
id.i
*info.SLOT_STRUCT
EndStructure
Structure MANAGER_STRUCT
*vtable
ticket_size.i
List slot.SLOT_STRUCT()
state.SLOT_STRUCT
EndStructure
Procedure.i Manager(TicketSize.i)
Protected *manager.MANAGER_STRUCT
If TicketSize > #Null
*manager = AllocateStructure(MANAGER_STRUCT)
If *manager
*manager\vtable = ?vtable_manager
*manager\ticket_size = TicketSize
*manager\state\manager = *manager
EndIf
EndIf
ProcedureReturn *manager
EndProcedure
Procedure.i ManagerTicketCreate(*manager.MANAGER_STRUCT,TickedId.i = #PB_Any)
Protected *ticket.TICKET_STRUCT
*ticket = AllocateMemory(SizeOf(TICKET_STRUCT) + *manager\ticket_size)
If *ticket
If AddElement(*manager\slot())
*ticket\vtable = ?vtable_ticket
If TickedId = #PB_Any
*ticket\id = *ticket
Else
*ticket\id = TickedId
EndIf
*ticket\info = *manager\slot()
*manager\slot()\id = *ticket
*manager\slot()\manager = *manager
*manager\slot()\buffer = *ticket + SizeOf(TICKET_STRUCT)
ProcedureReturn *ticket
EndIf
FreeMemory(*ticket)
EndIf
ProcedureReturn #Null
EndProcedure
Procedure.i ManagerTicketCount(*manager.MANAGER_STRUCT)
ProcedureReturn ListSize(*manager\slot())
EndProcedure
Procedure.i ManagerTicketInvalidate(*manager.MANAGER_STRUCT,*ticket.TICKET_STRUCT)
If Not *ticket\info = *manager\state
ChangeCurrentElement(*manager\slot(),*ticket\info)
If *manager\slot()
DeleteElement(*manager\slot())
EndIf
*ticket\info = *manager\state
EndIf
ProcedureReturn #Null
EndProcedure
Procedure.i ManagerRelease(*manager.MANAGER_STRUCT)
ForEach *manager\slot()
FreeMemory(*manager\slot()\id)
Next
FreeList(*manager\slot())
FreeStructure(*manager)
ProcedureReturn #Null
EndProcedure
Procedure.i TicketId(*ticket.TICKET_STRUCT)
ProcedureReturn *ticket\id
EndProcedure
Procedure.i TicketValidate(*ticket.TICKET_STRUCT)
ProcedureReturn Bool(Not *ticket\info = *ticket\info\manager\state)
EndProcedure
Procedure.i TicketInfo(*ticket.TICKET_STRUCT)
ProcedureReturn *ticket\info\buffer
EndProcedure
Procedure.i TicketSize(*ticket.TICKET_STRUCT)
ProcedureReturn *ticket\info\manager\ticket_size
EndProcedure
Procedure.i TicketRelease(*ticket.TICKET_STRUCT)
If TicketValidate(*ticket)
ManagerTicketInvalidate(*ticket\info\manager,*ticket)
EndIf
FreeMemory(*ticket)
ProcedureReturn #Null
EndProcedure
DataSection
vtable_manager:
Data.i @ManagerTicketCreate()
Data.i @ManagerTicketCount()
Data.i @ManagerTicketInvalidate()
Data.i @ManagerRelease()
vtable_ticket:
Data.i @TicketId()
Data.i @TicketValidate()
Data.i @TicketInfo()
Data.i @TicketSize()
Data.i @TicketRelease()
EndDataSection
EndModule
; Global *manager.TICKET::MANAGER_INTERFACE
; Global Dim *ticket.TICKET::TICKET_INTERFACE(1000)
; Global index.i
;
; *manager = TICKET::Manager(128)
;
; If *manager
;
; For index = 0 To 999
; *ticket(index) = *manager\TicketCreate(index)
; If *ticket(index)
; Debug *ticket(index)\Id()
; Debug *ticket(index)\Validate()
; Debug *ticket(index)\Info()
; Debug *ticket(index)\Size()
; Debug *manager\TicketCount()
; Debug "-> invalidate!"
; *manager\TicketInvalidate(*ticket(index))
; Debug *ticket(index)\Validate()
; *ticket(index)\Release()
; Debug "------------"
; EndIf
; Next
;
; *manager\Release()
; EndIf
Global index.i
Global *ticket.Ticket::iTicket
Global *manager.TICKET2::MANAGER_INTERFACE
Global *tk.TICKET2::TICKET_INTERFACE
Global dummy.i
Global check.i
Global start.q
Global stop.q
Global test.i
test = 100000
*ticket = Ticket::CreateTicketObject(128)
*manager = TICKET2::Manager(128)
start = ElapsedMilliseconds()
For index = 1 To test
dummy = *ticket\CreateTicket(index)
check = *ticket\IsTicket(dummy)
Next
*ticket\FreeTicket(*ticket)
stop = ElapsedMilliseconds()
MessageRequester("A",Str(stop - start))
start = ElapsedMilliseconds()
For index = 1 To test
*tk = *manager\TicketCreate(index)
check = *tk\Validate()
Next
*manager\Release()
stop = ElapsedMilliseconds()
MessageRequester("B",Str(stop - start))
End
Bisonte
Beiträge: 2468 Registriert: 01.04.2007 20:18
Beitrag
von Bisonte » 23.08.2019 09:19
Irgendwie schnall ich das gerade nicht.... Wie kommt ich denn in deinem Interface an eine ID ran ?
Code: Alles auswählen
myGadgets.Ticket::iTicket = TICKET::CreateTicketObject(128)
myGadget = myGadgets\CreateTicket(5)
myGadgetID = myGadgets\TicketID(myGadget)
myGadget2 = myGadgets\CreateTicket(#PB_Any)
myGadgetID2 = myGadgets\TicketID(myGadget2)
If myGadgetID
InitializeStructure(myGadgetID, myTicket)
EndIf
Debug myGadget ; 5
Debug myGadgetID ; Pointer
Debug myGadget2 ; Pointer = GadgetNo
Debug myGadgetID2 ; Pointer
P ureB asic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom
Mijikai
Beiträge: 754 Registriert: 25.09.2016 01:42
Beitrag
von Mijikai » 23.08.2019 12:07
Jedes Ticket kennt seine Id.
Code: Alles auswählen
*manager = TICKET::Manager(128)
*ticket = *manager\TicketCreate(123)
Debug *ticket\Id()
Ticket Buffer:
Code: Alles auswählen
Debug *ticket\Info();<- returns the reserved buffer
Debug *ticket\Size();<- returns the reserved buffer size
Code: Alles auswählen
Structure myTicket
Value.i
EndStructure
Global *manager.TICKET::MANAGER_INTERFACE
Global *ticket.TICKET::TICKET_INTERFACE
*manager = TICKET::Manager(128)
*ticket = *manager\TicketCreate(5)
Debug *ticket\Id()
InitializeStructure(*ticket\Info(),myTicket)
Bisonte
Beiträge: 2468 Registriert: 01.04.2007 20:18
Beitrag
von Bisonte » 23.08.2019 20:53
Hm wenn ich die Slots der MAP() erhöhe, ist die MAP gleich schnell (+- 1-2ms)... Aber ich finde das meine Version mehr "PB-Syntax" ist, bzw. leichter zu durchschauen...
Aber ich hab sie ja auch gebaut
Datt is datt schöne hier...
Eine Anforderung, mehrere Lösungen !
P ureB asic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom