From 77e4b066cb8d506b4bc944ab4eb2d6e4679e2202 Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Sat, 15 Jun 2024 13:58:30 +0300 Subject: enable multithreading with goroutines (#20) --- cmd/parser.go | 79 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 33 deletions(-) (limited to 'cmd/parser.go') diff --git a/cmd/parser.go b/cmd/parser.go index f21d91f..06ebbfe 100644 --- a/cmd/parser.go +++ b/cmd/parser.go @@ -4,21 +4,17 @@ import ( "errors" "fmt" "os" - "strings" + "path/filepath" + "sync" "github.com/pektezol/bitreader" "github.com/pektezol/sdp.go/pkg/packets" + "github.com/pektezol/sdp.go/pkg/types" "github.com/pektezol/sdp.go/pkg/writer" ) -type Demo struct { - Headers packets.Headers `json:"headers"` - Messages []packets.Message `json:"messages"` -} - type Parser struct { DemoPath string - writer strings.Builder } func NewParser(demoPath string) *Parser { @@ -35,48 +31,61 @@ func main() { os.Exit(1) } parser := NewParser(os.Args[1]) - _, err := parser.ParseDemos() + demos, err := parser.ParseDemos() if err != nil { fmt.Println(err.Error()) os.Exit(1) } - fmt.Println(parser.GetOutput()) -} - -func (p *Parser) GetOutput() string { - return p.writer.String() + for _, d := range demos { + fmt.Println(d.Writer.GetOutputString()) + // You can also marshal structs into JSON and print them: + // out, _ := json.Marshal(d) + // fmt.Println(string(out)) + } } -func (p *Parser) ParseDemos() ([]Demo, error) { - writer.AppendLine("Generated By: github.com/pektezol/sdp.go") +func (p *Parser) ParseDemos() ([]*types.Demo, error) { files, err := os.ReadDir(p.DemoPath) if err != nil { // not a directory file, err := os.Open(p.DemoPath) if err != nil { - return []Demo{}, err + return []*types.Demo{}, err } defer file.Close() + demo := &types.Demo{} + demo.Writer = writer.NewWriter() + demo.Writer.AppendLine("Generated By: github.com/pektezol/sdp.go") reader := bitreader.NewReader(file, littleEndian) - demo := demoParserHandler(reader, file.Name()) - p.writer = writer.GetWriter() - return []Demo{demo}, nil + p.demoParserHandler(reader, file.Name(), demo, nil) + return []*types.Demo{demo}, nil } else { - demos := []Demo{} // directory + demoCount := 0 for _, fileinfo := range files { if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" { - file, err := os.Open(p.DemoPath + fileinfo.Name()) + demoCount++ + } + } + wg := new(sync.WaitGroup) + wg.Add(demoCount) + demos := make([]*types.Demo, demoCount) + for i := 0; i < len(demos); i++ { + demos[i] = &types.Demo{} + demos[i].Writer = writer.NewWriter() + demos[i].Writer.AppendLine("Generated By: github.com/pektezol/sdp.go") + } + for i, fileinfo := range files { + if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" { + file, err := os.Open(filepath.Join(p.DemoPath, fileinfo.Name())) if err != nil { - return []Demo{}, err + return []*types.Demo{}, err } defer file.Close() - reader := bitreader.NewReader(file, littleEndian) - demo := demoParserHandler(reader, file.Name()) - demos = append(demos, demo) + go p.demoParserHandler(bitreader.NewReader(file, littleEndian), file.Name(), demos[i], wg) } } - p.writer = writer.GetWriter() + wg.Wait() if len(demos) == 0 { return demos, errors.New("no demo found in given directory") } @@ -84,23 +93,27 @@ func (p *Parser) ParseDemos() ([]Demo, error) { } } -func demoParserHandler(reader *bitreader.Reader, filename string) Demo { - demo := Demo{} - writer.AppendLine("\nFile Name: %s", filename) +func (p *Parser) demoParserHandler(reader *bitreader.Reader, filename string, demo *types.Demo, wg *sync.WaitGroup) { + demo.Writer.AppendLine("\nFile Name: %s", filename) // this is for recovering after a panic inside parse headers and packet. // this approach was taken since error handling bitreader functions would take a long time. defer func() { if err := recover(); err != nil { - writer.AppendLine("failed to parse demo: %v", err) + if wg != nil { + wg.Done() + } + demo.Writer.AppendLine("failed to parse demo: %v", err) } }() - demo.Headers = packets.ParseHeaders(reader) + demo.Headers = packets.ParseHeaders(reader, demo) for { - message := packets.ParseMessage(reader) + message := packets.ParseMessage(reader, demo) demo.Messages = append(demo.Messages, message) if message.PacketType == 7 { + if wg != nil { + wg.Done() + } break } } - return demo } -- cgit v1.2.3