Ticket System [All OS]

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.
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Ticket System [All OS]

Beitrag von Bisonte »

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)
PureBasic 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​​
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Ticket System [All OS]

Beitrag von Mijikai »

Sieht gut aus ich vermute aber das eine normale Liste anstelle der Map nochmal schneller wäre.
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: Ticket System [All OS]

Beitrag von Bisonte »

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...
PureBasic 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​​
Benutzeravatar
mk-soft
Beiträge: 3853
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Ticket System [All OS]

Beitrag von mk-soft »

Maps sind schneller. Gerade wenn man viele angelegt hat. Auch wenn man vorher ein Key erstellen muss.
Hatte ich schon mal getestet. :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Ticket System [All OS]

Beitrag von Mijikai »

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.
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Ticket System [All OS]

Beitrag von Mijikai »

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. :wink:
Ich habe bisher immer Listen für schneller gehalten.
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Ticket System [All OS]

Beitrag von Mijikai »

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
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: Ticket System [All OS]

Beitrag von Bisonte »

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
PureBasic 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​​
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Ticket System [All OS]

Beitrag von Mijikai »

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)
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: Ticket System [All OS]

Beitrag von Bisonte »

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 ! :allright:
PureBasic 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​​
Antworten