Seite 1 von 2

Ticket System [All OS]

Verfasst: 22.08.2019 08:33
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)

Re: Ticket System [All OS]

Verfasst: 22.08.2019 12:45
von Mijikai
Sieht gut aus ich vermute aber das eine normale Liste anstelle der Map nochmal schneller wäre.

Re: Ticket System [All OS]

Verfasst: 22.08.2019 16:56
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...

Re: Ticket System [All OS]

Verfasst: 22.08.2019 17:04
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:

Re: Ticket System [All OS]

Verfasst: 22.08.2019 18:28
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.

Re: Ticket System [All OS]

Verfasst: 22.08.2019 18:32
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.

Re: Ticket System [All OS]

Verfasst: 22.08.2019 20:29
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

Re: Ticket System [All OS]

Verfasst: 23.08.2019 09:19
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

Re: Ticket System [All OS]

Verfasst: 23.08.2019 12:07
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)

Re: Ticket System [All OS]

Verfasst: 23.08.2019 20:53
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: