Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Source/automaticcomponenttoolkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ func printUsageInfo() {
}

func main() {
ACTVersion := "1.8.0-alpha"
ACTVersion := "1.8.1-alpha"
fmt.Fprintln(os.Stdout, "Automatic Component Toolkit v"+ACTVersion)
if len(os.Args) < 2 {
printUsageInfo()
Expand Down Expand Up @@ -685,6 +685,11 @@ func main() {
log.Fatal(err)
}

addExtraGlobalMethodsResult := component.addExtraGlobalMethods();
if addExtraGlobalMethodsResult != nil {
log.Printf("%s", *addExtraGlobalMethodsResult)
}

if mode == eACTModeDiff {
log.Printf("Loading Component Description File to compare to")
componentB, err := ReadComponentDefinition(diffFile, ACTVersion)
Expand Down
74 changes: 61 additions & 13 deletions Source/buildbindingccpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,8 @@ func writeDynamicCPPMethodDeclaration(method ComponentDefinitionMethod, w Langua
}

func writeDynamicCPPMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassIdentifier string, ClassName string,
implementationLines []string, isGlobal bool, includeComments bool, doNotThrow bool, useCPPTypes bool, ExplicitLinking bool, forWASM bool) error {

implementationLines []string, isGlobal bool, includeComments bool, doNotThrow bool, useCPPTypes bool, ExplicitLinking bool, forWASM bool, multiThreadedEnv bool, classThreadSafetyOption ThreadSafetyOption) error {
WASMPrefix := ""
WASMCast := ""
WASMCastp := ""
Expand All @@ -614,6 +614,15 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w LanguageWriter, N

checkErrorCodeBegin := ""
checkErrorCodeEnd := ")"

if multiThreadedEnv {
if classThreadSafetyOption == eThreadSafetyStrict {
checkErrorCodeEnd = ", true)"
} else {
checkErrorCodeEnd = ", false)"
}
}

makeSharedParameter := ""

if isGlobal {
Expand Down Expand Up @@ -858,6 +867,12 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w LanguageWriter, N
initCallParameters = initCallParameters + initCallParameter
}

addThreadSafeCalls := multiThreadedEnv && ((classThreadSafetyOption == eThreadSafetySoft && requiresInitCall) || classThreadSafetyOption == eThreadSafetyStrict)

if addThreadSafeCalls {
checkErrorCodeEnd = ", true)"
}

w.Writeln(" ")
if includeComments {
w.Writeln(" /**")
Expand All @@ -876,9 +891,15 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w LanguageWriter, N

w.Writeln(" {")
w.Writelns(" ", definitionCodeLines)

if addThreadSafeCalls {
w.Writeln(" m_pWrapper->%s(this);", getLockInstanceMethodName())
}

if requiresInitCall {
w.Writeln(" %s%s(%s)%s;", checkErrorCodeBegin, CMethodName, initCallParameters, checkErrorCodeEnd)
}

w.Writelns(" ", functionCodeLines)
w.Writeln(" %s%s(%s)%s;", checkErrorCodeBegin, CMethodName, callParameters, checkErrorCodeEnd)
w.Writelns(" ", postCallCodeLines)
Expand All @@ -888,10 +909,15 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w LanguageWriter, N
w.Writelns(" ", implementationLines)
}

if addThreadSafeCalls {
w.Writeln(" m_pWrapper->%s(this);", getUnlockInstanceMethodName())
}

if len(returnCodeLines) > 0 {
w.Writeln(" ")
w.Writelns(" ", returnCodeLines)
}

w.Writeln(" }")

return nil
Expand All @@ -906,10 +932,18 @@ func writeDynamicCppBaseClassMethods(component ComponentDefinition, baseClass Co
w.Writeln(" %sHandle m_pHandle;", NameSpace)
w.Writeln("")
w.Writeln(" /* Checks for an Error code and raises Exceptions */")
w.Writeln(" void CheckError(%sResult nResult)", NameSpace)
if component.isMultiThreadedEnv() {
w.Writeln(" void CheckError(%sResult nResult, bool unlockIfError)", NameSpace)
} else {
w.Writeln(" void CheckError(%sResult nResult)", NameSpace)
}
w.Writeln(" {")
w.Writeln(" if (m_pWrapper != nullptr)")
w.Writeln(" m_pWrapper->CheckError(this, nResult);")
if component.isMultiThreadedEnv() {
w.Writeln(" m_pWrapper->CheckError(this, nResult, unlockIfError);")
} else {
w.Writeln(" m_pWrapper->CheckError(this, nResult);")
}
w.Writeln(" }")
w.Writeln("public:")
w.Writeln(" /**")
Expand Down Expand Up @@ -1450,13 +1484,22 @@ func writePolymorphicFactoryImplementation(w LanguageWriter, component Component
w.Writeln("}")
}

func writeCheckErrorImplementation(w LanguageWriter, ErrorMethodName string, ClassIdentifier string, cppBaseClassName string, NameSpace string) {
w.Writeln(" inline void C%sWrapper::CheckError(%s * pBaseClass, %sResult nResult)", ClassIdentifier, cppBaseClassName, NameSpace)
func writeCheckErrorImplementation(w LanguageWriter, ErrorMethodName string, ClassIdentifier string, cppBaseClassName string, NameSpace string, multiThreadedEnv bool) {
if multiThreadedEnv {
w.Writeln(" inline void C%sWrapper::CheckError(%s * pBaseClass, %sResult nResult, bool unlockIfError)", ClassIdentifier, cppBaseClassName, NameSpace)
} else {
w.Writeln(" inline void C%sWrapper::CheckError(%s * pBaseClass, %sResult nResult)", ClassIdentifier, cppBaseClassName, NameSpace)
}
w.Writeln(" {")
w.Writeln(" if (nResult != 0) {")
w.Writeln(" std::string sErrorMessage;")
w.Writeln(" if (pBaseClass != nullptr) {")
w.Writeln(" %s(pBaseClass, sErrorMessage);", ErrorMethodName)
if multiThreadedEnv {
w.Writeln(" if (unlockIfError) {")
w.Writeln(" %s(pBaseClass);", getUnlockInstanceMethodName())
w.Writeln(" }")
}
w.Writeln(" }")
w.Writeln(" throw E%sException(nResult, sErrorMessage);", NameSpace)
w.Writeln(" }")
Expand Down Expand Up @@ -1539,7 +1582,11 @@ func buildCppHeader(component ComponentDefinition, w LanguageWriter, NameSpace s
writeWrapperLifeTimeHandling(w, cppClassPrefix, ClassIdentifier, ExplicitLinking)

w.Writeln(" ")
w.Writeln(" inline void CheckError(%s * pBaseClass, %sResult nResult);", cppBaseClassName, NameSpace)
if component.isMultiThreadedEnv() {
w.Writeln(" inline void CheckError(%s * pBaseClass, %sResult nResult, bool unlockIfError = false);", cppBaseClassName, NameSpace)
} else {
w.Writeln(" inline void CheckError(%s * pBaseClass, %sResult nResult);", cppBaseClassName, NameSpace)
}
w.Writeln("")

for j := 0; j < len(global.Methods); j++ {
Expand Down Expand Up @@ -1622,15 +1669,15 @@ func buildCppHeader(component ComponentDefinition, w LanguageWriter, NameSpace s
implementationLines = append(implementationLines, fmt.Sprintf(" throw E%sException(%s_ERROR_COULDNOTLOADLIBRARY, \"Unknown namespace \" + %s);", NameSpace, strings.ToUpper(NameSpace), sParamName))
}

err = writeDynamicCPPMethod(method, w, NameSpace, ClassIdentifier, "Wrapper", implementationLines, true, true, false, useCPPTypes, ExplicitLinking, false)
err = writeDynamicCPPMethod(method, w, NameSpace, ClassIdentifier, "Wrapper", implementationLines, true, true, false, useCPPTypes, ExplicitLinking, false, false, eThreadSafetyNone)
if err != nil {
return err
}

}

w.Writeln("")
writeCheckErrorImplementation(w, component.Global.ErrorMethod, ClassIdentifier, cppBaseClassName, NameSpace)
writeCheckErrorImplementation(w, component.Global.ErrorMethod, ClassIdentifier, cppBaseClassName, NameSpace, component.isMultiThreadedEnv())
w.Writeln("")

if ExplicitLinking {
Expand All @@ -1648,7 +1695,7 @@ func buildCppHeader(component ComponentDefinition, w LanguageWriter, NameSpace s
w.Writeln(" */")
for j := 0; j < len(class.Methods); j++ {
method := class.Methods[j]
err := writeDynamicCPPMethod(method, w, NameSpace, ClassIdentifier, class.ClassName, make([]string, 0), false, true, false, useCPPTypes, ExplicitLinking, false)
err := writeDynamicCPPMethod(method, w, NameSpace, ClassIdentifier, class.ClassName, make([]string, 0), false, true, false, useCPPTypes, ExplicitLinking, false, component.isMultiThreadedEnv(), class.eThreadSafetyOption())
if err != nil {
return err
}
Expand Down Expand Up @@ -1934,6 +1981,7 @@ func buildCppwasmHostHeader(component ComponentDefinition, w LanguageWriter, Nam
if len(component.ImportedComponentDefinitions) > 0 {
return fmt.Errorf("C++ wasmtime bindings to not support imported components yet")
}

w.Writeln("")

w.Writeln("namespace %sWASM {", NameSpace)
Expand Down Expand Up @@ -2217,14 +2265,14 @@ func buildCppwasmGuestHeader(component ComponentDefinition, w LanguageWriter, Na
implementationLines = append(implementationLines, fmt.Sprintf(" throw E%sException(%s_ERROR_COULDNOTLOADLIBRARY, \"Unknown namespace \" + %s);", NameSpace, strings.ToUpper(NameSpace), sParamName))
}

err = writeDynamicCPPMethod(method, w, NameSpace, ClassIdentifier, "Wrapper", implementationLines, true, true, false, useCPPTypes, ExplicitLinking, true)
err = writeDynamicCPPMethod(method, w, NameSpace, ClassIdentifier, "Wrapper", implementationLines, true, true, false, useCPPTypes, ExplicitLinking, true, false, eThreadSafetyNone)
if err != nil {
return err
}
}

w.Writeln("")
writeCheckErrorImplementation(w, component.Global.ErrorMethod, ClassIdentifier, cppBaseClassName, NameSpace)
writeCheckErrorImplementation(w, component.Global.ErrorMethod, ClassIdentifier, cppBaseClassName, NameSpace, false)
w.Writeln("")

for i := 0; i < len(component.Classes); i++ {
Expand All @@ -2236,7 +2284,7 @@ func buildCppwasmGuestHeader(component ComponentDefinition, w LanguageWriter, Na
w.Writeln(" */")
for j := 0; j < len(class.Methods); j++ {
method := class.Methods[j]
err := writeDynamicCPPMethod(method, w, NameSpace, ClassIdentifier, class.ClassName, make([]string, 0), false, true, false, useCPPTypes, ExplicitLinking, true)
err := writeDynamicCPPMethod(method, w, NameSpace, ClassIdentifier, class.ClassName, make([]string, 0), false, true, false, useCPPTypes, ExplicitLinking, true, false, eThreadSafetyNone)
if err != nil {
return err
}
Expand Down
81 changes: 76 additions & 5 deletions Source/buildimplementationcpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,39 @@ func writeSharedPtrTemplate(component ComponentDefinition, w LanguageWriter, Cla
w.Writeln("")
}

func getWithMutexClassName(ClassIdentifier string, ClassName string) (string) {
return ClassIdentifier + ClassName + "WithMutex"
}

func writeBaseInterfaceWithMutexClass(baseClass ComponentDefinitionClass, w LanguageWriter, ClassIdentifier string) {
baseClassName:= "I" + baseClass.ClassName
className := "I" + getWithMutexClassName(ClassIdentifier, baseClass.ClassName)
lockInstanceMethod := LockInstanceMethod(baseClass.ClassName)
unlockInstanceMethod := UnlockInstanceMethod((baseClass.ClassName))

w.Writeln("")
w.Writeln("/**")
w.Writeln(" Definition of a class with mutex for %s", baseClassName)
w.Writeln("*/")
w.Writeln("class %s : public virtual %s", className, baseClassName)
w.Writeln("{")
w.Writeln("private:")
w.Writeln(" std::mutex m_mutex;")
w.Writeln("public:")
w.Writeln("")
w.Writeln(" /**")
w.Writeln(" * %s::%s - %s", className, lockInstanceMethod.MethodName, lockInstanceMethod.MethodDescription)
w.Writeln(" */")
w.Writeln(" virtual void %s() { m_mutex.lock(); }", lockInstanceMethod.MethodName)
w.Writeln("")
w.Writeln(" /**")
w.Writeln(" * %s::%s - %s", className, unlockInstanceMethod.MethodName, unlockInstanceMethod.MethodDescription)
w.Writeln(" */")
w.Writeln(" virtual void %s() { m_mutex.unlock();}", unlockInstanceMethod.MethodName)
w.Writeln("};")
w.Writeln("")
}

func writeCPPClassInterface(component ComponentDefinition, class ComponentDefinitionClass, w LanguageWriter, NameSpace string, NameSpaceImplementation string, ClassIdentifier string, BaseName string) (error) {
w.Writeln("")
w.Writeln("/*************************************************************************************************************************")
Expand All @@ -324,7 +357,11 @@ func writeCPPClassInterface(component ComponentDefinition, class ComponentDefini
if (!component.isBaseClass(class)) {
parentClassString = " : public virtual "
if (class.ParentClass == "") {
parentClassString += fmt.Sprintf("I%s%s ", ClassIdentifier, component.Global.BaseClassName)
if (class.isThreadSafe()) {
parentClassString += fmt.Sprintf("I%s ", getWithMutexClassName(ClassIdentifier, component.Global.BaseClassName))
} else {
parentClassString += fmt.Sprintf("I%s%s ", ClassIdentifier, component.Global.BaseClassName)
}
} else {
parentClassString += fmt.Sprintf("I%s%s ", ClassIdentifier, class.ParentClass)
}
Expand Down Expand Up @@ -411,7 +448,23 @@ func writeCPPClassInterface(component ComponentDefinition, class ComponentDefini
w.Writeln(" {")
w.Writeln(" return m_ParameterCache.get();")
w.Writeln(" }")
w.Writeln("")
w.Writeln("")

if component.isMultiThreadedEnv() {
lockInstanceMethod := LockInstanceMethod(component.Global.BaseClassName)
w.Writeln(" /**")
w.Writeln(" * %s::%s - %s", classInterfaceName, lockInstanceMethod.MethodName, lockInstanceMethod.MethodDescription)
w.Writeln(" */")
w.Writeln(" virtual void %s() {}", lockInstanceMethod.MethodName)
w.Writeln("")

unlockInstanceMethod := UnlockInstanceMethod(component.Global.BaseClassName)
w.Writeln(" /**")
w.Writeln(" * %s::%s - %s", classInterfaceName, unlockInstanceMethod.MethodName, unlockInstanceMethod.MethodDescription)
w.Writeln(" */")
w.Writeln(" virtual void %s() {}", unlockInstanceMethod.MethodName)
w.Writeln("")
}
}

if (component.isBaseClass(class)) {
Expand Down Expand Up @@ -452,6 +505,9 @@ func writeCPPClassInterface(component ComponentDefinition, class ComponentDefini

if component.isBaseClass(class) {
writeSharedPtrTemplate(component, w, ClassIdentifier)
if component.isMultiThreadedEnv() {
writeBaseInterfaceWithMutexClass(class, w, ClassIdentifier)
}
}

w.Writeln("")
Expand Down Expand Up @@ -535,6 +591,9 @@ func buildCPPInterfaces(component ComponentDefinition, w LanguageWriter, NameSpa

w.Writeln("#include <string>")
w.Writeln("#include <memory>")
if component.isMultiThreadedEnv() {
w.Writeln("#include <mutex>")
}
w.Writeln("")
w.Writeln("#include \"%s_types.hpp\"", BaseName)
w.Writeln("")
Expand Down Expand Up @@ -583,7 +642,7 @@ func buildCPPInterfaces(component ComponentDefinition, w LanguageWriter, NameSpa
global := component.Global;
for j := 0; j < len(global.Methods); j++ {
method := global.Methods[j]

// Omit special functions that are automatically implemented
isSpecialFunction, err := CheckHeaderSpecialFunction(method, global);
if err != nil {
Expand All @@ -598,7 +657,19 @@ func buildCPPInterfaces(component ComponentDefinition, w LanguageWriter, NameSpa
if err != nil {
return err
}
w.Writeln("%s;", methodstring)

if method.isExtraGlobalmethod() {
implementationString := ""
if method.MethodName == getLockInstanceMethodName() {
implementationString = fmt.Sprintf("p%s->%s();", method.Params[0].ParamName, getLockInstanceMethodName())
} else if method.MethodName == getUnlockInstanceMethodName() {
implementationString = fmt.Sprintf("p%s->%s();", method.Params[0].ParamName, getUnlockInstanceMethodName())
}
w.Writeln("%s { %s }", methodstring, implementationString)
} else {
w.Writeln("%s;", methodstring)
}

w.Writeln("")
}
w.Writeln("};")
Expand Down Expand Up @@ -873,7 +944,7 @@ func buildCPPInterfaceWrapper(component ComponentDefinition, w LanguageWriter, N
global := component.Global;
for j := 0; j < len(global.Methods); j++ {
method := global.Methods[j]

// Check for special functions
isSpecialFunction, err := CheckHeaderSpecialFunction(method, global);
if err != nil {
Expand Down
Loading