github.com/pawelgaczynski/gain@v0.4.0-alpha.0.20230821120126-41f1e60a18da/submitter_batch.go (about) 1 // Copyright (c) 2023 Paweł Gaczyński 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package gain 16 17 import ( 18 "errors" 19 "fmt" 20 "syscall" 21 "time" 22 23 gainErrors "github.com/pawelgaczynski/gain/pkg/errors" 24 "github.com/pawelgaczynski/giouring" 25 ) 26 27 var waitForArray = []uint32{ 28 1, 29 32, 30 64, 31 96, 32 128, 33 256, 34 384, 35 512, 36 768, 37 1024, 38 1536, 39 2048, 40 3072, 41 4096, 42 5120, 43 6144, 44 7168, 45 8192, 46 10240, 47 } 48 49 type batchSubmitter struct { 50 ring *giouring.Ring 51 timeoutTimeSpec syscall.Timespec 52 waitForIndex uint32 53 waitFor uint32 54 } 55 56 func (s *batchSubmitter) submit() error { 57 _, err := s.ring.SubmitAndWaitTimeout(s.waitFor, &s.timeoutTimeSpec, nil) 58 if errors.Is(err, syscall.EAGAIN) || errors.Is(err, syscall.EINTR) || 59 errors.Is(err, syscall.ETIME) { 60 if s.waitForIndex != 0 { 61 s.waitForIndex-- 62 s.waitFor = waitForArray[s.waitForIndex] 63 } 64 65 return gainErrors.ErrSkippable 66 } 67 68 if err != nil { 69 return fmt.Errorf("submitAndWaitTimeout error: %w", err) 70 } 71 72 return nil 73 } 74 75 func (s *batchSubmitter) advance(n uint32) { 76 s.ring.CQAdvance(n) 77 78 var ( 79 index uint32 80 lenWaitForArray = uint32(len(waitForArray)) 81 ) 82 83 for index = 1; index < lenWaitForArray; index++ { 84 if waitForArray[index] > n { 85 break 86 } 87 s.waitForIndex = index 88 } 89 s.waitFor = waitForArray[s.waitForIndex] 90 } 91 92 func newBatchSubmitter(ring *giouring.Ring) *batchSubmitter { 93 submitter := &batchSubmitter{ 94 ring: ring, 95 timeoutTimeSpec: syscall.NsecToTimespec((time.Millisecond).Nanoseconds()), 96 } 97 submitter.waitFor = waitForArray[submitter.waitForIndex] 98 99 return submitter 100 }