add nomutex support to disable it per message struct

This commit is contained in:
Jeff Carr 2025-01-12 08:28:23 -06:00
parent 721bbd8f92
commit 10f75f87a6
9 changed files with 70 additions and 32 deletions

View File

@ -47,6 +47,10 @@ build: goimports
bak: bak:
mv -f autogenpb autogenpb.last mv -f autogenpb autogenpb.last
redo-protobuf:
rm -f *.pb.go
autogenpb --proto file.proto --package main
install: test install: test
GO111MODULE=off go install \ GO111MODULE=off go install \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"

View File

@ -15,24 +15,24 @@ package main;
import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp import "google/protobuf/timestamp.proto"; // Import the well-known type for Timestamp
message Apple { // `autogenpb:marshal` message Apple {
string name = 1; // `autogenpb:unique` // generates SortByxxx() and AppendUnique() functions string name = 1; // `autogenpb:unique` // generates SortByxxx() and AppendUnique() functions
string genus = 2; // `autogenpb:unique` // generates same thing here but SortByGenus() string genus = 2; // `autogenpb:unique` // generates same thing here but SortByGenus()
google.protobuf.Timestamp ctime = 3; // when the apple was born google.protobuf.Timestamp ctime = 3; // when the apple was born
} }
message Pear { message Pear { // `autogenpb:nomutex`
string name = 1; // `autogenpb:sort` string name = 1; // `autogenpb:sort`
string favorite = 2; // `autogenpb:sort` `autogenpb:unique` string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
} }
message Banana { message Banana { // `autogenpb:nomutex`
repeated string name = 1; // `autogenpb:sort` repeated string name = 1; // `autogenpb:sort`
string favorite = 2; // `autogenpb:sort` `autogenpb:unique` string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
string country = 3; // `autogenpb:sort` string country = 3; // `autogenpb:sort`
} }
message Basket { message Basket { // `autogenpb:nomutex`
repeated string name = 1; // `autogenpb:sort` `autogenpb:unique` repeated string name = 1; // `autogenpb:sort` `autogenpb:unique`
string favorite = 2; // `autogenpb:sort` `autogenpb:unique` string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
int64 price = 3; // `autogenpb:sort` int64 price = 3; // `autogenpb:sort`
@ -42,7 +42,7 @@ message Basket {
} }
// "Fruit" must exist. you can put anything in it // "Fruit" must exist. you can put anything in it
message Fruit { // `autogenpb:marshal` message Fruit {
string brand = 1; // `autogenpb:unique` `autogenpb:sort` string brand = 1; // `autogenpb:unique` `autogenpb:sort`
repeated Apple apples = 2; repeated Apple apples = 2;
repeated Pear pears = 3; repeated Pear pears = 3;

View File

@ -45,6 +45,7 @@ message MsgName {
repeated MsgVar vars = 9; // store all the vars in the message repeated MsgVar vars = 9; // store all the vars in the message
bool needIter = 10; // true if the sort iterator has not been generated yet bool needIter = 10; // true if the sort iterator has not been generated yet
bool needAll = 11; // true if the sort iterator has not been generated yet bool needAll = 11; // true if the sort iterator has not been generated yet
bool noMutex = 12; // only use the global mutex
} }
message Sort { message Sort {

View File

@ -60,7 +60,13 @@ func (pb *Files) makeNewSortfile(pf *File) error {
APPLE := s.VarType APPLE := s.VarType
APPLES := s.VarName APPLES := s.VarName
LOCK := s.Lockname LOCK := s.Lockname
funcdef := newIterAll(wSort, FRUIT, APPLE, APPLES, LOCK)
msg := pf.findMsg(s.VarType)
if msg == nil {
return fmt.Errorf("failed to find struct %s", s.VarType)
}
funcdef := msg.newIterAll(wSort, FRUIT, APPLE, APPLES, LOCK)
log.Printf("JUNK: %-2d %20s %20s %20s %20s %s\n", i, FRUIT, APPLE, "", LOCK, funcdef) log.Printf("JUNK: %-2d %20s %20s %20s %20s %s\n", i, FRUIT, APPLE, "", LOCK, funcdef)
} }
log.Printf("\n") log.Printf("\n")
@ -73,7 +79,12 @@ func (pb *Files) makeNewSortfile(pf *File) error {
VARNAME := s.VarName VARNAME := s.VarName
LOCK := s.Lockname LOCK := s.Lockname
funcdef := addSelectAll(wSort, PARENT, CHILD, VARNAME, LOCK) msg := pf.findMsg(s.VarType)
if msg == nil {
return fmt.Errorf("failed to find struct %s", s.VarType)
}
funcdef := msg.addSelectAll(wSort, PARENT, CHILD, VARNAME, LOCK)
log.Printf("SORT: %-2d %20s %20s %20s %20s %s\n", i, PARENT, CHILD, VARNAME, LOCK, funcdef) log.Printf("SORT: %-2d %20s %20s %20s %20s %s\n", i, PARENT, CHILD, VARNAME, LOCK, funcdef)
} }
log.Printf("END SELECT\n") log.Printf("END SELECT\n")
@ -121,7 +132,7 @@ func (pb *Files) makeNewSortfile(pf *File) error {
} }
sortname := s.VarType + v.VarName sortname := s.VarType + v.VarName
selectName := "selectAll" + VARNAME selectName := "selectAll" + VARNAME
funcdef := newSortBy(wSort, PARENT, s.VarType, sortname, sortby, selectName) funcdef := newSortBy(wSort, PARENT, s.VarType, sortname, sortby, selectName, v.VarName)
log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcdef) log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcdef)
} else { } else {
funcname := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType + " # can not do this yet" funcname := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType + " # can not do this yet"

View File

@ -7,17 +7,6 @@ import (
// generates Find() and some other stuff // generates Find() and some other stuff
func (msg *MsgName) getLockname(s string) string {
// leave this function stubbed in for development of autogenpb
// if argv.Mutex {
// // use the mutex lock from the modified protoc.pb.go file
// return s + ".Lock"
// // return s // causes Marshal() to panic? always use the variable name 'Lock'?
// }
// a single global lock by struct name
return msg.Lockname
}
func (msg *MsgName) generateFindBy(w io.Writer, FUNCNAME, STRUCT, VARNAME, VARTYPE, COLOR string) string { func (msg *MsgName) generateFindBy(w io.Writer, FUNCNAME, STRUCT, VARNAME, VARTYPE, COLOR string) string {
LOCK := msg.getLockname("x") LOCK := msg.getLockname("x")
funcdef := "func (x *" + STRUCT + ") " + FUNCNAME + "(s string) *" + VARTYPE funcdef := "func (x *" + STRUCT + ") " + FUNCNAME + "(s string) *" + VARTYPE

View File

@ -13,8 +13,19 @@ import (
"go.wit.com/log" "go.wit.com/log"
) )
func (msg *MsgName) getLockname(s string) string {
// leave this function stubbed in for development of autogenpb
// if argv.Mutex {
// // use the mutex lock from the modified protoc.pb.go file
// return s + ".Lock"
// // return s // causes Marshal() to panic? always use the variable name 'Lock'?
// }
// a single global lock by struct name
return msg.Lockname
}
func (pf *File) syncLock(w io.Writer) { func (pf *File) syncLock(w io.Writer) {
var LOCK string = pf.Base.Lockname // if the Marshall code changes, this will have to change var LOCK string = pf.Filebase + "Mu" // this should be lowercase. do not export the Mutex
fmt.Fprintln(w, "// a simple global lock") fmt.Fprintln(w, "// a simple global lock")
fmt.Fprintln(w, "var "+LOCK+" sync.RWMutex") fmt.Fprintln(w, "var "+LOCK+" sync.RWMutex")
@ -110,7 +121,6 @@ func (pf *File) structMatch(line string) bool {
start = "type " + msg.Name + " struct {" start = "type " + msg.Name + " struct {"
if strings.HasPrefix(line, start) { if strings.HasPrefix(line, start) {
msg.MutexFound = true msg.MutexFound = true
msg.Lockname = "x.Lock"
return true return true
} }
@ -120,7 +130,7 @@ func (pf *File) structMatch(line string) bool {
start = "type " + msg.Name + " struct {" start = "type " + msg.Name + " struct {"
if strings.HasPrefix(line, start) { if strings.HasPrefix(line, start) {
msg.MutexFound = true msg.MutexFound = true
// msg.Lockname = "x.Lock" msg.Lockname = "x.Lock"
return true return true
} }
@ -128,7 +138,11 @@ func (pf *File) structMatch(line string) bool {
start = "type " + msg.Name + " struct {" start = "type " + msg.Name + " struct {"
if strings.HasPrefix(line, start) { if strings.HasPrefix(line, start) {
msg.MutexFound = true msg.MutexFound = true
// msg.Lockname = "x.Lock" if msg.NoMutex {
msg.Lockname = pf.Filebase + "Mu" // this should be lowercase. do not export the Mutex
} else {
msg.Lockname = "x.Lock"
}
return true return true
} }
} }

View File

@ -5,7 +5,9 @@ import (
"io" "io"
) )
func newIterAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string { func (msg *MsgName) newIterAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string {
LOCK = msg.getLockname("x")
funcdef := "func (x *" + FRUIT + ") all" + APPLES + "() []*" + APPLE + " {" funcdef := "func (x *" + FRUIT + ") all" + APPLES + "() []*" + APPLE + " {"
fmt.Fprintln(w, "// safely returns a slice of pointers to the FRUIT protobufs") fmt.Fprintln(w, "// safely returns a slice of pointers to the FRUIT protobufs")
@ -35,7 +37,9 @@ func newIter(w io.Writer, msg *MsgName) string {
msg.NeedIter = false msg.NeedIter = false
APPLE := msg.Name APPLE := msg.Name
funcdef := "func New" + APPLE + "Iterator(things []*" + APPLE + ") *" + APPLE + "Iterator" // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here
// in this file where it is "new or "New". I changed it to lower case 2025.01.12
funcdef := "func new" + APPLE + "Iterator(things []*" + APPLE + ") *" + APPLE + "Iterator"
fmt.Fprintln(w, "// DEFINE THE", APPLE, "ITERATOR.") fmt.Fprintln(w, "// DEFINE THE", APPLE, "ITERATOR.")
fmt.Fprintln(w, "// itializes a new iterator.") fmt.Fprintln(w, "// itializes a new iterator.")
@ -76,6 +80,8 @@ func newIter(w io.Writer, msg *MsgName) string {
// TODO; figure out what types this actually works on // TODO; figure out what types this actually works on
// TODO; add timestamppb compare // TODO; add timestamppb compare
func newSortType(w io.Writer, STRUCT, VARNAME string) string { func newSortType(w io.Writer, STRUCT, VARNAME string) string {
// Can these be lower case? Should they be lower case? maybe sort.Sort() requires upper case?
fmt.Fprintln(w, "// sort struct by", VARNAME) fmt.Fprintln(w, "// sort struct by", VARNAME)
fmt.Fprintln(w, "type "+STRUCT+VARNAME+" []*"+STRUCT+"") fmt.Fprintln(w, "type "+STRUCT+VARNAME+" []*"+STRUCT+"")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
@ -87,16 +93,21 @@ func newSortType(w io.Writer, STRUCT, VARNAME string) string {
return "type " + STRUCT + VARNAME + " []*" + STRUCT + " // { return a[i]." + VARNAME + " < a[j]." + VARNAME + " }" return "type " + STRUCT + VARNAME + " []*" + STRUCT + " // { return a[i]." + VARNAME + " < a[j]." + VARNAME + " }"
} }
func newSortBy(w io.Writer, STRUCT, ITER, SORTNAME, SORTBY, SELECT string) string { func newSortBy(w io.Writer, STRUCT, ITER, SORTNAME, SORTBY, SELECT, VARNAME string) string {
funcdef := "func (x *" + STRUCT + ") " + SORTBY + "() *" + ITER + "Iterator" funcdef := "func (x *" + STRUCT + ") " + SORTBY + "() *" + ITER + "Iterator"
fmt.Fprintln(w, funcdef, "{") fmt.Fprintln(w, funcdef, "{")
fmt.Fprintln(w, " // copy the pointers as fast as possible.")
fmt.Fprintln(w, " things := x."+SELECT+"()") fmt.Fprintln(w, " things := x."+SELECT+"()")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "// todo: try slices.SortFunc() instead to see what happens")
fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(things))") fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(things))")
fmt.Fprintln(w, "") fmt.Fprintln(w, "// slices.SortFunc(things, func(a, b *"+STRUCT+") bool {")
fmt.Fprintln(w, " iterator := New"+ITER+"Iterator(things)") fmt.Fprintln(w, "// return a."+VARNAME+" < b."+VARNAME+" // Sort by ??. let the compiler work it out??")
fmt.Fprintln(w, " return iterator") fmt.Fprintln(w, "// })")
// should this be 'new' or 'New' ? Does it matter? I think it's totally internal here
// in this file where it is "new or "New". I changed it to lower case 2025.01.12
fmt.Fprintln(w, " return new"+ITER+"Iterator(things)")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
return funcdef return funcdef
@ -108,7 +119,9 @@ func addAllFunc(w io.Writer, FRUIT, APPLE, APPLES string) string {
fmt.Fprintln(w, funcdef) fmt.Fprintln(w, funcdef)
fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLES+"()") fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLES+"()")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, " iterator := New"+APPLE+"Iterator("+APPLE+"Pointers)") // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here. I think there are only 3 places
// in this file where it is "new or "New". I changed it to lower case 2025.01.12
fmt.Fprintln(w, " iterator := new"+APPLE+"Iterator("+APPLE+"Pointers)")
fmt.Fprintln(w, " return iterator") fmt.Fprintln(w, " return iterator")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
@ -130,7 +143,9 @@ func addLenFunc(w io.Writer, FRUIT, APPLES, LOCK string) string {
return funcdef return funcdef
} }
func addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string { func (msg *MsgName) addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string {
LOCK = msg.getLockname("x")
funcdef := "func (x *" + FRUIT + ") selectAll" + APPLES + "() []*" + APPLE funcdef := "func (x *" + FRUIT + ") selectAll" + APPLES + "() []*" + APPLE
fmt.Fprintln(w, "// safely returns a slice of pointers to the "+APPLE+" protobufs") fmt.Fprintln(w, "// safely returns a slice of pointers to the "+APPLE+" protobufs")
fmt.Fprintln(w, funcdef, "{") fmt.Fprintln(w, funcdef, "{")

View File

@ -26,7 +26,7 @@ import (
var VERSION string var VERSION string
var BUILDTIME string var BUILDTIME string
var fsort *os.File // the sort.pb.go output file // var fsort *os.File // the sort.pb.go output file
func main() { func main() {
pp := arg.MustParse(&argv) pp := arg.MustParse(&argv)

View File

@ -265,6 +265,10 @@ func (pf *File) parseForMessage(line string) *MsgName {
msg.DoMutex = true msg.DoMutex = true
log.Info("Added Mutex=true:", msg.Name) log.Info("Added Mutex=true:", msg.Name)
} }
if strings.Contains(line, "`autogenpb:nomutex`") {
msg.NoMutex = true
log.Info("Added Mutex=true:", msg.Name)
}
if strings.Contains(line, "`autogenpb:marshal`") { if strings.Contains(line, "`autogenpb:marshal`") {
msg.DoMarshal = true msg.DoMarshal = true
log.Info("Added Marshal=true:", msg.Name) log.Info("Added Marshal=true:", msg.Name)